From 9d9043e1a9a15a8593319c045e807e4fb277ca7a Mon Sep 17 00:00:00 2001 From: Haoyu Qiu Date: Mon, 9 Aug 2021 22:51:26 +0800 Subject: [PATCH] Make 3D selection box independent of object size --- editor/plugins/spatial_editor_plugin.cpp | 52 ++++++++++++++++-------- editor/plugins/spatial_editor_plugin.h | 2 + 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 80e1a45b150..00df3201d7c 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -2410,15 +2410,28 @@ void SpatialEditorViewport::_notification(int p_what) { se->aabb = new_aabb; - t.translate(se->aabb.position); + Transform t_offset = t; // apply AABB scaling before item's global transform - Basis aabb_s; - aabb_s.scale(se->aabb.size); - t.basis = t.basis * aabb_s; + { + const Vector3 offset(0.005, 0.005, 0.005); + Basis aabb_s; + aabb_s.scale(se->aabb.size + offset); + t.translate(se->aabb.position - offset / 2); + t.basis = t.basis * aabb_s; + } + { + const Vector3 offset(0.01, 0.01, 0.01); + Basis aabb_s; + aabb_s.scale(se->aabb.size + offset); + t_offset.translate(se->aabb.position - offset / 2); + t_offset.basis = t_offset.basis * aabb_s; + } VisualServer::get_singleton()->instance_set_transform(se->sbox_instance, t); + VisualServer::get_singleton()->instance_set_transform(se->sbox_instance_offset, t_offset); VisualServer::get_singleton()->instance_set_transform(se->sbox_instance_xray, t); + VisualServer::get_singleton()->instance_set_transform(se->sbox_instance_xray_offset, t_offset); } if (changed || (spatial_editor->is_gizmo_visible() && !exist)) { @@ -4292,9 +4305,15 @@ SpatialEditorSelectedItem::~SpatialEditorSelectedItem() { if (sbox_instance.is_valid()) { VisualServer::get_singleton()->free(sbox_instance); } + if (sbox_instance_offset.is_valid()) { + VisualServer::get_singleton()->free(sbox_instance_offset); + } if (sbox_instance_xray.is_valid()) { VisualServer::get_singleton()->free(sbox_instance_xray); } + if (sbox_instance_xray_offset.is_valid()) { + VisualServer::get_singleton()->free(sbox_instance_xray_offset); + } } void SpatialEditor::select_gizmo_highlight_axis(int p_axis) { @@ -4425,21 +4444,32 @@ Object *SpatialEditor::_get_editor_data(Object *p_what) { si->sbox_instance = VisualServer::get_singleton()->instance_create2( selection_box->get_rid(), sp->get_world()->get_scenario()); + si->sbox_instance_offset = VisualServer::get_singleton()->instance_create2( + selection_box->get_rid(), + sp->get_world()->get_scenario()); VS::get_singleton()->instance_geometry_set_cast_shadows_setting( si->sbox_instance, VS::SHADOW_CASTING_SETTING_OFF); // Use the Edit layer to hide the selection box when View Gizmos is disabled, since it is a bit distracting. // It's still possible to approximately guess what is selected by looking at the manipulation gizmo position. VS::get_singleton()->instance_set_layer_mask(si->sbox_instance, 1 << SpatialEditorViewport::GIZMO_EDIT_LAYER); + VS::get_singleton()->instance_set_layer_mask(si->sbox_instance_offset, 1 << SpatialEditorViewport::GIZMO_EDIT_LAYER); si->sbox_instance_xray = VisualServer::get_singleton()->instance_create2( selection_box_xray->get_rid(), sp->get_world()->get_scenario()); + si->sbox_instance_xray_offset = VisualServer::get_singleton()->instance_create2( + selection_box_xray->get_rid(), + sp->get_world()->get_scenario()); VS::get_singleton()->instance_geometry_set_cast_shadows_setting( si->sbox_instance_xray, VS::SHADOW_CASTING_SETTING_OFF); + VS::get_singleton()->instance_geometry_set_cast_shadows_setting( + si->sbox_instance_xray_offset, + VS::SHADOW_CASTING_SETTING_OFF); // Use the Edit layer to hide the selection box when View Gizmos is disabled, since it is a bit distracting. // It's still possible to approximately guess what is selected by looking at the manipulation gizmo position. VS::get_singleton()->instance_set_layer_mask(si->sbox_instance_xray, 1 << SpatialEditorViewport::GIZMO_EDIT_LAYER); + VS::get_singleton()->instance_set_layer_mask(si->sbox_instance_xray_offset, 1 << SpatialEditorViewport::GIZMO_EDIT_LAYER); return si; } @@ -4447,10 +4477,6 @@ Object *SpatialEditor::_get_editor_data(Object *p_what) { void SpatialEditor::_generate_selection_boxes() { // Use two AABBs to create the illusion of a slightly thicker line. AABB aabb(Vector3(), Vector3(1, 1, 1)); - AABB aabb_offset(Vector3(), Vector3(1, 1, 1)); - // Grow the bounding boxes slightly to avoid Z-fighting with the mesh's edges. - aabb.grow_by(0.005); - aabb_offset.grow_by(0.01); // Create a x-ray (visible through solid surfaces) and standard version of the selection box. // Both will be drawn at the same position, but with different opacity. @@ -4470,16 +4496,6 @@ void SpatialEditor::_generate_selection_boxes() { st_xray->add_vertex(b); } - for (int i = 0; i < 12; i++) { - Vector3 a, b; - aabb_offset.get_edge(i, a, b); - - st->add_vertex(a); - st->add_vertex(b); - st_xray->add_vertex(a); - st_xray->add_vertex(b); - } - Ref mat = memnew(SpatialMaterial); mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); const Color selection_box_color = EDITOR_GET("editors/3d/selection_box_color"); diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index f0dcf689366..2e26e668caf 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -480,7 +480,9 @@ public: bool last_xform_dirty; Spatial *sp; RID sbox_instance; + RID sbox_instance_offset; RID sbox_instance_xray; + RID sbox_instance_xray_offset; SpatialEditorSelectedItem() { sp = nullptr;