Skip to content

Commit c714743

Browse files
committed
Merge pull request #105944 from syntaxerror247/main-menu
Add editor setting to collapse main menu into a `MenuButton`
2 parents 0ce3d75 + e03942a commit c714743

File tree

5 files changed

+169
-35
lines changed

5 files changed

+169
-35
lines changed

doc/classes/EditorSettings.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,11 @@
836836
<member name="interface/editor/code_font_size" type="int" setter="" getter="">
837837
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]).
838838
</member>
839+
<member name="interface/editor/collapse_main_menu" type="bool" setter="" getter="">
840+
If [code]true[/code], the main menu collapses into a [MenuButton].
841+
[b]Note:[/b] This setting is only applicable on macOS when [member interface/editor/use_embedded_menu] is [code]true[/code].
842+
[b]Note:[/b] Defaults to [code]true[/code] on the Android editor.
843+
</member>
839844
<member name="interface/editor/custom_display_scale" type="float" setter="" getter="">
840845
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.
841846
[b]Note:[/b] Only effective if [member interface/editor/display_scale] is set to [b]Custom[/b].

editor/editor_node.cpp

Lines changed: 140 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,10 @@ void EditorNode::_update_theme(bool p_skip_creation) {
573573
main_vbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, theme->get_constant(SNAME("window_border_margin"), EditorStringName(Editor)));
574574
main_vbox->add_theme_constant_override("separation", theme->get_constant(SNAME("top_bar_separation"), EditorStringName(Editor)));
575575

576+
if (main_menu_button != nullptr) {
577+
main_menu_button->set_button_icon(theme->get_icon(SNAME("TripleBar"), EditorStringName(EditorIcons)));
578+
}
579+
576580
editor_main_screen->add_theme_style_override(SceneStringName(panel), theme->get_stylebox(SNAME("Content"), EditorStringName(EditorStyles)));
577581
bottom_panel->add_theme_style_override(SceneStringName(panel), theme->get_stylebox(SNAME("BottomPanel"), EditorStringName(EditorStyles)));
578582
distraction_free->set_button_icon(theme->get_icon(SNAME("DistractionFree"), EditorStringName(EditorIcons)));
@@ -934,6 +938,7 @@ void EditorNode::_notification(int p_what) {
934938
if (EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor")) {
935939
_update_update_spinner();
936940
_update_vsync_mode();
941+
_update_main_menu_type();
937942
DisplayServer::get_singleton()->screen_set_keep_on(EDITOR_GET("interface/editor/keep_screen_on"));
938943
}
939944

@@ -7080,6 +7085,112 @@ void EditorNode::set_unfocused_low_processor_usage_mode_enabled(bool p_enabled)
70807085
unfocused_low_processor_usage_mode_enabled = p_enabled;
70817086
}
70827087

