mirror of
https://github.com/godotengine/godot.git
synced 2025-12-07 22:00:10 +00:00
Rework editor docks
This commit is contained in:
parent
9283328fe7
commit
97b398cba1
26 changed files with 806 additions and 387 deletions
|
|
@ -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<Texture2D> _get_dock_icon(const EditorDock *p_dock, const Callable &p_icon_fetch) {
|
||||
Ref<Texture2D> 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<TabContainer>(from_node->get_parent());
|
||||
if (!parent) {
|
||||
TabContainer *source_tab_container = Object::cast_to<TabContainer>(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<EditorDock>(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<InputEvent> &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<EditorDock>(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<InputEvent> &p_input, Control *p_dock, Button *p_bottom_button) {
|
||||
void EditorDockManager::_bottom_dock_button_gui_input(const Ref<InputEvent> &p_input, EditorDock *p_dock, Button *p_bottom_button) {
|
||||
Ref<InputEventMouseButton> 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<Control *, DockInfo> &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<Texture2D> 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<Texture2D> 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<PopupMenu>(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<EditorDock>(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<TabContainer>(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<TabContainer>(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<Texture2D> 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<Texture2D>());
|
||||
tab_container->set_tab_tooltip(index, String());
|
||||
} break;
|
||||
case TabStyle::ICON_ONLY: {
|
||||
const Ref<Texture2D> 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<Texture2D> 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<ConfigFile> 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<EditorDock>(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<ConfigFile> 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<EditorDock>(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<ConfigFile> 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<ConfigFile> p_layout, const Str
|
|||
// Save closed and bottom docks.
|
||||
Array bottom_docks_dump;
|
||||
Array closed_docks_dump;
|
||||
for (const KeyValue<Control *, DockInfo> &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<ConfigFile> 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<String, Control *> dock_map;
|
||||
for (const KeyValue<Control *, DockInfo> &dock : all_docks) {
|
||||
dock_map[dock.key->get_name()] = dock.key;
|
||||
HashMap<String, EditorDock *> 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<ConfigFile> p_layout, const S
|
|||
Vector<String> 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<ConfigFile> 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<ConfigFile> 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<ConfigFile> 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<TabContainer>(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<Shortcut> &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<Texture2D> &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<Control *, DockInfo> &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<InputEvent> &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<EditorDock>(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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue