diff options
Diffstat (limited to 'editor/editor_dock_manager.cpp')
-rw-r--r-- | editor/editor_dock_manager.cpp | 150 |
1 files changed, 115 insertions, 35 deletions
diff --git a/editor/editor_dock_manager.cpp b/editor/editor_dock_manager.cpp index b6250671ee..5d98fefa76 100644 --- a/editor/editor_dock_manager.cpp +++ b/editor/editor_dock_manager.cpp @@ -33,12 +33,10 @@ #include "scene/gui/box_container.h" #include "scene/gui/button.h" #include "scene/gui/label.h" -#include "scene/gui/popup.h" #include "scene/gui/split_container.h" #include "scene/gui/tab_container.h" #include "scene/main/window.h" -#include "editor/editor_command_palette.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" #include "editor/editor_string_names.h" @@ -47,6 +45,12 @@ #include "editor/themes/editor_scale.h" #include "editor/window_wrapper.h" +enum class TabStyle { + TEXT_ONLY, + ICON_ONLY, + TEXT_AND_ICON, +}; + EditorDockManager *EditorDockManager::singleton = nullptr; void DockSplitContainer::_update_visibility() { @@ -55,12 +59,13 @@ void DockSplitContainer::_update_visibility() { } is_updating = true; bool any_visible = false; - for (int i = 0; i < 2; i++) { - Control *split = get_containable_child(i); - if (split && split->is_visible()) { - any_visible = true; - break; + for (int i = 0; i < get_child_count(false); i++) { + Control *c = Object::cast_to<Control>(get_child(i, false)); + if (!c || !c->is_visible() || c->is_set_as_top_level()) { + continue; } + any_visible = c; + break; } set_visible(any_visible); is_updating = false; @@ -70,10 +75,13 @@ void DockSplitContainer::add_child_notify(Node *p_child) { SplitContainer::add_child_notify(p_child); Control *child_control = nullptr; - for (int i = 0; i < 2; i++) { - Control *split = get_containable_child(i); - if (p_child == split) { - child_control = split; + for (int i = 0; i < get_child_count(false); i++) { + Control *c = Object::cast_to<Control>(get_child(i, false)); + if (!c || c->is_set_as_top_level()) { + continue; + } + if (p_child == c) { + child_control = c; break; } } @@ -81,7 +89,7 @@ void DockSplitContainer::add_child_notify(Node *p_child) { return; } - child_control->connect("visibility_changed", callable_mp(this, &DockSplitContainer::_update_visibility)); + child_control->connect(SceneStringName(visibility_changed), callable_mp(this, &DockSplitContainer::_update_visibility)); _update_visibility(); } @@ -89,10 +97,13 @@ void DockSplitContainer::remove_child_notify(Node *p_child) { SplitContainer::remove_child_notify(p_child); Control *child_control = nullptr; - for (int i = 0; i < 2; i++) { - Control *split = get_containable_child(i); - if (p_child == split) { - child_control = split; + for (int i = 0; i < get_child_count(false); i++) { + Control *c = Object::cast_to<Control>(get_child(i, false)); + if (!c || c->is_set_as_top_level()) { + continue; + } + if (p_child == c) { + child_control = c; break; } } @@ -100,7 +111,7 @@ void DockSplitContainer::remove_child_notify(Node *p_child) { return; } - child_control->disconnect("visibility_changed", callable_mp(this, &DockSplitContainer::_update_visibility)); + child_control->disconnect(SceneStringName(visibility_changed), callable_mp(this, &DockSplitContainer::_update_visibility)); _update_visibility(); } @@ -147,7 +158,6 @@ void EditorDockManager::_update_layout() { if (!dock_context_popup->is_inside_tree() || EditorNode::get_singleton()->is_exiting()) { return; } - EditorNode::get_singleton()->edit_current(); dock_context_popup->docks_updated(); _update_docks_menu(); EditorNode::get_singleton()->save_editor_layout_delayed(); @@ -157,7 +167,7 @@ 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 Ref<Texture2D> default_icon = docks_menu->get_editor_theme_icon(SNAME("Window")); const Color closed_icon_color_mod = Color(1, 1, 1, 0.5); // Add docks. @@ -170,7 +180,8 @@ void EditorDockManager::_update_docks_menu() { } else { docks_menu->add_item(dock.value.title, id); } - docks_menu->set_item_icon(id, icon); + const Ref<Texture2D> icon = dock.value.icon_name ? docks_menu->get_editor_theme_icon(dock.value.icon_name) : dock.value.icon; + docks_menu->set_item_icon(id, icon.is_valid() ? icon : default_icon); if (!dock.value.open) { docks_menu->set_item_icon_modulate(id, closed_icon_color_mod); } @@ -181,7 +192,15 @@ void EditorDockManager::_update_docks_menu() { } void EditorDockManager::_docks_menu_option(int p_id) { - focus_dock(docks_menu_docks[p_id]); + Control *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) { + PopupMenu *parent_menu = Object::cast_to<PopupMenu>(docks_menu->get_parent()); + ERR_FAIL_NULL(parent_menu); + parent_menu->hide(); + } + focus_dock(dock); } void EditorDockManager::_window_close_request(WindowWrapper *p_wrapper) { @@ -268,7 +287,7 @@ void EditorDockManager::_dock_move_to_bottom(Control *p_dock) { // 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); - bottom_button->connect("gui_input", callable_mp(this, &EditorDockManager::_bottom_dock_button_gui_input).bind(bottom_button).bind(p_dock)); + 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); } @@ -345,7 +364,9 @@ void EditorDockManager::_move_dock(Control *p_dock, Control *p_target, int p_tab p_target->set_block_signals(false); TabContainer *dock_tab_container = Object::cast_to<TabContainer>(p_target); if (dock_tab_container) { - dock_tab_container->set_tab_title(dock_tab_container->get_tab_idx_from_control(p_dock), all_docks[p_dock].title); + if (dock_tab_container->is_inside_tree()) { + _update_tab_style(p_dock); + } if (p_tab_index >= 0) { _move_dock_tab_index(p_dock, p_tab_index, p_set_current); } @@ -353,6 +374,42 @@ 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) { + return; // Disabled by feature profile or manually closed by user. + } + if (dock_info.dock_window || dock_info.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(); + switch (style) { + case TabStyle::TEXT_ONLY: { + tab_container->set_tab_title(index, dock_info.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_icon(index, icon); + tab_container->set_tab_tooltip(index, icon.is_valid() ? dock_info.title : String()); + } 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_icon(index, icon); + tab_container->set_tab_tooltip(index, String()); + } break; + } +} + 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++) { @@ -666,14 +723,15 @@ 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) { +void EditorDockManager::add_dock(Control *p_dock, const String &p_title, DockSlot p_slot, const Ref<Shortcut> &p_shortcut, const StringName &p_icon_name) { 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())); DockInfo dock_info; - dock_info.title = !p_title.is_empty() ? p_title : String(p_dock->get_name()); + 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; if (p_slot != DOCK_SLOT_NONE) { @@ -696,6 +754,14 @@ void EditorDockManager::remove_dock(Control *p_dock) { _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; @@ -711,6 +777,19 @@ bool EditorDockManager::are_docks_visible() const { return docks_visible; } +void EditorDockManager::update_tab_styles() { + for (const KeyValue<Control *, DockInfo> &dock : all_docks) { + _update_tab_style(dock.key); + } +} + +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]; + tab_container->add_theme_constant_override(SNAME("icon_max_width"), p_max_width); + } +} + void EditorDockManager::add_vsplit(DockSplitContainer *p_split) { vsplits.push_back(p_split); p_split->connect("dragged", callable_mp(this, &EditorDockManager::_dock_split_dragged)); @@ -737,7 +816,7 @@ void EditorDockManager::register_dock_slot(DockSlot p_dock_slot, TabContainer *p 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->get_tab_bar()->connect("gui_input", callable_mp(this, &EditorDockManager::_dock_container_gui_input).bind(p_tab_container)); + p_tab_container->get_tab_bar()->connect(SceneStringName(gui_input), callable_mp(this, &EditorDockManager::_dock_container_gui_input).bind(p_tab_container)); p_tab_container->hide(); } @@ -758,8 +837,9 @@ EditorDockManager::EditorDockManager() { EditorNode::get_singleton()->get_gui_base()->add_child(dock_context_popup); docks_menu = memnew(PopupMenu); + docks_menu->set_hide_on_item_selection(false); 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)); + EditorNode::get_singleton()->get_gui_base()->connect(SceneStringName(theme_changed), callable_mp(this, &EditorDockManager::_update_docks_menu)); } void DockContextPopup::_notification(int p_what) { @@ -1000,7 +1080,7 @@ DockContextPopup::DockContextPopup() { tab_move_left_button = memnew(Button); tab_move_left_button->set_flat(true); tab_move_left_button->set_focus_mode(Control::FOCUS_NONE); - tab_move_left_button->connect("pressed", callable_mp(this, &DockContextPopup::_tab_move_left)); + tab_move_left_button->connect(SceneStringName(pressed), callable_mp(this, &DockContextPopup::_tab_move_left)); header_hb->add_child(tab_move_left_button); Label *position_label = memnew(Label); @@ -1012,16 +1092,16 @@ DockContextPopup::DockContextPopup() { tab_move_right_button = memnew(Button); tab_move_right_button->set_flat(true); tab_move_right_button->set_focus_mode(Control::FOCUS_NONE); - tab_move_right_button->connect("pressed", callable_mp(this, &DockContextPopup::_tab_move_right)); + tab_move_right_button->connect(SceneStringName(pressed), callable_mp(this, &DockContextPopup::_tab_move_right)); header_hb->add_child(tab_move_right_button); dock_select_popup_vb->add_child(header_hb); dock_select = memnew(Control); dock_select->set_custom_minimum_size(Size2(128, 64) * EDSCALE); - dock_select->connect("gui_input", callable_mp(this, &DockContextPopup::_dock_select_input)); - dock_select->connect("draw", callable_mp(this, &DockContextPopup::_dock_select_draw)); - dock_select->connect("mouse_exited", callable_mp(this, &DockContextPopup::_dock_select_mouse_exited)); + dock_select->connect(SceneStringName(gui_input), callable_mp(this, &DockContextPopup::_dock_select_input)); + dock_select->connect(SceneStringName(draw), callable_mp(this, &DockContextPopup::_dock_select_draw)); + dock_select->connect(SceneStringName(mouse_exited), callable_mp(this, &DockContextPopup::_dock_select_mouse_exited)); dock_select->set_v_size_flags(Control::SIZE_EXPAND_FILL); dock_select_popup_vb->add_child(dock_select); @@ -1035,7 +1115,7 @@ DockContextPopup::DockContextPopup() { } make_float_button->set_focus_mode(Control::FOCUS_NONE); make_float_button->set_h_size_flags(Control::SIZE_EXPAND_FILL); - make_float_button->connect("pressed", callable_mp(this, &DockContextPopup::_float_dock)); + 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); @@ -1043,7 +1123,7 @@ DockContextPopup::DockContextPopup() { dock_to_bottom_button->set_tooltip_text(TTR("Move this dock to the bottom panel.")); dock_to_bottom_button->set_focus_mode(Control::FOCUS_NONE); dock_to_bottom_button->set_h_size_flags(Control::SIZE_EXPAND_FILL); - dock_to_bottom_button->connect("pressed", callable_mp(this, &DockContextPopup::_move_dock_to_bottom)); + 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); @@ -1052,6 +1132,6 @@ DockContextPopup::DockContextPopup() { 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)); + close_button->connect(SceneStringName(pressed), callable_mp(this, &DockContextPopup::_close_dock)); dock_select_popup_vb->add_child(close_button); } |