diff --git a/doc/classes/EditorDock.xml b/doc/classes/EditorDock.xml
new file mode 100644
index 00000000000..5067e79ae8a
--- /dev/null
+++ b/doc/classes/EditorDock.xml
@@ -0,0 +1,100 @@
+
+
+
+ Dockable container for the editor.
+
+
+ EditorDock is a [Container] node that can be docked in one of the editor's dock slots. Docks are added by plugins to provide space for controls related to an [EditorPlugin]. The editor comes with a few built-in docks, such as the Scene dock, FileSystem dock, etc.
+ You can add a dock by using [method EditorPlugin.add_dock]. The dock can be customized by changing its properties.
+ [codeblock]
+ @tool
+ extends EditorPlugin
+
+ # Dock reference.
+ var dock
+
+ # Plugin initialization.
+ func _enter_tree():
+ dock = EditorDock.new()
+ dock.title = "My Dock"
+ dock.dock_icon = preload("./dock_icon.png")
+ dock.default_slot = EditorPlugin.DOCK_SLOT_RIGHT_UL
+ var dock_content = preload("./dock_content.tscn").instantiate()
+ dock.add_child(dock_content)
+ add_dock(dock)
+
+ # Plugin clean-up.
+ func _exit_tree():
+ remove_dock(dock)
+ dock.queue_free()
+ dock = null
+ [/codeblock]
+
+
+ $DOCS_URL/tutorials/plugins/editor/making_plugins.html
+
+
+
+
+
+
+
+ Implement this method to handle loading this dock's layout. It's equivalent to [method EditorPlugin._set_window_layout]. [param section] is a unique section based on [member layout_key].
+
+
+
+
+
+
+
+ Implement this method to handle saving this dock's layout. It's equivalent to [method EditorPlugin._get_window_layout]. [param section] is a unique section based on [member layout_key].
+
+
+
+
+
+
+ Implement this method to handle the layout switching for this dock. [param layout] is one of the [enum DockLayout] constants.
+ [codeblock]
+ _update_layout(layout):
+ box_container.vertical = (layout == DOCK_LAYOUT_VERTICAL)
+ [/codeblock]
+
+
+
+
+
+ The available layouts for this dock, as a bitmask.
+ If you want to make all layouts available, use [code]available_layouts = DOCK_LAYOUT_VERTICAL | DOCK_LAYOUT_HORIZONTAL[/code].
+
+
+
+ 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.
+
+
+ The icon for the dock, as a texture. If specified, it will override [member icon_name].
+
+
+ The shortcut used to open the dock. This property can only be set before this dock is added via [method EditorPlugin.add_dock].
+
+
+ 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].
+
+
+ The key representing this dock in the editor's layout file. If empty, the dock's displayed name will be used instead.
+
+
+ The title of the dock's tab. If empty, the dock's [member Node.name] will be used. If the name is auto-generated (contains [code]@[/code]), the first child's name will be used instead.
+
+
+
+
+ Allows placing the dock in the vertical dock slots on either side of the editor.
+ [b]Note:[/b] Currently this flag has no effect because the bottom panel is not a proper dock slot. This means that the dock can always be vertical.
+
+
+ Allows placing the dock in the editor's bottom panel. Implement [method _update_layout] to handle changing layouts.
+
+
+
diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml
index 9892d208329..6beb4044931 100644
--- a/doc/classes/EditorPlugin.xml
+++ b/doc/classes/EditorPlugin.xml
@@ -430,7 +430,7 @@
When your plugin is deactivated, make sure to remove your custom control with [method remove_control_from_container] and free it with [method Node.queue_free].
-
+
@@ -464,6 +464,14 @@
Adds a [Script] as debugger plugin to the Debugger. The script must extend [EditorDebuggerPlugin].
+
+
+
+
+ Adds a new dock.
+ When your plugin is deactivated, make sure to remove your custom dock with [method remove_dock] and free it with [method Node.queue_free].
+
+
@@ -655,7 +663,7 @@
Removes the control from the specified container. You have to manually [method Node.queue_free] the control.
-
+
@@ -676,6 +684,13 @@
Removes the debugger plugin with given script from the Debugger.
+
+
+
+
+ Removes [param dock] from the available docks. You should manually call [method Node.queue_free] to free it.
+
+
@@ -753,7 +768,7 @@
Removes a callback previously added by [method add_undo_redo_inspector_hook_callback].
-
+
@@ -854,6 +869,9 @@
Tab of Project Settings dialog, to the right of other tabs.
+
+ The dock is closed.
+
Dock slot, left side, upper-left (empty in default layout).
diff --git a/doc/classes/FileSystemDock.xml b/doc/classes/FileSystemDock.xml
index b3dc51ffaa6..b0b23a81c64 100644
--- a/doc/classes/FileSystemDock.xml
+++ b/doc/classes/FileSystemDock.xml
@@ -1,5 +1,5 @@
-
+
Godot editor's dock for managing files in the project.
diff --git a/editor/docks/editor_dock.cpp b/editor/docks/editor_dock.cpp
new file mode 100644
index 00000000000..d231c7639ac
--- /dev/null
+++ b/editor/docks/editor_dock.cpp
@@ -0,0 +1,131 @@
+/**************************************************************************/
+/* editor_dock.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "editor_dock.h"
+
+#include "core/input/shortcut.h"
+#include "core/io/config_file.h"
+
+void EditorDock::_set_default_slot_bind(EditorPlugin::DockSlot p_slot) {
+ ERR_FAIL_COND(p_slot < EditorPlugin::DOCK_SLOT_NONE || p_slot >= EditorPlugin::DOCK_SLOT_MAX);
+ default_slot = (EditorDockManager::DockSlot)p_slot;
+}
+
+void EditorDock::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_title", "title"), &EditorDock::set_title);
+ ClassDB::bind_method(D_METHOD("get_title"), &EditorDock::get_title);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
+
+ ClassDB::bind_method(D_METHOD("set_layout_key", "layout_key"), &EditorDock::set_layout_key);
+ ClassDB::bind_method(D_METHOD("get_layout_key"), &EditorDock::get_layout_key);
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "layout_key"), "set_layout_key", "get_layout_key");
+
+ 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");
+
+ ClassDB::bind_method(D_METHOD("set_dock_icon", "icon"), &EditorDock::set_dock_icon);
+ ClassDB::bind_method(D_METHOD("get_dock_icon"), &EditorDock::get_dock_icon);
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "dock_icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_dock_icon", "get_dock_icon");
+
+ ClassDB::bind_method(D_METHOD("set_dock_shortcut", "shortcut"), &EditorDock::set_dock_shortcut);
+ ClassDB::bind_method(D_METHOD("get_dock_shortcut"), &EditorDock::get_dock_shortcut);
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "dock_shortcut", PROPERTY_HINT_RESOURCE_TYPE, "ShortCut"), "set_dock_shortcut", "get_dock_shortcut");
+
+ ClassDB::bind_method(D_METHOD("set_default_slot", "slot"), &EditorDock::_set_default_slot_bind);
+ ClassDB::bind_method(D_METHOD("get_default_slot"), &EditorDock::_get_default_slot_bind);
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "default_slot"), "set_default_slot", "get_default_slot");
+
+ ClassDB::bind_method(D_METHOD("set_available_layouts", "layouts"), &EditorDock::set_available_layouts);
+ 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"), "set_available_layouts", "get_available_layouts");
+
+ BIND_BITFIELD_FLAG(DOCK_LAYOUT_VERTICAL);
+ BIND_BITFIELD_FLAG(DOCK_LAYOUT_HORIZONTAL);
+
+ GDVIRTUAL_BIND(_update_layout, "layout");
+ GDVIRTUAL_BIND(_save_layout_to_config, "config", "section");
+ GDVIRTUAL_BIND(_load_layout_from_config, "config", "section");
+}
+
+EditorDock::EditorDock() {
+ set_clip_contents(true);
+ add_user_signal(MethodInfo("tab_style_changed"));
+}
+
+void EditorDock::set_title(const String &p_title) {
+ if (title == p_title) {
+ return;
+ }
+ title = p_title;
+ emit_signal("tab_style_changed");
+}
+
+void EditorDock::set_icon_name(const StringName &p_name) {
+ if (icon_name == p_name) {
+ return;
+ }
+ icon_name = p_name;
+ emit_signal("tab_style_changed");
+}
+
+void EditorDock::set_dock_icon(const Ref &p_icon) {
+ if (dock_icon == p_icon) {
+ return;
+ }
+ dock_icon = p_icon;
+ emit_signal("tab_style_changed");
+}
+
+void EditorDock::set_default_slot(EditorDockManager::DockSlot p_slot) {
+ ERR_FAIL_INDEX(p_slot, EditorDockManager::DOCK_SLOT_MAX);
+ default_slot = p_slot;
+}
+
+String EditorDock::get_display_title() const {
+ if (!title.is_empty()) {
+ return title;
+ }
+
+ const String sname = get_name();
+ if (sname.contains_char('@')) {
+ // Auto-generated name, try to use something better.
+ const Node *child = get_child_count() > 0 ? get_child(0) : nullptr;
+ if (child) {
+ // In user plugins, the child will usually be dock's content and have a proper name.
+ return child->get_name();
+ }
+ }
+ return sname;
+}
+
+String EditorDock::get_effective_layout_key() const {
+ return layout_key.is_empty() ? get_display_title() : layout_key;
+}
diff --git a/editor/docks/editor_dock.h b/editor/docks/editor_dock.h
new file mode 100644
index 00000000000..6bd58669d58
--- /dev/null
+++ b/editor/docks/editor_dock.h
@@ -0,0 +1,113 @@
+/**************************************************************************/
+/* editor_dock.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#pragma once
+
+#include "editor/docks/editor_dock_manager.h"
+#include "editor/plugins/editor_plugin.h"
+#include "scene/gui/margin_container.h"
+
+class ConfigFile;
+class Shortcut;
+class WindowWrapper;
+
+class EditorDock : public MarginContainer {
+ GDCLASS(EditorDock, MarginContainer);
+
+public:
+ enum DockLayout {
+ DOCK_LAYOUT_VERTICAL = 1,
+ DOCK_LAYOUT_HORIZONTAL = 2,
+ };
+
+private:
+ friend class EditorDockManager;
+ friend class DockContextPopup;
+
+ String title;
+ String layout_key;
+ StringName icon_name;
+ Ref dock_icon;
+ Ref shortcut;
+ EditorDockManager::DockSlot default_slot = EditorDockManager::DOCK_SLOT_NONE;
+
+ BitField available_layouts = DOCK_LAYOUT_VERTICAL;
+
+ bool open = false;
+ bool enabled = true;
+ bool at_bottom = false;
+ int previous_tab_index = -1;
+ bool previous_at_bottom = false;
+ WindowWrapper *dock_window = nullptr;
+ int dock_slot_index = EditorDockManager::DOCK_SLOT_NONE;
+
+ void _set_default_slot_bind(EditorPlugin::DockSlot p_slot);
+ EditorPlugin::DockSlot _get_default_slot_bind() const { return (EditorPlugin::DockSlot)default_slot; }
+
+protected:
+ static void _bind_methods();
+
+ GDVIRTUAL1(_update_layout, int)
+ GDVIRTUAL2C(_save_layout_to_config, Ref, const String &)
+ GDVIRTUAL2(_load_layout_from_config, Ref, const String &)
+
+public:
+ EditorDock();
+
+ void set_title(const String &p_title);
+ String get_title() const { return title; }
+
+ void set_layout_key(const String &p_key) { layout_key = p_key; }
+ String get_layout_key() const { return layout_key; }
+
+ void set_icon_name(const StringName &p_name);
+ StringName get_icon_name() const { return icon_name; }
+
+ void set_dock_icon(const Ref &p_icon);
+ Ref get_dock_icon() const { return dock_icon; }
+
+ void set_dock_shortcut(const Ref &p_shortcut) { shortcut = p_shortcut; }
+ Ref get_dock_shortcut() const { return shortcut; }
+
+ void set_default_slot(EditorDockManager::DockSlot p_slot);
+ EditorDockManager::DockSlot get_default_slot() const { return default_slot; }
+
+ void set_available_layouts(BitField p_layouts) { available_layouts = p_layouts; }
+ BitField get_available_layouts() const { return available_layouts; }
+
+ String get_display_title() const;
+ String get_effective_layout_key() const;
+
+ virtual void update_layout(DockLayout p_layout) { GDVIRTUAL_CALL(_update_layout, p_layout); }
+ virtual void save_layout_to_config(Ref &p_layout, const String &p_section) const { GDVIRTUAL_CALL(_save_layout_to_config, p_layout, p_section); }
+ virtual void load_layout_from_config(const Ref &p_layout, const String &p_section) { GDVIRTUAL_CALL(_load_layout_from_config, p_layout, p_section); }
+};
+
+VARIANT_BITFIELD_CAST(EditorDock::DockLayout);
diff --git a/editor/docks/editor_dock_manager.cpp b/editor/docks/editor_dock_manager.cpp
index 4221f571e05..9f519e7db38 100644
--- a/editor/docks/editor_dock_manager.cpp
+++ b/editor/docks/editor_dock_manager.cpp
@@ -37,6 +37,7 @@
#include "scene/gui/tab_container.h"
#include "scene/main/window.h"
+#include "editor/docks/editor_dock.h"
#include "editor/editor_node.h"
#include "editor/editor_string_names.h"
#include "editor/gui/editor_bottom_panel.h"
@@ -51,7 +52,13 @@ enum class TabStyle {
TEXT_AND_ICON,
};
-EditorDockManager *EditorDockManager::singleton = nullptr;
+static inline Ref _get_dock_icon(const EditorDock *p_dock, const Callable &p_icon_fetch) {
+ Ref icon = p_dock->get_dock_icon();
+ if (icon.is_null() && !p_dock->get_icon_name().is_empty()) {
+ icon = p_icon_fetch.call(p_dock->get_icon_name());
+ }
+ return icon;
+}
bool EditorDockDragHint::can_drop_data(const Point2 &p_point, const Variant &p_data) const {
return can_drop_dock;
@@ -233,7 +240,7 @@ DockSplitContainer::DockSplitContainer() {
////////////////////////////////////////////////
////////////////////////////////////////////////
-Control *EditorDockManager::_get_dock_tab_dragged() {
+EditorDock *EditorDockManager::_get_dock_tab_dragged() {
if (dock_tab_dragged) {
return dock_tab_dragged;
}
@@ -243,23 +250,17 @@ Control *EditorDockManager::_get_dock_tab_dragged() {
// Check if we are dragging a dock.
const String type = dock_drop_data.get("type", "");
if (type == "tab_container_tab") {
- Node *from_node = dock_slot[DOCK_SLOT_LEFT_BL]->get_node(dock_drop_data["from_path"]);
- if (!from_node) {
+ Node *source_tab_bar = EditorNode::get_singleton()->get_node(dock_drop_data["from_path"]);
+ if (!source_tab_bar) {
return nullptr;
}
- TabContainer *parent = Object::cast_to(from_node->get_parent());
- if (!parent) {
+ TabContainer *source_tab_container = Object::cast_to(source_tab_bar->get_parent());
+ if (!source_tab_container) {
return nullptr;
}
- // TODO: Update logic when GH-106503 is merged to cast directly to EditorDock instead of the below check.
- for (int i = 0; i < DOCK_SLOT_MAX; i++) {
- if (dock_slot[i] == parent) {
- dock_tab_dragged = parent->get_tab_control(dock_drop_data["tab_index"]);
- break;
- }
- }
+ dock_tab_dragged = Object::cast_to(source_tab_container->get_tab_control(dock_drop_data["tab_index"]));
if (!dock_tab_dragged) {
return nullptr;
}
@@ -294,13 +295,13 @@ void EditorDockManager::_dock_container_gui_input(const Ref &p_input
}
// Right click context menu.
- dock_context_popup->set_dock(p_dock_container->get_tab_control(tab_id));
+ dock_context_popup->set_dock(Object::cast_to(p_dock_container->get_tab_control(tab_id)));
dock_context_popup->set_position(p_dock_container->get_screen_position() + mb->get_position());
dock_context_popup->popup();
}
}
-void EditorDockManager::_bottom_dock_button_gui_input(const Ref &p_input, Control *p_dock, Button *p_bottom_button) {
+void EditorDockManager::_bottom_dock_button_gui_input(const Ref &p_input, EditorDock *p_dock, Button *p_bottom_button) {
Ref mb = p_input;
if (mb.is_valid() && mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) {
@@ -337,38 +338,42 @@ void EditorDockManager::update_docks_menu() {
bool global_menu = !bool(EDITOR_GET("interface/editor/use_embedded_menu")) && NativeMenu::get_singleton()->has_feature(NativeMenu::FEATURE_GLOBAL_MENU);
bool dark_mode = DisplayServer::get_singleton()->is_dark_mode_supported() && DisplayServer::get_singleton()->is_dark_mode();
+ int icon_max_width = EditorNode::get_singleton()->get_editor_theme()->get_constant(SNAME("class_icon_size"), EditorStringName(Editor));
// Add docks.
docks_menu_docks.clear();
int id = 0;
- for (const KeyValue &dock : all_docks) {
- if (!dock.value.enabled) {
+ const Callable icon_fetch = callable_mp((Window *)docks_menu, &Window::get_editor_theme_native_menu_icon).bind(global_menu, dark_mode);
+ for (EditorDock *dock : all_docks) {
+ if (!dock->enabled) {
continue;
}
- if (dock.value.shortcut.is_valid()) {
- docks_menu->add_shortcut(dock.value.shortcut, id);
- docks_menu->set_item_text(id, dock.value.title);
+ if (dock->shortcut.is_valid()) {
+ docks_menu->add_shortcut(dock->shortcut, id);
+ docks_menu->set_item_text(id, dock->get_display_title());
} else {
- docks_menu->add_item(dock.value.title, id);
+ docks_menu->add_item(dock->get_display_title(), id);
}
- const Ref icon = dock.value.icon_name ? docks_menu->get_editor_theme_native_menu_icon(dock.value.icon_name, global_menu, dark_mode) : dock.value.icon;
+ docks_menu->set_item_icon_max_width(id, icon_max_width);
+
+ const Ref icon = _get_dock_icon(dock, icon_fetch);
docks_menu->set_item_icon(id, icon.is_valid() ? icon : default_icon);
- if (!dock.value.open) {
+ if (!dock->open) {
docks_menu->set_item_icon_modulate(id, closed_icon_color_mod);
- docks_menu->set_item_tooltip(id, vformat(TTR("Open the %s dock."), dock.value.title));
+ docks_menu->set_item_tooltip(id, vformat(TTR("Open the %s dock."), dock->get_display_title()));
} else {
- docks_menu->set_item_tooltip(id, vformat(TTR("Focus on the %s dock."), dock.value.title));
+ docks_menu->set_item_tooltip(id, vformat(TTR("Focus on the %s dock."), dock->get_display_title()));
}
- docks_menu_docks.push_back(dock.key);
+ docks_menu_docks.push_back(dock);
id++;
}
}
void EditorDockManager::_docks_menu_option(int p_id) {
- Control *dock = docks_menu_docks[p_id];
+ EditorDock *dock = docks_menu_docks[p_id];
ERR_FAIL_NULL(dock);
- ERR_FAIL_COND_MSG(!all_docks.has(dock), vformat("Menu option for unknown dock '%s'.", dock->get_name()));
- if (all_docks[dock].enabled && all_docks[dock].open) {
+ ERR_FAIL_COND_MSG(!all_docks.has(dock), vformat("Menu option for unknown dock '%s'.", dock->get_display_title()));
+ if (dock->enabled && dock->open) {
PopupMenu *parent_menu = Object::cast_to(docks_menu->get_parent());
ERR_FAIL_NULL(parent_menu);
parent_menu->hide();
@@ -378,11 +383,11 @@ void EditorDockManager::_docks_menu_option(int p_id) {
void EditorDockManager::_window_close_request(WindowWrapper *p_wrapper) {
// Give the dock back to the original owner.
- Control *dock = _close_window(p_wrapper);
+ EditorDock *dock = _close_window(p_wrapper);
ERR_FAIL_COND(!all_docks.has(dock));
- if (all_docks[dock].previous_at_bottom || all_docks[dock].dock_slot_index != DOCK_SLOT_NONE) {
- all_docks[dock].open = false;
+ if (dock->previous_at_bottom || dock->dock_slot_index != DOCK_SLOT_NONE) {
+ dock->open = false;
open_dock(dock);
focus_dock(dock);
} else {
@@ -390,19 +395,19 @@ void EditorDockManager::_window_close_request(WindowWrapper *p_wrapper) {
}
}
-Control *EditorDockManager::_close_window(WindowWrapper *p_wrapper) {
+EditorDock *EditorDockManager::_close_window(WindowWrapper *p_wrapper) {
p_wrapper->set_block_signals(true);
- Control *dock = p_wrapper->release_wrapped_control();
+ EditorDock *dock = Object::cast_to(p_wrapper->release_wrapped_control());
p_wrapper->set_block_signals(false);
ERR_FAIL_COND_V(!all_docks.has(dock), nullptr);
- all_docks[dock].dock_window = nullptr;
+ dock->dock_window = nullptr;
dock_windows.erase(p_wrapper);
p_wrapper->queue_free();
return dock;
}
-void EditorDockManager::_open_dock_in_window(Control *p_dock, bool p_show_window, bool p_reset_size) {
+void EditorDockManager::_open_dock_in_window(EditorDock *p_dock, bool p_show_window, bool p_reset_size) {
ERR_FAIL_NULL(p_dock);
Size2 borders = Size2(4, 4) * EDSCALE;
@@ -411,7 +416,7 @@ void EditorDockManager::_open_dock_in_window(Control *p_dock, bool p_show_window
Point2 dock_screen_pos = p_dock->get_screen_position();
WindowWrapper *wrapper = memnew(WindowWrapper);
- wrapper->set_window_title(vformat(TTR("%s - Godot Engine"), all_docks[p_dock].title));
+ wrapper->set_window_title(vformat(TTR("%s - Godot Engine"), p_dock->get_display_title()));
wrapper->set_margins_enabled(true);
EditorNode::get_singleton()->get_gui_base()->add_child(wrapper);
@@ -419,8 +424,8 @@ void EditorDockManager::_open_dock_in_window(Control *p_dock, bool p_show_window
_move_dock(p_dock, nullptr);
wrapper->set_wrapped_control(p_dock);
- all_docks[p_dock].dock_window = wrapper;
- all_docks[p_dock].open = true;
+ p_dock->dock_window = wrapper;
+ p_dock->open = true;
p_dock->show();
wrapper->connect("window_close_requested", callable_mp(this, &EditorDockManager::_window_close_request).bind(wrapper));
@@ -439,45 +444,44 @@ void EditorDockManager::_open_dock_in_window(Control *p_dock, bool p_show_window
}
}
-void EditorDockManager::_restore_dock_to_saved_window(Control *p_dock, const Dictionary &p_window_dump) {
- if (!all_docks[p_dock].dock_window) {
+void EditorDockManager::_restore_dock_to_saved_window(EditorDock *p_dock, const Dictionary &p_window_dump) {
+ if (!p_dock->dock_window) {
_open_dock_in_window(p_dock, false);
}
- all_docks[p_dock].dock_window->restore_window_from_saved_position(
+ p_dock->dock_window->restore_window_from_saved_position(
p_window_dump.get("window_rect", Rect2i()),
p_window_dump.get("window_screen", -1),
p_window_dump.get("window_screen_rect", Rect2i()));
}
-void EditorDockManager::_dock_move_to_bottom(Control *p_dock, bool p_visible) {
+void EditorDockManager::_dock_move_to_bottom(EditorDock *p_dock, bool p_visible) {
_move_dock(p_dock, nullptr);
- all_docks[p_dock].at_bottom = true;
- all_docks[p_dock].previous_at_bottom = false;
-
- p_dock->call("_set_dock_horizontal", true);
+ p_dock->at_bottom = true;
+ p_dock->previous_at_bottom = false;
+ p_dock->update_layout(EditorDock::DOCK_LAYOUT_HORIZONTAL);
// Force docks moved to the bottom to appear first in the list, and give them their associated shortcut to toggle their bottom panel.
- Button *bottom_button = EditorNode::get_bottom_panel()->add_item(all_docks[p_dock].title, p_dock, all_docks[p_dock].shortcut, true);
+ Button *bottom_button = EditorNode::get_bottom_panel()->add_item(p_dock->get_display_title(), p_dock, p_dock->shortcut, true);
bottom_button->connect(SceneStringName(gui_input), callable_mp(this, &EditorDockManager::_bottom_dock_button_gui_input).bind(bottom_button).bind(p_dock));
EditorNode::get_bottom_panel()->make_item_visible(p_dock, p_visible);
}
-void EditorDockManager::_dock_remove_from_bottom(Control *p_dock) {
- all_docks[p_dock].at_bottom = false;
- all_docks[p_dock].previous_at_bottom = true;
+void EditorDockManager::_dock_remove_from_bottom(EditorDock *p_dock) {
+ p_dock->at_bottom = false;
+ p_dock->previous_at_bottom = true;
EditorNode::get_bottom_panel()->remove_item(p_dock);
- p_dock->call("_set_dock_horizontal", false);
+ p_dock->update_layout(EditorDock::DOCK_LAYOUT_VERTICAL);
}
-bool EditorDockManager::_is_dock_at_bottom(Control *p_dock) {
+bool EditorDockManager::_is_dock_at_bottom(EditorDock *p_dock) {
ERR_FAIL_COND_V(!all_docks.has(p_dock), false);
- return all_docks[p_dock].at_bottom;
+ return p_dock->at_bottom;
}
-void EditorDockManager::_move_dock_tab_index(Control *p_dock, int p_tab_index, bool p_set_current) {
+void EditorDockManager::_move_dock_tab_index(EditorDock *p_dock, int p_tab_index, bool p_set_current) {
TabContainer *dock_tab_container = Object::cast_to(p_dock->get_parent());
if (!dock_tab_container) {
return;
@@ -486,7 +490,7 @@ void EditorDockManager::_move_dock_tab_index(Control *p_dock, int p_tab_index, b
dock_tab_container->set_block_signals(true);
int target_index = CLAMP(p_tab_index, 0, dock_tab_container->get_tab_count() - 1);
dock_tab_container->move_child(p_dock, dock_tab_container->get_tab_control(target_index)->get_index(false));
- all_docks[p_dock].previous_tab_index = target_index;
+ p_dock->previous_tab_index = target_index;
if (p_set_current) {
dock_tab_container->set_current_tab(target_index);
@@ -494,9 +498,9 @@ void EditorDockManager::_move_dock_tab_index(Control *p_dock, int p_tab_index, b
dock_tab_container->set_block_signals(false);
}
-void EditorDockManager::_move_dock(Control *p_dock, Control *p_target, int p_tab_index, bool p_set_current) {
+void EditorDockManager::_move_dock(EditorDock *p_dock, Control *p_target, int p_tab_index, bool p_set_current) {
ERR_FAIL_NULL(p_dock);
- ERR_FAIL_COND_MSG(!all_docks.has(p_dock), vformat("Cannot move unknown dock '%s'.", p_dock->get_name()));
+ ERR_FAIL_COND_MSG(!all_docks.has(p_dock), vformat("Cannot move unknown dock '%s'.", p_dock->get_display_title()));
Node *parent = p_dock->get_parent();
if (parent == p_target) {
@@ -509,15 +513,15 @@ void EditorDockManager::_move_dock(Control *p_dock, Control *p_target, int p_tab
// Remove dock from its existing parent.
if (parent) {
- if (all_docks[p_dock].dock_window) {
- _close_window(all_docks[p_dock].dock_window);
- } else if (all_docks[p_dock].at_bottom) {
+ if (p_dock->dock_window) {
+ _close_window(p_dock->dock_window);
+ } else if (p_dock->at_bottom) {
_dock_remove_from_bottom(p_dock);
} else {
- all_docks[p_dock].previous_at_bottom = false;
+ p_dock->previous_at_bottom = false;
TabContainer *parent_tabs = Object::cast_to(parent);
if (parent_tabs) {
- all_docks[p_dock].previous_tab_index = parent_tabs->get_tab_idx_from_control(p_dock);
+ p_dock->previous_tab_index = parent_tabs->get_tab_idx_from_control(p_dock);
}
parent->set_block_signals(true);
parent->remove_child(p_dock);
@@ -547,36 +551,35 @@ void EditorDockManager::_move_dock(Control *p_dock, Control *p_target, int p_tab
}
}
-void EditorDockManager::_update_tab_style(Control *p_dock) {
- const DockInfo &dock_info = all_docks[p_dock];
- if (!dock_info.enabled || !dock_info.open) {
+void EditorDockManager::_update_tab_style(EditorDock *p_dock) {
+ if (!p_dock->enabled || !p_dock->open) {
return; // Disabled by feature profile or manually closed by user.
}
- if (dock_info.dock_window || dock_info.at_bottom) {
+ if (p_dock->dock_window || p_dock->at_bottom) {
return; // Floating or sent to bottom.
}
TabContainer *tab_container = get_dock_tab_container(p_dock);
ERR_FAIL_NULL(tab_container);
+
int index = tab_container->get_tab_idx_from_control(p_dock);
ERR_FAIL_COND(index == -1);
const TabStyle style = (TabStyle)EDITOR_GET("interface/editor/dock_tab_style").operator int();
+ const Ref icon = _get_dock_icon(p_dock, callable_mp((Control *)tab_container, &Control::get_editor_theme_icon));
switch (style) {
case TabStyle::TEXT_ONLY: {
- tab_container->set_tab_title(index, dock_info.title);
+ tab_container->set_tab_title(index, p_dock->get_display_title());
tab_container->set_tab_icon(index, Ref());
tab_container->set_tab_tooltip(index, String());
} break;
case TabStyle::ICON_ONLY: {
- const Ref icon = dock_info.icon_name ? tab_container->get_editor_theme_icon(dock_info.icon_name) : dock_info.icon;
- tab_container->set_tab_title(index, icon.is_valid() ? String() : dock_info.title);
+ tab_container->set_tab_title(index, icon.is_valid() ? String() : p_dock->get_display_title());
tab_container->set_tab_icon(index, icon);
- tab_container->set_tab_tooltip(index, icon.is_valid() ? dock_info.title : String());
+ tab_container->set_tab_tooltip(index, p_dock->get_display_title());
} break;
case TabStyle::TEXT_AND_ICON: {
- const Ref icon = dock_info.icon_name ? tab_container->get_editor_theme_icon(dock_info.icon_name) : dock_info.icon;
- tab_container->set_tab_title(index, dock_info.title);
+ tab_container->set_tab_title(index, p_dock->get_display_title());
tab_container->set_tab_icon(index, icon);
tab_container->set_tab_tooltip(index, String());
} break;
@@ -588,7 +591,7 @@ void EditorDockManager::save_docks_to_config(Ref p_layout, const Str
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
String names;
for (int j = 0; j < dock_slot[i]->get_tab_count(); j++) {
- String name = dock_slot[i]->get_tab_control(j)->get_name();
+ String name = Object::cast_to(dock_slot[i]->get_tab_control(j))->get_effective_layout_key();
if (!names.is_empty()) {
names += ",";
}
@@ -618,7 +621,7 @@ void EditorDockManager::save_docks_to_config(Ref p_layout, const Str
// Save docks in windows.
Dictionary floating_docks_dump;
for (WindowWrapper *wrapper : dock_windows) {
- Control *dock = wrapper->get_wrapped_control();
+ EditorDock *dock = Object::cast_to(wrapper->get_wrapped_control());
Dictionary window_dump;
window_dump["window_rect"] = wrapper->get_window_rect();
@@ -627,11 +630,11 @@ void EditorDockManager::save_docks_to_config(Ref p_layout, const Str
window_dump["window_screen"] = wrapper->get_window_screen();
window_dump["window_screen_rect"] = DisplayServer::get_singleton()->screen_get_usable_rect(screen);
- String name = dock->get_name();
+ String name = dock->get_effective_layout_key();
floating_docks_dump[name] = window_dump;
// Append to regular dock section so we know where to restore it to.
- int dock_slot_id = all_docks[dock].dock_slot_index;
+ int dock_slot_id = dock->dock_slot_index;
String config_key = "dock_" + itos(dock_slot_id + 1);
String names = p_layout->get_value(p_section, config_key, "");
@@ -647,22 +650,23 @@ void EditorDockManager::save_docks_to_config(Ref p_layout, const Str
// Save closed and bottom docks.
Array bottom_docks_dump;
Array closed_docks_dump;
- for (const KeyValue &d : all_docks) {
- d.key->call(SNAME("_save_layout_to_config"), p_layout, p_section);
+ for (const EditorDock *dock : all_docks) {
+ const String section_name = p_section + "/" + dock->get_effective_layout_key();
+ dock->save_layout_to_config(p_layout, section_name);
- if (!d.value.at_bottom && d.value.open && (!d.value.previous_at_bottom || !d.value.dock_window)) {
+ if (!dock->at_bottom && dock->open && (!dock->previous_at_bottom || !dock->dock_window)) {
continue;
}
- // Use the name of the Control since it isn't translated.
- String name = d.key->get_name();
- if (d.value.at_bottom || (d.value.previous_at_bottom && d.value.dock_window)) {
+
+ const String name = dock->get_effective_layout_key();
+ if (dock->at_bottom || (dock->previous_at_bottom && dock->dock_window)) {
bottom_docks_dump.push_back(name);
}
- if (!d.value.open) {
+ if (!dock->open) {
closed_docks_dump.push_back(name);
}
- int dock_slot_id = all_docks[d.key].dock_slot_index;
+ int dock_slot_id = dock->dock_slot_index;
String config_key = "dock_" + itos(dock_slot_id + 1);
String names = p_layout->get_value(p_section, config_key, "");
@@ -696,9 +700,9 @@ void EditorDockManager::load_docks_from_config(Ref p_layout, const S
bool allow_floating_docks = EditorNode::get_singleton()->is_multi_window_enabled() && (!p_first_load || EDITOR_GET("interface/multi_window/restore_windows_on_load"));
// Store the docks by name for easy lookup.
- HashMap dock_map;
- for (const KeyValue &dock : all_docks) {
- dock_map[dock.key->get_name()] = dock.key;
+ HashMap dock_map;
+ for (EditorDock *dock : all_docks) {
+ dock_map[dock->get_effective_layout_key()] = dock;
}
// Load docks by slot. Index -1 is for docks that have no slot.
@@ -710,21 +714,22 @@ void EditorDockManager::load_docks_from_config(Ref p_layout, const S
Vector names = String(p_layout->get_value(p_section, "dock_" + itos(i + 1))).split(",");
for (int j = names.size() - 1; j >= 0; j--) {
- String name = names[j];
+ const String &name = names[j];
+ const String section_name = p_section + "/" + name;
if (!dock_map.has(name)) {
continue;
}
- Control *dock = dock_map[name];
+ EditorDock *dock = dock_map[name];
- if (!all_docks[dock].enabled) {
+ if (!dock->enabled) {
// Don't open disabled docks.
- dock->call(SNAME("_load_layout_from_config"), p_layout, p_section);
+ dock->load_layout_from_config(p_layout, section_name);
continue;
}
bool at_bottom = false;
if (allow_floating_docks && floating_docks_dump.has(name)) {
- all_docks[dock].previous_at_bottom = dock_bottom.has(name);
+ dock->previous_at_bottom = dock_bottom.has(name);
_restore_dock_to_saved_window(dock, floating_docks_dump[name]);
} else if (dock_bottom.has(name)) {
_dock_move_to_bottom(dock, false);
@@ -732,15 +737,15 @@ void EditorDockManager::load_docks_from_config(Ref p_layout, const S
} else if (i >= 0) {
_move_dock(dock, dock_slot[i], 0);
}
- dock->call(SNAME("_load_layout_from_config"), p_layout, p_section);
+ dock->load_layout_from_config(p_layout, section_name);
if (closed_docks.has(name)) {
_move_dock(dock, closed_dock_parent);
- all_docks[dock].open = false;
+ dock->open = false;
dock->hide();
} else {
// Make sure it is open.
- all_docks[dock].open = true;
+ dock->open = true;
// It's important to not update the visibility of bottom panels.
// Visibility of bottom panels are managed in EditorBottomPanel.
if (!at_bottom) {
@@ -748,8 +753,8 @@ void EditorDockManager::load_docks_from_config(Ref p_layout, const S
}
}
- all_docks[dock].dock_slot_index = i;
- all_docks[dock].previous_tab_index = i >= 0 ? j : 0;
+ dock->dock_slot_index = i;
+ dock->previous_tab_index = i >= 0 ? j : 0;
}
}
@@ -785,7 +790,7 @@ void EditorDockManager::load_docks_from_config(Ref p_layout, const S
update_docks_menu();
}
-void EditorDockManager::bottom_dock_show_placement_popup(const Rect2i &p_position, Control *p_dock) {
+void EditorDockManager::bottom_dock_show_placement_popup(const Rect2i &p_position, EditorDock *p_dock) {
ERR_FAIL_COND(!all_docks.has(p_dock));
dock_context_popup->set_dock(p_dock);
@@ -801,15 +806,15 @@ void EditorDockManager::bottom_dock_show_placement_popup(const Rect2i &p_positio
dock_context_popup->popup();
}
-void EditorDockManager::set_dock_enabled(Control *p_dock, bool p_enabled) {
+void EditorDockManager::set_dock_enabled(EditorDock *p_dock, bool p_enabled) {
ERR_FAIL_NULL(p_dock);
- ERR_FAIL_COND_MSG(!all_docks.has(p_dock), vformat("Cannot set enabled unknown dock '%s'.", p_dock->get_name()));
+ ERR_FAIL_COND_MSG(!all_docks.has(p_dock), vformat("Cannot set enabled unknown dock '%s'.", p_dock->get_display_title()));
- if (all_docks[p_dock].enabled == p_enabled) {
+ if (p_dock->enabled == p_enabled) {
return;
}
- all_docks[p_dock].enabled = p_enabled;
+ p_dock->enabled = p_enabled;
if (p_enabled) {
open_dock(p_dock, false);
} else {
@@ -817,39 +822,39 @@ void EditorDockManager::set_dock_enabled(Control *p_dock, bool p_enabled) {
}
}
-void EditorDockManager::close_dock(Control *p_dock) {
+void EditorDockManager::close_dock(EditorDock *p_dock) {
ERR_FAIL_NULL(p_dock);
- ERR_FAIL_COND_MSG(!all_docks.has(p_dock), vformat("Cannot close unknown dock '%s'.", p_dock->get_name()));
+ ERR_FAIL_COND_MSG(!all_docks.has(p_dock), vformat("Cannot close unknown dock '%s'.", p_dock->get_display_title()));
- if (!all_docks[p_dock].open) {
+ if (!p_dock->open) {
return;
}
_move_dock(p_dock, closed_dock_parent);
- all_docks[p_dock].open = false;
+ p_dock->open = false;
p_dock->hide();
_update_layout();
}
-void EditorDockManager::open_dock(Control *p_dock, bool p_set_current) {
+void EditorDockManager::open_dock(EditorDock *p_dock, bool p_set_current) {
ERR_FAIL_NULL(p_dock);
- ERR_FAIL_COND_MSG(!all_docks.has(p_dock), vformat("Cannot open unknown dock '%s'.", p_dock->get_name()));
+ ERR_FAIL_COND_MSG(!all_docks.has(p_dock), vformat("Cannot open unknown dock '%s'.", p_dock->get_display_title()));
- if (all_docks[p_dock].open) {
+ if (p_dock->open) {
return;
}
- all_docks[p_dock].open = true;
+ p_dock->open = true;
p_dock->show();
// Open dock to its previous location.
- if (all_docks[p_dock].previous_at_bottom) {
+ if (p_dock->previous_at_bottom) {
_dock_move_to_bottom(p_dock, true);
- } else if (all_docks[p_dock].dock_slot_index != DOCK_SLOT_NONE) {
- TabContainer *slot = dock_slot[all_docks[p_dock].dock_slot_index];
- int tab_index = all_docks[p_dock].previous_tab_index;
+ } else if (p_dock->dock_slot_index != DOCK_SLOT_NONE) {
+ TabContainer *slot = dock_slot[p_dock->dock_slot_index];
+ int tab_index = p_dock->previous_tab_index;
if (tab_index < 0) {
tab_index = slot->get_tab_count();
}
@@ -866,24 +871,24 @@ TabContainer *EditorDockManager::get_dock_tab_container(Control *p_dock) const {
return Object::cast_to(p_dock->get_parent());
}
-void EditorDockManager::focus_dock(Control *p_dock) {
+void EditorDockManager::focus_dock(EditorDock *p_dock) {
ERR_FAIL_NULL(p_dock);
- ERR_FAIL_COND_MSG(!all_docks.has(p_dock), vformat("Cannot focus unknown dock '%s'.", p_dock->get_name()));
+ ERR_FAIL_COND_MSG(!all_docks.has(p_dock), vformat("Cannot focus unknown dock '%s'.", p_dock->get_display_title()));
- if (!all_docks[p_dock].enabled) {
+ if (!p_dock->enabled) {
return;
}
- if (!all_docks[p_dock].open) {
+ if (!p_dock->open) {
open_dock(p_dock);
}
- if (all_docks[p_dock].dock_window) {
+ if (p_dock->dock_window) {
p_dock->get_window()->grab_focus();
return;
}
- if (all_docks[p_dock].at_bottom) {
+ if (p_dock->at_bottom) {
EditorNode::get_bottom_panel()->make_item_visible(p_dock, true, true);
return;
}
@@ -901,19 +906,16 @@ void EditorDockManager::focus_dock(Control *p_dock) {
tab_container->set_current_tab(tab_index);
}
-void EditorDockManager::add_dock(Control *p_dock, const String &p_title, DockSlot p_slot, const Ref &p_shortcut, const StringName &p_icon_name) {
+void EditorDockManager::add_dock(EditorDock *p_dock) {
ERR_FAIL_NULL(p_dock);
- ERR_FAIL_COND_MSG(all_docks.has(p_dock), vformat("Cannot add dock '%s', already added.", p_dock->get_name()));
+ ERR_FAIL_COND_MSG(all_docks.has(p_dock), vformat("Cannot add dock '%s', already added.", p_dock->get_display_title()));
- DockInfo dock_info;
- dock_info.title = p_title.is_empty() ? String(p_dock->get_name()) : p_title;
- dock_info.dock_slot_index = p_slot;
- dock_info.shortcut = p_shortcut;
- dock_info.icon_name = p_icon_name;
- all_docks[p_dock] = dock_info;
+ p_dock->dock_slot_index = p_dock->default_slot;
+ all_docks.push_back(p_dock);
+ p_dock->connect("tab_style_changed", callable_mp(this, &EditorDockManager::_update_tab_style).bind(p_dock));
+ p_dock->connect("renamed", callable_mp(this, &EditorDockManager::_update_tab_style).bind(p_dock));
- if (p_slot != DOCK_SLOT_NONE) {
- ERR_FAIL_INDEX(p_slot, DOCK_SLOT_MAX);
+ if (p_dock->default_slot != DOCK_SLOT_NONE) {
open_dock(p_dock, false);
} else {
closed_dock_parent->add_child(p_dock);
@@ -922,24 +924,18 @@ void EditorDockManager::add_dock(Control *p_dock, const String &p_title, DockSlo
}
}
-void EditorDockManager::remove_dock(Control *p_dock) {
+void EditorDockManager::remove_dock(EditorDock *p_dock) {
ERR_FAIL_NULL(p_dock);
- ERR_FAIL_COND_MSG(!all_docks.has(p_dock), vformat("Cannot remove unknown dock '%s'.", p_dock->get_name()));
+ ERR_FAIL_COND_MSG(!all_docks.has(p_dock), vformat("Cannot remove unknown dock '%s'.", p_dock->get_display_title()));
_move_dock(p_dock, nullptr);
all_docks.erase(p_dock);
+ p_dock->disconnect("tab_style_changed", callable_mp(this, &EditorDockManager::_update_tab_style));
+ p_dock->disconnect("renamed", callable_mp(this, &EditorDockManager::_update_tab_style));
_update_layout();
}
-void EditorDockManager::set_dock_tab_icon(Control *p_dock, const Ref &p_icon) {
- ERR_FAIL_NULL(p_dock);
- ERR_FAIL_COND_MSG(!all_docks.has(p_dock), vformat("Cannot set tab icon for unknown dock '%s'.", p_dock->get_name()));
-
- all_docks[p_dock].icon = p_icon;
- _update_tab_style(p_dock);
-}
-
void EditorDockManager::set_docks_visible(bool p_show) {
if (docks_visible == p_show) {
return;
@@ -956,8 +952,8 @@ bool EditorDockManager::are_docks_visible() const {
}
void EditorDockManager::update_tab_styles() {
- for (const KeyValue &dock : all_docks) {
- _update_tab_style(dock.key);
+ for (EditorDock *dock : all_docks) {
+ _update_tab_style(dock);
}
}
@@ -1125,7 +1121,7 @@ void DockContextPopup::_dock_select_input(const Ref &p_input) {
if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) {
if (dock_manager->get_dock_tab_container(context_dock) != target_tab_container) {
dock_manager->_move_dock(context_dock, target_tab_container, target_tab_container->get_tab_count());
- dock_manager->all_docks[context_dock].dock_slot_index = over_dock_slot;
+ context_dock->dock_slot_index = over_dock_slot;
dock_manager->_update_layout();
hide();
}
@@ -1238,21 +1234,21 @@ void DockContextPopup::_update_buttons() {
tab_move_right_button->set_disabled(context_tab_index >= context_tab_container->get_tab_count() - 1);
}
- dock_to_bottom_button->set_visible(!dock_at_bottom && bool(context_dock->call("_can_dock_horizontal")));
+ dock_to_bottom_button->set_visible(!dock_at_bottom && bool(context_dock->available_layouts & EditorDock::DOCK_LAYOUT_HORIZONTAL));
reset_size();
}
void DockContextPopup::select_current_dock_in_dock_slot(int p_dock_slot) {
- context_dock = dock_manager->dock_slot[p_dock_slot]->get_current_tab_control();
+ context_dock = Object::cast_to(dock_manager->dock_slot[p_dock_slot]->get_current_tab_control());
_update_buttons();
}
-void DockContextPopup::set_dock(Control *p_dock) {
+void DockContextPopup::set_dock(EditorDock *p_dock) {
context_dock = p_dock;
_update_buttons();
}
-Control *DockContextPopup::get_dock() const {
+EditorDock *DockContextPopup::get_dock() const {
return context_dock;
}
diff --git a/editor/docks/editor_dock_manager.h b/editor/docks/editor_dock_manager.h
index b46260ec8e2..cdf7818b3e4 100644
--- a/editor/docks/editor_dock_manager.h
+++ b/editor/docks/editor_dock_manager.h
@@ -36,6 +36,7 @@
class Button;
class ConfigFile;
class Control;
+class EditorDock;
class PopupMenu;
class TabBar;
class TabContainer;
@@ -83,21 +84,7 @@ private:
friend class DockContextPopup;
friend class EditorDockDragHint;
- struct DockInfo {
- String title;
- bool open = false;
- bool enabled = true;
- bool at_bottom = false;
- int previous_tab_index = -1;
- bool previous_at_bottom = false;
- WindowWrapper *dock_window = nullptr;
- int dock_slot_index = DOCK_SLOT_NONE;
- Ref shortcut;
- Ref icon; // Only used when `icon_name` is empty.
- StringName icon_name;
- };
-
- static EditorDockManager *singleton;
+ static inline EditorDockManager *singleton = nullptr;
// To access splits easily by index.
Vector vsplits;
@@ -106,38 +93,38 @@ private:
Vector dock_windows;
TabContainer *dock_slot[DOCK_SLOT_MAX];
EditorDockDragHint *dock_drag_rects[DOCK_SLOT_MAX];
- HashMap all_docks;
- Control *dock_tab_dragged = nullptr;
+ LocalVector all_docks;
+ EditorDock *dock_tab_dragged = nullptr;
bool docks_visible = true;
DockContextPopup *dock_context_popup = nullptr;
PopupMenu *docks_menu = nullptr;
- Vector docks_menu_docks;
+ LocalVector docks_menu_docks;
Control *closed_dock_parent = nullptr;
- Control *_get_dock_tab_dragged();
+ EditorDock *_get_dock_tab_dragged();
void _dock_drag_stopped();
void _dock_split_dragged(int p_offset);
void _dock_container_gui_input(const Ref &p_input, TabContainer *p_dock_container);
- void _bottom_dock_button_gui_input(const Ref &p_input, Control *p_dock, Button *p_bottom_button);
+ void _bottom_dock_button_gui_input(const Ref &p_input, EditorDock *p_dock, Button *p_bottom_button);
void _dock_container_update_visibility(TabContainer *p_dock_container);
void _update_layout();
void _docks_menu_option(int p_id);
void _window_close_request(WindowWrapper *p_wrapper);
- Control *_close_window(WindowWrapper *p_wrapper);
- void _open_dock_in_window(Control *p_dock, bool p_show_window = true, bool p_reset_size = false);
- void _restore_dock_to_saved_window(Control *p_dock, const Dictionary &p_window_dump);
+ EditorDock *_close_window(WindowWrapper *p_wrapper);
+ void _open_dock_in_window(EditorDock *p_dock, bool p_show_window = true, bool p_reset_size = false);
+ void _restore_dock_to_saved_window(EditorDock *p_dock, const Dictionary &p_window_dump);
- void _dock_move_to_bottom(Control *p_dock, bool p_visible);
- void _dock_remove_from_bottom(Control *p_dock);
- bool _is_dock_at_bottom(Control *p_dock);
+ void _dock_move_to_bottom(EditorDock *p_dock, bool p_visible);
+ void _dock_remove_from_bottom(EditorDock *p_dock);
+ bool _is_dock_at_bottom(EditorDock *p_dock);
- void _move_dock_tab_index(Control *p_dock, int p_tab_index, bool p_set_current);
- void _move_dock(Control *p_dock, Control *p_target, int p_tab_index = -1, bool p_set_current = true);
+ void _move_dock_tab_index(EditorDock *p_dock, int p_tab_index, bool p_set_current);
+ void _move_dock(EditorDock *p_dock, Control *p_target, int p_tab_index = -1, bool p_set_current = true);
- void _update_tab_style(Control *p_dock);
+ void _update_tab_style(EditorDock *p_dock);
public:
static EditorDockManager *get_singleton() { return singleton; }
@@ -156,22 +143,20 @@ public:
void save_docks_to_config(Ref p_layout, const String &p_section) const;
void load_docks_from_config(Ref p_layout, const String &p_section, bool p_first_load = false);
- void set_dock_enabled(Control *p_dock, bool p_enabled);
- void close_dock(Control *p_dock);
- void open_dock(Control *p_dock, bool p_set_current = true);
- void focus_dock(Control *p_dock);
+ void set_dock_enabled(EditorDock *p_dock, bool p_enabled);
+ void close_dock(EditorDock *p_dock);
+ void open_dock(EditorDock *p_dock, bool p_set_current = true);
+ void focus_dock(EditorDock *p_dock);
TabContainer *get_dock_tab_container(Control *p_dock) const;
- void bottom_dock_show_placement_popup(const Rect2i &p_position, Control *p_dock);
+ void bottom_dock_show_placement_popup(const Rect2i &p_position, EditorDock *p_dock);
void set_docks_visible(bool p_show);
bool are_docks_visible() const;
- void add_dock(Control *p_dock, const String &p_title = "", DockSlot p_slot = DOCK_SLOT_NONE, const Ref &p_shortcut = nullptr, const StringName &p_icon_name = StringName());
- void remove_dock(Control *p_dock);
-
- void set_dock_tab_icon(Control *p_dock, const Ref &p_icon);
+ void add_dock(EditorDock *p_dock);
+ void remove_dock(EditorDock *p_dock);
EditorDockManager();
};
@@ -222,7 +207,7 @@ private:
Rect2 dock_select_rects[EditorDockManager::DOCK_SLOT_MAX];
int dock_select_rect_over_idx = -1;
- Control *context_dock = nullptr;
+ EditorDock *context_dock = nullptr;
EditorDockManager *dock_manager = nullptr;
@@ -243,8 +228,8 @@ protected:
public:
void select_current_dock_in_dock_slot(int p_dock_slot);
- void set_dock(Control *p_dock);
- Control *get_dock() const;
+ void set_dock(EditorDock *p_dock);
+ EditorDock *get_dock() const;
void docks_updated();
DockContextPopup();
diff --git a/editor/docks/filesystem_dock.cpp b/editor/docks/filesystem_dock.cpp
index 0616dd97b8d..341317e68b4 100644
--- a/editor/docks/filesystem_dock.cpp
+++ b/editor/docks/filesystem_dock.cpp
@@ -53,11 +53,13 @@
#include "editor/plugins/editor_resource_conversion_plugin.h"
#include "editor/scene/editor_scene_tabs.h"
#include "editor/scene/scene_create_dialog.h"
+#include "editor/settings/editor_command_palette.h"
#include "editor/settings/editor_feature_profile.h"
#include "editor/settings/editor_settings.h"
#include "editor/shader/shader_create_dialog.h"
#include "editor/themes/editor_scale.h"
#include "editor/themes/editor_theme_manager.h"
+#include "scene/gui/box_container.h"
#include "scene/gui/item_list.h"
#include "scene/gui/label.h"
#include "scene/gui/line_edit.h"
@@ -4008,16 +4010,13 @@ MenuButton *FileSystemDock::_create_file_menu_button() {
return button;
}
-bool FileSystemDock::_can_dock_horizontal() const {
- return true;
-}
-
-void FileSystemDock::_set_dock_horizontal(bool p_enable) {
- if (button_dock_placement->is_visible() == p_enable) {
+void FileSystemDock::update_layout(EditorDock::DockLayout p_layout) {
+ bool horizontal = p_layout == EditorDock::DOCK_LAYOUT_HORIZONTAL;
+ if (button_dock_placement->is_visible() == horizontal) {
return;
}
- if (p_enable) {
+ if (horizontal) {
set_meta("_dock_display_mode", get_display_mode());
set_meta("_dock_file_display_mode", get_file_list_display_mode());
@@ -4041,75 +4040,49 @@ void FileSystemDock::_set_dock_horizontal(bool p_enable) {
set_file_list_display_mode(new_file_display_mode);
set_custom_minimum_size(Size2(0, 0));
}
-
- button_dock_placement->set_visible(p_enable);
+ button_dock_placement->set_visible(horizontal);
}
-void FileSystemDock::_bind_methods() {
- ClassDB::bind_method(D_METHOD("navigate_to_path", "path"), &FileSystemDock::navigate_to_path);
-
- ClassDB::bind_method(D_METHOD("add_resource_tooltip_plugin", "plugin"), &FileSystemDock::add_resource_tooltip_plugin);
- ClassDB::bind_method(D_METHOD("remove_resource_tooltip_plugin", "plugin"), &FileSystemDock::remove_resource_tooltip_plugin);
-
- ClassDB::bind_method(D_METHOD("_set_dock_horizontal", "enable"), &FileSystemDock::_set_dock_horizontal);
- ClassDB::bind_method(D_METHOD("_can_dock_horizontal"), &FileSystemDock::_can_dock_horizontal);
-
- ClassDB::bind_method(D_METHOD("_save_layout_to_config"), &FileSystemDock::_save_layout_to_config);
- ClassDB::bind_method(D_METHOD("_load_layout_from_config"), &FileSystemDock::_load_layout_from_config);
-
- ADD_SIGNAL(MethodInfo("inherit", PropertyInfo(Variant::STRING, "file")));
- ADD_SIGNAL(MethodInfo("instantiate", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files")));
-
- ADD_SIGNAL(MethodInfo("resource_removed", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource")));
- ADD_SIGNAL(MethodInfo("file_removed", PropertyInfo(Variant::STRING, "file")));
- ADD_SIGNAL(MethodInfo("folder_removed", PropertyInfo(Variant::STRING, "folder")));
- ADD_SIGNAL(MethodInfo("files_moved", PropertyInfo(Variant::STRING, "old_file"), PropertyInfo(Variant::STRING, "new_file")));
- ADD_SIGNAL(MethodInfo("folder_moved", PropertyInfo(Variant::STRING, "old_folder"), PropertyInfo(Variant::STRING, "new_folder")));
- ADD_SIGNAL(MethodInfo("folder_color_changed"));
-
- ADD_SIGNAL(MethodInfo("display_mode_changed"));
-}
-
-void FileSystemDock::_save_layout_to_config(Ref p_layout, const String &p_section) const {
- p_layout->set_value(p_section, "dock_filesystem_h_split_offset", get_h_split_offset());
- p_layout->set_value(p_section, "dock_filesystem_v_split_offset", get_v_split_offset());
- p_layout->set_value(p_section, "dock_filesystem_display_mode", get_display_mode());
- p_layout->set_value(p_section, "dock_filesystem_file_sort", (int)get_file_sort());
- p_layout->set_value(p_section, "dock_filesystem_file_list_display_mode", get_file_list_display_mode());
+void FileSystemDock::save_layout_to_config(Ref &p_layout, const String &p_section) const {
+ p_layout->set_value(p_section, "h_split_offset", get_h_split_offset());
+ p_layout->set_value(p_section, "v_split_offset", get_v_split_offset());
+ p_layout->set_value(p_section, "display_mode", get_display_mode());
+ p_layout->set_value(p_section, "file_sort", (int)get_file_sort());
+ p_layout->set_value(p_section, "file_list_display_mode", get_file_list_display_mode());
PackedStringArray selected_files = get_selected_paths();
- p_layout->set_value(p_section, "dock_filesystem_selected_paths", selected_files);
+ p_layout->set_value(p_section, "selected_paths", selected_files);
Vector uncollapsed_paths = get_uncollapsed_paths();
- p_layout->set_value(p_section, "dock_filesystem_uncollapsed_paths", searched_tokens.is_empty() ? uncollapsed_paths : uncollapsed_paths_before_search);
+ p_layout->set_value(p_section, "uncollapsed_paths", searched_tokens.is_empty() ? uncollapsed_paths : uncollapsed_paths_before_search);
}
-void FileSystemDock::_load_layout_from_config(Ref p_layout, const String &p_section) {
- if (p_layout->has_section_key(p_section, "dock_filesystem_h_split_offset")) {
- int fs_h_split_ofs = p_layout->get_value(p_section, "dock_filesystem_h_split_offset");
+void FileSystemDock::load_layout_from_config(const Ref &p_layout, const String &p_section) {
+ if (p_layout->has_section_key(p_section, "h_split_offset")) {
+ int fs_h_split_ofs = p_layout->get_value(p_section, "h_split_offset");
set_h_split_offset(fs_h_split_ofs);
}
- if (p_layout->has_section_key(p_section, "dock_filesystem_v_split_offset")) {
- int fs_v_split_ofs = p_layout->get_value(p_section, "dock_filesystem_v_split_offset");
+ if (p_layout->has_section_key(p_section, "v_split_offset")) {
+ int fs_v_split_ofs = p_layout->get_value(p_section, "v_split_offset");
set_v_split_offset(fs_v_split_ofs);
}
- if (p_layout->has_section_key(p_section, "dock_filesystem_display_mode")) {
- DisplayMode dock_filesystem_display_mode = DisplayMode(int(p_layout->get_value(p_section, "dock_filesystem_display_mode")));
+ if (p_layout->has_section_key(p_section, "display_mode")) {
+ DisplayMode dock_filesystem_display_mode = DisplayMode(int(p_layout->get_value(p_section, "display_mode")));
set_display_mode(dock_filesystem_display_mode);
}
- if (p_layout->has_section_key(p_section, "dock_filesystem_file_sort")) {
- FileSortOption dock_filesystem_file_sort = FileSortOption(int(p_layout->get_value(p_section, "dock_filesystem_file_sort")));
+ if (p_layout->has_section_key(p_section, "file_sort")) {
+ FileSortOption dock_filesystem_file_sort = FileSortOption(int(p_layout->get_value(p_section, "file_sort")));
set_file_sort(dock_filesystem_file_sort);
}
- if (p_layout->has_section_key(p_section, "dock_filesystem_file_list_display_mode")) {
- FileListDisplayMode dock_filesystem_file_list_display_mode = FileListDisplayMode(int(p_layout->get_value(p_section, "dock_filesystem_file_list_display_mode")));
+ if (p_layout->has_section_key(p_section, "file_list_display_mode")) {
+ FileListDisplayMode dock_filesystem_file_list_display_mode = FileListDisplayMode(int(p_layout->get_value(p_section, "file_list_display_mode")));
set_file_list_display_mode(dock_filesystem_file_list_display_mode);
}
- if (p_layout->has_section_key(p_section, "dock_filesystem_selected_paths")) {
- PackedStringArray dock_filesystem_selected_paths = p_layout->get_value(p_section, "dock_filesystem_selected_paths");
+ if (p_layout->has_section_key(p_section, "selected_paths")) {
+ PackedStringArray dock_filesystem_selected_paths = p_layout->get_value(p_section, "selected_paths");
for (int i = 0; i < dock_filesystem_selected_paths.size(); i++) {
select_file(dock_filesystem_selected_paths[i]);
}
@@ -4117,8 +4090,8 @@ void FileSystemDock::_load_layout_from_config(Ref p_layout, const St
// Restore collapsed state.
PackedStringArray uncollapsed_tis;
- if (p_layout->has_section_key(p_section, "dock_filesystem_uncollapsed_paths")) {
- uncollapsed_tis = p_layout->get_value(p_section, "dock_filesystem_uncollapsed_paths");
+ if (p_layout->has_section_key(p_section, "uncollapsed_paths")) {
+ uncollapsed_tis = p_layout->get_value(p_section, "uncollapsed_paths");
} else {
uncollapsed_tis = { "res://" };
}
@@ -4134,10 +4107,32 @@ void FileSystemDock::_load_layout_from_config(Ref p_layout, const St
}
}
+void FileSystemDock::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("navigate_to_path", "path"), &FileSystemDock::navigate_to_path);
+
+ ClassDB::bind_method(D_METHOD("add_resource_tooltip_plugin", "plugin"), &FileSystemDock::add_resource_tooltip_plugin);
+ ClassDB::bind_method(D_METHOD("remove_resource_tooltip_plugin", "plugin"), &FileSystemDock::remove_resource_tooltip_plugin);
+
+ ADD_SIGNAL(MethodInfo("inherit", PropertyInfo(Variant::STRING, "file")));
+ ADD_SIGNAL(MethodInfo("instantiate", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files")));
+
+ ADD_SIGNAL(MethodInfo("resource_removed", PropertyInfo(Variant::OBJECT, "resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource")));
+ ADD_SIGNAL(MethodInfo("file_removed", PropertyInfo(Variant::STRING, "file")));
+ ADD_SIGNAL(MethodInfo("folder_removed", PropertyInfo(Variant::STRING, "folder")));
+ ADD_SIGNAL(MethodInfo("files_moved", PropertyInfo(Variant::STRING, "old_file"), PropertyInfo(Variant::STRING, "new_file")));
+ ADD_SIGNAL(MethodInfo("folder_moved", PropertyInfo(Variant::STRING, "old_folder"), PropertyInfo(Variant::STRING, "new_folder")));
+ ADD_SIGNAL(MethodInfo("folder_color_changed"));
+
+ ADD_SIGNAL(MethodInfo("display_mode_changed"));
+}
+
FileSystemDock::FileSystemDock() {
singleton = this;
- set_name("FileSystem");
- current_path = "res://";
+ set_name(TTRC("FileSystem"));
+ set_icon_name("Folder");
+ set_dock_shortcut(ED_SHORTCUT_AND_COMMAND("docks/open_filesystem", TTRC("Open FileSystem Dock"), KeyModifierMask::ALT | Key::F));
+ set_default_slot(EditorDockManager::DOCK_SLOT_LEFT_BR);
+ set_available_layouts(DOCK_LAYOUT_VERTICAL | DOCK_LAYOUT_HORIZONTAL);
ProjectSettings::get_singleton()->add_hidden_prefix("file_customization/");
@@ -4171,8 +4166,11 @@ FileSystemDock::FileSystemDock() {
editor_is_dark_theme = EditorThemeManager::is_dark_theme();
+ VBoxContainer *main_vb = memnew(VBoxContainer);
+ add_child(main_vb);
+
VBoxContainer *top_vbc = memnew(VBoxContainer);
- add_child(top_vbc);
+ main_vb->add_child(top_vbc);
HBoxContainer *toolbar_hbc = memnew(HBoxContainer);
top_vbc->add_child(toolbar_hbc);
@@ -4241,7 +4239,7 @@ FileSystemDock::FileSystemDock() {
split_box->set_v_size_flags(SIZE_EXPAND_FILL);
split_box->connect("dragged", callable_mp(this, &FileSystemDock::_split_dragged));
split_box_offset_h = 240 * EDSCALE;
- add_child(split_box);
+ main_vb->add_child(split_box);
tree = memnew(FileSystemTree);
tree->set_accessibility_name(TTRC("Directories"));
@@ -4305,7 +4303,7 @@ FileSystemDock::FileSystemDock() {
scanning_vb = memnew(VBoxContainer);
scanning_vb->hide();
- add_child(scanning_vb);
+ main_vb->add_child(scanning_vb);
Label *slabel = memnew(Label);
slabel->set_text(TTRC("Scanning Files,\nPlease Wait..."));
diff --git a/editor/docks/filesystem_dock.h b/editor/docks/filesystem_dock.h
index 1be6542bc8f..a5ed30ad346 100644
--- a/editor/docks/filesystem_dock.h
+++ b/editor/docks/filesystem_dock.h
@@ -30,6 +30,7 @@
#pragma once
+#include "editor/docks/editor_dock.h"
#include "editor/file_system/dependency_editor.h"
#include "editor/file_system/editor_file_system.h"
#include "editor/file_system/file_info.h"
@@ -44,6 +45,7 @@
class CreateDialog;
class EditorDirDialog;
+class HBoxContainer;
class ItemList;
class LineEdit;
class ProgressBar;
@@ -51,6 +53,7 @@ class SceneCreateDialog;
class ShaderCreateDialog;
class DirectoryCreateDialog;
class EditorResourceTooltipPlugin;
+class VBoxContainer;
class FileSystemTree : public Tree {
virtual Control *make_custom_tooltip(const String &p_text) const;
@@ -78,8 +81,8 @@ public:
FileSystemList();
};
-class FileSystemDock : public VBoxContainer {
- GDCLASS(FileSystemDock, VBoxContainer);
+class FileSystemDock : public EditorDock {
+ GDCLASS(FileSystemDock, EditorDock);
public:
enum FileListDisplayMode {
@@ -230,7 +233,7 @@ private:
int history_pos;
int history_max_size;
- String current_path;
+ String current_path = "res://";
String select_after_scan;
bool updating_tree = false;
@@ -361,12 +364,6 @@ private:
void _change_bottom_dock_placement();
- bool _can_dock_horizontal() const;
- void _set_dock_horizontal(bool p_enable);
-
- void _save_layout_to_config(Ref p_layout, const String &p_section) const;
- void _load_layout_from_config(Ref p_layout, const String &p_section);
-
private:
inline static FileSystemDock *singleton = nullptr;
@@ -377,6 +374,10 @@ protected:
void _notification(int p_what);
static void _bind_methods();
+ virtual void update_layout(EditorDock::DockLayout p_layout) override;
+ virtual void save_layout_to_config(Ref &p_layout, const String &p_section) const override;
+ virtual void load_layout_from_config(const Ref &p_layout, const String &p_section) override;
+
public:
static constexpr double ITEM_COLOR_SCALE = 1.75;
static constexpr double ITEM_ALPHA_MIN = 0.1;
diff --git a/editor/docks/history_dock.cpp b/editor/docks/history_dock.cpp
index 8e0fed8a3d6..fafad00aefc 100644
--- a/editor/docks/history_dock.cpp
+++ b/editor/docks/history_dock.cpp
@@ -34,6 +34,7 @@
#include "editor/editor_node.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
+#include "editor/settings/editor_command_palette.h"
#include "editor/settings/editor_settings.h"
#include "scene/gui/check_box.h"
#include "scene/gui/item_list.h"
@@ -175,14 +176,14 @@ void HistoryDock::refresh_version() {
action_list->set_current(idx);
}
-void HistoryDock::_save_layout_to_config(Ref p_layout, const String &p_section) const {
- p_layout->set_value(p_section, "dock_history_include_scene", current_scene_checkbox->is_pressed());
- p_layout->set_value(p_section, "dock_history_include_global", global_history_checkbox->is_pressed());
+void HistoryDock::save_layout_to_config(Ref &p_layout, const String &p_section) const {
+ p_layout->set_value(p_section, "include_scene", current_scene_checkbox->is_pressed());
+ p_layout->set_value(p_section, "include_global", global_history_checkbox->is_pressed());
}
-void HistoryDock::_load_layout_from_config(Ref p_layout, const String &p_section) {
- current_scene_checkbox->set_pressed_no_signal(p_layout->get_value(p_section, "dock_history_include_scene", true));
- global_history_checkbox->set_pressed_no_signal(p_layout->get_value(p_section, "dock_history_include_global", true));
+void HistoryDock::load_layout_from_config(const Ref &p_layout, const String &p_section) {
+ current_scene_checkbox->set_pressed_no_signal(p_layout->get_value(p_section, "include_scene", true));
+ global_history_checkbox->set_pressed_no_signal(p_layout->get_value(p_section, "include_global", true));
refresh_history();
}
@@ -234,20 +235,21 @@ void HistoryDock::_notification(int p_notification) {
}
}
-void HistoryDock::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_save_layout_to_config"), &HistoryDock::_save_layout_to_config);
- ClassDB::bind_method(D_METHOD("_load_layout_from_config"), &HistoryDock::_load_layout_from_config);
-}
-
HistoryDock::HistoryDock() {
- set_name("History");
+ set_name(TTRC("History"));
+ set_icon_name("History");
+ set_dock_shortcut(ED_SHORTCUT_AND_COMMAND("docks/open_history", TTRC("Open History Dock")));
+ set_default_slot(EditorDockManager::DOCK_SLOT_RIGHT_UL);
ur_manager = EditorUndoRedoManager::get_singleton();
ur_manager->connect("history_changed", callable_mp(this, &HistoryDock::on_history_changed));
ur_manager->connect("version_changed", callable_mp(this, &HistoryDock::on_version_changed));
+ VBoxContainer *main_vb = memnew(VBoxContainer);
+ add_child(main_vb);
+
HBoxContainer *mode_hb = memnew(HBoxContainer);
- add_child(mode_hb);
+ main_vb->add_child(mode_hb);
current_scene_checkbox = memnew(CheckBox);
mode_hb->add_child(current_scene_checkbox);
@@ -269,7 +271,7 @@ HistoryDock::HistoryDock() {
action_list = memnew(ItemList);
action_list->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
- add_child(action_list);
+ main_vb->add_child(action_list);
action_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
action_list->connect(SceneStringName(item_selected), callable_mp(this, &HistoryDock::seek_history));
}
diff --git a/editor/docks/history_dock.h b/editor/docks/history_dock.h
index 4f435d16d9c..0c1604be53d 100644
--- a/editor/docks/history_dock.h
+++ b/editor/docks/history_dock.h
@@ -30,15 +30,15 @@
#pragma once
-#include "scene/gui/box_container.h"
+#include "editor/docks/editor_dock.h"
class CheckBox;
class ConfigFile;
class ItemList;
class EditorUndoRedoManager;
-class HistoryDock : public VBoxContainer {
- GDCLASS(HistoryDock, VBoxContainer);
+class HistoryDock : public EditorDock {
+ GDCLASS(HistoryDock, EditorDock);
EditorUndoRedoManager *ur_manager;
ItemList *action_list = nullptr;
@@ -54,12 +54,11 @@ class HistoryDock : public VBoxContainer {
void on_version_changed();
void refresh_version();
- void _save_layout_to_config(Ref p_layout, const String &p_section) const;
- void _load_layout_from_config(Ref p_layout, const String &p_section);
-
protected:
void _notification(int p_notification);
- static void _bind_methods();
+
+ virtual void save_layout_to_config(Ref &p_layout, const String &p_section) const override;
+ virtual void load_layout_from_config(const Ref &p_layout, const String &p_section) override;
public:
void seek_history(int p_index);
diff --git a/editor/docks/import_dock.cpp b/editor/docks/import_dock.cpp
index 279e846089c..f434f8a2d20 100644
--- a/editor/docks/import_dock.cpp
+++ b/editor/docks/import_dock.cpp
@@ -35,9 +35,11 @@
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/inspector/editor_resource_preview.h"
+#include "editor/settings/editor_command_palette.h"
#include "editor/settings/editor_settings.h"
#include "editor/themes/editor_scale.h"
#include "editor/themes/editor_theme_manager.h"
+#include "scene/gui/box_container.h"
class ImportDockParameters : public Object {
GDCLASS(ImportDockParameters, Object);
@@ -742,11 +744,17 @@ void ImportDock::initialize_import_options() const {
ImportDock::ImportDock() {
singleton = this;
- set_name("Import");
+ set_name(TTRC("Import"));
+ set_icon_name("FileAccess");
+ set_dock_shortcut(ED_SHORTCUT_AND_COMMAND("docks/open_import", TTRC("Open Import Dock")));
+ set_default_slot(EditorDockManager::DOCK_SLOT_LEFT_UR);
+
+ VBoxContainer *main_vb = memnew(VBoxContainer);
+ add_child(main_vb);
content = memnew(VBoxContainer);
content->set_v_size_flags(SIZE_EXPAND_FILL);
- add_child(content);
+ main_vb->add_child(content);
content->hide();
imported = memnew(Label);
@@ -819,7 +827,7 @@ ImportDock::ImportDock() {
select_a_resource->set_v_size_flags(SIZE_EXPAND_FILL);
select_a_resource->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
select_a_resource->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
- add_child(select_a_resource);
+ main_vb->add_child(select_a_resource);
}
ImportDock::~ImportDock() {
diff --git a/editor/docks/import_dock.h b/editor/docks/import_dock.h
index 94a36841f7d..8f0b69ad70a 100644
--- a/editor/docks/import_dock.h
+++ b/editor/docks/import_dock.h
@@ -32,6 +32,7 @@
#include "core/io/config_file.h"
#include "core/io/resource_importer.h"
+#include "editor/docks/editor_dock.h"
#include "editor/file_system/editor_file_system.h"
#include "editor/inspector/editor_inspector.h"
#include "scene/gui/box_container.h"
@@ -41,8 +42,10 @@
#include "scene/gui/popup_menu.h"
class ImportDockParameters;
-class ImportDock : public VBoxContainer {
- GDCLASS(ImportDock, VBoxContainer);
+class VBoxContainer;
+
+class ImportDock : public EditorDock {
+ GDCLASS(ImportDock, EditorDock);
Label *imported = nullptr;
OptionButton *import_as = nullptr;
diff --git a/editor/docks/inspector_dock.cpp b/editor/docks/inspector_dock.cpp
index fd994121e59..2e5185b8e76 100644
--- a/editor/docks/inspector_dock.cpp
+++ b/editor/docks/inspector_dock.cpp
@@ -40,10 +40,10 @@
#include "editor/gui/editor_file_dialog.h"
#include "editor/gui/editor_object_selector.h"
#include "editor/script/script_editor_plugin.h"
+#include "editor/settings/editor_command_palette.h"
#include "editor/settings/editor_settings.h"
#include "editor/themes/editor_scale.h"
-
-InspectorDock *InspectorDock::singleton = nullptr;
+#include "scene/gui/box_container.h"
void InspectorDock::_prepare_menu() {
PopupMenu *menu = object_menu->get_popup();
@@ -707,14 +707,20 @@ void InspectorDock::shortcut_input(const Ref &p_event) {
InspectorDock::InspectorDock(EditorData &p_editor_data) {
singleton = this;
- set_name("Inspector");
+ set_name(TTRC("Inspector"));
+ set_icon_name("AnimationTrackList");
+ set_dock_shortcut(ED_SHORTCUT_AND_COMMAND("docks/open_inspector", TTRC("Open Inspector Dock")));
+ set_default_slot(EditorDockManager::DOCK_SLOT_RIGHT_UL);
+
+ VBoxContainer *main_vb = memnew(VBoxContainer);
+ add_child(main_vb);
editor_data = &p_editor_data;
property_name_style = EditorPropertyNameProcessor::get_default_inspector_style();
HBoxContainer *general_options_hb = memnew(HBoxContainer);
- add_child(general_options_hb);
+ main_vb->add_child(general_options_hb);
resource_new_button = memnew(Button);
resource_new_button->set_theme_type_variation("FlatMenuButton");
@@ -782,7 +788,7 @@ InspectorDock::InspectorDock(EditorData &p_editor_data) {
history_menu->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &InspectorDock::_select_history));
HBoxContainer *subresource_hb = memnew(HBoxContainer);
- add_child(subresource_hb);
+ main_vb->add_child(subresource_hb);
object_selector = memnew(EditorObjectSelector(EditorNode::get_singleton()->get_editor_selection_history()));
object_selector->set_h_size_flags(Control::SIZE_EXPAND_FILL);
subresource_hb->add_child(object_selector);
@@ -801,7 +807,7 @@ InspectorDock::InspectorDock(EditorData &p_editor_data) {
new_resource_dialog->connect("create", callable_mp(this, &InspectorDock::_resource_created));
HBoxContainer *property_tools_hb = memnew(HBoxContainer);
- add_child(property_tools_hb);
+ main_vb->add_child(property_tools_hb);
search = memnew(LineEdit);
search->set_h_size_flags(Control::SIZE_EXPAND_FILL);
@@ -818,14 +824,14 @@ InspectorDock::InspectorDock(EditorData &p_editor_data) {
object_menu->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &InspectorDock::_menu_option));
info = memnew(Button);
- add_child(info);
+ main_vb->add_child(info);
info->set_clip_text(true);
info->set_accessibility_name(TTRC("Information"));
info->hide();
info->connect(SceneStringName(pressed), callable_mp(this, &InspectorDock::_info_pressed));
unique_resources_confirmation = memnew(ConfirmationDialog);
- add_child(unique_resources_confirmation);
+ main_vb->add_child(unique_resources_confirmation);
VBoxContainer *container = memnew(VBoxContainer);
unique_resources_confirmation->add_child(container);
@@ -852,12 +858,12 @@ InspectorDock::InspectorDock(EditorData &p_editor_data) {
EditorNode::get_singleton()->get_gui_base()->add_child(info_dialog);
load_resource_dialog = memnew(EditorFileDialog);
- add_child(load_resource_dialog);
+ main_vb->add_child(load_resource_dialog);
load_resource_dialog->set_current_dir("res://");
load_resource_dialog->connect("file_selected", callable_mp(this, &InspectorDock::_resource_file_selected));
inspector = memnew(EditorInspector);
- add_child(inspector);
+ main_vb->add_child(inspector);
inspector->set_autoclear(true);
inspector->set_show_categories(true, true);
inspector->set_v_size_flags(Control::SIZE_EXPAND_FILL);
diff --git a/editor/docks/inspector_dock.h b/editor/docks/inspector_dock.h
index 3627d23963b..55eff2a4f1a 100644
--- a/editor/docks/inspector_dock.h
+++ b/editor/docks/inspector_dock.h
@@ -30,6 +30,7 @@
#pragma once
+#include "editor/docks/editor_dock.h"
#include "editor/editor_data.h"
#include "editor/gui/create_dialog.h"
#include "editor/inspector/editor_inspector.h"
@@ -43,8 +44,8 @@
class EditorFileDialog;
class EditorObjectSelector;
-class InspectorDock : public VBoxContainer {
- GDCLASS(InspectorDock, VBoxContainer);
+class InspectorDock : public EditorDock {
+ GDCLASS(InspectorDock, EditorDock);
enum MenuOptions {
RESOURCE_LOAD,
@@ -136,7 +137,7 @@ class InspectorDock : public VBoxContainer {
virtual void shortcut_input(const Ref &p_event) override;
private:
- static InspectorDock *singleton;
+ static inline InspectorDock *singleton = nullptr;
public:
static InspectorDock *get_singleton() { return singleton; }
diff --git a/editor/docks/node_dock.cpp b/editor/docks/node_dock.cpp
index 12bcbcda3f0..1f02d87e57b 100644
--- a/editor/docks/node_dock.cpp
+++ b/editor/docks/node_dock.cpp
@@ -32,6 +32,7 @@
#include "core/io/config_file.h"
#include "editor/scene/connections_dialog.h"
+#include "editor/settings/editor_command_palette.h"
#include "editor/themes/editor_scale.h"
void NodeDock::show_groups() {
@@ -48,12 +49,12 @@ void NodeDock::show_connections() {
connections->show();
}
-void NodeDock::_save_layout_to_config(Ref p_layout, const String &p_section) const {
- p_layout->set_value(p_section, "dock_node_current_tab", int(groups_button->is_pressed()));
+void NodeDock::save_layout_to_config(Ref &p_layout, const String &p_section) const {
+ p_layout->set_value(p_section, "current_tab", int(groups_button->is_pressed()));
}
-void NodeDock::_load_layout_from_config(Ref p_layout, const String &p_section) {
- const int current_tab = p_layout->get_value(p_section, "dock_node_current_tab", 0);
+void NodeDock::load_layout_from_config(const Ref &p_layout, const String &p_section) {
+ const int current_tab = p_layout->get_value(p_section, "current_tab", 0);
if (select_a_node->is_visible()) {
if (current_tab == 0) {
groups_button->set_pressed_no_signal(false);
@@ -78,11 +79,6 @@ void NodeDock::_notification(int p_what) {
}
}
-void NodeDock::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_save_layout_to_config"), &NodeDock::_save_layout_to_config);
- ClassDB::bind_method(D_METHOD("_load_layout_from_config"), &NodeDock::_load_layout_from_config);
-}
-
void NodeDock::update_lists() {
connections->update_tree();
}
@@ -110,10 +106,16 @@ void NodeDock::set_node(Node *p_node) {
NodeDock::NodeDock() {
singleton = this;
+ set_name(TTRC("Node"));
+ set_icon_name("Object");
+ set_dock_shortcut(ED_SHORTCUT_AND_COMMAND("docks/open_node", TTRC("Open Node Dock")));
+ set_default_slot(EditorDockManager::DOCK_SLOT_RIGHT_UL);
+
+ VBoxContainer *main_vb = memnew(VBoxContainer);
+ add_child(main_vb);
- set_name("Node");
mode_hb = memnew(HBoxContainer);
- add_child(mode_hb);
+ main_vb->add_child(mode_hb);
mode_hb->hide();
connections_button = memnew(Button);
@@ -137,12 +139,12 @@ NodeDock::NodeDock() {
groups_button->connect(SceneStringName(pressed), callable_mp(this, &NodeDock::show_groups));
connections = memnew(ConnectionsDock);
- add_child(connections);
+ main_vb->add_child(connections);
connections->set_v_size_flags(SIZE_EXPAND_FILL);
connections->hide();
groups = memnew(GroupsEditor);
- add_child(groups);
+ main_vb->add_child(groups);
groups->set_v_size_flags(SIZE_EXPAND_FILL);
groups->hide();
@@ -154,7 +156,7 @@ NodeDock::NodeDock() {
select_a_node->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
select_a_node->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
select_a_node->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
- add_child(select_a_node);
+ main_vb->add_child(select_a_node);
}
NodeDock::~NodeDock() {
diff --git a/editor/docks/node_dock.h b/editor/docks/node_dock.h
index c27de1cd2b5..cf7a67cb39d 100644
--- a/editor/docks/node_dock.h
+++ b/editor/docks/node_dock.h
@@ -30,13 +30,14 @@
#pragma once
+#include "editor/docks/editor_dock.h"
#include "groups_editor.h"
class ConfigFile;
class ConnectionsDock;
-class NodeDock : public VBoxContainer {
- GDCLASS(NodeDock, VBoxContainer);
+class NodeDock : public EditorDock {
+ GDCLASS(NodeDock, EditorDock);
Button *connections_button = nullptr;
Button *groups_button = nullptr;
@@ -48,9 +49,6 @@ class NodeDock : public VBoxContainer {
Label *select_a_node = nullptr;
- void _save_layout_to_config(Ref p_layout, const String &p_section) const;
- void _load_layout_from_config(Ref p_layout, const String &p_section);
-
private:
inline static NodeDock *singleton = nullptr;
@@ -59,7 +57,9 @@ public:
protected:
void _notification(int p_what);
- static void _bind_methods();
+
+ virtual void save_layout_to_config(Ref &p_layout, const String &p_section) const override;
+ virtual void load_layout_from_config(const Ref &p_layout, const String &p_section) override;
public:
void set_node(Node *p_node);
diff --git a/editor/docks/scene_tree_dock.cpp b/editor/docks/scene_tree_dock.cpp
index fe9502b5a01..d4a66f0425c 100644
--- a/editor/docks/scene_tree_dock.cpp
+++ b/editor/docks/scene_tree_dock.cpp
@@ -55,6 +55,7 @@
#include "editor/scene/rename_dialog.h"
#include "editor/scene/reparent_dialog.h"
#include "editor/script/script_editor_plugin.h"
+#include "editor/settings/editor_command_palette.h"
#include "editor/settings/editor_feature_profile.h"
#include "editor/settings/editor_settings.h"
#include "editor/shader/shader_create_dialog.h"
@@ -62,6 +63,7 @@
#include "scene/2d/node_2d.h"
#include "scene/animation/animation_tree.h"
#include "scene/audio/audio_stream_player.h"
+#include "scene/gui/box_container.h"
#include "scene/gui/check_box.h"
#include "scene/property_utils.h"
#include "scene/resources/packed_scene.h"
@@ -4689,13 +4691,18 @@ void SceneTreeDock::_update_configuration_warning() {
}
SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selection, EditorData &p_editor_data) {
+ set_name(TTRC("Scene"));
+ set_icon_name("PackedScene");
+ set_dock_shortcut(ED_SHORTCUT_AND_COMMAND("docks/open_scene", TTRC("Open Scene Dock")));
+ set_default_slot(EditorDockManager::DOCK_SLOT_LEFT_UR);
+
singleton = this;
- set_name("Scene");
editor_data = &p_editor_data;
editor_selection = p_editor_selection;
scene_root = p_scene_root;
- VBoxContainer *vbc = this;
+ VBoxContainer *vbc = memnew(VBoxContainer);
+ add_child(vbc);
HBoxContainer *filter_hbc = memnew(HBoxContainer);
filter_hbc->add_theme_constant_override("separate", 0);
diff --git a/editor/docks/scene_tree_dock.h b/editor/docks/scene_tree_dock.h
index 4425a895c92..9804189a2e5 100644
--- a/editor/docks/scene_tree_dock.h
+++ b/editor/docks/scene_tree_dock.h
@@ -30,22 +30,24 @@
#pragma once
+#include "editor/docks/editor_dock.h"
#include "editor/scene/scene_tree_editor.h"
#include "editor/script/script_create_dialog.h"
-#include "scene/gui/box_container.h"
#include "scene/resources/animation.h"
class CheckBox;
class EditorData;
class EditorSelection;
+class HBoxContainer;
class MenuButton;
class RenameDialog;
class ReparentDialog;
class ShaderCreateDialog;
class TextureRect;
+class VBoxContainer;
-class SceneTreeDock : public VBoxContainer {
- GDCLASS(SceneTreeDock, VBoxContainer);
+class SceneTreeDock : public EditorDock {
+ GDCLASS(SceneTreeDock, EditorDock);
enum Tool {
TOOL_NEW,
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index e268872beb8..bc35e8556d8 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -6070,9 +6070,14 @@ void EditorNode::_update_layouts_menu() {
}
Vector layouts = config->get_sections();
+ const String default_layout_name = TTR("Default");
for (const String &layout : layouts) {
- if (layout == TTR("Default")) {
+ if (layout.contains_char('/')) {
+ continue;
+ }
+
+ if (layout == default_layout_name) {
editor_layouts->remove_item(editor_layouts->get_item_index(LAYOUT_DEFAULT));
overridden_default_layout = editor_layouts->get_item_count();
}
@@ -8383,36 +8388,26 @@ EditorNode::EditorNode() {
// Instantiate and place editor docks.
memnew(SceneTreeDock(scene_root, editor_selection, editor_data));
- memnew(FileSystemDock);
- memnew(InspectorDock(editor_data));
- memnew(ImportDock);
- memnew(NodeDock);
+ editor_dock_manager->add_dock(SceneTreeDock::get_singleton());
- FileSystemDock *filesystem_dock = FileSystemDock::get_singleton();
+ memnew(ImportDock);
+ editor_dock_manager->add_dock(ImportDock::get_singleton());
+
+ FileSystemDock *filesystem_dock = memnew(FileSystemDock);
filesystem_dock->connect("inherit", callable_mp(this, &EditorNode::_inherit_request));
filesystem_dock->connect("instantiate", callable_mp(this, &EditorNode::_instantiate_request));
filesystem_dock->connect("display_mode_changed", callable_mp(this, &EditorNode::_save_editor_layout));
get_project_settings()->connect_filesystem_dock_signals(filesystem_dock);
+ editor_dock_manager->add_dock(filesystem_dock);
+
+ memnew(InspectorDock(editor_data));
+ editor_dock_manager->add_dock(InspectorDock::get_singleton());
+
+ memnew(NodeDock);
+ editor_dock_manager->add_dock(NodeDock::get_singleton());
history_dock = memnew(HistoryDock);
-
- // Scene: Top left.
- editor_dock_manager->add_dock(SceneTreeDock::get_singleton(), TTRC("Scene"), EditorDockManager::DOCK_SLOT_LEFT_UR, ED_SHORTCUT_AND_COMMAND("docks/open_scene", TTRC("Open Scene Dock")), "PackedScene");
-
- // Import: Top left, behind Scene.
- editor_dock_manager->add_dock(ImportDock::get_singleton(), TTRC("Import"), EditorDockManager::DOCK_SLOT_LEFT_UR, ED_SHORTCUT_AND_COMMAND("docks/open_import", TTRC("Open Import Dock")), "FileAccess");
-
- // FileSystem: Bottom left.
- editor_dock_manager->add_dock(FileSystemDock::get_singleton(), TTRC("FileSystem"), EditorDockManager::DOCK_SLOT_LEFT_BR, ED_SHORTCUT_AND_COMMAND("docks/open_filesystem", TTRC("Open FileSystem Dock"), KeyModifierMask::ALT | Key::F), "Folder");
-
- // Inspector: Full height right.
- editor_dock_manager->add_dock(InspectorDock::get_singleton(), TTRC("Inspector"), EditorDockManager::DOCK_SLOT_RIGHT_UL, ED_SHORTCUT_AND_COMMAND("docks/open_inspector", TTRC("Open Inspector Dock")), "AnimationTrackList");
-
- // Node: Full height right, behind Inspector.
- editor_dock_manager->add_dock(NodeDock::get_singleton(), TTRC("Node"), EditorDockManager::DOCK_SLOT_RIGHT_UL, ED_SHORTCUT_AND_COMMAND("docks/open_node", TTRC("Open Node Dock")), "Object");
-
- // History: Full height right, behind Node.
- editor_dock_manager->add_dock(history_dock, TTRC("History"), EditorDockManager::DOCK_SLOT_RIGHT_UL, ED_SHORTCUT_AND_COMMAND("docks/open_history", TTRC("Open History Dock")), "History");
+ editor_dock_manager->add_dock(history_dock);
// Add some offsets to left_r and main hsplits to make LEFT_R and RIGHT_L docks wider than minsize.
left_r_hsplit->set_split_offset(270 * EDSCALE);
diff --git a/editor/plugins/editor_plugin.cpp b/editor/plugins/editor_plugin.cpp
index e2567221363..bab001ba9cf 100644
--- a/editor/plugins/editor_plugin.cpp
+++ b/editor/plugins/editor_plugin.cpp
@@ -33,6 +33,7 @@
#include "editor/debugger/editor_debugger_node.h"
#include "editor/debugger/editor_debugger_plugin.h"
+#include "editor/docks/editor_dock.h"
#include "editor/docks/editor_dock_manager.h"
#include "editor/docks/inspector_dock.h"
#include "editor/docks/scene_tree_dock.h"
@@ -84,24 +85,48 @@ Button *EditorPlugin::add_control_to_bottom_panel(Control *p_control, const Stri
return EditorNode::get_bottom_panel()->add_item(p_title, p_control, p_shortcut);
}
+#ifndef DISABLE_DEPRECATED
void EditorPlugin::add_control_to_dock(DockSlot p_slot, Control *p_control, const Ref &p_shortcut) {
ERR_FAIL_NULL(p_control);
- EditorDockManager::get_singleton()->add_dock(p_control, String(), EditorDockManager::DockSlot(p_slot), p_shortcut);
+ ERR_FAIL_COND(legacy_docks.has(p_control));
+
+ EditorDock *dock = memnew(EditorDock);
+ dock->set_title(p_control->get_name());
+ dock->set_dock_shortcut(p_shortcut);
+ dock->set_default_slot((EditorDockManager::DockSlot)p_slot);
+ dock->add_child(p_control);
+ legacy_docks[p_control] = dock;
+
+ EditorDockManager::get_singleton()->add_dock(dock);
}
void EditorPlugin::remove_control_from_docks(Control *p_control) {
ERR_FAIL_NULL(p_control);
- EditorDockManager::get_singleton()->remove_dock(p_control);
+ ERR_FAIL_COND(!legacy_docks.has(p_control));
+
+ EditorDockManager::get_singleton()->remove_dock(legacy_docks[p_control]);
+ legacy_docks[p_control]->queue_free();
+ legacy_docks.erase(p_control);
}
+void EditorPlugin::set_dock_tab_icon(Control *p_control, const Ref &p_icon) {
+ ERR_FAIL_NULL(p_control);
+ ERR_FAIL_COND(!legacy_docks.has(p_control));
+ legacy_docks[p_control]->set_dock_icon(p_icon);
+}
+#endif
+
void EditorPlugin::remove_control_from_bottom_panel(Control *p_control) {
ERR_FAIL_NULL(p_control);
EditorNode::get_bottom_panel()->remove_item(p_control);
}
-void EditorPlugin::set_dock_tab_icon(Control *p_control, const Ref &p_icon) {
- ERR_FAIL_NULL(p_control);
- EditorDockManager::get_singleton()->set_dock_tab_icon(p_control, p_icon);
+void EditorPlugin::add_dock(EditorDock *p_dock) {
+ EditorDockManager::get_singleton()->add_dock(p_dock);
+}
+
+void EditorPlugin::remove_dock(EditorDock *p_dock) {
+ EditorDockManager::get_singleton()->remove_dock(p_dock);
}
void EditorPlugin::add_control_to_container(CustomControlContainer p_location, Control *p_control) {
@@ -588,13 +613,12 @@ void EditorPlugin::_notification(int p_what) {
}
void EditorPlugin::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("add_dock", "dock"), &EditorPlugin::add_dock);
+ ClassDB::bind_method(D_METHOD("remove_dock", "dock"), &EditorPlugin::remove_dock);
ClassDB::bind_method(D_METHOD("add_control_to_container", "container", "control"), &EditorPlugin::add_control_to_container);
ClassDB::bind_method(D_METHOD("add_control_to_bottom_panel", "control", "title", "shortcut"), &EditorPlugin::add_control_to_bottom_panel, DEFVAL(Ref()));
- ClassDB::bind_method(D_METHOD("add_control_to_dock", "slot", "control", "shortcut"), &EditorPlugin::add_control_to_dock, DEFVAL(Ref()));
- ClassDB::bind_method(D_METHOD("remove_control_from_docks", "control"), &EditorPlugin::remove_control_from_docks);
ClassDB::bind_method(D_METHOD("remove_control_from_bottom_panel", "control"), &EditorPlugin::remove_control_from_bottom_panel);
ClassDB::bind_method(D_METHOD("remove_control_from_container", "container", "control"), &EditorPlugin::remove_control_from_container);
- ClassDB::bind_method(D_METHOD("set_dock_tab_icon", "control", "icon"), &EditorPlugin::set_dock_tab_icon);
ClassDB::bind_method(D_METHOD("add_tool_menu_item", "name", "callable"), &EditorPlugin::add_tool_menu_item);
ClassDB::bind_method(D_METHOD("add_tool_submenu_item", "name", "submenu"), &EditorPlugin::add_tool_submenu_item);
ClassDB::bind_method(D_METHOD("remove_tool_menu_item", "name"), &EditorPlugin::remove_tool_menu_item);
@@ -602,6 +626,12 @@ void EditorPlugin::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_custom_type", "type", "base", "script", "icon"), &EditorPlugin::add_custom_type);
ClassDB::bind_method(D_METHOD("remove_custom_type", "type"), &EditorPlugin::remove_custom_type);
+#ifndef DISABLE_DEPRECATED
+ ClassDB::bind_method(D_METHOD("add_control_to_dock", "slot", "control", "shortcut"), &EditorPlugin::add_control_to_dock, DEFVAL(Ref()));
+ ClassDB::bind_method(D_METHOD("remove_control_from_docks", "control"), &EditorPlugin::remove_control_from_docks);
+ ClassDB::bind_method(D_METHOD("set_dock_tab_icon", "control", "icon"), &EditorPlugin::set_dock_tab_icon);
+#endif
+
ClassDB::bind_method(D_METHOD("add_autoload_singleton", "name", "path"), &EditorPlugin::add_autoload_singleton);
ClassDB::bind_method(D_METHOD("remove_autoload_singleton", "name"), &EditorPlugin::remove_autoload_singleton);
@@ -688,6 +718,7 @@ void EditorPlugin::_bind_methods() {
BIND_ENUM_CONSTANT(CONTAINER_PROJECT_SETTING_TAB_LEFT);
BIND_ENUM_CONSTANT(CONTAINER_PROJECT_SETTING_TAB_RIGHT);
+ BIND_ENUM_CONSTANT(DOCK_SLOT_NONE);
BIND_ENUM_CONSTANT(DOCK_SLOT_LEFT_UL);
BIND_ENUM_CONSTANT(DOCK_SLOT_LEFT_BL);
BIND_ENUM_CONSTANT(DOCK_SLOT_LEFT_UR);
diff --git a/editor/plugins/editor_plugin.h b/editor/plugins/editor_plugin.h
index 70e247f0bdb..2f1396e5648 100644
--- a/editor/plugins/editor_plugin.h
+++ b/editor/plugins/editor_plugin.h
@@ -31,6 +31,7 @@
#pragma once
#include "core/io/config_file.h"
+#include "editor/docks/editor_dock_manager.h"
#include "editor/inspector/editor_context_menu_plugin.h"
#include "scene/3d/camera_3d.h"
#include "scene/gui/control.h"
@@ -39,6 +40,7 @@ class Node3D;
class Button;
class PopupMenu;
class EditorDebuggerPlugin;
+class EditorDock;
class EditorExport;
class EditorExportPlugin;
class EditorExportPlatform;
@@ -65,6 +67,8 @@ class EditorPlugin : public Node {
String plugin_version;
#ifndef DISABLE_DEPRECATED
+ static inline HashMap legacy_docks;
+
void _editor_project_settings_changed();
#endif
@@ -85,15 +89,16 @@ public:
};
enum DockSlot {
- DOCK_SLOT_LEFT_UL,
- DOCK_SLOT_LEFT_BL,
- DOCK_SLOT_LEFT_UR,
- DOCK_SLOT_LEFT_BR,
- DOCK_SLOT_RIGHT_UL,
- DOCK_SLOT_RIGHT_BL,
- DOCK_SLOT_RIGHT_UR,
- DOCK_SLOT_RIGHT_BR,
- DOCK_SLOT_MAX
+ DOCK_SLOT_NONE = EditorDockManager::DOCK_SLOT_NONE,
+ DOCK_SLOT_LEFT_UL = EditorDockManager::DOCK_SLOT_LEFT_UL,
+ DOCK_SLOT_LEFT_BL = EditorDockManager::DOCK_SLOT_LEFT_BL,
+ DOCK_SLOT_LEFT_UR = EditorDockManager::DOCK_SLOT_LEFT_UR,
+ DOCK_SLOT_LEFT_BR = EditorDockManager::DOCK_SLOT_LEFT_BR,
+ DOCK_SLOT_RIGHT_UL = EditorDockManager::DOCK_SLOT_RIGHT_UL,
+ DOCK_SLOT_RIGHT_BL = EditorDockManager::DOCK_SLOT_RIGHT_BL,
+ DOCK_SLOT_RIGHT_UR = EditorDockManager::DOCK_SLOT_RIGHT_UR,
+ DOCK_SLOT_RIGHT_BR = EditorDockManager::DOCK_SLOT_RIGHT_BR,
+ DOCK_SLOT_MAX = EditorDockManager::DOCK_SLOT_MAX
};
enum AfterGUIInput {
@@ -140,6 +145,10 @@ protected:
Button *_add_control_to_bottom_panel_compat_88081(Control *p_control, const String &p_title);
void _add_control_to_dock_compat_88081(DockSlot p_slot, Control *p_control);
static void _bind_compatibility_methods();
+
+ void add_control_to_dock(DockSlot p_slot, Control *p_control, const Ref &p_shortcut = nullptr);
+ void remove_control_from_docks(Control *p_control);
+ void set_dock_tab_icon(Control *p_control, const Ref &p_icon);
#endif
public:
@@ -148,11 +157,10 @@ public:
void add_control_to_container(CustomControlContainer p_location, Control *p_control);
void remove_control_from_container(CustomControlContainer p_location, Control *p_control);
Button *add_control_to_bottom_panel(Control *p_control, const String &p_title, const Ref &p_shortcut = nullptr);
- void add_control_to_dock(DockSlot p_slot, Control *p_control, const Ref &p_shortcut = nullptr);
- void remove_control_from_docks(Control *p_control);
void remove_control_from_bottom_panel(Control *p_control);
- void set_dock_tab_icon(Control *p_control, const Ref &p_icon);
+ void add_dock(EditorDock *p_dock);
+ void remove_dock(EditorDock *p_dock);
void add_tool_menu_item(const String &p_name, const Callable &p_callable);
void add_tool_submenu_item(const String &p_name, PopupMenu *p_submenu);
diff --git a/editor/register_editor_types.cpp b/editor/register_editor_types.cpp
index f3e1aa86980..1029ec28eb6 100644
--- a/editor/register_editor_types.cpp
+++ b/editor/register_editor_types.cpp
@@ -146,6 +146,7 @@ void register_editor_types() {
GDREGISTER_CLASS(EditorTranslationParserPlugin);
GDREGISTER_CLASS(EditorImportPlugin);
GDREGISTER_CLASS(EditorScript);
+ GDREGISTER_CLASS(EditorDock);
GDREGISTER_CLASS(EditorSelection);
GDREGISTER_CLASS(EditorFileDialog);
GDREGISTER_CLASS(EditorSettings);
diff --git a/editor/settings/editor_layouts_dialog.cpp b/editor/settings/editor_layouts_dialog.cpp
index 46c0e2b9a93..44db265e0b4 100644
--- a/editor/settings/editor_layouts_dialog.cpp
+++ b/editor/settings/editor_layouts_dialog.cpp
@@ -98,7 +98,9 @@ void EditorLayoutsDialog::_post_popup() {
Vector layouts = config->get_sections();
for (const String &E : layouts) {
- layout_names->add_item(E);
+ if (!E.contains_char('/')) {
+ layout_names->add_item(E);
+ }
}
if (name->is_visible()) {
name->grab_focus();
diff --git a/editor/version_control/version_control_editor_plugin.cpp b/editor/version_control/version_control_editor_plugin.cpp
index 6d7f4a0beef..b9b44313ccf 100644
--- a/editor/version_control/version_control_editor_plugin.cpp
+++ b/editor/version_control/version_control_editor_plugin.cpp
@@ -33,6 +33,7 @@
#include "core/config/project_settings.h"
#include "core/os/keyboard.h"
#include "core/os/time.h"
+#include "editor/docks/editor_dock.h"
#include "editor/docks/editor_dock_manager.h"
#include "editor/docks/filesystem_dock.h"
#include "editor/editor_interface.h"
@@ -907,7 +908,7 @@ void VersionControlEditorPlugin::fetch_available_vcs_plugin_names() {
}
void VersionControlEditorPlugin::register_editor() {
- EditorDockManager::get_singleton()->add_dock(version_commit_dock, "", EditorDockManager::DOCK_SLOT_RIGHT_UL, ED_SHORTCUT_AND_COMMAND("docks/open_version_control", TTRC("Open Version Control Dock")));
+ EditorDockManager::get_singleton()->add_dock(version_commit_dock);
version_control_dock_button = EditorNode::get_bottom_panel()->add_item(TTRC("Version Control"), version_control_dock, ED_SHORTCUT_AND_COMMAND("bottom_panels/toggle_version_control_bottom_panel", TTRC("Toggle Version Control Bottom Panel")));
@@ -1144,14 +1145,21 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
set_up_warning_text->set_h_size_flags(Control::SIZE_EXPAND_FILL);
set_up_settings_vbc->add_child(set_up_warning_text);
- version_commit_dock = memnew(VBoxContainer);
+ version_commit_dock = memnew(EditorDock);
version_commit_dock->set_visible(false);
- version_commit_dock->set_name(TTR("Commit"));
+ version_commit_dock->set_name(TTRC("Commit"));
+ version_commit_dock->set_layout_key("VersionCommit");
+ version_commit_dock->set_icon_name("VcsBranches");
+ version_commit_dock->set_dock_shortcut(ED_SHORTCUT_AND_COMMAND("docks/open_version_control", TTRC("Open Version Control Dock")));
+ version_commit_dock->set_default_slot(EditorDockManager::DOCK_SLOT_RIGHT_UL);
+
+ VBoxContainer *dock_vb = memnew(VBoxContainer);
+ version_commit_dock->add_child(dock_vb);
VBoxContainer *unstage_area = memnew(VBoxContainer);
unstage_area->set_v_size_flags(Control::SIZE_EXPAND_FILL);
unstage_area->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- version_commit_dock->add_child(unstage_area);
+ dock_vb->add_child(unstage_area);
HBoxContainer *unstage_title = memnew(HBoxContainer);
unstage_area->add_child(unstage_title);
@@ -1178,7 +1186,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
discard_all_confirm->set_hide_on_ok(true);
discard_all_confirm->set_ok_button_text(TTR("Permanentally delete my changes"));
discard_all_confirm->add_cancel_button();
- version_commit_dock->add_child(discard_all_confirm);
+ dock_vb->add_child(discard_all_confirm);
discard_all_confirm->get_ok_button()->connect(SceneStringName(pressed), callable_mp(this, &VersionControlEditorPlugin::_discard_all));
@@ -1210,7 +1218,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
VBoxContainer *stage_area = memnew(VBoxContainer);
stage_area->set_v_size_flags(Control::SIZE_EXPAND_FILL);
stage_area->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- version_commit_dock->add_child(stage_area);
+ dock_vb->add_child(stage_area);
HBoxContainer *stage_title = memnew(HBoxContainer);
stage_area->add_child(stage_title);
@@ -1242,10 +1250,10 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
unstage_all_button->connect(SceneStringName(pressed), callable_mp(this, &VersionControlEditorPlugin::_move_all).bind(staged_files));
stage_all_button->connect(SceneStringName(pressed), callable_mp(this, &VersionControlEditorPlugin::_move_all).bind(unstaged_files));
- version_commit_dock->add_child(memnew(HSeparator));
+ dock_vb->add_child(memnew(HSeparator));
VBoxContainer *commit_area = memnew(VBoxContainer);
- version_commit_dock->add_child(commit_area);
+ dock_vb->add_child(commit_area);
Label *commit_label = memnew(Label);
commit_label->set_text(TTR("Commit Message"));
@@ -1271,10 +1279,10 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
commit_button->connect(SceneStringName(pressed), callable_mp(this, &VersionControlEditorPlugin::_commit));
commit_area->add_child(commit_button);
- version_commit_dock->add_child(memnew(HSeparator));
+ dock_vb->add_child(memnew(HSeparator));
HBoxContainer *commit_list_hbc = memnew(HBoxContainer);
- version_commit_dock->add_child(commit_list_hbc);
+ dock_vb->add_child(commit_list_hbc);
Label *commit_list_label = memnew(Label);
commit_list_label->set_text(TTR("Commit List"));
@@ -1304,14 +1312,14 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() {
commit_list->set_column_custom_minimum_width(1, 20);
commit_list->set_theme_type_variation("TreeSecondary");
commit_list->connect(SceneStringName(item_selected), callable_mp(this, &VersionControlEditorPlugin::_load_diff).bind(commit_list));
- version_commit_dock->add_child(commit_list);
+ dock_vb->add_child(commit_list);
- version_commit_dock->add_child(memnew(HSeparator));
+ dock_vb->add_child(memnew(HSeparator));
HFlowContainer *menu_bar = memnew(HFlowContainer);
menu_bar->set_h_size_flags(Control::SIZE_EXPAND_FILL);
menu_bar->set_v_size_flags(Control::SIZE_FILL);
- version_commit_dock->add_child(menu_bar);
+ dock_vb->add_child(menu_bar);
branch_select = memnew(OptionButton);
branch_select->set_tooltip_text(TTR("Branches"));
diff --git a/editor/version_control/version_control_editor_plugin.h b/editor/version_control/version_control_editor_plugin.h
index 0e7319c8f0e..017baaa096d 100644
--- a/editor/version_control/version_control_editor_plugin.h
+++ b/editor/version_control/version_control_editor_plugin.h
@@ -39,6 +39,8 @@
#include "scene/gui/text_edit.h"
#include "scene/gui/tree.h"
+class EditorDock;
+
class VersionControlEditorPlugin : public EditorPlugin {
GDCLASS(VersionControlEditorPlugin, EditorPlugin)
@@ -98,7 +100,7 @@ private:
HashMap change_type_to_color;
HashMap> change_type_to_icon;
- VBoxContainer *version_commit_dock = nullptr;
+ EditorDock *version_commit_dock = nullptr;
Tree *staged_files = nullptr;
Tree *unstaged_files = nullptr;
Tree *commit_list = nullptr;