From 2de97cafb7b2c8b88c5d950b684dbe9cf83788bf Mon Sep 17 00:00:00 2001 From: kobewi Date: Mon, 24 Nov 2025 20:10:34 +0100 Subject: [PATCH] Change Theme to EditorDock and add closable property --- doc/classes/EditorDock.xml | 12 ++++++- editor/docks/editor_dock.cpp | 6 ++++ editor/docks/editor_dock.h | 4 +++ editor/docks/editor_dock_manager.cpp | 3 +- editor/icons/ThemeDock.svg | 1 + editor/scene/gui/theme_editor_plugin.cpp | 44 +++++++++++++++--------- editor/scene/gui/theme_editor_plugin.h | 7 ++-- 7 files changed, 55 insertions(+), 22 deletions(-) create mode 100644 editor/icons/ThemeDock.svg diff --git a/doc/classes/EditorDock.xml b/doc/classes/EditorDock.xml index 2b1524cc3b7..b8d1692756e 100644 --- a/doc/classes/EditorDock.xml +++ b/doc/classes/EditorDock.xml @@ -85,6 +85,9 @@ The available layouts for this dock, as a bitmask. By default, the dock allows vertical and floating layouts. + + If [code]true[/code], the dock can be closed with the Close button in the context popup. Docks with [member global] enabled are always closable. + The default dock slot used when adding the dock with [method EditorPlugin.add_dock]. After the dock is added, it can be moved to a different slot and the editor will automatically remember its position between sessions. If you remove and re-add the dock, it will be reset to default. @@ -99,7 +102,7 @@ If [code]true[/code], the dock will always display an icon, regardless of [member EditorSettings.interface/editor/dock_tab_style] or [member EditorSettings.interface/editor/bottom_dock_tab_style]. - If [code]true[/code], the dock appears in the [b]Editor > Editor Docks[/b] menu and can be closed. Non-global docks can still be closed using [method close]. + If [code]true[/code], the dock appears in the [b]Editor > Editor Docks[/b] menu and can be closed. Non-global docks can still be closed using [method close] or when [member closable] is [code]true[/code]. The icon for the dock, as a name from the [code]EditorIcons[/code] theme type in the editor theme. You can find the list of available icons [url=https://godot-editor-icons.github.io/]here[/url]. @@ -117,6 +120,13 @@ If [code]true[/code], the dock is not automatically opened or closed when loading an editor layout, only moved. It also can't be opened using a shortcut. This is meant for docks that are opened and closed in specific cases, such as when selecting a [TileMap] or [AnimationTree] node. + + + + Emitted when the dock is closed with the Close button in the context popup, before it's removed from its parent. See [member closable]. + + + Allows placing the dock in the vertical dock slots on either side of the editor. diff --git a/editor/docks/editor_dock.cpp b/editor/docks/editor_dock.cpp index a38a2851805..0d63ff0c05d 100644 --- a/editor/docks/editor_dock.cpp +++ b/editor/docks/editor_dock.cpp @@ -60,6 +60,10 @@ void EditorDock::_bind_methods() { ClassDB::bind_method(D_METHOD("is_transient"), &EditorDock::is_transient); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "transient"), "set_transient", "is_transient"); + ClassDB::bind_method(D_METHOD("set_closable", "closable"), &EditorDock::set_closable); + ClassDB::bind_method(D_METHOD("is_closable"), &EditorDock::is_closable); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "closable"), "set_closable", "is_closable"); + ClassDB::bind_method(D_METHOD("set_icon_name", "icon_name"), &EditorDock::set_icon_name); ClassDB::bind_method(D_METHOD("get_icon_name"), &EditorDock::get_icon_name); ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "icon_name"), "set_icon_name", "get_icon_name"); @@ -88,6 +92,8 @@ void EditorDock::_bind_methods() { ClassDB::bind_method(D_METHOD("get_available_layouts"), &EditorDock::get_available_layouts); ADD_PROPERTY(PropertyInfo(Variant::INT, "available_layouts", PROPERTY_HINT_FLAGS, "Vertical:1,Horizontal:2,Floating:3"), "set_available_layouts", "get_available_layouts"); + ADD_SIGNAL(MethodInfo("closed")); + BIND_BITFIELD_FLAG(DOCK_LAYOUT_VERTICAL); BIND_BITFIELD_FLAG(DOCK_LAYOUT_HORIZONTAL); BIND_BITFIELD_FLAG(DOCK_LAYOUT_FLOATING); diff --git a/editor/docks/editor_dock.h b/editor/docks/editor_dock.h index 60547f83c93..e33a31d94db 100644 --- a/editor/docks/editor_dock.h +++ b/editor/docks/editor_dock.h @@ -64,6 +64,7 @@ private: DockConstants::DockSlot default_slot = DockConstants::DOCK_SLOT_NONE; bool global = true; bool transient = false; + bool closable = false; BitField available_layouts = DOCK_LAYOUT_VERTICAL | DOCK_LAYOUT_FLOATING; @@ -102,6 +103,9 @@ public: void set_transient(bool p_transient) { transient = p_transient; } bool is_transient() const { return transient; } + void set_closable(bool p_closable) { closable = p_closable; } + bool is_closable() const { return closable; } + void set_icon_name(const StringName &p_name); StringName get_icon_name() const { return icon_name; } diff --git a/editor/docks/editor_dock_manager.cpp b/editor/docks/editor_dock_manager.cpp index 1c7d256d9aa..b1a846be293 100644 --- a/editor/docks/editor_dock_manager.cpp +++ b/editor/docks/editor_dock_manager.cpp @@ -1051,6 +1051,7 @@ void DockContextPopup::_tab_move_right() { void DockContextPopup::_close_dock() { hide(); + context_dock->emit_signal("closed"); dock_manager->close_dock(context_dock); } @@ -1206,7 +1207,7 @@ void DockContextPopup::_dock_select_draw() { void DockContextPopup::_update_buttons() { TabContainer *context_tab_container = dock_manager->get_dock_tab_container(context_dock); - if (context_dock->global) { + if (context_dock->global || context_dock->closable) { close_button->set_tooltip_text(TTRC("Close this dock.")); close_button->set_disabled(false); } else { diff --git a/editor/icons/ThemeDock.svg b/editor/icons/ThemeDock.svg new file mode 100644 index 00000000000..25de7aea0d1 --- /dev/null +++ b/editor/icons/ThemeDock.svg @@ -0,0 +1 @@ + diff --git a/editor/scene/gui/theme_editor_plugin.cpp b/editor/scene/gui/theme_editor_plugin.cpp index 84af02e31e7..5627d9f4cf9 100644 --- a/editor/scene/gui/theme_editor_plugin.cpp +++ b/editor/scene/gui/theme_editor_plugin.cpp @@ -31,6 +31,7 @@ #include "theme_editor_plugin.h" #include "editor/doc/editor_help.h" +#include "editor/docks/editor_dock_manager.h" #include "editor/docks/filesystem_dock.h" #include "editor/docks/inspector_dock.h" #include "editor/editor_node.h" @@ -3723,13 +3724,15 @@ void ThemeEditor::_theme_edit_button_cbk() { } void ThemeEditor::_theme_close_button_cbk() { - plugin->make_visible(false); // Enables auto hide. + close(); + _dock_closed_cbk(); +} + +void ThemeEditor::_dock_closed_cbk() { if (theme.is_valid() && InspectorDock::get_inspector_singleton()->get_edited_object() == theme.ptr()) { EditorNode::get_singleton()->push_item(nullptr); - } else { - theme = Ref(); - EditorNode::get_singleton()->hide_unused_editors(plugin); } + theme = Ref(); } void ThemeEditor::_scene_closed(const String &p_path) { @@ -3917,6 +3920,7 @@ void ThemeEditor::_preview_tabs_resized() { void ThemeEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { + connect("closed", callable_mp(this, &ThemeEditor::_dock_closed_cbk)); EditorNode::get_singleton()->connect("scene_closed", callable_mp(this, &ThemeEditor::_scene_closed)); EditorNode::get_singleton()->connect("resource_saved", callable_mp(this, &ThemeEditor::_resource_saved)); FileSystemDock::get_singleton()->connect("files_moved", callable_mp(this, &ThemeEditor::_files_moved)); @@ -3945,8 +3949,21 @@ void ThemeEditor::_notification(int p_what) { } ThemeEditor::ThemeEditor() { + set_name(TTRC("Theme")); + set_icon_name("ThemeDock"); + set_dock_shortcut(ED_SHORTCUT_AND_COMMAND("bottom_panels/toggle_theme_bottom_panel", TTRC("Toggle Theme Dock"))); + set_default_slot(DockConstants::DOCK_SLOT_BOTTOM); + set_available_layouts(EditorDock::DOCK_LAYOUT_HORIZONTAL | EditorDock::DOCK_LAYOUT_FLOATING); + set_global(false); + set_transient(true); + set_closable(true); + set_custom_minimum_size(Size2(0, 200 * EDSCALE)); + + VBoxContainer *content_vb = memnew(VBoxContainer); + add_child(content_vb); + HBoxContainer *top_menu = memnew(HBoxContainer); - add_child(top_menu); + content_vb->add_child(top_menu); Label *theme_label = memnew(Label); theme_label->set_text(TTRC("Theme:")); @@ -3997,7 +4014,7 @@ ThemeEditor::ThemeEditor() { HSplitContainer *main_hs = memnew(HSplitContainer); main_hs->set_v_size_flags(SIZE_EXPAND_FILL); - add_child(main_hs); + content_vb->add_child(main_hs); main_hs->set_split_offset(520 * EDSCALE); @@ -4065,14 +4082,9 @@ bool ThemeEditorPlugin::handles(Object *p_object) const { void ThemeEditorPlugin::make_visible(bool p_visible) { if (p_visible) { - button->show(); - EditorNode::get_bottom_panel()->make_item_visible(theme_editor); + theme_editor->make_visible(); } else { - if (theme_editor->is_visible_in_tree()) { - EditorNode::get_bottom_panel()->hide_bottom_panel(); - } - - button->hide(); + theme_editor->close(); } } @@ -4083,8 +4095,6 @@ bool ThemeEditorPlugin::can_auto_hide() const { ThemeEditorPlugin::ThemeEditorPlugin() { theme_editor = memnew(ThemeEditor); theme_editor->plugin = this; - theme_editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE); - - button = EditorNode::get_bottom_panel()->add_item(TTRC("Theme"), theme_editor, ED_SHORTCUT_AND_COMMAND("bottom_panels/toggle_theme_bottom_panel", TTRC("Toggle Theme Bottom Panel"))); - button->hide(); + EditorDockManager::get_singleton()->add_dock(theme_editor); + theme_editor->close(); } diff --git a/editor/scene/gui/theme_editor_plugin.h b/editor/scene/gui/theme_editor_plugin.h index fc63e40b3b1..ca87b2b17a3 100644 --- a/editor/scene/gui/theme_editor_plugin.h +++ b/editor/scene/gui/theme_editor_plugin.h @@ -30,6 +30,7 @@ #pragma once +#include "editor/docks/editor_dock.h" #include "editor/plugins/editor_plugin.h" #include "editor/scene/gui/theme_editor_preview.h" #include "scene/gui/dialogs.h" @@ -432,8 +433,8 @@ public: ThemeTypeEditor(); }; -class ThemeEditor : public VBoxContainer { - GDCLASS(ThemeEditor, VBoxContainer); +class ThemeEditor : public EditorDock { + GDCLASS(ThemeEditor, EditorDock); friend class ThemeEditorPlugin; ThemeEditorPlugin *plugin = nullptr; @@ -457,6 +458,7 @@ class ThemeEditor : public VBoxContainer { void _theme_save_button_cbk(bool p_save_as); void _theme_edit_button_cbk(); void _theme_close_button_cbk(); + void _dock_closed_cbk(); void _scene_closed(const String &p_path); void _resource_saved(const Ref &p_resource); void _files_moved(const String &p_old_path, const String &p_new_path); @@ -489,7 +491,6 @@ class ThemeEditorPlugin : public EditorPlugin { GDCLASS(ThemeEditorPlugin, EditorPlugin); ThemeEditor *theme_editor = nullptr; - Button *button = nullptr; public: virtual String get_plugin_name() const override { return "Theme"; }