Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow docks to be closed and opened #89017

Merged
merged 1 commit into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 92 additions & 13 deletions editor/editor_dock_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,17 +149,53 @@ void EditorDockManager::_update_layout() {
}
EditorNode::get_singleton()->edit_current();
dock_context_popup->docks_updated();
_update_docks_menu();
EditorNode::get_singleton()->save_editor_layout_delayed();
}

void EditorDockManager::_update_docks_menu() {
docks_menu->clear();
docks_menu->reset_size();

const Ref<Texture2D> icon = docks_menu->get_editor_theme_icon(SNAME("Window"));
const Color closed_icon_color_mod = Color(1, 1, 1, 0.5);

// Add docks.
docks_menu_docks.clear();
int id = 0;
for (const KeyValue<Control *, DockInfo> &dock : all_docks) {
if (dock.value.shortcut.is_valid()) {
docks_menu->add_shortcut(dock.value.shortcut, id);
docks_menu->set_item_text(id, dock.value.title);
} else {
docks_menu->add_item(dock.value.title, id);
}
docks_menu->set_item_icon(id, icon);
if (!dock.value.open) {
docks_menu->set_item_icon_modulate(id, closed_icon_color_mod);
}
docks_menu->set_item_disabled(id, !dock.value.enabled);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Features that are disabled via Feature Profiles usually get hidden in the UI, not disabled. Seems like a simple change to skip adding the menu item in this case, instead of disabling.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I forgot about this for a while.

docks_menu_docks.push_back(dock.key);
id++;
}
}

void EditorDockManager::_docks_menu_option(int p_id) {
focus_dock(docks_menu_docks[p_id]);
}

void EditorDockManager::_window_close_request(WindowWrapper *p_wrapper) {
// Give the dock back to the original owner.
Control *dock = _close_window(p_wrapper);
ERR_FAIL_COND(!all_docks.has(dock));

all_docks[dock].open = false;
open_dock(dock);
focus_dock(dock);
if (all_docks[dock].previous_at_bottom || all_docks[dock].dock_slot_index != DOCK_SLOT_NONE) {
all_docks[dock].open = false;
open_dock(dock);
focus_dock(dock);
} else {
close_dock(dock);
}
}

