From 26d429566ba8a12587d7e44375ebf8bda7225936 Mon Sep 17 00:00:00 2001 From: Hendrik Brucker Date: Sat, 9 Apr 2022 04:15:58 +0200 Subject: [PATCH] Add flag for editor-only nodes --- doc/classes/Light2D.xml | 3 - doc/classes/Light3D.xml | 3 - doc/classes/ProjectSettings.xml | 3 + doc/classes/ReferenceRect.xml | 3 - editor/editor_themes.cpp | 3 + editor/icons/EditorOnly.svg | 1 + editor/plugins/canvas_item_editor_plugin.cpp | 57 ++++++++++++++++++ editor/plugins/canvas_item_editor_plugin.h | 3 + editor/plugins/node_3d_editor_plugin.cpp | 61 +++++++++++++++++++- editor/plugins/node_3d_editor_plugin.h | 2 + editor/scene_tree_dock.cpp | 2 + editor/scene_tree_editor.cpp | 21 +++++++ editor/scene_tree_editor.h | 1 + main/main.cpp | 2 + scene/2d/light_2d.cpp | 31 +--------- scene/2d/light_2d.h | 4 -- scene/3d/light_3d.cpp | 33 +---------- scene/3d/light_3d.h | 7 +-- scene/gui/reference_rect.cpp | 15 +---- scene/gui/reference_rect.h | 4 -- scene/main/node.cpp | 17 ++++++ scene/main/node.h | 2 + scene/resources/packed_scene.cpp | 7 +++ 23 files changed, 186 insertions(+), 99 deletions(-) create mode 100644 editor/icons/EditorOnly.svg diff --git a/doc/classes/Light2D.xml b/doc/classes/Light2D.xml index 32bf6a67a93d..fdadb502e926 100644 --- a/doc/classes/Light2D.xml +++ b/doc/classes/Light2D.xml @@ -30,9 +30,6 @@ The Light2D's [Color]. - - If [code]true[/code], Light2D will only appear when editing the scene. - If [code]true[/code], Light2D will emit light. diff --git a/doc/classes/Light3D.xml b/doc/classes/Light3D.xml index b7822f1bb0f3..020ceb15ba9f 100644 --- a/doc/classes/Light3D.xml +++ b/doc/classes/Light3D.xml @@ -45,9 +45,6 @@ [b]Note:[/b] Only effective for [OmniLight3D] and [SpotLight3D], and only when [member shadow_enabled] is [code]true[/code]. [b]Note:[/b] Due to a rendering engine limitation, shadows will be disabled instantly instead of fading smoothly according to [member distance_fade_length]. This may result in visible pop-in depending on the scene topography. - - If [code]true[/code], the light only appears in the editor and will not be visible at runtime. - The light's angular size in degrees. Increasing this will make shadows softer at greater distances. Only available for [DirectionalLight3D]s. For reference, the Sun from the Earth is approximately [code]0.5[/code]. diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index ee32677b3a6a..17b4bdb3f2af 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -442,6 +442,9 @@ Maximum call stack allowed for debugging GDScript. + + If [code]true[/code], the editor-only flag is ignored when a scene is loaded, meaning that all nodes will be added to the scene tree. + Maximum amount of functions per frame allowed when profiling. diff --git a/doc/classes/ReferenceRect.xml b/doc/classes/ReferenceRect.xml index 00c83851174a..8868751b677d 100644 --- a/doc/classes/ReferenceRect.xml +++ b/doc/classes/ReferenceRect.xml @@ -15,8 +15,5 @@ Sets the border width of the [ReferenceRect]. The border grows both inwards and outwards with respect to the rectangle box. - - If [code]true[/code], the [ReferenceRect] will only be visible while in editor. Otherwise, [ReferenceRect] will be visible in the running project. - diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 1fea759a900d..07355d53ce39 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -454,6 +454,8 @@ Ref create_editor_theme(const Ref p_theme) { const Color font_disabled_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.3); const Color font_readonly_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.65); const Color font_placeholder_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.6); + const Color font_editor_only_color = dark_theme ? Color(1.0, 0.94, 0.5) : Color(0.5, 0.45, 0.08); + const Color selection_color = accent_color * Color(1, 1, 1, 0.4); const Color disabled_color = mono_color.inverted().lerp(base_color, 0.7); const Color disabled_bg_color = mono_color.inverted().lerp(base_color, 0.9); @@ -975,6 +977,7 @@ Ref create_editor_theme(const Ref p_theme) { theme->set_color("custom_button_font_highlight", "Tree", font_hover_color); theme->set_color("font_color", "Tree", font_color); theme->set_color("font_selected_color", "Tree", mono_color); + theme->set_color("font_editor_only_color", "Tree", font_editor_only_color); theme->set_color("title_button_color", "Tree", font_color); theme->set_color("drop_position_color", "Tree", accent_color); theme->set_constant("vseparation", "Tree", widget_default_margin.y - EDSCALE); diff --git a/editor/icons/EditorOnly.svg b/editor/icons/EditorOnly.svg new file mode 100644 index 000000000000..a826978f6fb0 --- /dev/null +++ b/editor/icons/EditorOnly.svg @@ -0,0 +1 @@ + diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index a90e151adb70..9b13d9a2c1d2 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -3681,10 +3681,13 @@ void CanvasItemEditor::_draw_viewport() { // hide/show buttons depending on the selection bool all_locked = true; bool all_group = true; + bool all_editor_only = true; + bool contains_root_node = false; List selection = editor_selection->get_selected_node_list(); if (selection.is_empty()) { all_locked = false; all_group = false; + all_editor_only = false; } else { for (Node *E : selection) { if (Object::cast_to(E) && !Object::cast_to(E)->has_meta("_edit_lock_")) { @@ -3698,15 +3701,31 @@ void CanvasItemEditor::_draw_viewport() { break; } } + for (Node *E : selection) { + if (!E->has_meta(SNAME("_editor_only_"))) { + all_editor_only = false; + break; + } + } + for (Node *E : selection) { + if (!E->get_owner()) { + contains_root_node = true; + break; + } + } } lock_button->set_visible(!all_locked); lock_button->set_disabled(selection.is_empty()); unlock_button->set_visible(all_locked); + group_button->set_visible(!all_group); group_button->set_disabled(selection.is_empty()); ungroup_button->set_visible(all_group); + toggle_editor_only_button->set_pressed(all_editor_only); + toggle_editor_only_button->set_disabled(selection.is_empty() || contains_root_node); + _draw_grid(); _draw_ruler_tool(); _draw_axis(); @@ -3768,6 +3787,7 @@ void CanvasItemEditor::_update_editor_settings() { unlock_button->set_icon(get_theme_icon(SNAME("Unlock"), SNAME("EditorIcons"))); group_button->set_icon(get_theme_icon(SNAME("Group"), SNAME("EditorIcons"))); ungroup_button->set_icon(get_theme_icon(SNAME("Ungroup"), SNAME("EditorIcons"))); + toggle_editor_only_button->set_icon(get_theme_icon(SNAME("EditorOnly"), SNAME("EditorIcons"))); key_loc_button->set_icon(get_theme_icon(SNAME("KeyPosition"), SNAME("EditorIcons"))); key_rot_button->set_icon(get_theme_icon(SNAME("KeyRotation"), SNAME("EditorIcons"))); key_scale_button->set_icon(get_theme_icon(SNAME("KeyScale"), SNAME("EditorIcons"))); @@ -3895,6 +3915,7 @@ void CanvasItemEditor::_notification(int p_what) { debugger->set_camera_override(EditorDebuggerNode::OVERRIDE_NONE); override_camera_button->set_pressed(false); } + } break; } } @@ -4392,7 +4413,33 @@ void CanvasItemEditor::_popup_callback(int p_op) { undo_redo->add_undo_method(viewport, "update"); undo_redo->commit_action(); } break; + case TOGGLE_EDITOR_ONLY_SELECTED: { + undo_redo->create_action(TTR("Toggle Editor Only Flag")); + + List selection = editor_selection->get_selected_node_list(); + bool all_editor_only = true; + for (Node *E : selection) { + if (!E->has_meta(SNAME("_editor_only_"))) { + all_editor_only = false; + break; + } + } + for (Node *node : selection) { + if (all_editor_only) { + undo_redo->add_do_method(node, "remove_meta", "_editor_only_"); + undo_redo->add_undo_method(node, "set_meta", "_editor_only_", true); + } else { + undo_redo->add_do_method(node, "set_meta", "_editor_only_", true); + undo_redo->add_undo_method(node, "remove_meta", "_editor_only_"); + } + undo_redo->add_do_method(this, "emit_signal", "item_editor_only_status_changed"); + undo_redo->add_undo_method(this, "emit_signal", "item_editor_only_status_changed"); + } + undo_redo->add_do_method(viewport, "update", Variant()); + undo_redo->add_undo_method(viewport, "update", Variant()); + undo_redo->commit_action(); + } break; case ANIM_INSERT_KEY: case ANIM_INSERT_KEY_EXISTING: { bool existing = p_op == ANIM_INSERT_KEY_EXISTING; @@ -4642,6 +4689,7 @@ void CanvasItemEditor::_bind_methods() { ADD_SIGNAL(MethodInfo("item_lock_status_changed")); ADD_SIGNAL(MethodInfo("item_group_status_changed")); + ADD_SIGNAL(MethodInfo("item_editor_only_status_changed")); } Dictionary CanvasItemEditor::get_state() const { @@ -5140,6 +5188,15 @@ CanvasItemEditor::CanvasItemEditor() { // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. ungroup_button->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::G)); + toggle_editor_only_button = memnew(Button); + toggle_editor_only_button->set_flat(true); + toggle_editor_only_button->set_toggle_mode(true); + hb->add_child(toggle_editor_only_button); + toggle_editor_only_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback), varray(TOGGLE_EDITOR_ONLY_SELECTED)); + toggle_editor_only_button->set_tooltip(TTR("Editor-only nodes will not be loaded in the scene tree when the project is run or exported.")); + // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. + toggle_editor_only_button->set_shortcut(ED_SHORTCUT("editor/toggle_editor_only_selected_nodes", TTR("Toggle Editor Only Flag For Selected Node(s)"), KeyModifierMask::CMD | Key::E)); + hb->add_child(memnew(VSeparator)); skeleton_menu = memnew(MenuButton); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 26852ea8ed5d..f2d0785f9725 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -127,6 +127,7 @@ class CanvasItemEditor : public VBoxContainer { UNLOCK_SELECTED, GROUP_SELECTED, UNGROUP_SELECTED, + TOGGLE_EDITOR_ONLY_SELECTED, ANIM_INSERT_KEY, ANIM_INSERT_KEY_EXISTING, ANIM_INSERT_POS, @@ -316,6 +317,8 @@ class CanvasItemEditor : public VBoxContainer { Button *group_button = nullptr; Button *ungroup_button = nullptr; + Button *toggle_editor_only_button = nullptr; + MenuButton *skeleton_menu = nullptr; Button *override_camera_button = nullptr; MenuButton *view_menu = nullptr; diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 855fc2b2a9b8..46ddbe799e6b 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -5848,6 +5848,37 @@ void Node3DEditor::_menu_item_pressed(int p_option) { undo_redo->add_undo_method(this, "_refresh_menu_icons"); undo_redo->commit_action(); } break; + case MENU_TOGGLE_EDITOR_ONLY_SELECTED: { + undo_redo->create_action(TTR("Toggle Editor Only Flag")); + + List selection = editor_selection->get_selected_node_list(); + bool all_editor_only = true; + for (Node *E : selection) { + if (!E->get_owner()) { + break; // Disallow setting the scene's root node editor-only. + } + if (!E->has_meta(SNAME("_editor_only_"))) { + all_editor_only = false; + break; + } + } + + for (Node *node : selection) { + if (all_editor_only) { + undo_redo->add_do_method(node, "remove_meta", "_editor_only_"); + undo_redo->add_undo_method(node, "set_meta", "_editor_only_", true); + } else { + undo_redo->add_do_method(node, "set_meta", "_editor_only_", true); + undo_redo->add_undo_method(node, "remove_meta", "_editor_only_"); + } + + undo_redo->add_do_method(this, "emit_signal", "item_editor_only_status_changed"); + undo_redo->add_undo_method(this, "emit_signal", "item_editor_only_status_changed"); + } + undo_redo->add_do_method(this, "_refresh_menu_icons"); + undo_redo->add_undo_method(this, "_refresh_menu_icons"); + undo_redo->commit_action(); + } break; } } @@ -6656,7 +6687,8 @@ void Node3DEditor::_selection_changed() { void Node3DEditor::_refresh_menu_icons() { bool all_locked = true; bool all_grouped = true; - + bool all_editor_only = true; + bool contains_root_node = false; List &selection = editor_selection->get_selected_node_list(); if (selection.is_empty()) { @@ -6675,6 +6707,18 @@ void Node3DEditor::_refresh_menu_icons() { break; } } + for (Node *E : selection) { + if (!E->has_meta(SNAME("_editor_only_"))) { + all_editor_only = false; + break; + } + } + for (Node *E : selection) { + if (!E->get_owner()) { + contains_root_node = true; + break; + } + } } tool_button[TOOL_LOCK_SELECTED]->set_visible(!all_locked); @@ -6684,6 +6728,9 @@ void Node3DEditor::_refresh_menu_icons() { tool_button[TOOL_GROUP_SELECTED]->set_visible(!all_grouped); tool_button[TOOL_GROUP_SELECTED]->set_disabled(selection.is_empty()); tool_button[TOOL_UNGROUP_SELECTED]->set_visible(all_grouped); + + tool_button[TOOL_TOGGLE_EDITOR_ONLY_SELECTED]->set_pressed(all_editor_only); + tool_button[TOOL_TOGGLE_EDITOR_ONLY_SELECTED]->set_disabled(selection.is_empty() || contains_root_node); } template @@ -6933,6 +6980,7 @@ void Node3DEditor::_update_theme() { tool_button[TOOL_UNLOCK_SELECTED]->set_icon(get_theme_icon(SNAME("Unlock"), SNAME("EditorIcons"))); tool_button[TOOL_GROUP_SELECTED]->set_icon(get_theme_icon(SNAME("Group"), SNAME("EditorIcons"))); tool_button[TOOL_UNGROUP_SELECTED]->set_icon(get_theme_icon(SNAME("Ungroup"), SNAME("EditorIcons"))); + tool_button[TOOL_TOGGLE_EDITOR_ONLY_SELECTED]->set_icon(get_theme_icon(SNAME("EditorOnly"), SNAME("EditorIcons"))); tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_icon(get_theme_icon(SNAME("Object"), SNAME("EditorIcons"))); tool_option_button[TOOL_OPT_USE_SNAP]->set_icon(get_theme_icon(SNAME("Snap"), SNAME("EditorIcons"))); @@ -7308,6 +7356,7 @@ void Node3DEditor::_bind_methods() { ADD_SIGNAL(MethodInfo("transform_key_request")); ADD_SIGNAL(MethodInfo("item_lock_status_changed")); ADD_SIGNAL(MethodInfo("item_group_status_changed")); + ADD_SIGNAL(MethodInfo("item_editor_only_status_changed")); } void Node3DEditor::clear() { @@ -7593,6 +7642,16 @@ Node3DEditor::Node3DEditor() { // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. tool_button[TOOL_UNGROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::G)); + tool_button[TOOL_TOGGLE_EDITOR_ONLY_SELECTED] = memnew(Button); + tool_button[TOOL_TOGGLE_EDITOR_ONLY_SELECTED]->set_flat(true); + tool_button[TOOL_TOGGLE_EDITOR_ONLY_SELECTED]->set_toggle_mode(true); + hbc_menu->add_child(tool_button[TOOL_TOGGLE_EDITOR_ONLY_SELECTED]); + button_binds.write[0] = MENU_TOGGLE_EDITOR_ONLY_SELECTED; + tool_button[TOOL_TOGGLE_EDITOR_ONLY_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed), button_binds); + tool_button[TOOL_TOGGLE_EDITOR_ONLY_SELECTED]->set_tooltip(TTR("Editor-only nodes will not be loaded in the scene tree when the project is run or exported.")); + // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. + tool_button[TOOL_TOGGLE_EDITOR_ONLY_SELECTED]->set_shortcut(ED_SHORTCUT("editor/toggle_editor_only_selected_nodes", TTR("Toggle Editor Only Flag For Selected Node(s)"), KeyModifierMask::CMD | Key::E)); + hbc_menu->add_child(memnew(VSeparator)); tool_option_button[TOOL_OPT_LOCAL_COORDS] = memnew(Button); diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index d5d50c743c5f..0ca6c35881bd 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -525,6 +525,7 @@ class Node3DEditor : public VBoxContainer { TOOL_UNLOCK_SELECTED, TOOL_GROUP_SELECTED, TOOL_UNGROUP_SELECTED, + TOOL_TOGGLE_EDITOR_ONLY_SELECTED, TOOL_MAX }; @@ -622,6 +623,7 @@ class Node3DEditor : public VBoxContainer { MENU_UNLOCK_SELECTED, MENU_GROUP_SELECTED, MENU_UNGROUP_SELECTED, + MENU_TOGGLE_EDITOR_ONLY_SELECTED, MENU_SNAP_TO_FLOOR }; diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 71ea625013c6..8e48a47c45f5 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -1172,12 +1172,14 @@ void SceneTreeDock::_notification(int p_what) { if (canvas_item_plugin) { canvas_item_plugin->get_canvas_item_editor()->connect("item_lock_status_changed", Callable(scene_tree, "_update_tree")); canvas_item_plugin->get_canvas_item_editor()->connect("item_group_status_changed", Callable(scene_tree, "_update_tree")); + canvas_item_plugin->get_canvas_item_editor()->connect("item_editor_only_status_changed", Callable(scene_tree, "_update_tree")); scene_tree->connect("node_changed", callable_mp((CanvasItem *)canvas_item_plugin->get_canvas_item_editor()->get_viewport_control(), &CanvasItem::update)); } Node3DEditorPlugin *spatial_editor_plugin = Object::cast_to(editor_data->get_editor("3D")); spatial_editor_plugin->get_spatial_editor()->connect("item_lock_status_changed", Callable(scene_tree, "_update_tree")); spatial_editor_plugin->get_spatial_editor()->connect("item_group_status_changed", Callable(scene_tree, "_update_tree")); + spatial_editor_plugin->get_spatial_editor()->connect("item_editor_only_status_changed", Callable(scene_tree, "_update_tree")); button_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); button_instance->set_icon(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons"))); diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index 44eb5c670d3f..0ae2f417de80 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -148,6 +148,17 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i TabContainer *tab_container = Object::cast_to(NodeDock::get_singleton()->get_parent()); NodeDock::get_singleton()->get_parent()->call("set_current_tab", tab_container->get_tab_idx_from_control(NodeDock::get_singleton())); NodeDock::get_singleton()->show_groups(); + } else if (p_id == BUTTON_EDITOR_ONLY) { + undo_redo->create_action(TTR("Remove editor-only flag")); + + undo_redo->add_do_method(n, "remove_meta", "_editor_only_"); + undo_redo->add_undo_method(n, "set_meta", "_editor_only_", true); + undo_redo->add_do_method(this, "_update_tree"); + undo_redo->add_undo_method(this, "_update_tree"); + undo_redo->add_do_method(this, "emit_signal", "node_changed"); + undo_redo->add_undo_method(this, "emit_signal", "node_changed"); + + undo_redo->commit_action(); } } @@ -335,6 +346,16 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent, bool p_scroll p_node->connect("script_changed", callable_mp(this, &SceneTreeEditor::_node_script_changed), varray(p_node)); } + bool editor_only = p_node->has_meta("_editor_only_"); + if (editor_only) { + item->add_button(0, get_theme_icon(SNAME("EditorOnly"), SNAME("EditorIcons")), BUTTON_EDITOR_ONLY, false, TTR("Node is editor only.\nClick to remove this flag.")); + } + + if (p_node->is_editor_only()) { + Color editor_only_font_color = get_theme_color(SNAME("font_editor_only_color"), SNAME("Tree")); + item->set_custom_color(0, editor_only_font_color); + } + Ref