From 64b4598baa9c404ba0c3b83c1c2524b6d2dcbcdd Mon Sep 17 00:00:00 2001 From: Anish Mishra Date: Thu, 1 May 2025 18:09:19 +0530 Subject: [PATCH 1/2] Improve Android editor layout --- editor/editor_node.cpp | 14 ++++++++++---- editor/editor_node.h | 3 ++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 558e8856a3a..ffe6a3e574e 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -7426,21 +7426,27 @@ EditorNode::EditorNode() { main_vbox = memnew(VBoxContainer); #ifdef ANDROID_ENABLED - main_hbox = memnew(HBoxContainer); - main_hbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); + base_vbox = memnew(VBoxContainer); + base_vbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, theme->get_constant(SNAME("window_border_margin"), EditorStringName(Editor))); + title_bar = memnew(EditorTitleBar); + base_vbox->add_child(title_bar); + + main_hbox = memnew(HBoxContainer); main_hbox->add_child(main_vbox); main_vbox->set_h_size_flags(Control::SIZE_EXPAND_FILL); + main_hbox->set_v_size_flags(Control::SIZE_EXPAND_FILL); + base_vbox->add_child(main_hbox); _touch_actions_panel_mode_changed(); - gui_base->add_child(main_hbox); + gui_base->add_child(base_vbox); #else gui_base->add_child(main_vbox); -#endif title_bar = memnew(EditorTitleBar); main_vbox->add_child(title_bar); +#endif left_l_hsplit = memnew(DockSplitContainer); left_l_hsplit->set_name("DockHSplitLeftL"); diff --git a/editor/editor_node.h b/editor/editor_node.h index a120d9b95da..4733194bfe5 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -282,7 +282,8 @@ private: OptionButton *renderer = nullptr; #ifdef ANDROID_ENABLED - HBoxContainer *main_hbox = nullptr; // Only created on Android for TouchActionsPanel. + VBoxContainer *base_vbox = nullptr; // It only contains the title_bar and main_hbox. + HBoxContainer *main_hbox = nullptr; // It only contains the touch_actions_panel and main_vbox. TouchActionsPanel *touch_actions_panel = nullptr; void _touch_actions_panel_mode_changed(); #endif From e03942a6ef4254e62b661a5553b0433d4bee9b3d Mon Sep 17 00:00:00 2001 From: Anish Mishra Date: Thu, 1 May 2025 18:09:31 +0530 Subject: [PATCH 2/2] Add editor setting to collapse main menu --- doc/classes/EditorSettings.xml | 5 + editor/editor_node.cpp | 157 ++++++++++++++++++++++++----- editor/editor_node.h | 16 ++- editor/editor_settings.cpp | 8 ++ editor/gui/touch_actions_panel.cpp | 1 - 5 files changed, 157 insertions(+), 30 deletions(-) diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml index a2939efd366..5071fc62351 100644 --- a/doc/classes/EditorSettings.xml +++ b/doc/classes/EditorSettings.xml @@ -836,6 +836,11 @@ The size of the font in the script editor. This setting does not impact the font size of the Output panel (see [member run/output/font_size]). + + If [code]true[/code], the main menu collapses into a [MenuButton]. + [b]Note:[/b] This setting is only applicable on macOS when [member interface/editor/use_embedded_menu] is [code]true[/code]. + [b]Note:[/b] Defaults to [code]true[/code] on the Android editor. + The custom editor scale factor to use. This can be used for displays with very high DPI where a scale factor of 200% is not sufficient. [b]Note:[/b] Only effective if [member interface/editor/display_scale] is set to [b]Custom[/b]. diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index ffe6a3e574e..4f83b3e1cc4 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -573,6 +573,10 @@ void EditorNode::_update_theme(bool p_skip_creation) { main_vbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, theme->get_constant(SNAME("window_border_margin"), EditorStringName(Editor))); main_vbox->add_theme_constant_override("separation", theme->get_constant(SNAME("top_bar_separation"), EditorStringName(Editor))); + if (main_menu_button != nullptr) { + main_menu_button->set_button_icon(theme->get_icon(SNAME("TripleBar"), EditorStringName(EditorIcons))); + } + editor_main_screen->add_theme_style_override(SceneStringName(panel), theme->get_stylebox(SNAME("Content"), EditorStringName(EditorStyles))); bottom_panel->add_theme_style_override(SceneStringName(panel), theme->get_stylebox(SNAME("BottomPanel"), EditorStringName(EditorStyles))); distraction_free->set_button_icon(theme->get_icon(SNAME("DistractionFree"), EditorStringName(EditorIcons))); @@ -934,6 +938,7 @@ void EditorNode::_notification(int p_what) { if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor")) { _update_update_spinner(); _update_vsync_mode(); + _update_main_menu_type(); DisplayServer::get_singleton()->screen_set_keep_on(EDITOR_GET("interface/editor/keep_screen_on")); } @@ -7080,6 +7085,112 @@ void EditorNode::set_unfocused_low_processor_usage_mode_enabled(bool p_enabled) unfocused_low_processor_usage_mode_enabled = p_enabled; } +void EditorNode::_update_main_menu_type() { + bool use_menu_button = EDITOR_GET("interface/editor/collapse_main_menu"); + bool global_menu = !bool(EDITOR_GET("interface/editor/use_embedded_menu")) && NativeMenu::get_singleton()->has_feature(NativeMenu::FEATURE_GLOBAL_MENU); + + bool already_using_button = main_menu_button != nullptr; + bool already_using_bar = main_menu_bar != nullptr; + if ((use_menu_button && already_using_button) || (!use_menu_button && already_using_bar)) { + return; // Already correctly configured. + } + + if (use_menu_button && !global_menu) { + main_menu_button = memnew(MenuButton); + main_menu_button->set_text(TTRC("Main Menu")); + main_menu_button->set_theme_type_variation("MainScreenButton"); + main_menu_button->set_focus_mode(Control::FOCUS_NONE); + if (is_inside_tree()) { + main_menu_button->set_button_icon(theme->get_icon(SNAME("TripleBar"), EditorStringName(EditorIcons))); + } + main_menu_button->set_switch_on_hover(true); + + if (main_menu_bar != nullptr) { + Vector menus_to_move; + for (int i = 0; i < main_menu_bar->get_child_count(); i++) { + PopupMenu *menu = Object::cast_to(main_menu_bar->get_child(i)); + if (menu != nullptr) { + menus_to_move.push_back(menu); + } + } + for (PopupMenu *menu : menus_to_move) { + main_menu_bar->remove_child(menu); + main_menu_button->get_popup()->add_submenu_node_item(menu->get_name(), menu); + } + } + +#ifdef ANDROID_ENABLED + // Align main menu icon visually with TouchActionsPanel buttons. + main_menu_button->get_popup()->add_theme_constant_override("v_separation", 16 * EDSCALE); + menu_btn_spacer = memnew(Control); + menu_btn_spacer->set_custom_minimum_size(Vector2(8, 0) * EDSCALE); + title_bar->add_child(menu_btn_spacer); + title_bar->move_child(menu_btn_spacer, 0); +#endif + title_bar->add_child(main_menu_button); + if (menu_btn_spacer == nullptr) { + title_bar->move_child(main_menu_button, 0); + } else { + title_bar->move_child(main_menu_button, 1); + } + memdelete_notnull(main_menu_bar); + main_menu_bar = nullptr; + + if (project_run_bar != nullptr) { + // Adjust spacers to center 2D / 3D / Script buttons. + int max_w = MAX(project_run_bar->get_minimum_size().x + right_menu_hb->get_minimum_size().x, main_menu_button->get_minimum_size().x); + left_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - main_menu_button->get_minimum_size().x), 0)); + right_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - project_run_bar->get_minimum_size().x - right_menu_hb->get_minimum_size().x), 0)); + } + } else { + main_menu_bar = memnew(MenuBar); + main_menu_bar->set_mouse_filter(Control::MOUSE_FILTER_STOP); + main_menu_bar->set_v_size_flags(Control::SIZE_SHRINK_CENTER); + main_menu_bar->set_theme_type_variation("MainMenuBar"); + main_menu_bar->set_start_index(0); // Main menu, add to the start of global menu. + main_menu_bar->set_prefer_global_menu(global_menu); + main_menu_bar->set_switch_on_hover(true); + + if (main_menu_button != nullptr) { + Vector menus_to_move; + for (int i = 0; i < main_menu_button->get_item_count(); i++) { + PopupMenu *menu = main_menu_button->get_popup()->get_item_submenu_node(i); + if (menu != nullptr) { + menus_to_move.push_back(menu); + } + } + for (PopupMenu *menu : menus_to_move) { + menu->get_parent()->remove_child(menu); + main_menu_bar->add_child(menu); + } + } + + title_bar->add_child(main_menu_bar); + title_bar->move_child(main_menu_bar, 0); + + memdelete_notnull(menu_btn_spacer); + memdelete_notnull(main_menu_button); + menu_btn_spacer = nullptr; + main_menu_button = nullptr; + + if (project_run_bar != nullptr) { + // Adjust spacers to center 2D / 3D / Script buttons. + int max_w = MAX(project_run_bar->get_minimum_size().x + right_menu_hb->get_minimum_size().x, main_menu_bar->get_minimum_size().x); + left_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - main_menu_bar->get_minimum_size().x), 0)); + right_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - project_run_bar->get_minimum_size().x - right_menu_hb->get_minimum_size().x), 0)); + } + } +} + +void EditorNode::_add_to_main_menu(const String &p_name, PopupMenu *p_menu) { + p_menu->set_name(p_name); + if (main_menu_button != nullptr) { + main_menu_button->get_popup()->add_submenu_node_item(p_name, p_menu); + } else { + main_menu_bar->add_child(p_menu); + } +} + #ifdef ANDROID_ENABLED void EditorNode::_touch_actions_panel_mode_changed() { int panel_mode = EDITOR_GET("interface/touchscreen/touch_actions_panel"); @@ -7601,19 +7712,10 @@ EditorNode::EditorNode() { title_bar->add_child(left_menu_spacer); } - main_menu = memnew(MenuBar); - main_menu->set_mouse_filter(Control::MOUSE_FILTER_STOP); - title_bar->add_child(main_menu); - main_menu->set_v_size_flags(Control::SIZE_SHRINK_CENTER); - main_menu->set_theme_type_variation("MainMenuBar"); - main_menu->set_start_index(0); // Main menu, add to the start of global menu. - main_menu->set_prefer_global_menu(global_menu); - main_menu->set_switch_on_hover(true); + _update_main_menu_type(); file_menu = memnew(PopupMenu); - file_menu->set_name(TTRC("Scene")); - main_menu->add_child(file_menu); - main_menu->set_menu_tooltip(0, TTR("Operations with scene files.")); + _add_to_main_menu(TTRC("Scene"), file_menu); accept = memnew(AcceptDialog); accept->set_autowrap(true); @@ -7728,7 +7830,7 @@ EditorNode::EditorNode() { if (global_menu && NativeMenu::get_singleton()->has_system_menu(NativeMenu::APPLICATION_MENU_ID)) { apple_menu = memnew(PopupMenu); apple_menu->set_system_menu(NativeMenu::APPLICATION_MENU_ID); - main_menu->add_child(apple_menu); + main_menu_bar->add_child(apple_menu); apple_menu->add_shortcut(ED_GET_SHORTCUT("editor/editor_settings"), EDITOR_OPEN_SETTINGS); apple_menu->add_separator(); @@ -7737,8 +7839,7 @@ EditorNode::EditorNode() { #endif project_menu = memnew(PopupMenu); - project_menu->set_name(TTRC("Project")); - main_menu->add_child(project_menu); + _add_to_main_menu(TTRC("Project"), project_menu); project_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/project_settings", TTRC("Project Settings..."), Key::NONE, TTRC("Project Settings")), PROJECT_OPEN_SETTINGS); project_menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorNode::_menu_option)); @@ -7770,7 +7871,7 @@ EditorNode::EditorNode() { project_menu->add_shortcut(ED_GET_SHORTCUT("editor/quit_to_project_list"), PROJECT_QUIT_TO_PROJECT_MANAGER, true); // Spacer to center 2D / 3D / Script buttons. - HBoxContainer *left_spacer = memnew(HBoxContainer); + left_spacer = memnew(HBoxContainer); left_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS); left_spacer->set_h_size_flags(Control::SIZE_EXPAND_FILL); title_bar->add_child(left_spacer); @@ -7794,12 +7895,10 @@ EditorNode::EditorNode() { // Options are added and handled by DebuggerEditorPlugin. debug_menu = memnew(PopupMenu); - debug_menu->set_name(TTRC("Debug")); - main_menu->add_child(debug_menu); + _add_to_main_menu(TTRC("Debug"), debug_menu); settings_menu = memnew(PopupMenu); - settings_menu->set_name(TTRC("Editor")); - main_menu->add_child(settings_menu); + _add_to_main_menu(TTRC("Editor"), settings_menu); #ifdef MACOS_ENABLED if (!global_menu) { @@ -7848,11 +7947,10 @@ EditorNode::EditorNode() { #endif help_menu = memnew(PopupMenu); - help_menu->set_name(TTRC("Help")); if (global_menu && NativeMenu::get_singleton()->has_system_menu(NativeMenu::HELP_MENU_ID)) { help_menu->set_system_menu(NativeMenu::HELP_MENU_ID); } - main_menu->add_child(help_menu); + _add_to_main_menu(TTRC("Help"), help_menu); help_menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorNode::_menu_option)); @@ -7877,7 +7975,7 @@ EditorNode::EditorNode() { help_menu->add_icon_shortcut(_get_editor_theme_native_menu_icon(SNAME("Heart"), global_menu, dark_mode), ED_SHORTCUT_AND_COMMAND("editor/support_development", TTRC("Support Godot Development")), HELP_SUPPORT_GODOT_DEVELOPMENT); // Spacer to center 2D / 3D / Script buttons. - Control *right_spacer = memnew(Control); + right_spacer = memnew(Control); right_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS); right_spacer->set_h_size_flags(Control::SIZE_EXPAND_FILL); title_bar->add_child(right_spacer); @@ -7888,7 +7986,7 @@ EditorNode::EditorNode() { project_run_bar->connect("play_pressed", callable_mp(this, &EditorNode::_project_run_started)); project_run_bar->connect("stop_pressed", callable_mp(this, &EditorNode::_project_run_stopped)); - HBoxContainer *right_menu_hb = memnew(HBoxContainer); + right_menu_hb = memnew(HBoxContainer); right_menu_hb->set_mouse_filter(Control::MOUSE_FILTER_STOP); title_bar->add_child(right_menu_hb); @@ -8415,10 +8513,15 @@ EditorNode::EditorNode() { screenshot_timer->set_owner(get_owner()); // Adjust spacers to center 2D / 3D / Script buttons. - int max_w = MAX(project_run_bar->get_minimum_size().x + right_menu_hb->get_minimum_size().x, main_menu->get_minimum_size().x); - left_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - main_menu->get_minimum_size().x), 0)); - right_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - project_run_bar->get_minimum_size().x - right_menu_hb->get_minimum_size().x), 0)); - + if (main_menu_button != nullptr) { + int max_w = MAX(project_run_bar->get_minimum_size().x + right_menu_hb->get_minimum_size().x, main_menu_button->get_minimum_size().x); + left_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - main_menu_button->get_minimum_size().x), 0)); + right_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - project_run_bar->get_minimum_size().x - right_menu_hb->get_minimum_size().x), 0)); + } else { + int max_w = MAX(project_run_bar->get_minimum_size().x + right_menu_hb->get_minimum_size().x, main_menu_bar->get_minimum_size().x); + left_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - main_menu_bar->get_minimum_size().x), 0)); + right_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - project_run_bar->get_minimum_size().x - right_menu_hb->get_minimum_size().x), 0)); + } // Extend menu bar to window title. if (can_expand) { DisplayServer::get_singleton()->process_events(); diff --git a/editor/editor_node.h b/editor/editor_node.h index 4733194bfe5..835a4bf8a22 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -45,6 +45,7 @@ class ColorPicker; class ConfirmationDialog; class Control; class FileDialog; +class HBoxContainer; class MenuBar; class MenuButton; class OptionButton; @@ -100,7 +101,6 @@ class SceneImportSettingsDialog; class ProjectUpgradeTool; #ifdef ANDROID_ENABLED -class HBoxContainer; class TouchActionsPanel; #endif @@ -325,7 +325,16 @@ private: Control *right_menu_spacer = nullptr; EditorTitleBar *title_bar = nullptr; EditorRunBar *project_run_bar = nullptr; - MenuBar *main_menu = nullptr; + HBoxContainer *right_menu_hb = nullptr; + + // Spacers to center 2D / 3D / Script buttons. + HBoxContainer *left_spacer = nullptr; + Control *right_spacer = nullptr; + + Control *menu_btn_spacer = nullptr; + MenuButton *main_menu_button = nullptr; + MenuBar *main_menu_bar = nullptr; + PopupMenu *apple_menu = nullptr; PopupMenu *file_menu = nullptr; PopupMenu *project_menu = nullptr; @@ -689,6 +698,9 @@ private: bool _is_project_data_missing(); + void _update_main_menu_type(); + void _add_to_main_menu(const String &p_name, PopupMenu *p_menu); + protected: friend class FileSystemDock; diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index a6861a4a872..b177ba81a7e 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -529,6 +529,14 @@ void EditorSettings::_load_defaults(Ref p_extra_config) { EDITOR_SETTING_BASIC(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/vsync_mode", 1, "Disabled,Enabled,Adaptive,Mailbox") EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/update_continuously", false, "") + bool is_android_editor = false; +#ifdef ANDROID_ENABLED + if (!OS::get_singleton()->has_feature("xr_editor")) { + is_android_editor = true; + } +#endif + EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/collapse_main_menu", is_android_editor, "") + _initial_set("interface/editors/show_scene_tree_root_selection", true); _initial_set("interface/editors/derive_script_globals_by_name", true); _initial_set("docks/scene_tree/ask_before_revoking_unique_name", true); diff --git a/editor/gui/touch_actions_panel.cpp b/editor/gui/touch_actions_panel.cpp index bec5a25a287..8cb04dd4e6b 100644 --- a/editor/gui/touch_actions_panel.cpp +++ b/editor/gui/touch_actions_panel.cpp @@ -240,7 +240,6 @@ TouchActionsPanel::TouchActionsPanel() { } box = memnew(BoxContainer); - box->set_alignment(BoxContainer::ALIGNMENT_CENTER); box->add_theme_constant_override("separation", 20); if (is_floating) { box->set_vertical(EDITOR_DEF("_touch_actions_panel_vertical_layout", false));