Control *EditorDockManager::_close_window(WindowWrapper *p_wrapper) {
Expand All @@ -174,7 +210,7 @@ Control *EditorDockManager::_close_window(WindowWrapper *p_wrapper) {
return dock;
}

void EditorDockManager::_open_dock_in_window(Control *p_dock, bool p_show_window) {
void EditorDockManager::_open_dock_in_window(Control *p_dock, bool p_show_window, bool p_reset_size) {
ERR_FAIL_NULL(p_dock);

Size2 borders = Size2(4, 4) * EDSCALE;
Expand All @@ -201,6 +237,12 @@ void EditorDockManager::_open_dock_in_window(Control *p_dock, bool p_show_window
if (p_show_window) {
wrapper->restore_window(Rect2i(dock_screen_pos, dock_size), EditorNode::get_singleton()->get_gui_base()->get_window()->get_current_screen());
_update_layout();
if (p_reset_size) {
// Use a default size of one third the current window size.
Size2i popup_size = EditorNode::get_singleton()->get_window()->get_size() / 3.0;
p_dock->get_window()->set_size(popup_size);
p_dock->get_window()->move_to_center();
}
p_dock->get_window()->grab_focus();
}
}
Expand Down Expand Up @@ -338,6 +380,10 @@ void EditorDockManager::save_docks_to_config(Ref<ConfigFile> p_layout, const Str
p_layout->set_value(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx", selected_tab_idx);
}
}
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;
Expand Down Expand Up @@ -425,8 +471,8 @@ void EditorDockManager::load_docks_from_config(Ref<ConfigFile> p_layout, const S
dock_map[dock.key->get_name()] = dock.key;
}

// Load docks by slot.
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
// Load docks by slot. Index -1 is for docks that have no slot.
for (int i = -1; i < DOCK_SLOT_MAX; i++) {
if (!p_layout->has_section_key(p_section, "dock_" + itos(i + 1))) {
continue;
}
Expand All @@ -450,7 +496,7 @@ void EditorDockManager::load_docks_from_config(Ref<ConfigFile> p_layout, const S
_restore_dock_to_saved_window(dock, floating_docks_dump[name]);
} else if (dock_bottom.has(name)) {
_dock_move_to_bottom(dock);
} else {
} else if (i >= 0) {
_move_dock(dock, dock_slot[i], 0);
}

Expand All @@ -465,7 +511,7 @@ 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 = j;
all_docks[dock].previous_tab_index = i >= 0 ? j : 0;
}
}

Expand Down Expand Up @@ -500,6 +546,8 @@ void EditorDockManager::load_docks_from_config(Ref<ConfigFile> p_layout, const S
}

FileSystemDock::get_singleton()->load_layout_from_config(p_layout, p_section);

_update_docks_menu();
}

void EditorDockManager::bottom_dock_show_placement_popup(const Rect2i &p_position, Control *p_dock) {
Expand Down Expand Up @@ -564,13 +612,16 @@ void EditorDockManager::open_dock(Control *p_dock, bool p_set_current) {
// Open dock to its previous location.
if (all_docks[p_dock].previous_at_bottom) {
_dock_move_to_bottom(p_dock);
} else {
} 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;
if (tab_index < 0) {
tab_index = slot->get_tab_count();
}
_move_dock(p_dock, slot, tab_index, p_set_current);
} else {
_open_dock_in_window(p_dock, true, true);
return;
}

_update_layout();
Expand Down Expand Up @@ -615,9 +666,8 @@ void EditorDockManager::focus_dock(Control *p_dock) {
tab_container->set_current_tab(tab_index);
}

void EditorDockManager::add_control_to_dock(DockSlot p_slot, Control *p_dock, const String &p_title, const Ref<Shortcut> &p_shortcut) {
void EditorDockManager::add_dock(Control *p_dock, const String &p_title, DockSlot p_slot, const Ref<Shortcut> &p_shortcut) {
ERR_FAIL_NULL(p_dock);
ERR_FAIL_INDEX(p_slot, DOCK_SLOT_MAX);
ERR_FAIL_COND_MSG(all_docks.has(p_dock), vformat("Cannot add dock '%s', already added.", p_dock->get_name()));

DockInfo dock_info;
Expand All @@ -626,10 +676,17 @@ void EditorDockManager::add_control_to_dock(DockSlot p_slot, Control *p_dock, co
dock_info.shortcut = p_shortcut;
all_docks[p_dock] = dock_info;

open_dock(p_dock, false);
if (p_slot != DOCK_SLOT_NONE) {
ERR_FAIL_INDEX(p_slot, DOCK_SLOT_MAX);
open_dock(p_dock, false);
} else {
closed_dock_parent->add_child(p_dock);
p_dock->hide();
_update_layout();
}
}

void EditorDockManager::remove_control_from_dock(Control *p_dock) {
void EditorDockManager::remove_dock(Control *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()));

Expand Down Expand Up @@ -688,13 +745,21 @@ int EditorDockManager::get_vsplit_count() const {
return vsplits.size();
}

PopupMenu *EditorDockManager::get_docks_menu() {
return docks_menu;
}

EditorDockManager::EditorDockManager() {
singleton = this;

closed_dock_parent = EditorNode::get_singleton()->get_gui_base();

dock_context_popup = memnew(DockContextPopup);
EditorNode::get_singleton()->get_gui_base()->add_child(dock_context_popup);

docks_menu = memnew(PopupMenu);
docks_menu->connect("id_pressed", callable_mp(this, &EditorDockManager::_docks_menu_option));
EditorNode::get_singleton()->get_gui_base()->connect("theme_changed", callable_mp(this, &EditorDockManager::_update_docks_menu));
}

void DockContextPopup::_notification(int p_what) {
Expand All @@ -715,6 +780,7 @@ void DockContextPopup::_notification(int p_what) {
tab_move_right_button->set_tooltip_text(TTR("Move this dock right one tab."));
}
dock_to_bottom_button->set_icon(get_editor_theme_icon(SNAME("ControlAlignBottomWide")));
close_button->set_icon(get_editor_theme_icon(SNAME("Close")));
} break;
}
}
Expand All @@ -741,6 +807,11 @@ void DockContextPopup::_tab_move_right() {
dock_select->queue_redraw();
}

void DockContextPopup::_close_dock() {
hide();
dock_manager->close_dock(context_dock);
}

void DockContextPopup::_float_dock() {
hide();
dock_manager->_open_dock_in_window(context_dock);
Expand Down Expand Up @@ -975,4 +1046,12 @@ DockContextPopup::DockContextPopup() {
dock_to_bottom_button->connect("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_focus_mode(Control::FOCUS_NONE);
close_button->set_h_size_flags(Control::SIZE_EXPAND_FILL);
close_button->connect("pressed", callable_mp(this, &DockContextPopup::_close_dock));
dock_select_popup_vb->add_child(close_button);
}
17 changes: 13 additions & 4 deletions editor/editor_dock_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class EditorDockManager : public Object {

public:
enum DockSlot {
DOCK_SLOT_NONE = -1,
DOCK_SLOT_LEFT_UL,
DOCK_SLOT_LEFT_BL,
DOCK_SLOT_LEFT_UR,
Expand All @@ -84,7 +85,7 @@ class EditorDockManager : public Object {
int previous_tab_index = -1;
bool previous_at_bottom = false;
WindowWrapper *dock_window = nullptr;
int dock_slot_index = DOCK_SLOT_LEFT_UL;
int dock_slot_index = DOCK_SLOT_NONE;
Ref<Shortcut> shortcut;
};

Expand All @@ -100,6 +101,8 @@ class EditorDockManager : public Object {
bool docks_visible = true;

DockContextPopup *dock_context_popup = nullptr;
PopupMenu *docks_menu = nullptr;
Vector<Control *> docks_menu_docks;
Control *closed_dock_parent = nullptr;

void _dock_split_dragged(int p_offset);
Expand All @@ -108,9 +111,12 @@ class EditorDockManager : public Object {
void _dock_container_update_visibility(TabContainer *p_dock_container);
void _update_layout();

void _update_docks_menu();
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);
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);

void _dock_move_to_bottom(Control *p_dock);
Expand All @@ -127,6 +133,7 @@ class EditorDockManager : public Object {
void add_hsplit(DockSplitContainer *p_split);
void register_dock_slot(DockSlot p_dock_slot, TabContainer *p_tab_container);
int get_vsplit_count() const;
PopupMenu *get_docks_menu();

void save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section) const;
void load_docks_from_config(Ref<ConfigFile> p_layout, const String &p_section);
Expand All @@ -143,8 +150,8 @@ class EditorDockManager : public Object {
void set_docks_visible(bool p_show);
bool are_docks_visible() const;

void add_control_to_dock(DockSlot p_slot, Control *p_dock, const String &p_title = "", const Ref<Shortcut> &p_shortcut = nullptr);
void remove_control_from_dock(Control *p_dock);
void add_dock(Control *p_dock, const String &p_title = "", DockSlot p_slot = DOCK_SLOT_NONE, const Ref<Shortcut> &p_shortcut = nullptr);
void remove_dock(Control *p_dock);

EditorDockManager();
};
Expand All @@ -157,6 +164,7 @@ class DockContextPopup : public PopupPanel {
Button *make_float_button = nullptr;
Button *tab_move_left_button = nullptr;
Button *tab_move_right_button = nullptr;
Button *close_button = nullptr;
Button *dock_to_bottom_button = nullptr;

Control *dock_select = nullptr;
Expand All @@ -169,6 +177,7 @@ class DockContextPopup : public PopupPanel {

void _tab_move_left();
void _tab_move_right();
void _close_dock();
void _float_dock();
void _move_dock_to_bottom();

Expand Down
14 changes: 8 additions & 6 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6829,6 +6829,8 @@ EditorNode::EditorNode() {
settings_menu->add_shortcut(ED_SHORTCUT("editor/command_palette", TTR("Command Palette..."), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::P), HELP_COMMAND_PALETTE);
settings_menu->add_separator();

settings_menu->add_submenu_node_item(TTR("Editor Docks"), editor_dock_manager->get_docks_menu());

editor_layouts = memnew(PopupMenu);
editor_layouts->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
settings_menu->add_submenu_node_item(TTR("Editor Layout"), editor_layouts);
Expand Down Expand Up @@ -6998,22 +7000,22 @@ EditorNode::EditorNode() {
history_dock = memnew(HistoryDock);

// Scene: Top left.
editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_LEFT_UR, SceneTreeDock::get_singleton(), TTR("Scene"));
editor_dock_manager->add_dock(SceneTreeDock::get_singleton(), TTR("Scene"), EditorDockManager::DOCK_SLOT_LEFT_UR);

// Import: Top left, behind Scene.
editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_LEFT_UR, ImportDock::get_singleton(), TTR("Import"));
editor_dock_manager->add_dock(ImportDock::get_singleton(), TTR("Import"), EditorDockManager::DOCK_SLOT_LEFT_UR);

// FileSystem: Bottom left.
editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_LEFT_BR, FileSystemDock::get_singleton(), TTR("FileSystem"), ED_SHORTCUT_AND_COMMAND("bottom_panels/toggle_filesystem_bottom_panel", TTR("Toggle FileSystem Bottom Panel"), KeyModifierMask::ALT | Key::F));
editor_dock_manager->add_dock(FileSystemDock::get_singleton(), TTR("FileSystem"), EditorDockManager::DOCK_SLOT_LEFT_BR, ED_SHORTCUT_AND_COMMAND("bottom_panels/toggle_filesystem_bottom_panel", TTR("Toggle FileSystem Bottom Panel"), KeyModifierMask::ALT | Key::F));

// Inspector: Full height right.
editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_RIGHT_UL, InspectorDock::get_singleton(), TTR("Inspector"));
editor_dock_manager->add_dock(InspectorDock::get_singleton(), TTR("Inspector"), EditorDockManager::DOCK_SLOT_RIGHT_UL);

// Node: Full height right, behind Inspector.
editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_RIGHT_UL, NodeDock::get_singleton(), TTR("Node"));
editor_dock_manager->add_dock(NodeDock::get_singleton(), TTR("Node"), EditorDockManager::DOCK_SLOT_RIGHT_UL);

// History: Full height right, behind Node.
editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_RIGHT_UL, history_dock, TTR("History"));
editor_dock_manager->add_dock(history_dock, TTR("History"), EditorDockManager::DOCK_SLOT_RIGHT_UL);

// 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);
Expand Down
4 changes: 2 additions & 2 deletions editor/editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@ Button *EditorPlugin::add_control_to_bottom_panel(Control *p_control, const Stri

void EditorPlugin::add_control_to_dock(DockSlot p_slot, Control *p_control, const Ref<Shortcut> &p_shortcut) {
ERR_FAIL_NULL(p_control);
EditorDockManager::get_singleton()->add_control_to_dock(EditorDockManager::DockSlot(p_slot), p_control, String(), p_shortcut);
EditorDockManager::get_singleton()->add_dock(p_control, String(), EditorDockManager::DockSlot(p_slot), p_shortcut);
}

void EditorPlugin::remove_control_from_docks(Control *p_control) {
ERR_FAIL_NULL(p_control);
EditorDockManager::get_singleton()->remove_control_from_dock(p_control);
EditorDockManager::get_singleton()->remove_dock(p_control);
}

void EditorPlugin::remove_control_from_bottom_panel(Control *p_control) {
Expand Down
4 changes: 2 additions & 2 deletions editor/plugins/version_control_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,7 @@ void VersionControlEditorPlugin::fetch_available_vcs_plugin_names() {
}

void VersionControlEditorPlugin::register_editor() {
EditorDockManager::get_singleton()->add_control_to_dock(EditorDockManager::DOCK_SLOT_RIGHT_UL, version_commit_dock);
EditorDockManager::get_singleton()->add_dock(version_commit_dock, "", EditorDockManager::DOCK_SLOT_RIGHT_UL);

version_control_dock_button = EditorNode::get_bottom_panel()->add_item(TTR("Version Control"), version_control_dock, ED_SHORTCUT_AND_COMMAND("bottom_panels/toggle_version_control_bottom_panel", TTR("Toggle Version Control Bottom Panel")));

Expand All @@ -931,7 +931,7 @@ void VersionControlEditorPlugin::shut_down() {
memdelete(EditorVCSInterface::get_singleton());
EditorVCSInterface::set_singleton(nullptr);

EditorDockManager::get_singleton()->remove_control_from_dock(version_commit_dock);
EditorDockManager::get_singleton()->remove_dock(version_commit_dock);
EditorNode::get_bottom_panel()->remove_item(version_control_dock);

_set_vcs_ui_state(false);
Expand Down
Loading