|
|
|
|
@ -69,7 +69,7 @@ void EditorDockDragHint::drop_data(const Point2 &p_point, const Variant &p_data)
|
|
|
|
|
if (drop_tabbar->get_rect().has_point(p_point)) {
|
|
|
|
|
drop_tabbar->_handle_drop_data("tab_container_tab", p_point, p_data, callable_mp(this, &EditorDockDragHint::_drag_move_tab), callable_mp(this, &EditorDockDragHint::_drag_move_tab_from));
|
|
|
|
|
} else {
|
|
|
|
|
dock_manager->_move_dock(dock_manager->_get_dock_tab_dragged(), dock_manager->dock_slot[occupied_slot], drop_tabbar->get_tab_count());
|
|
|
|
|
dock_manager->_move_dock(dock_manager->_get_dock_tab_dragged(), dock_manager->dock_slots[occupied_slot].container, drop_tabbar->get_tab_count());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -78,7 +78,7 @@ void EditorDockDragHint::_drag_move_tab(int p_from_index, int p_to_index) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EditorDockDragHint::_drag_move_tab_from(TabBar *p_from_tabbar, int p_from_index, int p_to_index) {
|
|
|
|
|
dock_manager->_move_dock(dock_manager->_get_dock_tab_dragged(), dock_manager->dock_slot[occupied_slot], p_to_index);
|
|
|
|
|
dock_manager->_move_dock(dock_manager->_get_dock_tab_dragged(), dock_manager->dock_slots[occupied_slot].container, p_to_index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EditorDockDragHint::gui_input(const Ref<InputEvent> &p_event) {
|
|
|
|
|
@ -96,9 +96,9 @@ void EditorDockDragHint::gui_input(const Ref<InputEvent> &p_event) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EditorDockDragHint::set_slot(EditorDockManager::DockSlot p_slot) {
|
|
|
|
|
void EditorDockDragHint::set_slot(DockConstants::DockSlot p_slot) {
|
|
|
|
|
occupied_slot = p_slot;
|
|
|
|
|
drop_tabbar = dock_manager->dock_slot[occupied_slot]->get_tab_bar();
|
|
|
|
|
drop_tabbar = dock_manager->dock_slots[occupied_slot].container->get_tab_bar();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EditorDockDragHint::_notification(int p_what) {
|
|
|
|
|
@ -123,12 +123,12 @@ void EditorDockDragHint::_notification(int p_what) {
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
case NOTIFICATION_DRAG_BEGIN: {
|
|
|
|
|
Control *dragged_dock = dock_manager->_get_dock_tab_dragged();
|
|
|
|
|
EditorDock *dragged_dock = dock_manager->_get_dock_tab_dragged();
|
|
|
|
|
if (!dragged_dock) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
can_drop_dock = true;
|
|
|
|
|
can_drop_dock = dragged_dock->get_available_layouts() & (EditorDock::DockLayout)EditorDockManager::get_singleton()->dock_slots[occupied_slot].layout;
|
|
|
|
|
|
|
|
|
|
dock_drop_highlight->set_border_color(valid_drop_color);
|
|
|
|
|
dock_drop_highlight->set_bg_color(valid_drop_color * Color(1, 1, 1, 0.1));
|
|
|
|
|
@ -141,7 +141,7 @@ void EditorDockDragHint::_notification(int p_what) {
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
case NOTIFICATION_DRAW: {
|
|
|
|
|
if (!mouse_inside) {
|
|
|
|
|
if (!mouse_inside || !can_drop_dock) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -151,6 +151,7 @@ void EditorDockDragHint::_notification(int p_what) {
|
|
|
|
|
|
|
|
|
|
// Only display tabbar hint if the mouse is over the tabbar.
|
|
|
|
|
if (drop_tabbar->get_global_rect().has_point(get_global_mouse_position())) {
|
|
|
|
|
draw_set_transform(drop_tabbar->get_position()); // The TabBar isn't always on top.
|
|
|
|
|
drop_tabbar->_draw_tab_drop(get_canvas_item());
|
|
|
|
|
}
|
|
|
|
|
} break;
|
|
|
|
|
@ -245,7 +246,7 @@ EditorDock *EditorDockManager::_get_dock_tab_dragged() {
|
|
|
|
|
return dock_tab_dragged;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Dictionary dock_drop_data = dock_slot[DOCK_SLOT_LEFT_BL]->get_viewport()->gui_get_drag_data();
|
|
|
|
|
Dictionary dock_drop_data = dock_slots[DockConstants::DOCK_SLOT_LEFT_BL].container->get_viewport()->gui_get_drag_data();
|
|
|
|
|
|
|
|
|
|
// Check if we are dragging a dock.
|
|
|
|
|
if (dock_drop_data.get("type", "").operator String() != "tab") {
|
|
|
|
|
@ -269,10 +270,10 @@ EditorDock *EditorDockManager::_get_dock_tab_dragged() {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
|
|
|
|
if (dock_slot[i]->is_visible_in_tree()) {
|
|
|
|
|
dock_drag_rects[i]->set_rect(dock_slot[i]->get_global_rect());
|
|
|
|
|
dock_drag_rects[i]->show();
|
|
|
|
|
for (int i = 0; i < DockConstants::DOCK_SLOT_MAX; i++) {
|
|
|
|
|
if (dock_slots[i].container->is_visible_in_tree()) {
|
|
|
|
|
dock_slots[i].drag_hint->set_rect(dock_slots[i].container->get_global_rect());
|
|
|
|
|
dock_slots[i].drag_hint->show();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -334,7 +335,7 @@ void EditorDockManager::update_docks_menu() {
|
|
|
|
|
int id = 0;
|
|
|
|
|
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) {
|
|
|
|
|
if (!dock->enabled || !dock->global) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (dock->shortcut.is_valid()) {
|
|
|
|
|
@ -347,7 +348,7 @@ void EditorDockManager::update_docks_menu() {
|
|
|
|
|
|
|
|
|
|
const Ref<Texture2D> icon = _get_dock_icon(dock, icon_fetch);
|
|
|
|
|
docks_menu->set_item_icon(id, icon.is_valid() ? icon : default_icon);
|
|
|
|
|
if (!dock->open) {
|
|
|
|
|
if (!dock->is_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->get_display_title()));
|
|
|
|
|
} else {
|
|
|
|
|
@ -362,7 +363,7 @@ void EditorDockManager::_docks_menu_option(int 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_display_title()));
|
|
|
|
|
if (dock->enabled && dock->open) {
|
|
|
|
|
if (dock->enabled && dock->is_open) {
|
|
|
|
|
PopupMenu *parent_menu = Object::cast_to<PopupMenu>(docks_menu->get_parent());
|
|
|
|
|
ERR_FAIL_NULL(parent_menu);
|
|
|
|
|
parent_menu->hide();
|
|
|
|
|
@ -375,8 +376,8 @@ void EditorDockManager::_window_close_request(WindowWrapper *p_wrapper) {
|
|
|
|
|
EditorDock *dock = _close_window(p_wrapper);
|
|
|
|
|
ERR_FAIL_COND(!all_docks.has(dock));
|
|
|
|
|
|
|
|
|
|
if (dock->previous_at_bottom || dock->dock_slot_index != DOCK_SLOT_NONE) {
|
|
|
|
|
dock->open = false;
|
|
|
|
|
if (dock->dock_slot_index != DockConstants::DOCK_SLOT_NONE) {
|
|
|
|
|
dock->is_open = false;
|
|
|
|
|
open_dock(dock);
|
|
|
|
|
focus_dock(dock);
|
|
|
|
|
} else {
|
|
|
|
|
@ -411,10 +412,11 @@ void EditorDockManager::_open_dock_in_window(EditorDock *p_dock, bool p_show_win
|
|
|
|
|
EditorNode::get_singleton()->get_gui_base()->add_child(wrapper);
|
|
|
|
|
|
|
|
|
|
_move_dock(p_dock, nullptr);
|
|
|
|
|
p_dock->update_layout(EditorDock::DOCK_LAYOUT_FLOATING);
|
|
|
|
|
wrapper->set_wrapped_control(p_dock);
|
|
|
|
|
|
|
|
|
|
p_dock->dock_window = wrapper;
|
|
|
|
|
p_dock->open = true;
|
|
|
|
|
p_dock->is_open = true;
|
|
|
|
|
p_dock->show();
|
|
|
|
|
|
|
|
|
|
wrapper->connect("window_close_requested", callable_mp(this, &EditorDockManager::_window_close_request).bind(wrapper));
|
|
|
|
|
@ -444,31 +446,6 @@ void EditorDockManager::_restore_dock_to_saved_window(EditorDock *p_dock, const
|
|
|
|
|
p_window_dump.get("window_screen_rect", Rect2i()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EditorDockManager::_dock_move_to_bottom(EditorDock *p_dock, bool p_visible) {
|
|
|
|
|
_move_dock(p_dock, nullptr);
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
EditorNode::get_bottom_panel()->add_item(p_dock->get_display_title(), p_dock, p_dock->shortcut, true);
|
|
|
|
|
EditorNode::get_bottom_panel()->make_item_visible(p_dock, p_visible);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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->update_layout(EditorDock::DOCK_LAYOUT_VERTICAL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool EditorDockManager::_is_dock_at_bottom(EditorDock *p_dock) {
|
|
|
|
|
ERR_FAIL_COND_V(!all_docks.has(p_dock), false);
|
|
|
|
|
return p_dock->at_bottom;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
@ -492,7 +469,7 @@ void EditorDockManager::_move_dock(EditorDock *p_dock, Control *p_target, int p_
|
|
|
|
|
|
|
|
|
|
Node *parent = p_dock->get_parent();
|
|
|
|
|
if (parent == p_target) {
|
|
|
|
|
if (p_tab_index >= 0 && parent) {
|
|
|
|
|
if (parent && p_tab_index >= 0) {
|
|
|
|
|
// Only change the tab index.
|
|
|
|
|
_move_dock_tab_index(p_dock, p_tab_index, p_set_current);
|
|
|
|
|
}
|
|
|
|
|
@ -503,10 +480,7 @@ void EditorDockManager::_move_dock(EditorDock *p_dock, Control *p_target, int p_
|
|
|
|
|
if (parent) {
|
|
|
|
|
if (p_dock->dock_window) {
|
|
|
|
|
_close_window(p_dock->dock_window);
|
|
|
|
|
} else if (p_dock->at_bottom) {
|
|
|
|
|
_dock_remove_from_bottom(p_dock);
|
|
|
|
|
} else {
|
|
|
|
|
p_dock->previous_at_bottom = false;
|
|
|
|
|
TabContainer *parent_tabs = Object::cast_to<TabContainer>(parent);
|
|
|
|
|
if (parent_tabs) {
|
|
|
|
|
p_dock->previous_tab_index = parent_tabs->get_tab_idx_from_control(p_dock);
|
|
|
|
|
@ -520,13 +494,20 @@ void EditorDockManager::_move_dock(EditorDock *p_dock, Control *p_target, int p_
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add dock to its new parent, at the given tab index.
|
|
|
|
|
if (!p_target) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_target != closed_dock_parent) {
|
|
|
|
|
p_dock->update_layout(p_target->get_meta("dock_layout"));
|
|
|
|
|
p_dock->dock_slot_index = p_target->get_meta("dock_slot");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add dock to its new parent, at the given tab index.
|
|
|
|
|
p_target->set_block_signals(true);
|
|
|
|
|
p_target->add_child(p_dock);
|
|
|
|
|
p_target->set_block_signals(false);
|
|
|
|
|
|
|
|
|
|
TabContainer *dock_tab_container = Object::cast_to<TabContainer>(p_target);
|
|
|
|
|
if (dock_tab_container) {
|
|
|
|
|
if (dock_tab_container->is_inside_tree()) {
|
|
|
|
|
@ -540,11 +521,11 @@ void EditorDockManager::_move_dock(EditorDock *p_dock, Control *p_target, int p_
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EditorDockManager::_update_tab_style(EditorDock *p_dock) {
|
|
|
|
|
if (!p_dock->enabled || !p_dock->open) {
|
|
|
|
|
if (!p_dock->enabled || !p_dock->is_open) {
|
|
|
|
|
return; // Disabled by feature profile or manually closed by user.
|
|
|
|
|
}
|
|
|
|
|
if (p_dock->dock_window || p_dock->at_bottom) {
|
|
|
|
|
return; // Floating or sent to bottom.
|
|
|
|
|
if (p_dock->dock_window) {
|
|
|
|
|
return; // Floating.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TabContainer *tab_container = get_dock_tab_container(p_dock);
|
|
|
|
|
@ -553,6 +534,12 @@ void EditorDockManager::_update_tab_style(EditorDock *p_dock) {
|
|
|
|
|
int index = tab_container->get_tab_idx_from_control(p_dock);
|
|
|
|
|
ERR_FAIL_COND(index == -1);
|
|
|
|
|
|
|
|
|
|
if (p_dock->global) {
|
|
|
|
|
update_docks_menu();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tab_container->get_tab_bar()->set_font_color_override_all(index, p_dock->title_color);
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
@ -576,35 +563,34 @@ void EditorDockManager::_update_tab_style(EditorDock *p_dock) {
|
|
|
|
|
|
|
|
|
|
void EditorDockManager::save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section) const {
|
|
|
|
|
// Save docks by dock slot.
|
|
|
|
|
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 = Object::cast_to<EditorDock>(dock_slot[i]->get_tab_control(j))->get_effective_layout_key();
|
|
|
|
|
if (!names.is_empty()) {
|
|
|
|
|
names += ",";
|
|
|
|
|
}
|
|
|
|
|
names += name;
|
|
|
|
|
for (int i = 0; i < DockConstants::DOCK_SLOT_MAX; i++) {
|
|
|
|
|
const DockSlot &dock_slot = dock_slots[i];
|
|
|
|
|
|
|
|
|
|
PackedStringArray names;
|
|
|
|
|
names.reserve_exact(dock_slot.container->get_tab_count());
|
|
|
|
|
for (int j = 0; j < dock_slot.container->get_tab_count(); j++) {
|
|
|
|
|
const String name = Object::cast_to<EditorDock>(dock_slot.container->get_tab_control(j))->get_effective_layout_key();
|
|
|
|
|
names.append(name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String config_key = "dock_" + itos(i + 1);
|
|
|
|
|
|
|
|
|
|
const String config_key = "dock_" + itos(i + 1);
|
|
|
|
|
if (p_layout->has_section_key(p_section, config_key)) {
|
|
|
|
|
p_layout->erase_section_key(p_section, config_key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!names.is_empty()) {
|
|
|
|
|
p_layout->set_value(p_section, config_key, names);
|
|
|
|
|
p_layout->set_value(p_section, config_key, String(",").join(names));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int selected_tab_idx = dock_slot[i]->get_current_tab();
|
|
|
|
|
const String tab_key = config_key + "_selected_tab_idx";
|
|
|
|
|
|
|
|
|
|
int selected_tab_idx = dock_slots[i].container->get_current_tab();
|
|
|
|
|
if (selected_tab_idx >= 0) {
|
|
|
|
|
p_layout->set_value(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx", selected_tab_idx);
|
|
|
|
|
p_layout->set_value(p_section, tab_key, selected_tab_idx);
|
|
|
|
|
} else if (p_layout->has_section_key(p_section, tab_key)) {
|
|
|
|
|
p_layout->erase_section_key(p_section, tab_key);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (p_layout->has_section_key(p_section, "dock_0")) {
|
|
|
|
|
// Clear the keys where the dock has no slot so it is overridden.
|
|
|
|
|
p_layout->erase_section_key(p_section, "dock_0");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Save docks in windows.
|
|
|
|
|
Dictionary floating_docks_dump;
|
|
|
|
|
@ -635,22 +621,18 @@ void EditorDockManager::save_docks_to_config(Ref<ConfigFile> p_layout, const Str
|
|
|
|
|
}
|
|
|
|
|
p_layout->set_value(p_section, "dock_floating", floating_docks_dump);
|
|
|
|
|
|
|
|
|
|
// Save closed and bottom docks.
|
|
|
|
|
Array bottom_docks_dump;
|
|
|
|
|
// Save closed docks.
|
|
|
|
|
Array closed_docks_dump;
|
|
|
|
|
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 (!dock->at_bottom && dock->open && (!dock->previous_at_bottom || !dock->dock_window)) {
|
|
|
|
|
if (dock->is_open) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 (!dock->open) {
|
|
|
|
|
if (!dock->is_open && !dock->transient) {
|
|
|
|
|
closed_docks_dump.push_back(name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -665,7 +647,6 @@ void EditorDockManager::save_docks_to_config(Ref<ConfigFile> p_layout, const Str
|
|
|
|
|
}
|
|
|
|
|
p_layout->set_value(p_section, config_key, names);
|
|
|
|
|
}
|
|
|
|
|
p_layout->set_value(p_section, "dock_bottom", bottom_docks_dump);
|
|
|
|
|
p_layout->set_value(p_section, "dock_closed", closed_docks_dump);
|
|
|
|
|
|
|
|
|
|
// Save SplitContainer offsets.
|
|
|
|
|
@ -682,7 +663,6 @@ void EditorDockManager::save_docks_to_config(Ref<ConfigFile> p_layout, const Str
|
|
|
|
|
|
|
|
|
|
void EditorDockManager::load_docks_from_config(Ref<ConfigFile> p_layout, const String &p_section, bool p_first_load) {
|
|
|
|
|
Dictionary floating_docks_dump = p_layout->get_value(p_section, "dock_floating", Dictionary());
|
|
|
|
|
Array dock_bottom = p_layout->get_value(p_section, "dock_bottom", Array());
|
|
|
|
|
Array closed_docks = p_layout->get_value(p_section, "dock_closed", Array());
|
|
|
|
|
|
|
|
|
|
bool allow_floating_docks = EditorNode::get_singleton()->is_multi_window_enabled() && (!p_first_load || EDITOR_GET("interface/multi_window/restore_windows_on_load"));
|
|
|
|
|
@ -694,7 +674,7 @@ void EditorDockManager::load_docks_from_config(Ref<ConfigFile> p_layout, const S
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Load docks by slot. Index -1 is for docks that have no slot.
|
|
|
|
|
for (int i = -1; i < DOCK_SLOT_MAX; i++) {
|
|
|
|
|
for (int i = -1; i < DockConstants::DOCK_SLOT_MAX; i++) {
|
|
|
|
|
if (!p_layout->has_section_key(p_section, "dock_" + itos(i + 1))) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
@ -711,32 +691,28 @@ void EditorDockManager::load_docks_from_config(Ref<ConfigFile> p_layout, const S
|
|
|
|
|
EditorDock *dock = dock_map[name];
|
|
|
|
|
|
|
|
|
|
if (!dock->enabled) {
|
|
|
|
|
// Don't open disabled docks.
|
|
|
|
|
// Don't is_open disabled docks.
|
|
|
|
|
dock->load_layout_from_config(p_layout, section_name);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
bool at_bottom = false;
|
|
|
|
|
if (allow_floating_docks && floating_docks_dump.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);
|
|
|
|
|
at_bottom = true;
|
|
|
|
|
} else if (i >= 0) {
|
|
|
|
|
_move_dock(dock, dock_slot[i], 0);
|
|
|
|
|
if (dock->transient && !dock->is_open) {
|
|
|
|
|
dock->dock_slot_index = i;
|
|
|
|
|
} else {
|
|
|
|
|
_move_dock(dock, dock_slots[i].container, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
dock->load_layout_from_config(p_layout, section_name);
|
|
|
|
|
|
|
|
|
|
if (closed_docks.has(name)) {
|
|
|
|
|
_move_dock(dock, closed_dock_parent);
|
|
|
|
|
dock->open = false;
|
|
|
|
|
dock->hide();
|
|
|
|
|
} else {
|
|
|
|
|
// Make sure it is open.
|
|
|
|
|
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) {
|
|
|
|
|
if (!dock->transient) {
|
|
|
|
|
if (closed_docks.has(name)) {
|
|
|
|
|
_move_dock(dock, closed_dock_parent);
|
|
|
|
|
dock->is_open = false;
|
|
|
|
|
dock->hide();
|
|
|
|
|
} else {
|
|
|
|
|
dock->is_open = true;
|
|
|
|
|
dock->show();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -747,16 +723,24 @@ void EditorDockManager::load_docks_from_config(Ref<ConfigFile> p_layout, const S
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set the selected tabs.
|
|
|
|
|
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
|
|
|
|
if (dock_slot[i]->get_tab_count() == 0 || !p_layout->has_section_key(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx")) {
|
|
|
|
|
for (int i = 0; i < DockConstants::DOCK_SLOT_MAX; i++) {
|
|
|
|
|
const DockSlot &dock_slot = dock_slots[i];
|
|
|
|
|
|
|
|
|
|
int selected_tab_idx = p_layout->get_value(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx", -1);
|
|
|
|
|
if (selected_tab_idx <= 0 || selected_tab_idx >= dock_slot.container->get_tab_count()) {
|
|
|
|
|
if (i == DockConstants::DOCK_SLOT_BOTTOM) {
|
|
|
|
|
dock_slot.container->set_current_tab(-1);
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
int selected_tab_idx = p_layout->get_value(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx");
|
|
|
|
|
if (selected_tab_idx >= 0 && selected_tab_idx < dock_slot[i]->get_tab_count()) {
|
|
|
|
|
dock_slot[i]->set_block_signals(true);
|
|
|
|
|
dock_slot[i]->set_current_tab(selected_tab_idx);
|
|
|
|
|
dock_slot[i]->set_block_signals(false);
|
|
|
|
|
|
|
|
|
|
EditorDock *selected_dock = Object::cast_to<EditorDock>(dock_slot.container->get_tab_control(selected_tab_idx));
|
|
|
|
|
if (!selected_dock) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
dock_slot.container->set_block_signals(true);
|
|
|
|
|
dock_slot.container->set_current_tab(selected_tab_idx);
|
|
|
|
|
dock_slot.container->set_block_signals(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Load SplitContainer offsets.
|
|
|
|
|
@ -778,22 +762,6 @@ 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, EditorDock *p_dock) {
|
|
|
|
|
ERR_FAIL_COND(!all_docks.has(p_dock));
|
|
|
|
|
|
|
|
|
|
dock_context_popup->set_dock(p_dock);
|
|
|
|
|
|
|
|
|
|
Vector2 popup_pos = p_position.position;
|
|
|
|
|
popup_pos.y += p_position.size.height;
|
|
|
|
|
|
|
|
|
|
if (!EditorNode::get_singleton()->get_gui_base()->is_layout_rtl()) {
|
|
|
|
|
popup_pos.x -= dock_context_popup->get_size().width;
|
|
|
|
|
popup_pos.x += p_position.size.width;
|
|
|
|
|
}
|
|
|
|
|
dock_context_popup->set_position(popup_pos);
|
|
|
|
|
dock_context_popup->popup();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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_display_title()));
|
|
|
|
|
@ -814,13 +782,17 @@ 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_display_title()));
|
|
|
|
|
|
|
|
|
|
if (!p_dock->open) {
|
|
|
|
|
if (!p_dock->is_open) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EditorBottomPanel *bottom_panel = EditorNode::get_bottom_panel();
|
|
|
|
|
if (get_dock_tab_container(p_dock) == bottom_panel && bottom_panel->get_current_tab_control() == p_dock) {
|
|
|
|
|
bottom_panel->hide_bottom_panel();
|
|
|
|
|
}
|
|
|
|
|
_move_dock(p_dock, closed_dock_parent);
|
|
|
|
|
|
|
|
|
|
p_dock->open = false;
|
|
|
|
|
p_dock->is_open = false;
|
|
|
|
|
p_dock->hide();
|
|
|
|
|
|
|
|
|
|
_update_layout();
|
|
|
|
|
@ -830,18 +802,16 @@ 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_display_title()));
|
|
|
|
|
|
|
|
|
|
if (p_dock->open) {
|
|
|
|
|
if (p_dock->is_open) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_dock->open = true;
|
|
|
|
|
p_dock->is_open = true;
|
|
|
|
|
p_dock->show();
|
|
|
|
|
|
|
|
|
|
// Open dock to its previous location.
|
|
|
|
|
if (p_dock->previous_at_bottom) {
|
|
|
|
|
_dock_move_to_bottom(p_dock, true);
|
|
|
|
|
} else if (p_dock->dock_slot_index != DOCK_SLOT_NONE) {
|
|
|
|
|
TabContainer *slot = dock_slot[p_dock->dock_slot_index];
|
|
|
|
|
if (p_dock->dock_slot_index != DockConstants::DOCK_SLOT_NONE) {
|
|
|
|
|
TabContainer *slot = dock_slots[p_dock->dock_slot_index].container;
|
|
|
|
|
int tab_index = p_dock->previous_tab_index;
|
|
|
|
|
if (tab_index < 0) {
|
|
|
|
|
tab_index = slot->get_tab_count();
|
|
|
|
|
@ -867,7 +837,7 @@ void EditorDockManager::focus_dock(EditorDock *p_dock) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!p_dock->open) {
|
|
|
|
|
if (!p_dock->is_open) {
|
|
|
|
|
open_dock(p_dock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -876,11 +846,6 @@ void EditorDockManager::focus_dock(EditorDock *p_dock) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_dock->at_bottom) {
|
|
|
|
|
EditorNode::get_bottom_panel()->make_item_visible(p_dock, true, true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!docks_visible) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
@ -903,7 +868,7 @@ void EditorDockManager::add_dock(EditorDock *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_dock->default_slot != DOCK_SLOT_NONE) {
|
|
|
|
|
if (p_dock->default_slot != DockConstants::DOCK_SLOT_NONE) {
|
|
|
|
|
open_dock(p_dock, false);
|
|
|
|
|
} else {
|
|
|
|
|
closed_dock_parent->add_child(p_dock);
|
|
|
|
|
@ -929,8 +894,8 @@ void EditorDockManager::set_docks_visible(bool p_show) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
docks_visible = p_show;
|
|
|
|
|
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
|
|
|
|
dock_slot[i]->set_visible(docks_visible && dock_slot[i]->get_tab_count() > 0);
|
|
|
|
|
for (int i = 0; i < DockConstants::DOCK_SLOT_MAX; i++) {
|
|
|
|
|
dock_slots[i].container->set_visible(docks_visible && dock_slots[i].container->get_tab_count() > 0);
|
|
|
|
|
}
|
|
|
|
|
_update_layout();
|
|
|
|
|
}
|
|
|
|
|
@ -946,8 +911,8 @@ void EditorDockManager::update_tab_styles() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EditorDockManager::set_tab_icon_max_width(int p_max_width) {
|
|
|
|
|
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
|
|
|
|
TabContainer *tab_container = dock_slot[i];
|
|
|
|
|
for (int i = 0; i < DockConstants::DOCK_SLOT_MAX; i++) {
|
|
|
|
|
TabContainer *tab_container = dock_slots[i].container;
|
|
|
|
|
tab_container->add_theme_constant_override(SNAME("icon_max_width"), p_max_width);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -962,14 +927,14 @@ void EditorDockManager::add_hsplit(DockSplitContainer *p_split) {
|
|
|
|
|
p_split->connect("dragged", callable_mp(this, &EditorDockManager::_dock_split_dragged));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EditorDockManager::register_dock_slot(DockSlot p_dock_slot, TabContainer *p_tab_container) {
|
|
|
|
|
void EditorDockManager::register_dock_slot(DockConstants::DockSlot p_dock_slot, TabContainer *p_tab_container, DockConstants::DockLayout p_layout) {
|
|
|
|
|
ERR_FAIL_NULL(p_tab_container);
|
|
|
|
|
ERR_FAIL_INDEX(p_dock_slot, DOCK_SLOT_MAX);
|
|
|
|
|
ERR_FAIL_INDEX(p_dock_slot, DockConstants::DOCK_SLOT_MAX);
|
|
|
|
|
|
|
|
|
|
dock_slot[p_dock_slot] = p_tab_container;
|
|
|
|
|
DockSlot slot;
|
|
|
|
|
slot.layout = p_layout;
|
|
|
|
|
|
|
|
|
|
p_tab_container->set_custom_minimum_size(Size2(170, 0) * EDSCALE);
|
|
|
|
|
p_tab_container->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
|
|
|
|
slot.container = p_tab_container;
|
|
|
|
|
p_tab_container->set_popup(dock_context_popup);
|
|
|
|
|
p_tab_container->connect("pre_popup_pressed", callable_mp(dock_context_popup, &DockContextPopup::select_current_dock_in_dock_slot).bind(p_dock_slot));
|
|
|
|
|
p_tab_container->get_tab_bar()->connect("tab_rmb_clicked", callable_mp(this, &EditorDockManager::_dock_container_popup).bind(p_tab_container));
|
|
|
|
|
@ -978,14 +943,23 @@ void EditorDockManager::register_dock_slot(DockSlot p_dock_slot, TabContainer *p
|
|
|
|
|
p_tab_container->connect("tab_changed", callable_mp(this, &EditorDockManager::_update_layout).unbind(1));
|
|
|
|
|
p_tab_container->connect("active_tab_rearranged", callable_mp(this, &EditorDockManager::_update_layout).unbind(1));
|
|
|
|
|
p_tab_container->connect("child_order_changed", callable_mp(this, &EditorDockManager::_dock_container_update_visibility).bind(p_tab_container));
|
|
|
|
|
p_tab_container->set_use_hidden_tabs_for_min_size(true);
|
|
|
|
|
p_tab_container->hide();
|
|
|
|
|
p_tab_container->set_meta("dock_slot", p_dock_slot);
|
|
|
|
|
p_tab_container->set_meta("dock_layout", p_layout);
|
|
|
|
|
|
|
|
|
|
if (p_layout == DockConstants::DOCK_LAYOUT_VERTICAL) {
|
|
|
|
|
p_tab_container->set_custom_minimum_size(Size2(170, 0) * EDSCALE);
|
|
|
|
|
p_tab_container->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
|
|
|
|
p_tab_container->set_use_hidden_tabs_for_min_size(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create dock dragging hint.
|
|
|
|
|
dock_drag_rects[p_dock_slot] = memnew(EditorDockDragHint);
|
|
|
|
|
dock_drag_rects[p_dock_slot]->set_slot(p_dock_slot);
|
|
|
|
|
dock_drag_rects[p_dock_slot]->hide();
|
|
|
|
|
EditorNode::get_singleton()->get_gui_base()->add_child(dock_drag_rects[p_dock_slot]);
|
|
|
|
|
slot.drag_hint = memnew(EditorDockDragHint);
|
|
|
|
|
slot.drag_hint->hide();
|
|
|
|
|
EditorNode::get_singleton()->get_gui_base()->add_child(slot.drag_hint);
|
|
|
|
|
|
|
|
|
|
dock_slots[p_dock_slot] = slot;
|
|
|
|
|
slot.drag_hint->set_slot(p_dock_slot);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int EditorDockManager::get_hsplit_count() const {
|
|
|
|
|
@ -1007,6 +981,7 @@ EditorDockManager::EditorDockManager() {
|
|
|
|
|
|
|
|
|
|
dock_context_popup = memnew(DockContextPopup);
|
|
|
|
|
EditorNode::get_singleton()->get_gui_base()->add_child(dock_context_popup);
|
|
|
|
|
EditorNode::get_singleton()->add_child(memnew(DockShortcutHandler));
|
|
|
|
|
|
|
|
|
|
docks_menu = memnew(PopupMenu);
|
|
|
|
|
docks_menu->set_hide_on_item_selection(false);
|
|
|
|
|
@ -1036,7 +1011,6 @@ void DockContextPopup::_notification(int p_what) {
|
|
|
|
|
tab_move_left_button->set_tooltip_text(TTR("Move this dock left one tab."));
|
|
|
|
|
tab_move_right_button->set_tooltip_text(TTR("Move this dock right one tab."));
|
|
|
|
|
}
|
|
|
|
|
dock_to_bottom_button->set_button_icon(get_editor_theme_icon(SNAME("ControlAlignBottomWide")));
|
|
|
|
|
close_button->set_button_icon(get_editor_theme_icon(SNAME("Close")));
|
|
|
|
|
} break;
|
|
|
|
|
}
|
|
|
|
|
@ -1074,10 +1048,8 @@ void DockContextPopup::_float_dock() {
|
|
|
|
|
dock_manager->_open_dock_in_window(context_dock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DockContextPopup::_move_dock_to_bottom() {
|
|
|
|
|
hide();
|
|
|
|
|
dock_manager->_dock_move_to_bottom(context_dock, true);
|
|
|
|
|
dock_manager->_update_layout();
|
|
|
|
|
bool DockContextPopup::_is_slot_available(int p_slot) const {
|
|
|
|
|
return context_dock->available_layouts & (EditorDock::DockLayout)EditorDockManager::get_singleton()->dock_slots[p_slot].layout;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DockContextPopup::_dock_select_input(const Ref<InputEvent> &p_input) {
|
|
|
|
|
@ -1087,7 +1059,7 @@ void DockContextPopup::_dock_select_input(const Ref<InputEvent> &p_input) {
|
|
|
|
|
Vector2 point = me->get_position();
|
|
|
|
|
|
|
|
|
|
int over_dock_slot = -1;
|
|
|
|
|
for (int i = 0; i < EditorDockManager::DOCK_SLOT_MAX; i++) {
|
|
|
|
|
for (int i = 0; i < DockConstants::DOCK_SLOT_MAX; i++) {
|
|
|
|
|
if (dock_select_rects[i].has_point(point)) {
|
|
|
|
|
over_dock_slot = i;
|
|
|
|
|
break;
|
|
|
|
|
@ -1104,12 +1076,11 @@ void DockContextPopup::_dock_select_input(const Ref<InputEvent> &p_input) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ref<InputEventMouseButton> mb = me;
|
|
|
|
|
TabContainer *target_tab_container = dock_manager->dock_slot[over_dock_slot];
|
|
|
|
|
TabContainer *target_tab_container = dock_manager->dock_slots[over_dock_slot].container;
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
if (dock_manager->get_dock_tab_container(context_dock) != target_tab_container && _is_slot_available(over_dock_slot)) {
|
|
|
|
|
dock_manager->_move_dock(context_dock, target_tab_container, target_tab_container->get_tab_count());
|
|
|
|
|
context_dock->dock_slot_index = over_dock_slot;
|
|
|
|
|
dock_manager->_update_layout();
|
|
|
|
|
hide();
|
|
|
|
|
}
|
|
|
|
|
@ -1137,30 +1108,30 @@ void DockContextPopup::_dock_select_draw() {
|
|
|
|
|
dock_size.x /= 6.0;
|
|
|
|
|
dock_size.y /= 2.0;
|
|
|
|
|
|
|
|
|
|
Size2 center_panel_size = dock_size * 2.0;
|
|
|
|
|
Rect2 center_panel_rect(center_panel_size.x, 0, center_panel_size.x, center_panel_size.y);
|
|
|
|
|
real_t center_panel_width = dock_size.x * 2.0;
|
|
|
|
|
Rect2 center_panel_rect(center_panel_width, 0, center_panel_width, dock_size.y);
|
|
|
|
|
|
|
|
|
|
if (dock_select->is_layout_rtl()) {
|
|
|
|
|
dock_select_rects[EditorDockManager::DOCK_SLOT_RIGHT_UR] = Rect2(Point2(), dock_size);
|
|
|
|
|
dock_select_rects[EditorDockManager::DOCK_SLOT_RIGHT_BR] = Rect2(Point2(0, dock_size.y), dock_size);
|
|
|
|
|
dock_select_rects[EditorDockManager::DOCK_SLOT_RIGHT_UL] = Rect2(Point2(dock_size.x, 0), dock_size);
|
|
|
|
|
dock_select_rects[EditorDockManager::DOCK_SLOT_RIGHT_BL] = Rect2(dock_size, dock_size);
|
|
|
|
|
dock_select_rects[EditorDockManager::DOCK_SLOT_LEFT_UR] = Rect2(Point2(dock_size.x * 4, 0), dock_size);
|
|
|
|
|
dock_select_rects[EditorDockManager::DOCK_SLOT_LEFT_BR] = Rect2(Point2(dock_size.x * 4, dock_size.y), dock_size);
|
|
|
|
|
dock_select_rects[EditorDockManager::DOCK_SLOT_LEFT_UL] = Rect2(Point2(dock_size.x * 5, 0), dock_size);
|
|
|
|
|
dock_select_rects[EditorDockManager::DOCK_SLOT_LEFT_BL] = Rect2(Point2(dock_size.x * 5, dock_size.y), dock_size);
|
|
|
|
|
dock_select_rects[DockConstants::DOCK_SLOT_RIGHT_UR] = Rect2(Point2(), dock_size);
|
|
|
|
|
dock_select_rects[DockConstants::DOCK_SLOT_RIGHT_BR] = Rect2(Point2(0, dock_size.y), dock_size);
|
|
|
|
|
dock_select_rects[DockConstants::DOCK_SLOT_RIGHT_UL] = Rect2(Point2(dock_size.x, 0), dock_size);
|
|
|
|
|
dock_select_rects[DockConstants::DOCK_SLOT_RIGHT_BL] = Rect2(dock_size, dock_size);
|
|
|
|
|
dock_select_rects[DockConstants::DOCK_SLOT_LEFT_UR] = Rect2(Point2(dock_size.x * 4, 0), dock_size);
|
|
|
|
|
dock_select_rects[DockConstants::DOCK_SLOT_LEFT_BR] = Rect2(Point2(dock_size.x * 4, dock_size.y), dock_size);
|
|
|
|
|
dock_select_rects[DockConstants::DOCK_SLOT_LEFT_UL] = Rect2(Point2(dock_size.x * 5, 0), dock_size);
|
|
|
|
|
dock_select_rects[DockConstants::DOCK_SLOT_LEFT_BL] = Rect2(Point2(dock_size.x * 5, dock_size.y), dock_size);
|
|
|
|
|
} else {
|
|
|
|
|
dock_select_rects[EditorDockManager::DOCK_SLOT_LEFT_UL] = Rect2(Point2(), dock_size);
|
|
|
|
|
dock_select_rects[EditorDockManager::DOCK_SLOT_LEFT_BL] = Rect2(Point2(0, dock_size.y), dock_size);
|
|
|
|
|
dock_select_rects[EditorDockManager::DOCK_SLOT_LEFT_UR] = Rect2(Point2(dock_size.x, 0), dock_size);
|
|
|
|
|
dock_select_rects[EditorDockManager::DOCK_SLOT_LEFT_BR] = Rect2(dock_size, dock_size);
|
|
|
|
|
dock_select_rects[EditorDockManager::DOCK_SLOT_RIGHT_UL] = Rect2(Point2(dock_size.x * 4, 0), dock_size);
|
|
|
|
|
dock_select_rects[EditorDockManager::DOCK_SLOT_RIGHT_BL] = Rect2(Point2(dock_size.x * 4, dock_size.y), dock_size);
|
|
|
|
|
dock_select_rects[EditorDockManager::DOCK_SLOT_RIGHT_UR] = Rect2(Point2(dock_size.x * 5, 0), dock_size);
|
|
|
|
|
dock_select_rects[EditorDockManager::DOCK_SLOT_RIGHT_BR] = Rect2(Point2(dock_size.x * 5, dock_size.y), dock_size);
|
|
|
|
|
dock_select_rects[DockConstants::DOCK_SLOT_LEFT_UL] = Rect2(Point2(), dock_size);
|
|
|
|
|
dock_select_rects[DockConstants::DOCK_SLOT_LEFT_BL] = Rect2(Point2(0, dock_size.y), dock_size);
|
|
|
|
|
dock_select_rects[DockConstants::DOCK_SLOT_LEFT_UR] = Rect2(Point2(dock_size.x, 0), dock_size);
|
|
|
|
|
dock_select_rects[DockConstants::DOCK_SLOT_LEFT_BR] = Rect2(dock_size, dock_size);
|
|
|
|
|
dock_select_rects[DockConstants::DOCK_SLOT_RIGHT_UL] = Rect2(Point2(dock_size.x * 4, 0), dock_size);
|
|
|
|
|
dock_select_rects[DockConstants::DOCK_SLOT_RIGHT_BL] = Rect2(Point2(dock_size.x * 4, dock_size.y), dock_size);
|
|
|
|
|
dock_select_rects[DockConstants::DOCK_SLOT_RIGHT_UR] = Rect2(Point2(dock_size.x * 5, 0), dock_size);
|
|
|
|
|
dock_select_rects[DockConstants::DOCK_SLOT_RIGHT_BR] = Rect2(Point2(dock_size.x * 5, dock_size.y), dock_size);
|
|
|
|
|
}
|
|
|
|
|
dock_select_rects[DockConstants::DOCK_SLOT_BOTTOM] = Rect2(center_panel_width, dock_size.y, center_panel_width, dock_size.y);
|
|
|
|
|
|
|
|
|
|
int max_tabs = 3;
|
|
|
|
|
int rtl_dir = dock_select->is_layout_rtl() ? -1 : 1;
|
|
|
|
|
real_t tab_height = 3.0 * EDSCALE;
|
|
|
|
|
real_t tab_spacing = 1.0 * EDSCALE;
|
|
|
|
|
@ -1178,17 +1149,30 @@ void DockContextPopup::_dock_select_draw() {
|
|
|
|
|
dock_select->draw_rect(center_panel_draw_rect, unusable_dock_color);
|
|
|
|
|
|
|
|
|
|
// Draw all dock slots.
|
|
|
|
|
for (int i = 0; i < EditorDockManager::DOCK_SLOT_MAX; i++) {
|
|
|
|
|
for (int i = 0; i < DockConstants::DOCK_SLOT_MAX; i++) {
|
|
|
|
|
int max_tabs = (i == DockConstants::DOCK_SLOT_BOTTOM) ? 6 : 3;
|
|
|
|
|
const EditorDockManager::DockSlot &dock_slot = dock_manager->dock_slots[i];
|
|
|
|
|
|
|
|
|
|
Rect2 dock_slot_draw_rect = dock_select_rects[i].grow_individual(-dock_spacing, -dock_top_spacing, -dock_spacing, -dock_spacing);
|
|
|
|
|
real_t tab_width = Math::round(dock_slot_draw_rect.size.width / max_tabs);
|
|
|
|
|
Rect2 tab_draw_rect = Rect2(dock_slot_draw_rect.position.x, dock_select_rects[i].position.y, tab_width - tab_spacing, tab_height);
|
|
|
|
|
|
|
|
|
|
real_t max_width = tab_width * max_tabs;
|
|
|
|
|
// Tabs may not fit perfectly, so they need to be re-centered.
|
|
|
|
|
if (max_width > dock_slot_draw_rect.size.x) {
|
|
|
|
|
tab_draw_rect.position.x -= int(max_width - dock_slot_draw_rect.size.x) / 2 * rtl_dir;
|
|
|
|
|
}
|
|
|
|
|
if (dock_select->is_layout_rtl()) {
|
|
|
|
|
tab_draw_rect.position.x += dock_slot_draw_rect.size.x - tab_draw_rect.size.x;
|
|
|
|
|
}
|
|
|
|
|
bool is_context_dock = context_tab_container == dock_manager->dock_slot[i];
|
|
|
|
|
int tabs_to_draw = MIN(max_tabs, dock_manager->dock_slot[i]->get_tab_count());
|
|
|
|
|
|
|
|
|
|
if (i == dock_select_rect_over_idx) {
|
|
|
|
|
int tabs_to_draw = MIN(max_tabs, dock_slot.container->get_tab_count());
|
|
|
|
|
bool is_context_dock = context_tab_container == dock_slot.container;
|
|
|
|
|
if (i == context_dock->dock_slot_index) {
|
|
|
|
|
dock_select->draw_rect(dock_slot_draw_rect, tab_selected_color);
|
|
|
|
|
} else if (!_is_slot_available(i)) {
|
|
|
|
|
dock_select->draw_rect(dock_slot_draw_rect, unusable_dock_color);
|
|
|
|
|
} else if (i == dock_select_rect_over_idx) {
|
|
|
|
|
dock_select->draw_rect(dock_slot_draw_rect, hovered_dock_color);
|
|
|
|
|
} else if (tabs_to_draw == 0) {
|
|
|
|
|
dock_select->draw_rect(dock_slot_draw_rect, unused_dock_color);
|
|
|
|
|
@ -1211,23 +1195,36 @@ void DockContextPopup::_dock_select_draw() {
|
|
|
|
|
|
|
|
|
|
void DockContextPopup::_update_buttons() {
|
|
|
|
|
TabContainer *context_tab_container = dock_manager->get_dock_tab_container(context_dock);
|
|
|
|
|
bool dock_at_bottom = dock_manager->_is_dock_at_bottom(context_dock);
|
|
|
|
|
if (context_dock->global) {
|
|
|
|
|
close_button->set_tooltip_text(TTRC("Close this dock."));
|
|
|
|
|
close_button->set_disabled(false);
|
|
|
|
|
} else {
|
|
|
|
|
close_button->set_tooltip_text(TTRC("This dock can't be closed."));
|
|
|
|
|
close_button->set_disabled(true);
|
|
|
|
|
}
|
|
|
|
|
if (EditorNode::get_singleton()->is_multi_window_enabled()) {
|
|
|
|
|
if (!(context_dock->available_layouts & EditorDock::DOCK_LAYOUT_FLOATING)) {
|
|
|
|
|
make_float_button->set_tooltip_text(TTRC("This dock does not support floating."));
|
|
|
|
|
make_float_button->set_disabled(true);
|
|
|
|
|
} else {
|
|
|
|
|
make_float_button->set_tooltip_text(TTRC("Make this dock floating."));
|
|
|
|
|
make_float_button->set_disabled(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update tab move buttons.
|
|
|
|
|
tab_move_left_button->set_disabled(true);
|
|
|
|
|
tab_move_right_button->set_disabled(true);
|
|
|
|
|
if (!dock_at_bottom && context_tab_container && context_tab_container->get_tab_count() > 0) {
|
|
|
|
|
if (context_tab_container && context_tab_container->get_tab_count() > 0) {
|
|
|
|
|
int context_tab_index = context_tab_container->get_tab_idx_from_control(context_dock);
|
|
|
|
|
tab_move_left_button->set_disabled(context_tab_index == 0);
|
|
|
|
|
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->available_layouts & EditorDock::DOCK_LAYOUT_HORIZONTAL));
|
|
|
|
|
reset_size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DockContextPopup::select_current_dock_in_dock_slot(int p_dock_slot) {
|
|
|
|
|
context_dock = Object::cast_to<EditorDock>(dock_manager->dock_slot[p_dock_slot]->get_current_tab_control());
|
|
|
|
|
context_dock = Object::cast_to<EditorDock>(dock_manager->dock_slots[p_dock_slot].container->get_current_tab_control());
|
|
|
|
|
_update_buttons();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -1262,7 +1259,7 @@ DockContextPopup::DockContextPopup() {
|
|
|
|
|
header_hb->add_child(tab_move_left_button);
|
|
|
|
|
|
|
|
|
|
Label *position_label = memnew(Label);
|
|
|
|
|
position_label->set_text(TTR("Dock Position"));
|
|
|
|
|
position_label->set_text(TTRC("Dock Position"));
|
|
|
|
|
position_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
|
|
|
|
position_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
|
|
|
|
|
header_hb->add_child(position_label);
|
|
|
|
|
@ -1285,32 +1282,39 @@ DockContextPopup::DockContextPopup() {
|
|
|
|
|
dock_select_popup_vb->add_child(dock_select);
|
|
|
|
|
|
|
|
|
|
make_float_button = memnew(Button);
|
|
|
|
|
make_float_button->set_text(TTR("Make Floating"));
|
|
|
|
|
make_float_button->set_text(TTRC("Make Floating"));
|
|
|
|
|
if (!EditorNode::get_singleton()->is_multi_window_enabled()) {
|
|
|
|
|
make_float_button->set_disabled(true);
|
|
|
|
|
make_float_button->set_tooltip_text(EditorNode::get_singleton()->get_multiwindow_support_tooltip_text());
|
|
|
|
|
} else {
|
|
|
|
|
make_float_button->set_tooltip_text(TTR("Make this dock floating."));
|
|
|
|
|
}
|
|
|
|
|
make_float_button->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
|
|
|
|
|
make_float_button->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
|
|
|
|
make_float_button->connect(SceneStringName(pressed), callable_mp(this, &DockContextPopup::_float_dock));
|
|
|
|
|
dock_select_popup_vb->add_child(make_float_button);
|
|
|
|
|
|
|
|
|
|
dock_to_bottom_button = memnew(Button);
|
|
|
|
|
dock_to_bottom_button->set_text(TTR("Move to Bottom"));
|
|
|
|
|
dock_to_bottom_button->set_tooltip_text(TTR("Move this dock to the bottom panel."));
|
|
|
|
|
dock_to_bottom_button->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
|
|
|
|
|
dock_to_bottom_button->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
|
|
|
|
dock_to_bottom_button->connect(SceneStringName(pressed), callable_mp(this, &DockContextPopup::_move_dock_to_bottom));
|
|
|
|
|
dock_to_bottom_button->hide();
|
|
|
|
|
dock_select_popup_vb->add_child(dock_to_bottom_button);
|
|
|
|
|
|
|
|
|
|
close_button = memnew(Button);
|
|
|
|
|
close_button->set_text(TTR("Close"));
|
|
|
|
|
close_button->set_tooltip_text(TTR("Close this dock."));
|
|
|
|
|
close_button->set_text(TTRC("Close"));
|
|
|
|
|
close_button->set_focus_mode(Control::FOCUS_ACCESSIBILITY);
|
|
|
|
|
close_button->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
|
|
|
|
close_button->connect(SceneStringName(pressed), callable_mp(this, &DockContextPopup::_close_dock));
|
|
|
|
|
dock_select_popup_vb->add_child(close_button);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DockShortcutHandler::shortcut_input(const Ref<InputEvent> &p_event) {
|
|
|
|
|
if (p_event.is_null() || !p_event->is_pressed() || p_event->is_echo()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (EditorDock *dock : EditorDockManager::get_singleton()->all_docks) {
|
|
|
|
|
const Ref<Shortcut> &dock_shortcut = dock->get_dock_shortcut();
|
|
|
|
|
if (dock_shortcut.is_valid() && dock_shortcut->matches_event(p_event)) {
|
|
|
|
|
if (dock->is_visible() && dock->get_parent() == EditorNode::get_bottom_panel()) {
|
|
|
|
|
EditorNode::get_bottom_panel()->hide_bottom_panel();
|
|
|
|
|
} else if (!dock->transient || dock->is_open) {
|
|
|
|
|
EditorDockManager::get_singleton()->focus_dock(dock);
|
|
|
|
|
}
|
|
|
|
|
get_viewport()->set_input_as_handled();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|