7088+
void EditorNode::_update_main_menu_type() {
7089+
bool use_menu_button = EDITOR_GET("interface/editor/collapse_main_menu");
7090+
bool global_menu = !bool(EDITOR_GET("interface/editor/use_embedded_menu")) && NativeMenu::get_singleton()->has_feature(NativeMenu::FEATURE_GLOBAL_MENU);
7091+
7092+
bool already_using_button = main_menu_button != nullptr;
7093+
bool already_using_bar = main_menu_bar != nullptr;
7094+
if ((use_menu_button && already_using_button) || (!use_menu_button && already_using_bar)) {
7095+
return; // Already correctly configured.
7096+
}
7097+
7098+
if (use_menu_button && !global_menu) {
7099+
main_menu_button = memnew(MenuButton);
7100+
main_menu_button->set_text(TTRC("Main Menu"));
7101+
main_menu_button->set_theme_type_variation("MainScreenButton");
7102+
main_menu_button->set_focus_mode(Control::FOCUS_NONE);
7103+
if (is_inside_tree()) {
7104+
main_menu_button->set_button_icon(theme->get_icon(SNAME("TripleBar"), EditorStringName(EditorIcons)));
7105+
}
7106+
main_menu_button->set_switch_on_hover(true);
7107+
7108+
if (main_menu_bar != nullptr) {
7109+
Vector<PopupMenu *> menus_to_move;
7110+
for (int i = 0; i < main_menu_bar->get_child_count(); i++) {
7111+
PopupMenu *menu = Object::cast_to<PopupMenu>(main_menu_bar->get_child(i));
7112+
if (menu != nullptr) {
7113+
menus_to_move.push_back(menu);
7114+
}
7115+
}
7116+
for (PopupMenu *menu : menus_to_move) {
7117+
main_menu_bar->remove_child(menu);
7118+
main_menu_button->get_popup()->add_submenu_node_item(menu->get_name(), menu);
7119+
}
7120+
}
7121+
7122+
#ifdef ANDROID_ENABLED
7123+
// Align main menu icon visually with TouchActionsPanel buttons.
7124+
main_menu_button->get_popup()->add_theme_constant_override("v_separation", 16 * EDSCALE);
7125+
menu_btn_spacer = memnew(Control);
7126+
menu_btn_spacer->set_custom_minimum_size(Vector2(8, 0) * EDSCALE);
7127+
title_bar->add_child(menu_btn_spacer);
7128+
title_bar->move_child(menu_btn_spacer, 0);
7129+
#endif
7130+
title_bar->add_child(main_menu_button);
7131+
if (menu_btn_spacer == nullptr) {
7132+
title_bar->move_child(main_menu_button, 0);
7133+
} else {
7134+
title_bar->move_child(main_menu_button, 1);
7135+
}
7136+
memdelete_notnull(main_menu_bar);
7137+
main_menu_bar = nullptr;
7138+
7139+
if (project_run_bar != nullptr) {
7140+
// Adjust spacers to center 2D / 3D / Script buttons.
7141+
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);
7142+
left_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - main_menu_button->get_minimum_size().x), 0));
7143+
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));
7144+
}
7145+
} else {
7146+
main_menu_bar = memnew(MenuBar);
7147+
main_menu_bar->set_mouse_filter(Control::MOUSE_FILTER_STOP);
7148+
main_menu_bar->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
7149+
main_menu_bar->set_theme_type_variation("MainMenuBar");
7150+
main_menu_bar->set_start_index(0); // Main menu, add to the start of global menu.
7151+
main_menu_bar->set_prefer_global_menu(global_menu);
7152+
main_menu_bar->set_switch_on_hover(true);
7153+
7154+
if (main_menu_button != nullptr) {
7155+
Vector<PopupMenu *> menus_to_move;
7156+
for (int i = 0; i < main_menu_button->get_item_count(); i++) {
7157+
PopupMenu *menu = main_menu_button->get_popup()->get_item_submenu_node(i);
7158+
if (menu != nullptr) {
7159+
menus_to_move.push_back(menu);
7160+
}
7161+
}
7162+
for (PopupMenu *menu : menus_to_move) {
7163+
menu->get_parent()->remove_child(menu);
7164+
main_menu_bar->add_child(menu);
7165+
}
7166+
}
7167+
7168+
title_bar->add_child(main_menu_bar);
7169+
title_bar->move_child(main_menu_bar, 0);
7170+
7171+
memdelete_notnull(menu_btn_spacer);
7172+
memdelete_notnull(main_menu_button);
7173+
menu_btn_spacer = nullptr;
7174+
main_menu_button = nullptr;
7175+
7176+
if (project_run_bar != nullptr) {
7177+
// Adjust spacers to center 2D / 3D / Script buttons.
7178+
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);
7179+
left_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - main_menu_bar->get_minimum_size().x), 0));
7180+
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));
7181+
}
7182+
}
7183+
}
7184+
7185+
void EditorNode::_add_to_main_menu(const String &p_name, PopupMenu *p_menu) {
7186+
p_menu->set_name(p_name);
7187+
if (main_menu_button != nullptr) {
7188+
main_menu_button->get_popup()->add_submenu_node_item(p_name, p_menu);
7189+
} else {
7190+
main_menu_bar->add_child(p_menu);
7191+
}
7192+
}
7193+
70837194
#ifdef ANDROID_ENABLED
70847195
void EditorNode::_touch_actions_panel_mode_changed() {
70857196
int panel_mode = EDITOR_GET("interface/touchscreen/touch_actions_panel");
@@ -7426,21 +7537,27 @@ EditorNode::EditorNode() {
74267537
main_vbox = memnew(VBoxContainer);
74277538

74287539
#ifdef ANDROID_ENABLED
7429-
main_hbox = memnew(HBoxContainer);
7430-
main_hbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
7540+
base_vbox = memnew(VBoxContainer);
7541+
base_vbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, theme->get_constant(SNAME("window_border_margin"), EditorStringName(Editor)));
74317542

7543+
title_bar = memnew(EditorTitleBar);
7544+
base_vbox->add_child(title_bar);
7545+
7546+
main_hbox = memnew(HBoxContainer);
74327547
main_hbox->add_child(main_vbox);
74337548
main_vbox->set_h_size_flags(Control::SIZE_EXPAND_FILL);
7549+
main_hbox->set_v_size_flags(Control::SIZE_EXPAND_FILL);
7550+
base_vbox->add_child(main_hbox);
74347551

74357552
_touch_actions_panel_mode_changed();
74367553

7437-
gui_base->add_child(main_hbox);
7554+
gui_base->add_child(base_vbox);
74387555
#else
74397556
gui_base->add_child(main_vbox);
7440-
#endif
74417557

74427558
title_bar = memnew(EditorTitleBar);
74437559
main_vbox->add_child(title_bar);
7560+
#endif
74447561

74457562
left_l_hsplit = memnew(DockSplitContainer);
74467563
left_l_hsplit->set_name("DockHSplitLeftL");
@@ -7595,19 +7712,10 @@ EditorNode::EditorNode() {
75957712
title_bar->add_child(left_menu_spacer);
75967713
}
75977714

7598-
main_menu = memnew(MenuBar);
7599-
main_menu->set_mouse_filter(Control::MOUSE_FILTER_STOP);
7600-
title_bar->add_child(main_menu);
7601-
main_menu->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
7602-
main_menu->set_theme_type_variation("MainMenuBar");
7603-
main_menu->set_start_index(0); // Main menu, add to the start of global menu.
7604-
main_menu->set_prefer_global_menu(global_menu);
7605-
main_menu->set_switch_on_hover(true);
7715+
_update_main_menu_type();
76067716

76077717
file_menu = memnew(PopupMenu);
7608-
file_menu->set_name(TTRC("Scene"));
7609-
main_menu->add_child(file_menu);
7610-
main_menu->set_menu_tooltip(0, TTR("Operations with scene files."));
7718+
_add_to_main_menu(TTRC("Scene"), file_menu);
76117719

76127720
accept = memnew(AcceptDialog);
76137721
accept->set_autowrap(true);
@@ -7722,7 +7830,7 @@ EditorNode::EditorNode() {
77227830
if (global_menu && NativeMenu::get_singleton()->has_system_menu(NativeMenu::APPLICATION_MENU_ID)) {
77237831
apple_menu = memnew(PopupMenu);
77247832
apple_menu->set_system_menu(NativeMenu::APPLICATION_MENU_ID);
7725-
main_menu->add_child(apple_menu);
7833+
main_menu_bar->add_child(apple_menu);
77267834

77277835
apple_menu->add_shortcut(ED_GET_SHORTCUT("editor/editor_settings"), EDITOR_OPEN_SETTINGS);
77287836
apple_menu->add_separator();
@@ -7731,8 +7839,7 @@ EditorNode::EditorNode() {
77317839
#endif
77327840

77337841
project_menu = memnew(PopupMenu);
7734-
project_menu->set_name(TTRC("Project"));
7735-
main_menu->add_child(project_menu);
7842+
_add_to_main_menu(TTRC("Project"), project_menu);
77367843

77377844
project_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/project_settings", TTRC("Project Settings..."), Key::NONE, TTRC("Project Settings")), PROJECT_OPEN_SETTINGS);
77387845
project_menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorNode::_menu_option));
@@ -7764,7 +7871,7 @@ EditorNode::EditorNode() {
77647871
project_menu->add_shortcut(ED_GET_SHORTCUT("editor/quit_to_project_list"), PROJECT_QUIT_TO_PROJECT_MANAGER, true);
77657872

77667873
// Spacer to center 2D / 3D / Script buttons.
7767-
HBoxContainer *left_spacer = memnew(HBoxContainer);
7874+
left_spacer = memnew(HBoxContainer);
77687875
left_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS);
77697876
left_spacer->set_h_size_flags(Control::SIZE_EXPAND_FILL);
77707877
title_bar->add_child(left_spacer);
@@ -7788,12 +7895,10 @@ EditorNode::EditorNode() {
77887895

77897896
// Options are added and handled by DebuggerEditorPlugin.
77907897
debug_menu = memnew(PopupMenu);
7791-
debug_menu->set_name(TTRC("Debug"));
7792-
main_menu->add_child(debug_menu);
7898+
_add_to_main_menu(TTRC("Debug"), debug_menu);
77937899

77947900
settings_menu = memnew(PopupMenu);
7795-
settings_menu->set_name(TTRC("Editor"));
7796-
main_menu->add_child(settings_menu);
7901+
_add_to_main_menu(TTRC("Editor"), settings_menu);
77977902

77987903
#ifdef MACOS_ENABLED
77997904
if (!global_menu) {
@@ -7842,11 +7947,10 @@ EditorNode::EditorNode() {
78427947
#endif
78437948

78447949
help_menu = memnew(PopupMenu);
7845-
help_menu->set_name(TTRC("Help"));
78467950
if (global_menu && NativeMenu::get_singleton()->has_system_menu(NativeMenu::HELP_MENU_ID)) {
78477951
help_menu->set_system_menu(NativeMenu::HELP_MENU_ID);
78487952
}
7849-
main_menu->add_child(help_menu);
7953+
_add_to_main_menu(TTRC("Help"), help_menu);
78507954

78517955
help_menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorNode::_menu_option));
78527956

@@ -7871,7 +7975,7 @@ EditorNode::EditorNode() {
78717975
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);
78727976

78737977
// Spacer to center 2D / 3D / Script buttons.
7874-
Control *right_spacer = memnew(Control);
7978+
right_spacer = memnew(Control);
78757979
right_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS);
78767980
right_spacer->set_h_size_flags(Control::SIZE_EXPAND_FILL);
78777981
title_bar->add_child(right_spacer);
@@ -7882,7 +7986,7 @@ EditorNode::EditorNode() {
78827986
project_run_bar->connect("play_pressed", callable_mp(this, &EditorNode::_project_run_started));
78837987
project_run_bar->connect("stop_pressed", callable_mp(this, &EditorNode::_project_run_stopped));
78847988

7885-
HBoxContainer *right_menu_hb = memnew(HBoxContainer);
7989+
right_menu_hb = memnew(HBoxContainer);
78867990
right_menu_hb->set_mouse_filter(Control::MOUSE_FILTER_STOP);
78877991
title_bar->add_child(right_menu_hb);
78887992

@@ -8409,10 +8513,15 @@ EditorNode::EditorNode() {
84098513
screenshot_timer->set_owner(get_owner());
84108514

84118515
// Adjust spacers to center 2D / 3D / Script buttons.
8412-
int max_w = MAX(project_run_bar->get_minimum_size().x + right_menu_hb->get_minimum_size().x, main_menu->get_minimum_size().x);
8413-
left_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - main_menu->get_minimum_size().x), 0));
8414-
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));
8415-
8516+
if (main_menu_button != nullptr) {
8517+
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);
8518+
left_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - main_menu_button->get_minimum_size().x), 0));
8519+
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));
8520+
} else {
8521+
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);
8522+
left_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - main_menu_bar->get_minimum_size().x), 0));
8523+
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));
8524+
}
84168525
// Extend menu bar to window title.
84178526
if (can_expand) {
84188527
DisplayServer::get_singleton()->process_events();

editor/editor_node.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class ColorPicker;
4545
class ConfirmationDialog;
4646
class Control;
4747
class FileDialog;
48+
class HBoxContainer;
4849
class MenuBar;
4950
class MenuButton;
5051
class OptionButton;
@@ -100,7 +101,6 @@ class SceneImportSettingsDialog;
100101
class ProjectUpgradeTool;
101102

102103
#ifdef ANDROID_ENABLED
103-
class HBoxContainer;
104104
class TouchActionsPanel;
105105
#endif
106106

@@ -282,7 +282,8 @@ class EditorNode : public Node {
282282
OptionButton *renderer = nullptr;
283283

284284
#ifdef ANDROID_ENABLED
285-
HBoxContainer *main_hbox = nullptr; // Only created on Android for TouchActionsPanel.
285+
VBoxContainer *base_vbox = nullptr; // It only contains the title_bar and main_hbox.
286+
HBoxContainer *main_hbox = nullptr; // It only contains the touch_actions_panel and main_vbox.
286287
TouchActionsPanel *touch_actions_panel = nullptr;
287288
void _touch_actions_panel_mode_changed();
288289
#endif
@@ -324,7 +325,16 @@ class EditorNode : public Node {
324325
Control *right_menu_spacer = nullptr;
325326
EditorTitleBar *title_bar = nullptr;
326327
EditorRunBar *project_run_bar = nullptr;
327-
MenuBar *main_menu = nullptr;
328+
HBoxContainer *right_menu_hb = nullptr;
329+
330+
// Spacers to center 2D / 3D / Script buttons.
331+
HBoxContainer *left_spacer = nullptr;
332+
Control *right_spacer = nullptr;
333+
334+
Control *menu_btn_spacer = nullptr;
335+
MenuButton *main_menu_button = nullptr;
336+
MenuBar *main_menu_bar = nullptr;
337+
328338
PopupMenu *apple_menu = nullptr;
329339
PopupMenu *file_menu = nullptr;
330340
PopupMenu *project_menu = nullptr;
@@ -688,6 +698,9 @@ class EditorNode : public Node {
688698

689699
bool _is_project_data_missing();
690700

701+
void _update_main_menu_type();
702+
void _add_to_main_menu(const String &p_name, PopupMenu *p_menu);
703+
691704
protected:
692705
friend class FileSystemDock;
693706

editor/editor_settings.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,14 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
529529
EDITOR_SETTING_BASIC(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/vsync_mode", 1, "Disabled,Enabled,Adaptive,Mailbox")
530530
EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/update_continuously", false, "")
531531

532+
bool is_android_editor = false;
533+
#ifdef ANDROID_ENABLED
534+
if (!OS::get_singleton()->has_feature("xr_editor")) {
535+
is_android_editor = true;
536+
}
537+
#endif
538+
EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/collapse_main_menu", is_android_editor, "")
539+
532540
_initial_set("interface/editors/show_scene_tree_root_selection", true);
533541
_initial_set("interface/editors/derive_script_globals_by_name", true);
534542
_initial_set("docks/scene_tree/ask_before_revoking_unique_name", true);

editor/gui/touch_actions_panel.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,6 @@ TouchActionsPanel::TouchActionsPanel() {
240240
}
241241

242242
box = memnew(BoxContainer);
243-
box->set_alignment(BoxContainer::ALIGNMENT_CENTER);
244243
box->add_theme_constant_override("separation", 20);
245244
if (is_floating) {
246245
box->set_vertical(EDITOR_DEF("_touch_actions_panel_vertical_layout", false));

0 commit comments

Comments
 (0)