From 5878b880ae71f5d80f0d2b8f6b156951e5392fe1 Mon Sep 17 00:00:00 2001 From: Robert Yevdokimov <105675984+ryevdokimov@users.noreply.github.com> Date: Sat, 1 Feb 2025 13:34:15 +0400 Subject: [PATCH] Add "active" state to one of the multiple selected Node3Ds to determine basis in Local mode --- doc/classes/EditorSettings.xml | 4 ++ editor/editor_settings.cpp | 1 + editor/plugins/node_3d_editor_plugin.cpp | 66 ++++++++++++++++++++++-- editor/plugins/node_3d_editor_plugin.h | 3 ++ 4 files changed, 70 insertions(+), 4 deletions(-) diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml index 3900a81502c..919ccaf5caa 100644 --- a/doc/classes/EditorSettings.xml +++ b/doc/classes/EditorSettings.xml @@ -288,6 +288,10 @@ The factor to use when zooming in or out in the 2D editor. For example, [code]1.1[/code] will zoom in by 10% with every step. If set to [code]2.0[/code], zooming will only cycle through powers of two. + + The color to use for the active selection box that surrounds selected nodes in the 3D editor viewport. The color's alpha channel influences the selection box's opacity. + [b]Note:[/b] The term "active" indicates that this object is the primary selection used as the basis for certain operations. This is the last selected [Node3D], which can be reordered with [kbd]Shift + Left mouse button[/kbd]. + The default camera vertical field of view to use in the 3D editor (in degrees). The camera field of view can be adjusted on a per-scene basis using the [b]View[/b] menu at the top of the 3D editor. If a scene had its camera field of view adjusted using the [b]View[/b] menu, this setting is ignored in the scene in question. This setting is also ignored while a [Camera3D] node is being previewed in the editor. [b]Note:[/b] The editor camera always uses the [b]Keep Height[/b] aspect mode. diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 9a5a51a18a2..7b46566b2ca 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -771,6 +771,7 @@ void EditorSettings::_load_defaults(Ref p_extra_config) { // Use a similar color to the 2D editor selection. EDITOR_SETTING_USAGE(Variant::COLOR, PROPERTY_HINT_NONE, "editors/3d/selection_box_color", Color(1.0, 0.5, 0), "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) + EDITOR_SETTING_USAGE(Variant::COLOR, PROPERTY_HINT_NONE, "editors/3d/active_selection_box_color", Color(1.5, 0.75, 0, 1.0), "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) EDITOR_SETTING_USAGE(Variant::COLOR, PROPERTY_HINT_NONE, "editors/3d_gizmos/gizmo_colors/instantiated", Color(0.7, 0.7, 0.7, 0.6), "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) EDITOR_SETTING_USAGE(Variant::COLOR, PROPERTY_HINT_NONE, "editors/3d_gizmos/gizmo_colors/joint", Color(0.5, 0.8, 1), "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) EDITOR_SETTING_USAGE(Variant::COLOR, PROPERTY_HINT_NONE, "editors/3d_gizmos/gizmo_colors/aabb", Color(0.28, 0.8, 0.82), "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 2e89bb47061..08d3e48b722 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -791,8 +791,12 @@ void Node3DEditorViewport::_select_clicked(bool p_allow_locked) { if (p_allow_locked || (selected != nullptr && !_is_node_locked(selected))) { if (clicked_wants_append) { + Node *active_node = editor_selection->get_selected_node_list().is_empty() ? nullptr : editor_selection->get_selected_node_list().back()->get(); if (editor_selection->is_selected(selected)) { editor_selection->remove_node(selected); + if (selected != active_node) { + editor_selection->add_node(selected); + } } else { editor_selection->add_node(selected); } @@ -6238,7 +6242,7 @@ void Node3DEditor::update_transform_gizmo() { for (const KeyValue &E : se->subgizmos) { Transform3D xf = se->sp->get_global_transform() * se->gizmo->get_subgizmo_transform(E.key); gizmo_center += xf.origin; - if (count == 0 && local_gizmo_coords) { + if ((unsigned int)count == se->subgizmos.size() - 1 && local_gizmo_coords) { gizmo_basis = xf.basis; } count++; @@ -6262,7 +6266,7 @@ void Node3DEditor::update_transform_gizmo() { Transform3D xf = sel_item->sp->get_global_transform(); gizmo_center += xf.origin; - if (count == 0 && local_gizmo_coords) { + if (count == selection.size() - 1 && local_gizmo_coords) { gizmo_basis = xf.basis; } count++; @@ -6271,7 +6275,7 @@ void Node3DEditor::update_transform_gizmo() { gizmo.visible = count > 0; gizmo.transform.origin = (count > 0) ? gizmo_center / count : Vector3(); - gizmo.transform.basis = (count == 1) ? gizmo_basis : Basis(); + gizmo.transform.basis = gizmo_basis; for (uint32_t i = 0; i < VIEWPORTS_COUNT; i++) { viewports[i]->update_transform_gizmo_view(); @@ -6363,23 +6367,33 @@ void Node3DEditor::_generate_selection_boxes() { // This lets the user see where the selection is while still having a sense of depth. Ref st = memnew(SurfaceTool); Ref st_xray = memnew(SurfaceTool); + Ref active_st = memnew(SurfaceTool); + Ref active_st_xray = memnew(SurfaceTool); st->begin(Mesh::PRIMITIVE_LINES); st_xray->begin(Mesh::PRIMITIVE_LINES); + active_st->begin(Mesh::PRIMITIVE_LINES); + active_st_xray->begin(Mesh::PRIMITIVE_LINES); for (int i = 0; i < 12; i++) { Vector3 a, b; aabb.get_edge(i, a, b); st->add_vertex(a); st->add_vertex(b); + active_st->add_vertex(a); + active_st->add_vertex(b); st_xray->add_vertex(a); st_xray->add_vertex(b); + active_st_xray->add_vertex(a); + active_st_xray->add_vertex(b); } + const Color selection_box_color = EDITOR_GET("editors/3d/selection_box_color"); + const Color active_selection_box_color = EDITOR_GET("editors/3d/active_selection_box_color"); + Ref mat = memnew(StandardMaterial3D); mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); mat->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true); - const Color selection_box_color = EDITOR_GET("editors/3d/selection_box_color"); mat->set_albedo(selection_box_color); mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); st->set_material(mat); @@ -6393,6 +6407,23 @@ void Node3DEditor::_generate_selection_boxes() { mat_xray->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); st_xray->set_material(mat_xray); selection_box_xray = st_xray->commit(); + + Ref active_mat = memnew(StandardMaterial3D); + active_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + active_mat->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true); + active_mat->set_albedo(active_selection_box_color); + active_mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); + active_st->set_material(active_mat); + active_selection_box = active_st->commit(); + + Ref active_mat_xray = memnew(StandardMaterial3D); + active_mat_xray->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + active_mat_xray->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true); + active_mat_xray->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true); + active_mat_xray->set_albedo(active_selection_box_color * Color(1, 1, 1, 0.15)); + active_mat_xray->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); + active_st_xray->set_material(active_mat_xray); + active_selection_box_xray = active_st_xray->commit(); } Dictionary Node3DEditor::get_state() const { @@ -7827,6 +7858,33 @@ void Node3DEditor::update_grid() { void Node3DEditor::_selection_changed() { _refresh_menu_icons(); + + const HashMap &selection = editor_selection->get_selection(); + + for (const KeyValue &E : selection) { + Node3D *sp = Object::cast_to(E.key); + if (!sp) { + continue; + } + + Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data(sp); + if (!se) { + continue; + } + + if (sp == editor_selection->get_selected_node_list().back()->get()) { + RenderingServer::get_singleton()->instance_set_base(se->sbox_instance, active_selection_box->get_rid()); + RenderingServer::get_singleton()->instance_set_base(se->sbox_instance_xray, active_selection_box_xray->get_rid()); + RenderingServer::get_singleton()->instance_set_base(se->sbox_instance_offset, active_selection_box->get_rid()); + RenderingServer::get_singleton()->instance_set_base(se->sbox_instance_xray_offset, active_selection_box_xray->get_rid()); + } else { + RenderingServer::get_singleton()->instance_set_base(se->sbox_instance, selection_box->get_rid()); + RenderingServer::get_singleton()->instance_set_base(se->sbox_instance_xray, selection_box_xray->get_rid()); + RenderingServer::get_singleton()->instance_set_base(se->sbox_instance_offset, selection_box->get_rid()); + RenderingServer::get_singleton()->instance_set_base(se->sbox_instance_xray_offset, selection_box_xray->get_rid()); + } + } + if (selected && editor_selection->get_selected_node_list().size() != 1) { Vector> gizmos = selected->get_gizmos(); for (int i = 0; i < gizmos.size(); i++) { diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index 27c709fb064..d9b9d933ccd 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -694,8 +694,11 @@ private: real_t snap_rotate_value; real_t snap_scale_value; + Ref active_selection_box_xray; + Ref active_selection_box; Ref selection_box_xray; Ref selection_box; + RID indicators; RID indicators_instance; RID cursor_mesh;