From 2f4e6b9de47c1a00d9c2f04986ef379297988867 Mon Sep 17 00:00:00 2001 From: Michael Alexsander Date: Mon, 31 Mar 2025 17:37:46 -0300 Subject: [PATCH] Allow to change the color of canvas selection --- doc/classes/EditorSettings.xml | 10 ++++- editor/run/game_view_plugin.cpp | 4 +- editor/scene/canvas_item_editor_plugin.cpp | 11 ++--- editor/scene/canvas_item_editor_plugin.h | 5 ++- editor/settings/editor_settings.cpp | 2 + scene/debugger/runtime_node_select.cpp | 51 +++++++++++----------- scene/debugger/runtime_node_select.h | 19 ++++---- 7 files changed, 54 insertions(+), 48 deletions(-) diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml index 1fea855339..578dc5718f 100644 --- a/doc/classes/EditorSettings.xml +++ b/doc/classes/EditorSettings.xml @@ -352,9 +352,15 @@ The guides color to use in the 2D editor. Guides can be created by dragging the mouse cursor from the rulers. + + The color to use for the selection rectangle that surrounds selected locked nodes in the 2D editor viewport. + The thickness of the coordinate ruler in the 2D editor. Increasing this will also increase the size of the ruler font, improving readability when using a lower editor scale. The editor may force a minimum size to keep the ruler numbers legible. + + The color to use for the selection rectangle outlines that surrounds selected nodes in the 2D editor viewport. + The color to use when drawing smart snapping lines in the 2D editor. The smart snapping lines will automatically display when moving 2D nodes if smart snapping is enabled in the Snapping Options menu at the top of the 2D editor viewport. @@ -368,7 +374,7 @@ 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. + The color to use for the active selection box that surrounds selected nodes in the 3D editor viewport. [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]. @@ -507,7 +513,7 @@ The color to use for the secondary 3D grid. This is generally a less visible color than [member editors/3d/primary_grid_color]. The color's alpha channel affects the grid's opacity. - The color to use for the selection box that surrounds selected nodes in the 3D editor viewport. The color's alpha channel influences the selection box's opacity. + The color to use for the selection box that surrounds selected nodes in the 3D editor viewport. If checked, the transform gizmo remains visible during rotation in that transform mode. diff --git a/editor/run/game_view_plugin.cpp b/editor/run/game_view_plugin.cpp index a557e0d392..4df1688a67 100644 --- a/editor/run/game_view_plugin.cpp +++ b/editor/run/game_view_plugin.cpp @@ -66,6 +66,7 @@ void GameViewDebugger::_session_started(Ref p_session) { Dictionary settings; settings["debugger/max_node_selection"] = EDITOR_GET("debugger/max_node_selection"); + settings["editors/2d/selection_rectangle_color"] = EDITOR_GET("editors/2d/selection_rectangle_color"); settings["editors/panning/2d_editor_panning_scheme"] = EDITOR_GET("editors/panning/2d_editor_panning_scheme"); settings["editors/panning/simple_panning"] = EDITOR_GET("editors/panning/simple_panning"); settings["editors/panning/warped_mouse_panning"] = EDITOR_GET("editors/panning/warped_mouse_panning"); @@ -1623,8 +1624,7 @@ GameViewPluginBase::GameViewPluginBase() { #endif } -GameViewPlugin::GameViewPlugin() : - GameViewPluginBase() { +GameViewPlugin::GameViewPlugin() { #ifndef ANDROID_ENABLED Ref game_view_debugger; game_view_debugger.instantiate(); diff --git a/editor/scene/canvas_item_editor_plugin.cpp b/editor/scene/canvas_item_editor_plugin.cpp index 6c84c4a21a..c69ba19748 100644 --- a/editor/scene/canvas_item_editor_plugin.cpp +++ b/editor/scene/canvas_item_editor_plugin.cpp @@ -3807,14 +3807,8 @@ void CanvasItemEditor::_draw_selection() { xform.xform(rect.position + Vector2(0, rect.size.y)) }; - Color c = Color(1, 0.6, 0.4, 0.7); - - if (item_locked) { - c = Color(0.7, 0.7, 0.7, 0.7); - } - for (int i = 0; i < 4; i++) { - viewport->draw_line(endpoints[i], endpoints[(i + 1) % 4], c, Math::round(2 * EDSCALE)); + viewport->draw_line(endpoints[i], endpoints[(i + 1) % 4], item_locked ? locked_selection_rectangle_color : selection_rectangle_color, Math::round(2 * EDSCALE)); } } else { Transform2D unscaled_transform = (xform * ci->get_transform().affine_inverse() * ci->_edit_get_transform()).orthonormalized(); @@ -4348,6 +4342,9 @@ void CanvasItemEditor::_update_editor_settings() { key_auto_insert_button->add_theme_color_override("icon_pressed_color", key_auto_color.lerp(Color(1, 0, 0), 0.55)); animation_menu->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); + selection_rectangle_color = EDITOR_GET("editors/2d/selection_rectangle_color"); + locked_selection_rectangle_color = EDITOR_GET("editors/2d/locked_selection_rectangle_color"); + context_toolbar_panel->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SNAME("ContextualToolbar"), EditorStringName(EditorStyles))); simple_panning = EDITOR_GET("editors/panning/simple_panning"); diff --git a/editor/scene/canvas_item_editor_plugin.h b/editor/scene/canvas_item_editor_plugin.h index dc4f9d1e9d..29ea7e5fc1 100644 --- a/editor/scene/canvas_item_editor_plugin.h +++ b/editor/scene/canvas_item_editor_plugin.h @@ -244,6 +244,9 @@ private: Vector2i primary_grid_step; int grid_step_multiplier = 0; + Color selection_rectangle_color; + Color locked_selection_rectangle_color; + real_t snap_rotation_step = 0.0; real_t snap_rotation_offset = 0.0; real_t snap_scale_step = 0.0; @@ -279,7 +282,7 @@ private: real_t grab_distance = 0.0; bool simple_panning = false; - MenuOption last_option; + MenuOption last_option = SNAP_USE; public: struct SelectResult { diff --git a/editor/settings/editor_settings.cpp b/editor/settings/editor_settings.cpp index 76f54fbd99..f7c2b49146 100644 --- a/editor/settings/editor_settings.cpp +++ b/editor/settings/editor_settings.cpp @@ -993,6 +993,8 @@ void EditorSettings::_load_defaults(Ref p_extra_config) { _initial_set("editors/2d/grid_color", Color(1.0, 1.0, 1.0, 0.07), true); _initial_set("editors/2d/guides_color", Color(0.6, 0.0, 0.8), true); _initial_set("editors/2d/smart_snapping_line_color", Color(0.9, 0.1, 0.1), true); + _initial_set("editors/2d/selection_rectangle_color", Color(1, 0.6, 0.4, 0.7), true); + _initial_set("editors/2d/locked_selection_rectangle_color", Color(0.7, 0.7, 0.7, 0.7), true); EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "editors/2d/bone_width", 5.0, "0.01,20,0.01,or_greater") _initial_set("editors/2d/bone_color1", Color(1.0, 1.0, 1.0, 0.7)); _initial_set("editors/2d/bone_color2", Color(0.6, 0.6, 0.6, 0.7)); diff --git a/scene/debugger/runtime_node_select.cpp b/scene/debugger/runtime_node_select.cpp index b458bbad05..81461f45c7 100644 --- a/scene/debugger/runtime_node_select.cpp +++ b/scene/debugger/runtime_node_select.cpp @@ -78,7 +78,7 @@ RuntimeNodeSelect::~RuntimeNodeSelect() { if (draw_canvas.is_valid()) { RS::get_singleton()->free_rid(sel_drag_ci); - RS::get_singleton()->free_rid(sbox_2d_ci); + RS::get_singleton()->free_rid(srect_ci); RS::get_singleton()->free_rid(draw_canvas); } } @@ -114,12 +114,14 @@ void RuntimeNodeSelect::_setup(const Dictionary &p_settings) { draw_canvas = RS::get_singleton()->canvas_create(); sel_drag_ci = RS::get_singleton()->canvas_item_create(); - /// 2D Selection Box Generation + /// 2D Selection Rectangle Generation - sbox_2d_ci = RS::get_singleton()->canvas_item_create(); + srect_color = p_settings.get("editors/2d/selection_rectangle_color", Color()); + + srect_ci = RS::get_singleton()->canvas_item_create(); RS::get_singleton()->viewport_attach_canvas(root->get_viewport_rid(), draw_canvas); RS::get_singleton()->canvas_item_set_parent(sel_drag_ci, draw_canvas); - RS::get_singleton()->canvas_item_set_parent(sbox_2d_ci, draw_canvas); + RS::get_singleton()->canvas_item_set_parent(srect_ci, draw_canvas); #ifndef _3D_DISABLED camera_fov = p_settings.get("editors/3d/default_fov", 70); @@ -199,7 +201,7 @@ void RuntimeNodeSelect::_setup(const Dictionary &p_settings) { /// 3D Selection Box Generation // Copied from the Node3DEditor implementation. - sbox_3d_color = p_settings.get("editors/3d/selection_box_color", Color()); + sbox_color = p_settings.get("editors/3d/selection_box_color", Color()); // Use two AABBs to create the illusion of a slightly thicker line. AABB aabb(Vector3(), Vector3(1, 1, 1)); @@ -225,19 +227,19 @@ void RuntimeNodeSelect::_setup(const Dictionary &p_settings) { Ref mat = memnew(StandardMaterial3D); mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); mat->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true); - mat->set_albedo(sbox_3d_color); + mat->set_albedo(sbox_color); mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); st->set_material(mat); - sbox_3d_mesh = st->commit(); + sbox_mesh = st->commit(); Ref mat_xray = memnew(StandardMaterial3D); mat_xray->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); mat_xray->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true); mat_xray->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true); - mat_xray->set_albedo(sbox_3d_color * Color(1, 1, 1, 0.15)); + mat_xray->set_albedo(sbox_color * Color(1, 1, 1, 0.15)); mat_xray->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); st_xray->set_material(mat_xray); - sbox_3d_mesh_xray = st_xray->commit(); + sbox_mesh_xray = st_xray->commit(); #endif // _3D_DISABLED SceneTree::get_singleton()->connect("process_frame", callable_mp(this, &RuntimeNodeSelect::_process_frame)); @@ -633,7 +635,7 @@ void RuntimeNodeSelect::_send_ids(const Vector &p_picked_nodes, bool p_i nodes.push_back(ObjectDB::get_instance(id)); } #ifndef _3D_DISABLED - for (const KeyValue> &KV : selected_3d_nodes) { + for (const KeyValue> &KV : selected_3d_nodes) { ids.push_back(KV.key); nodes.push_back(ObjectDB::get_instance(KV.key)); } @@ -664,7 +666,7 @@ void RuntimeNodeSelect::_set_selected_nodes(const Vector &p_nodes) { bool changed = false; LocalVector nodes_ci; #ifndef _3D_DISABLED - HashMap> nodes_3d; + HashMap> nodes_3d; #endif // _3D_DISABLED for (Node *node : p_nodes) { @@ -692,18 +694,18 @@ void RuntimeNodeSelect::_set_selected_nodes(const Vector &p_nodes) { continue; } - if (sbox_3d_mesh.is_null() || sbox_3d_mesh_xray.is_null()) { + if (sbox_mesh.is_null() || sbox_mesh_xray.is_null()) { continue; } - Ref sb; + Ref sb; sb.instantiate(); nodes_3d[id] = sb; RID scenario = node_3d->get_world_3d()->get_scenario(); - sb->instance = RS::get_singleton()->instance_create2(sbox_3d_mesh->get_rid(), scenario); - sb->instance_ofs = RS::get_singleton()->instance_create2(sbox_3d_mesh->get_rid(), scenario); + sb->instance = RS::get_singleton()->instance_create2(sbox_mesh->get_rid(), scenario); + sb->instance_ofs = RS::get_singleton()->instance_create2(sbox_mesh->get_rid(), scenario); RS::get_singleton()->instance_geometry_set_cast_shadows_setting(sb->instance, RSE::SHADOW_CASTING_SETTING_OFF); RS::get_singleton()->instance_geometry_set_cast_shadows_setting(sb->instance_ofs, RSE::SHADOW_CASTING_SETTING_OFF); RS::get_singleton()->instance_geometry_set_flag(sb->instance, RSE::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true); @@ -711,8 +713,8 @@ void RuntimeNodeSelect::_set_selected_nodes(const Vector &p_nodes) { RS::get_singleton()->instance_geometry_set_flag(sb->instance_ofs, RSE::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true); RS::get_singleton()->instance_geometry_set_flag(sb->instance_ofs, RSE::INSTANCE_FLAG_USE_BAKED_LIGHT, false); - sb->instance_xray = RS::get_singleton()->instance_create2(sbox_3d_mesh_xray->get_rid(), scenario); - sb->instance_xray_ofs = RS::get_singleton()->instance_create2(sbox_3d_mesh_xray->get_rid(), scenario); + sb->instance_xray = RS::get_singleton()->instance_create2(sbox_mesh_xray->get_rid(), scenario); + sb->instance_xray_ofs = RS::get_singleton()->instance_create2(sbox_mesh_xray->get_rid(), scenario); RS::get_singleton()->instance_geometry_set_cast_shadows_setting(sb->instance_xray, RSE::SHADOW_CASTING_SETTING_OFF); RS::get_singleton()->instance_geometry_set_cast_shadows_setting(sb->instance_xray_ofs, RSE::SHADOW_CASTING_SETTING_OFF); RS::get_singleton()->instance_geometry_set_flag(sb->instance_xray, RSE::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true); @@ -758,8 +760,8 @@ void RuntimeNodeSelect::_queue_selection_update() { } void RuntimeNodeSelect::_update_selection() { - RS::get_singleton()->canvas_item_clear(sbox_2d_ci); - RS::get_singleton()->canvas_item_set_visible(sbox_2d_ci, selection_visible); + RS::get_singleton()->canvas_item_clear(srect_ci); + RS::get_singleton()->canvas_item_set_visible(srect_ci, selection_visible); for (LocalVector::Iterator E = selected_ci_nodes.begin(); E != selected_ci_nodes.end(); ++E) { ObjectID id = *E; @@ -800,14 +802,13 @@ void RuntimeNodeSelect::_update_selection() { xform.xform(rect.position + Point2(0, rect.size.y)) }; - const Color selection_color_2d = Color(1, 0.6, 0.4, 0.7); for (int i = 0; i < 4; i++) { - RS::get_singleton()->canvas_item_add_line(sbox_2d_ci, endpoints[i], endpoints[(i + 1) % 4], selection_color_2d, sel_2d_scale); + RS::get_singleton()->canvas_item_add_line(srect_ci, endpoints[i], endpoints[(i + 1) % 4], srect_color, sel_2d_scale); } } #ifndef _3D_DISABLED - for (HashMap>::ConstIterator KV = selected_3d_nodes.begin(); KV != selected_3d_nodes.end(); ++KV) { + for (HashMap>::ConstIterator KV = selected_3d_nodes.begin(); KV != selected_3d_nodes.end(); ++KV) { ObjectID id = KV->key; Node3D *node_3d = ObjectDB::get_instance(id); if (!node_3d) { @@ -842,7 +843,7 @@ void RuntimeNodeSelect::_update_selection() { bounds = xform_to_top_level_parent_space.xform(bounds); Transform3D t = node_3d->get_global_transform(); - Ref sb = KV->value; + Ref sb = KV->value; if (t == sb->transform && bounds == sb->bounds) { continue; // Nothing changed. } @@ -883,7 +884,7 @@ void RuntimeNodeSelect::_update_selection() { void RuntimeNodeSelect::_clear_selection() { selected_ci_nodes.clear(); if (draw_canvas.is_valid()) { - RS::get_singleton()->canvas_item_clear(sbox_2d_ci); + RS::get_singleton()->canvas_item_clear(srect_ci); } #ifndef _3D_DISABLED @@ -1489,7 +1490,7 @@ void RuntimeNodeSelect::_reset_camera_3d() { } } -RuntimeNodeSelect::SelectionBox3D::~SelectionBox3D() { +RuntimeNodeSelect::SelectionBox::~SelectionBox() { if (instance.is_valid()) { RS::get_singleton()->free_rid(instance); RS::get_singleton()->free_rid(instance_ofs); diff --git a/scene/debugger/runtime_node_select.h b/scene/debugger/runtime_node_select.h index 02721a43ca..e28264b235 100644 --- a/scene/debugger/runtime_node_select.h +++ b/scene/debugger/runtime_node_select.h @@ -119,7 +119,8 @@ private: real_t sel_2d_grab_dist = 0; int sel_2d_scale = 1; - RID sbox_2d_ci; + Color srect_color; + RID srect_ci; #ifndef _3D_DISABLED Ref view_3d_controller; @@ -128,7 +129,7 @@ private: real_t camera_znear = 0; real_t camera_zfar = 0; - struct SelectionBox3D : public RefCounted { + struct SelectionBox : public RefCounted { RID instance; RID instance_ofs; RID instance_xray; @@ -137,17 +138,13 @@ private: Transform3D transform; AABB bounds; - ~SelectionBox3D(); + ~SelectionBox(); }; - HashMap> selected_3d_nodes; + HashMap> selected_3d_nodes; - Color sbox_3d_color; - Ref sbox_3d_mesh; - Ref sbox_3d_mesh_xray; - RID sbox_3d; - RID sbox_3d_ofs; - RID sbox_3d_xray; - RID sbox_3d_xray_ofs; + Color sbox_color; + Ref sbox_mesh; + Ref sbox_mesh_xray; #endif // _3D_DISABLED void _setup(const Dictionary &p_settings);