1
0
mirror of https://github.com/godotengine/godot.git synced 2025-12-31 18:41:20 +00:00

Reorganize editor menu setup, allow switching global menu without restart.

This commit is contained in:
Pāvels Nadtočajevs
2025-12-09 14:07:23 +02:00
parent 1ea6b0ccff
commit 89324bc6d2
3 changed files with 364 additions and 257 deletions

View File

@@ -669,7 +669,6 @@ void EditorNode::_update_theme(bool p_skip_creation) {
// Update styles. // Update styles.
{ {
bool global_menu = !bool(EDITOR_GET("interface/editor/use_embedded_menu")) && NativeMenu::get_singleton()->has_feature(NativeMenu::FEATURE_GLOBAL_MENU);
bool dark_mode = DisplayServer::get_singleton()->is_dark_mode_supported() && DisplayServer::get_singleton()->is_dark_mode(); bool dark_mode = DisplayServer::get_singleton()->is_dark_mode_supported() && DisplayServer::get_singleton()->is_dark_mode();
gui_base->add_theme_style_override(SceneStringName(panel), theme->get_stylebox(SNAME("Background"), EditorStringName(EditorStyles))); gui_base->add_theme_style_override(SceneStringName(panel), theme->get_stylebox(SNAME("Background"), EditorStringName(EditorStyles)));
@@ -685,10 +684,10 @@ void EditorNode::_update_theme(bool p_skip_creation) {
distraction_free->set_button_icon(theme->get_icon(SNAME("DistractionFree"), EditorStringName(EditorIcons))); distraction_free->set_button_icon(theme->get_icon(SNAME("DistractionFree"), EditorStringName(EditorIcons)));
update_distraction_free_button_theme(); update_distraction_free_button_theme();
help_menu->set_item_icon(help_menu->get_item_index(HELP_SEARCH), get_editor_theme_native_menu_icon(SNAME("HelpSearch"), global_menu, dark_mode)); help_menu->set_item_icon(help_menu->get_item_index(HELP_SEARCH), get_editor_theme_native_menu_icon(SNAME("HelpSearch"), menu_type == MENU_TYPE_GLOBAL, dark_mode));
help_menu->set_item_icon(help_menu->get_item_index(HELP_COPY_SYSTEM_INFO), get_editor_theme_native_menu_icon(SNAME("ActionCopy"), global_menu, dark_mode)); help_menu->set_item_icon(help_menu->get_item_index(HELP_COPY_SYSTEM_INFO), get_editor_theme_native_menu_icon(SNAME("ActionCopy"), menu_type == MENU_TYPE_GLOBAL, dark_mode));
help_menu->set_item_icon(help_menu->get_item_index(HELP_ABOUT), get_editor_theme_native_menu_icon(SNAME("Godot"), global_menu, dark_mode)); help_menu->set_item_icon(help_menu->get_item_index(HELP_ABOUT), get_editor_theme_native_menu_icon(SNAME("Godot"), menu_type == MENU_TYPE_GLOBAL, dark_mode));
help_menu->set_item_icon(help_menu->get_item_index(HELP_SUPPORT_GODOT_DEVELOPMENT), get_editor_theme_native_menu_icon(SNAME("Heart"), global_menu, dark_mode)); help_menu->set_item_icon(help_menu->get_item_index(HELP_SUPPORT_GODOT_DEVELOPMENT), get_editor_theme_native_menu_icon(SNAME("Heart"), menu_type == MENU_TYPE_GLOBAL, dark_mode));
_update_renderer_color(); _update_renderer_color();
} }
@@ -3895,7 +3894,6 @@ void EditorNode::_save_screenshot(const String &p_path) {
void EditorNode::_check_system_theme_changed() { void EditorNode::_check_system_theme_changed() {
DisplayServer *display_server = DisplayServer::get_singleton(); DisplayServer *display_server = DisplayServer::get_singleton();
bool global_menu = !bool(EDITOR_GET("interface/editor/use_embedded_menu")) && NativeMenu::get_singleton()->has_feature(NativeMenu::FEATURE_GLOBAL_MENU);
bool system_theme_changed = false; bool system_theme_changed = false;
if (follow_system_theme) { if (follow_system_theme) {
@@ -3919,16 +3917,16 @@ void EditorNode::_check_system_theme_changed() {
if (system_theme_changed) { if (system_theme_changed) {
_update_theme(); _update_theme();
} else if (global_menu && display_server->is_dark_mode_supported() && display_server->is_dark_mode() != last_dark_mode_state) { } else if (menu_type == MENU_TYPE_GLOBAL && display_server->is_dark_mode_supported() && display_server->is_dark_mode() != last_dark_mode_state) {
last_dark_mode_state = display_server->is_dark_mode(); last_dark_mode_state = display_server->is_dark_mode();
// Update system menus. // Update system menus.
bool dark_mode = DisplayServer::get_singleton()->is_dark_mode(); bool dark_mode = DisplayServer::get_singleton()->is_dark_mode();
help_menu->set_item_icon(help_menu->get_item_index(HELP_SEARCH), get_editor_theme_native_menu_icon(SNAME("HelpSearch"), global_menu, dark_mode)); help_menu->set_item_icon(help_menu->get_item_index(HELP_SEARCH), get_editor_theme_native_menu_icon(SNAME("HelpSearch"), menu_type == MENU_TYPE_GLOBAL, dark_mode));
help_menu->set_item_icon(help_menu->get_item_index(HELP_COPY_SYSTEM_INFO), get_editor_theme_native_menu_icon(SNAME("ActionCopy"), global_menu, dark_mode)); help_menu->set_item_icon(help_menu->get_item_index(HELP_COPY_SYSTEM_INFO), get_editor_theme_native_menu_icon(SNAME("ActionCopy"), menu_type == MENU_TYPE_GLOBAL, dark_mode));
help_menu->set_item_icon(help_menu->get_item_index(HELP_ABOUT), get_editor_theme_native_menu_icon(SNAME("Godot"), global_menu, dark_mode)); help_menu->set_item_icon(help_menu->get_item_index(HELP_ABOUT), get_editor_theme_native_menu_icon(SNAME("Godot"), menu_type == MENU_TYPE_GLOBAL, dark_mode));
help_menu->set_item_icon(help_menu->get_item_index(HELP_SUPPORT_GODOT_DEVELOPMENT), get_editor_theme_native_menu_icon(SNAME("Heart"), global_menu, dark_mode)); help_menu->set_item_icon(help_menu->get_item_index(HELP_SUPPORT_GODOT_DEVELOPMENT), get_editor_theme_native_menu_icon(SNAME("Heart"), menu_type == MENU_TYPE_GLOBAL, dark_mode));
editor_dock_manager->update_docks_menu(); editor_dock_manager->update_docks_menu();
} }
} }
@@ -7737,17 +7735,239 @@ void EditorNode::set_unfocused_low_processor_usage_mode_enabled(bool p_enabled)
unfocused_low_processor_usage_mode_enabled = p_enabled; unfocused_low_processor_usage_mode_enabled = p_enabled;
} }
void EditorNode::_build_file_menu() {
if (!file_menu) {
return;
}
file_menu->clear(false);
file_menu->add_shortcut(ED_GET_SHORTCUT("editor/new_scene"), SCENE_NEW_SCENE);
file_menu->add_shortcut(ED_GET_SHORTCUT("editor/new_inherited_scene"), SCENE_NEW_INHERITED_SCENE);
file_menu->add_shortcut(ED_GET_SHORTCUT("editor/open_scene"), SCENE_OPEN_SCENE);
file_menu->add_shortcut(ED_GET_SHORTCUT("editor/reopen_closed_scene"), SCENE_OPEN_PREV);
if (!recent_scenes) {
recent_scenes = memnew(PopupMenu);
recent_scenes->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
recent_scenes->connect(SceneStringName(id_pressed), callable_mp(this, &EditorNode::_open_recent_scene));
}
file_menu->add_submenu_node_item(TTRC("Open Recent"), recent_scenes, SCENE_OPEN_RECENT);
file_menu->add_separator();
file_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_scene"), SCENE_SAVE_SCENE);
file_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_scene_as"), SCENE_SAVE_AS_SCENE);
file_menu->add_shortcut(ED_GET_SHORTCUT("editor/save_all_scenes"), SCENE_SAVE_ALL_SCENES);
file_menu->add_separator();
file_menu->add_shortcut(ED_GET_SHORTCUT("editor/quick_open"), SCENE_QUICK_OPEN);
file_menu->add_shortcut(ED_GET_SHORTCUT("editor/quick_open_scene"), SCENE_QUICK_OPEN_SCENE);
file_menu->add_shortcut(ED_GET_SHORTCUT("editor/quick_open_script"), SCENE_QUICK_OPEN_SCRIPT);
file_menu->add_separator();
if (!export_as_menu) {
export_as_menu = memnew(PopupMenu);
export_as_menu->add_shortcut(ED_GET_SHORTCUT("editor/export_as_mesh_library"), FILE_EXPORT_MESH_LIBRARY);
export_as_menu->connect("index_pressed", callable_mp(this, &EditorNode::_export_as_menu_option));
}
file_menu->add_submenu_node_item(TTRC("Export As..."), export_as_menu, SCENE_EXPORT_AS);
file_menu->add_separator();
file_menu->add_shortcut(ED_GET_SHORTCUT("ui_undo"), SCENE_UNDO, false, true);
file_menu->add_shortcut(ED_GET_SHORTCUT("ui_redo"), SCENE_REDO, false, true);
file_menu->add_separator();
file_menu->add_shortcut(ED_GET_SHORTCUT("editor/reload_saved_scene"), SCENE_RELOAD_SAVED_SCENE);
file_menu->add_shortcut(ED_GET_SHORTCUT("editor/close_scene"), SCENE_CLOSE);
file_menu->add_shortcut(ED_GET_SHORTCUT("editor/close_all_scenes"), SCENE_CLOSE_ALL);
#ifdef MACOS_ENABLED
if (menu_type != MENU_TYPE_GLOBAL) {
// On macOS "Quit" option is in the "app" menu.
file_menu->add_separator();
file_menu->add_shortcut(ED_GET_SHORTCUT("editor/file_quit"), SCENE_QUIT, true);
}
#else
file_menu->add_separator();
file_menu->add_shortcut(ED_GET_SHORTCUT("editor/file_quit"), SCENE_QUIT, true);
#endif
}
void EditorNode::_build_project_menu() {
if (!project_menu) {
return;
}
project_menu->clear(false);
project_menu->add_shortcut(ED_GET_SHORTCUT("editor/project_settings"), PROJECT_OPEN_SETTINGS);
project_menu->add_shortcut(ED_GET_SHORTCUT("editor/find_in_files"), PROJECT_FIND_IN_FILES);
project_menu->add_separator();
project_menu->add_item(TTRC("Version Control"), PROJECT_VERSION_CONTROL);
if (!vcs_actions_menu) {
vcs_actions_menu = VersionControlEditorPlugin::get_singleton()->get_version_control_actions_panel();
vcs_actions_menu->connect("index_pressed", callable_mp(this, &EditorNode::_version_control_menu_option));
vcs_actions_menu->add_item(TTRC("Create/Override Version Control Metadata..."), VCS_METADATA);
vcs_actions_menu->add_item(TTRC("Version Control Settings..."), VCS_SETTINGS);
}
project_menu->set_item_submenu_node(project_menu->get_item_index(PROJECT_VERSION_CONTROL), vcs_actions_menu);
project_menu->add_separator();
project_menu->add_shortcut(ED_GET_SHORTCUT("editor/export"), PROJECT_EXPORT);
project_menu->add_item(TTRC("Pack Project as ZIP..."), PROJECT_PACK_AS_ZIP);
project_menu->add_item(TTRC("Install Android Build Template..."), PROJECT_INSTALL_ANDROID_SOURCE);
#ifndef ANDROID_ENABLED
project_menu->add_item(TTRC("Open User Data Folder"), PROJECT_OPEN_USER_DATA_FOLDER);
#endif
project_menu->add_separator();
if (!tool_menu) {
tool_menu = memnew(PopupMenu);
tool_menu->connect("index_pressed", callable_mp(this, &EditorNode::_tool_menu_option));
tool_menu->add_shortcut(ED_GET_SHORTCUT("editor/orphan_resource_explorer"), TOOLS_ORPHAN_RESOURCES);
tool_menu->add_shortcut(ED_GET_SHORTCUT("editor/engine_compilation_configuration_editor"), TOOLS_BUILD_PROFILE_MANAGER);
tool_menu->add_shortcut(ED_GET_SHORTCUT("editor/upgrade_project"), TOOLS_PROJECT_UPGRADE);
}
project_menu->add_submenu_node_item(TTRC("Tools"), tool_menu);
project_menu->add_separator();
project_menu->add_shortcut(ED_GET_SHORTCUT("editor/reload_current_project"), PROJECT_RELOAD_CURRENT_PROJECT);
project_menu->add_shortcut(ED_GET_SHORTCUT("editor/quit_to_project_list"), PROJECT_QUIT_TO_PROJECT_MANAGER, true);
}
void EditorNode::_build_settings_menu() {
if (!settings_menu) {
return;
}
settings_menu->clear(false);
#ifdef MACOS_ENABLED
if (menu_type != MENU_TYPE_GLOBAL) {
// On macOS "Settings" option is in the "app" menu.
settings_menu->add_shortcut(ED_GET_SHORTCUT("editor/editor_settings"), EDITOR_OPEN_SETTINGS);
}
#else
settings_menu->add_shortcut(ED_GET_SHORTCUT("editor/editor_settings"), EDITOR_OPEN_SETTINGS);
#endif
settings_menu->add_shortcut(ED_GET_SHORTCUT("editor/command_palette"), EDITOR_COMMAND_PALETTE);
settings_menu->add_separator();
settings_menu->add_submenu_node_item(TTRC("Editor Docks"), editor_dock_manager->get_docks_menu());
if (!editor_layouts) {
editor_layouts = memnew(PopupMenu);
editor_layouts->connect(SceneStringName(id_pressed), callable_mp(this, &EditorNode::_layout_menu_option));
}
settings_menu->add_submenu_node_item(TTRC("Editor Layout"), editor_layouts);
settings_menu->add_separator();
settings_menu->add_shortcut(ED_GET_SHORTCUT("editor/take_screenshot"), EDITOR_TAKE_SCREENSHOT);
settings_menu->set_item_tooltip(-1, TTRC("Screenshots are stored in the user data folder (\"user://\")."));
settings_menu->add_shortcut(ED_GET_SHORTCUT("editor/fullscreen_mode"), EDITOR_TOGGLE_FULLSCREEN);
settings_menu->add_separator();
#ifndef ANDROID_ENABLED
if (EditorPaths::get_singleton()->get_data_dir() == EditorPaths::get_singleton()->get_config_dir()) {
// Configuration and data folders are located in the same place.
settings_menu->add_item(TTRC("Open Editor Data/Settings Folder"), EDITOR_OPEN_DATA_FOLDER);
} else {
// Separate configuration and data folders.
settings_menu->add_item(TTRC("Open Editor Data Folder"), EDITOR_OPEN_DATA_FOLDER);
settings_menu->add_item(TTRC("Open Editor Settings Folder"), EDITOR_OPEN_CONFIG_FOLDER);
}
settings_menu->add_separator();
#endif
settings_menu->add_item(TTRC("Manage Editor Features..."), EDITOR_MANAGE_FEATURE_PROFILES);
settings_menu->add_item(TTRC("Manage Export Templates..."), EDITOR_MANAGE_EXPORT_TEMPLATES);
#if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED)
settings_menu->add_item(TTRC("Configure FBX Importer..."), EDITOR_CONFIGURE_FBX_IMPORTER);
#endif
}
void EditorNode::_build_help_menu() {
if (!help_menu) {
return;
}
help_menu->clear(false);
if (menu_type == MENU_TYPE_GLOBAL && NativeMenu::get_singleton()->has_system_menu(NativeMenu::HELP_MENU_ID)) {
help_menu->set_system_menu(NativeMenu::HELP_MENU_ID);
} else {
help_menu->set_system_menu(NativeMenu::INVALID_MENU_ID);
}
bool dark_mode = DisplayServer::get_singleton()->is_dark_mode_supported() && DisplayServer::get_singleton()->is_dark_mode();
help_menu->add_icon_shortcut(get_editor_theme_native_menu_icon(SNAME("HelpSearch"), menu_type == MENU_TYPE_GLOBAL, dark_mode), ED_GET_SHORTCUT("editor/editor_help"), HELP_SEARCH);
help_menu->add_separator();
help_menu->add_shortcut(ED_GET_SHORTCUT("editor/online_docs"), HELP_DOCS);
help_menu->add_shortcut(ED_GET_SHORTCUT("editor/forum"), HELP_FORUM);
help_menu->add_shortcut(ED_GET_SHORTCUT("editor/community"), HELP_COMMUNITY);
help_menu->add_separator();
help_menu->add_icon_shortcut(get_editor_theme_native_menu_icon(SNAME("ActionCopy"), menu_type == MENU_TYPE_GLOBAL, dark_mode), ED_GET_SHORTCUT("editor/copy_system_info"), HELP_COPY_SYSTEM_INFO);
help_menu->set_item_tooltip(-1, TTRC("Copies the system info as a single-line text into the clipboard."));
help_menu->add_shortcut(ED_GET_SHORTCUT("editor/report_a_bug"), HELP_REPORT_A_BUG);
help_menu->add_shortcut(ED_GET_SHORTCUT("editor/suggest_a_feature"), HELP_SUGGEST_A_FEATURE);
help_menu->add_shortcut(ED_GET_SHORTCUT("editor/send_docs_feedback"), HELP_SEND_DOCS_FEEDBACK);
help_menu->add_separator();
#ifdef MACOS_ENABLED
if (menu_type != MENU_TYPE_GLOBAL) {
// On macOS "About" option is in the "app" menu.
help_menu->add_icon_shortcut(get_editor_theme_native_menu_icon(SNAME("Godot"), menu_type == MENU_TYPE_GLOBAL, dark_mode), ED_GET_SHORTCUT("editor/about"), HELP_ABOUT);
}
#else
help_menu->add_icon_shortcut(get_editor_theme_native_menu_icon(SNAME("Godot"), menu_type == MENU_TYPE_GLOBAL, dark_mode), ED_GET_SHORTCUT("editor/about"), HELP_ABOUT);
#endif
help_menu->add_icon_shortcut(get_editor_theme_native_menu_icon(SNAME("Heart"), menu_type == MENU_TYPE_GLOBAL, dark_mode), ED_GET_SHORTCUT("editor/support_development"), HELP_SUPPORT_GODOT_DEVELOPMENT);
}
void EditorNode::_add_to_main_menu(const String &p_name, PopupMenu *p_menu) {
p_menu->set_name(p_name);
main_menu_items.push_back(p_menu);
}
void EditorNode::_update_main_menu_type() { void EditorNode::_update_main_menu_type() {
bool can_expand = bool(EDITOR_GET("interface/editor/expand_to_title")) && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_EXTEND_TO_TITLE);
bool use_menu_button = EDITOR_GET("interface/editor/collapse_main_menu"); 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 global_menu = !bool(EDITOR_GET("interface/editor/use_embedded_menu")) && NativeMenu::get_singleton()->has_feature(NativeMenu::FEATURE_GLOBAL_MENU);
MenuType new_menu_type;
bool already_using_button = main_menu_button != nullptr; if (global_menu) {
bool already_using_bar = main_menu_bar != nullptr; new_menu_type = MENU_TYPE_GLOBAL;
if ((use_menu_button && already_using_button) || (!use_menu_button && already_using_bar)) { } else if (use_menu_button) {
return; // Already correctly configured. new_menu_type = MENU_TYPE_COMPACT;
} else {
new_menu_type = MENU_TYPE_FULL;
} }
if (use_menu_button && !global_menu) { if (new_menu_type == menu_type) {
return; // Nothing to do.
}
menu_type = new_menu_type;
// Update menu items.
_build_file_menu();
_build_project_menu();
_build_settings_menu();
_build_help_menu();
// Delete all menu.
if (main_menu_bar) {
for (PopupMenu *menu : main_menu_items) {
main_menu_bar->remove_child(menu);
}
memdelete(main_menu_bar);
main_menu_bar = nullptr;
}
if (main_menu_button) {
main_menu_button->get_popup()->clear(false);
for (PopupMenu *menu : main_menu_items) {
main_menu_button->get_popup()->remove_child(menu);
}
memdelete(main_menu_button);
main_menu_button = nullptr;
}
memdelete_notnull(menu_btn_spacer);
menu_btn_spacer = nullptr;
// Create new menu.
if (new_menu_type == MENU_TYPE_COMPACT) {
main_menu_button = memnew(MenuButton); main_menu_button = memnew(MenuButton);
main_menu_button->set_text(TTRC("Main Menu")); main_menu_button->set_text(TTRC("Main Menu"));
main_menu_button->set_theme_type_variation("MainScreenButton"); main_menu_button->set_theme_type_variation("MainScreenButton");
@@ -7757,18 +7977,8 @@ void EditorNode::_update_main_menu_type() {
} }
main_menu_button->set_switch_on_hover(true); main_menu_button->set_switch_on_hover(true);
if (main_menu_bar != nullptr) { for (PopupMenu *menu : main_menu_items) {
Vector<PopupMenu *> menus_to_move; main_menu_button->get_popup()->add_submenu_node_item(menu->get_name(), menu);
for (int i = 0; i < main_menu_bar->get_child_count(); i++) {
PopupMenu *menu = Object::cast_to<PopupMenu>(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 #ifdef ANDROID_ENABLED
@@ -7784,47 +7994,26 @@ void EditorNode::_update_main_menu_type() {
} else { } else {
title_bar->move_child(main_menu_button, menu_btn_spacer->get_index() + 1); title_bar->move_child(main_menu_button, menu_btn_spacer->get_index() + 1);
} }
memdelete_notnull(main_menu_bar);
main_menu_bar = nullptr;
} else { } else {
main_menu_bar = memnew(MenuBar); main_menu_bar = memnew(MenuBar);
main_menu_bar->set_mouse_filter(Control::MOUSE_FILTER_STOP); 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_v_size_flags(Control::SIZE_SHRINK_CENTER);
main_menu_bar->set_theme_type_variation("MainMenuBar"); 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_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_prefer_global_menu(menu_type == MENU_TYPE_GLOBAL);
main_menu_bar->set_switch_on_hover(true); main_menu_bar->set_switch_on_hover(true);
if (main_menu_button != nullptr) { for (PopupMenu *menu : main_menu_items) {
Vector<PopupMenu *> menus_to_move; main_menu_bar->add_child(menu);
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->add_child(main_menu_bar);
title_bar->move_child(main_menu_bar, left_menu_spacer ? left_menu_spacer->get_index() + 1 : 0); title_bar->move_child(main_menu_bar, left_menu_spacer ? left_menu_spacer->get_index() + 1 : 0);
memdelete_notnull(menu_btn_spacer);
memdelete_notnull(main_menu_button);
menu_btn_spacer = nullptr;
main_menu_button = nullptr;
} }
}
void EditorNode::_add_to_main_menu(const String &p_name, PopupMenu *p_menu) { // Show/hide project title.
p_menu->set_name(p_name); if (project_title) {
if (main_menu_button != nullptr) { project_title->set_visible(can_expand && menu_type == MENU_TYPE_GLOBAL);
main_menu_button->get_popup()->add_submenu_node_item(p_name, p_menu);
} else {
main_menu_bar->add_child(p_menu);
} }
} }
@@ -8358,22 +8547,6 @@ EditorNode::EditorNode() {
scene_root->set_disable_input(true); scene_root->set_disable_input(true);
scene_root->set_as_audio_listener_2d(true); scene_root->set_as_audio_listener_2d(true);
bool global_menu = !bool(EDITOR_GET("interface/editor/use_embedded_menu")) && NativeMenu::get_singleton()->has_feature(NativeMenu::FEATURE_GLOBAL_MENU);
bool dark_mode = DisplayServer::get_singleton()->is_dark_mode_supported() && DisplayServer::get_singleton()->is_dark_mode();
bool can_expand = bool(EDITOR_GET("interface/editor/expand_to_title")) && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_EXTEND_TO_TITLE);
if (can_expand) {
// Add spacer to avoid other controls under window minimize/maximize/close buttons (left side).
left_menu_spacer = memnew(Control);
left_menu_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS);
title_bar->add_child(left_menu_spacer);
}
_update_main_menu_type();
file_menu = memnew(PopupMenu);
_add_to_main_menu(TTRC("Scene"), file_menu);
accept = memnew(AcceptDialog); accept = memnew(AcceptDialog);
accept->set_autowrap(true); accept->set_autowrap(true);
accept->set_min_size(Vector2i(600, 0)); accept->set_min_size(Vector2i(600, 0));
@@ -8428,211 +8601,74 @@ EditorNode::EditorNode() {
warning->add_button(TTRC("Copy Text"), true, "copy"); warning->add_button(TTRC("Copy Text"), true, "copy");
warning->connect("custom_action", callable_mp(this, &EditorNode::_copy_warning)); warning->connect("custom_action", callable_mp(this, &EditorNode::_copy_warning));
ED_SHORTCUT("editor/next_tab", TTRC("Next Scene Tab"), KeyModifierMask::CTRL + Key::TAB); // Command palette and editor shortcuts.
ED_SHORTCUT("editor/prev_tab", TTRC("Previous Scene Tab"), KeyModifierMask::CTRL + KeyModifierMask::SHIFT + Key::TAB);
ED_SHORTCUT("editor/filter_files", TTRC("Focus FileSystem Filter"), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::ALT + Key::P);
command_palette = EditorCommandPalette::get_singleton(); command_palette = EditorCommandPalette::get_singleton();
command_palette->set_title(TTR("Command Palette")); command_palette->set_title(TTR("Command Palette"));
gui_base->add_child(command_palette); gui_base->add_child(command_palette);
file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/new_scene", TTRC("New Scene"), KeyModifierMask::CMD_OR_CTRL + Key::N), SCENE_NEW_SCENE); ED_SHORTCUT("editor/next_tab", TTRC("Next Scene Tab"), KeyModifierMask::CTRL + Key::TAB);
file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/new_inherited_scene", TTRC("New Inherited Scene..."), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::N), SCENE_NEW_INHERITED_SCENE); ED_SHORTCUT("editor/prev_tab", TTRC("Previous Scene Tab"), KeyModifierMask::CTRL + KeyModifierMask::SHIFT + Key::TAB);
file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/open_scene", TTRC("Open Scene..."), KeyModifierMask::CMD_OR_CTRL + Key::O), SCENE_OPEN_SCENE); ED_SHORTCUT("editor/filter_files", TTRC("Focus FileSystem Filter"), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::ALT + Key::P);
file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/reopen_closed_scene", TTRC("Reopen Closed Scene"), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::T), SCENE_OPEN_PREV);
recent_scenes = memnew(PopupMenu); ED_SHORTCUT_AND_COMMAND("editor/new_scene", TTRC("New Scene"), KeyModifierMask::CMD_OR_CTRL + Key::N);
recent_scenes->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED); ED_SHORTCUT_AND_COMMAND("editor/new_inherited_scene", TTRC("New Inherited Scene..."), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::N);
file_menu->add_submenu_node_item(TTRC("Open Recent"), recent_scenes, SCENE_OPEN_RECENT); ED_SHORTCUT_AND_COMMAND("editor/open_scene", TTRC("Open Scene..."), KeyModifierMask::CMD_OR_CTRL + Key::O);
recent_scenes->connect(SceneStringName(id_pressed), callable_mp(this, &EditorNode::_open_recent_scene)); ED_SHORTCUT_AND_COMMAND("editor/reopen_closed_scene", TTRC("Reopen Closed Scene"), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::T);
file_menu->add_separator(); ED_SHORTCUT_AND_COMMAND("editor/save_scene", TTRC("Save Scene"), KeyModifierMask::CMD_OR_CTRL + Key::S);
file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_scene", TTRC("Save Scene"), KeyModifierMask::CMD_OR_CTRL + Key::S), SCENE_SAVE_SCENE); ED_SHORTCUT_AND_COMMAND("editor/save_scene_as", TTRC("Save Scene As..."), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::S);
file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_scene_as", TTRC("Save Scene As..."), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::S), SCENE_SAVE_AS_SCENE); ED_SHORTCUT_AND_COMMAND("editor/save_all_scenes", TTRC("Save All Scenes"), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + KeyModifierMask::ALT + Key::S);
file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/save_all_scenes", TTRC("Save All Scenes"), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + KeyModifierMask::ALT + Key::S), SCENE_SAVE_ALL_SCENES);
file_menu->add_separator(); ED_SHORTCUT_ARRAY_AND_COMMAND("editor/quick_open", TTRC("Quick Open..."), { int32_t(KeyModifierMask::SHIFT + KeyModifierMask::ALT + Key::O), int32_t(KeyModifierMask::CMD_OR_CTRL + Key::P) });
file_menu->add_shortcut(ED_SHORTCUT_ARRAY_AND_COMMAND("editor/quick_open", TTRC("Quick Open..."), { int32_t(KeyModifierMask::SHIFT + KeyModifierMask::ALT + Key::O), int32_t(KeyModifierMask::CMD_OR_CTRL + Key::P) }), SCENE_QUICK_OPEN);
ED_SHORTCUT_OVERRIDE_ARRAY("editor/quick_open", "macos", { int32_t(KeyModifierMask::META + KeyModifierMask::CTRL + Key::O), int32_t(KeyModifierMask::CMD_OR_CTRL + Key::P) }); ED_SHORTCUT_OVERRIDE_ARRAY("editor/quick_open", "macos", { int32_t(KeyModifierMask::META + KeyModifierMask::CTRL + Key::O), int32_t(KeyModifierMask::CMD_OR_CTRL + Key::P) });
file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open_scene", TTRC("Quick Open Scene..."), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::O), SCENE_QUICK_OPEN_SCENE); ED_SHORTCUT_AND_COMMAND("editor/quick_open_scene", TTRC("Quick Open Scene..."), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::O);
file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/quick_open_script", TTRC("Quick Open Script..."), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::ALT + Key::O), SCENE_QUICK_OPEN_SCRIPT); ED_SHORTCUT_AND_COMMAND("editor/quick_open_script", TTRC("Quick Open Script..."), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::ALT + Key::O);
file_menu->add_separator(); ED_SHORTCUT("editor/export_as_mesh_library", TTRC("MeshLibrary...")),
export_as_menu = memnew(PopupMenu);
file_menu->add_submenu_node_item(TTRC("Export As..."), export_as_menu, SCENE_EXPORT_AS);
export_as_menu->add_shortcut(ED_SHORTCUT("editor/export_as_mesh_library", TTRC("MeshLibrary...")), FILE_EXPORT_MESH_LIBRARY);
export_as_menu->connect("index_pressed", callable_mp(this, &EditorNode::_export_as_menu_option));
file_menu->add_separator(); ED_SHORTCUT_AND_COMMAND("editor/reload_saved_scene", TTRC("Reload Saved Scene"));
file_menu->add_shortcut(ED_GET_SHORTCUT("ui_undo"), SCENE_UNDO, false, true); ED_SHORTCUT_AND_COMMAND("editor/close_scene", TTRC("Close Scene"), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::W);
file_menu->add_shortcut(ED_GET_SHORTCUT("ui_redo"), SCENE_REDO, false, true); ED_SHORTCUT_AND_COMMAND("editor/close_all_scenes", TTRC("Close All Scenes"));
file_menu->add_separator();
file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/reload_saved_scene", TTRC("Reload Saved Scene")), SCENE_RELOAD_SAVED_SCENE);
file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/close_scene", TTRC("Close Scene"), KeyModifierMask::CMD_OR_CTRL + KeyModifierMask::SHIFT + Key::W), SCENE_CLOSE);
file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/close_all_scenes", TTRC("Close All Scenes")), SCENE_CLOSE_ALL);
ED_SHORTCUT_OVERRIDE("editor/close_scene", "macos", KeyModifierMask::CMD_OR_CTRL + Key::W); ED_SHORTCUT_OVERRIDE("editor/close_scene", "macos", KeyModifierMask::CMD_OR_CTRL + Key::W);
if (!global_menu || !OS::get_singleton()->has_feature("macos")) {
// On macOS "Quit" and "About" options are in the "app" menu.
file_menu->add_separator();
file_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/file_quit", TTRC("Quit"), KeyModifierMask::CMD_OR_CTRL + Key::Q), SCENE_QUIT, true);
}
ED_SHORTCUT_AND_COMMAND("editor/editor_settings", TTRC("Editor Settings...")); ED_SHORTCUT_AND_COMMAND("editor/editor_settings", TTRC("Editor Settings..."));
ED_SHORTCUT_OVERRIDE("editor/editor_settings", "macos", KeyModifierMask::META + Key::COMMA); ED_SHORTCUT_OVERRIDE("editor/editor_settings", "macos", KeyModifierMask::META + Key::COMMA);
#ifdef MACOS_ENABLED
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_bar->add_child(apple_menu);
apple_menu->add_shortcut(ED_GET_SHORTCUT("editor/editor_settings"), EDITOR_OPEN_SETTINGS); ED_SHORTCUT_AND_COMMAND("editor/file_quit", TTRC("Quit"), KeyModifierMask::CMD_OR_CTRL + Key::Q);
apple_menu->add_separator();
apple_menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorNode::_menu_option));
}
#endif
project_menu = memnew(PopupMenu);
_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));
ED_SHORTCUT_AND_COMMAND("editor/project_settings", TTRC("Project Settings..."), Key::NONE, TTRC("Project Settings"));
ED_SHORTCUT_AND_COMMAND("editor/find_in_files", TTRC("Find in Files..."), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::F); ED_SHORTCUT_AND_COMMAND("editor/find_in_files", TTRC("Find in Files..."), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::F);
project_menu->add_shortcut(ED_GET_SHORTCUT("editor/find_in_files"), PROJECT_FIND_IN_FILES);
project_menu->add_separator(); ED_SHORTCUT_AND_COMMAND("editor/export", TTRC("Export..."), Key::NONE, TTRC("Export"));
project_menu->add_item(TTRC("Version Control"), PROJECT_VERSION_CONTROL);
project_menu->add_separator(); ED_SHORTCUT_AND_COMMAND("editor/orphan_resource_explorer", TTRC("Orphan Resource Explorer..."));
project_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/export", TTRC("Export..."), Key::NONE, TTRC("Export")), PROJECT_EXPORT); ED_SHORTCUT_AND_COMMAND("editor/engine_compilation_configuration_editor", TTRC("Engine Compilation Configuration Editor..."));
project_menu->add_item(TTRC("Pack Project as ZIP..."), PROJECT_PACK_AS_ZIP); ED_SHORTCUT_AND_COMMAND("editor/upgrade_project", TTRC("Upgrade Project Files..."));
project_menu->add_item(TTRC("Install Android Build Template..."), PROJECT_INSTALL_ANDROID_SOURCE);
#ifndef ANDROID_ENABLED
project_menu->add_item(TTRC("Open User Data Folder"), PROJECT_OPEN_USER_DATA_FOLDER);
#endif
project_menu->add_separator(); ED_SHORTCUT("editor/reload_current_project", TTRC("Reload Current Project"));
tool_menu = memnew(PopupMenu);
tool_menu->connect("index_pressed", callable_mp(this, &EditorNode::_tool_menu_option));
project_menu->add_submenu_node_item(TTRC("Tools"), tool_menu);
tool_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/orphan_resource_explorer", TTRC("Orphan Resource Explorer...")), TOOLS_ORPHAN_RESOURCES);
tool_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/engine_compilation_configuration_editor", TTRC("Engine Compilation Configuration Editor...")), TOOLS_BUILD_PROFILE_MANAGER);
tool_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/upgrade_project", TTRC("Upgrade Project Files...")), TOOLS_PROJECT_UPGRADE);
project_menu->add_separator();
project_menu->add_shortcut(ED_SHORTCUT("editor/reload_current_project", TTRC("Reload Current Project")), PROJECT_RELOAD_CURRENT_PROJECT);
ED_SHORTCUT_AND_COMMAND("editor/quit_to_project_list", TTRC("Quit to Project List"), KeyModifierMask::CTRL + KeyModifierMask::SHIFT + Key::Q); ED_SHORTCUT_AND_COMMAND("editor/quit_to_project_list", TTRC("Quit to Project List"), KeyModifierMask::CTRL + KeyModifierMask::SHIFT + Key::Q);
ED_SHORTCUT_OVERRIDE("editor/quit_to_project_list", "macos", KeyModifierMask::META + KeyModifierMask::CTRL + KeyModifierMask::ALT + Key::Q); ED_SHORTCUT_OVERRIDE("editor/quit_to_project_list", "macos", KeyModifierMask::META + KeyModifierMask::CTRL + KeyModifierMask::ALT + Key::Q);
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. ED_SHORTCUT("editor/command_palette", TTRC("Command Palette..."), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::P);
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);
if (can_expand && global_menu) {
project_title = memnew(Label);
project_title->add_theme_font_override(SceneStringName(font), theme->get_font(SNAME("bold"), EditorStringName(EditorFonts)));
project_title->add_theme_font_size_override(SceneStringName(font_size), theme->get_font_size(SNAME("bold_size"), EditorStringName(EditorFonts)));
project_title->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS);
project_title->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
project_title->set_h_size_flags(Control::SIZE_EXPAND_FILL);
project_title->set_mouse_filter(Control::MOUSE_FILTER_PASS);
left_spacer->add_child(project_title);
}
HBoxContainer *main_editor_button_hb = memnew(HBoxContainer);
main_editor_button_hb->set_mouse_filter(Control::MOUSE_FILTER_STOP);
main_editor_button_hb->set_name("EditorMainScreenButtons");
editor_main_screen->set_button_container(main_editor_button_hb);
title_bar->add_child(main_editor_button_hb);
title_bar->set_center_control(main_editor_button_hb);
// Options are added and handled by DebuggerEditorPlugin.
debug_menu = memnew(PopupMenu);
_add_to_main_menu(TTRC("Debug"), debug_menu);
settings_menu = memnew(PopupMenu);
_add_to_main_menu(TTRC("Editor"), settings_menu);
#ifdef MACOS_ENABLED
if (!global_menu) {
settings_menu->add_shortcut(ED_GET_SHORTCUT("editor/editor_settings"), EDITOR_OPEN_SETTINGS);
}
#else
settings_menu->add_shortcut(ED_GET_SHORTCUT("editor/editor_settings"), EDITOR_OPEN_SETTINGS);
#endif
settings_menu->add_shortcut(ED_SHORTCUT("editor/command_palette", TTRC("Command Palette..."), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::P), EDITOR_COMMAND_PALETTE);
settings_menu->add_separator();
settings_menu->add_submenu_node_item(TTRC("Editor Docks"), editor_dock_manager->get_docks_menu());
editor_layouts = memnew(PopupMenu);
settings_menu->add_submenu_node_item(TTRC("Editor Layout"), editor_layouts);
editor_layouts->connect(SceneStringName(id_pressed), callable_mp(this, &EditorNode::_layout_menu_option));
settings_menu->add_separator();
ED_SHORTCUT_AND_COMMAND("editor/take_screenshot", TTRC("Take Screenshot"), KeyModifierMask::CTRL | Key::F12); ED_SHORTCUT_AND_COMMAND("editor/take_screenshot", TTRC("Take Screenshot"), KeyModifierMask::CTRL | Key::F12);
ED_SHORTCUT_OVERRIDE("editor/take_screenshot", "macos", KeyModifierMask::META | Key::F12); ED_SHORTCUT_OVERRIDE("editor/take_screenshot", "macos", KeyModifierMask::META | Key::F12);
settings_menu->add_shortcut(ED_GET_SHORTCUT("editor/take_screenshot"), EDITOR_TAKE_SCREENSHOT);
settings_menu->set_item_tooltip(-1, TTRC("Screenshots are stored in the user data folder (\"user://\")."));
ED_SHORTCUT_AND_COMMAND("editor/fullscreen_mode", TTRC("Toggle Fullscreen"), KeyModifierMask::SHIFT | Key::F11); ED_SHORTCUT_AND_COMMAND("editor/fullscreen_mode", TTRC("Toggle Fullscreen"), KeyModifierMask::SHIFT | Key::F11);
ED_SHORTCUT_OVERRIDE("editor/fullscreen_mode", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::F); ED_SHORTCUT_OVERRIDE("editor/fullscreen_mode", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::F);
settings_menu->add_shortcut(ED_GET_SHORTCUT("editor/fullscreen_mode"), EDITOR_TOGGLE_FULLSCREEN);
settings_menu->add_separator();
#ifndef ANDROID_ENABLED
if (EditorPaths::get_singleton()->get_data_dir() == EditorPaths::get_singleton()->get_config_dir()) {
// Configuration and data folders are located in the same place.
settings_menu->add_item(TTRC("Open Editor Data/Settings Folder"), EDITOR_OPEN_DATA_FOLDER);
} else {
// Separate configuration and data folders.
settings_menu->add_item(TTRC("Open Editor Data Folder"), EDITOR_OPEN_DATA_FOLDER);
settings_menu->add_item(TTRC("Open Editor Settings Folder"), EDITOR_OPEN_CONFIG_FOLDER);
}
settings_menu->add_separator();
#endif
settings_menu->add_item(TTRC("Manage Editor Features..."), EDITOR_MANAGE_FEATURE_PROFILES);
settings_menu->add_item(TTRC("Manage Export Templates..."), EDITOR_MANAGE_EXPORT_TEMPLATES);
#if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED)
settings_menu->add_item(TTRC("Configure FBX Importer..."), EDITOR_CONFIGURE_FBX_IMPORTER);
#endif
help_menu = memnew(PopupMenu);
if (global_menu && NativeMenu::get_singleton()->has_system_menu(NativeMenu::HELP_MENU_ID)) {
help_menu->set_system_menu(NativeMenu::HELP_MENU_ID);
}
_add_to_main_menu(TTRC("Help"), help_menu);
help_menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorNode::_menu_option));
ED_SHORTCUT_AND_COMMAND("editor/editor_help", TTRC("Search Help..."), Key::F1); ED_SHORTCUT_AND_COMMAND("editor/editor_help", TTRC("Search Help..."), Key::F1);
ED_SHORTCUT_OVERRIDE("editor/editor_help", "macos", KeyModifierMask::ALT | Key::SPACE); ED_SHORTCUT_OVERRIDE("editor/editor_help", "macos", KeyModifierMask::ALT | Key::SPACE);
help_menu->add_icon_shortcut(get_editor_theme_native_menu_icon(SNAME("HelpSearch"), global_menu, dark_mode), ED_GET_SHORTCUT("editor/editor_help"), HELP_SEARCH); ED_SHORTCUT_AND_COMMAND("editor/online_docs", TTRC("Online Documentation"));
help_menu->add_separator(); ED_SHORTCUT_AND_COMMAND("editor/forum", TTRC("Forum"));
help_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/online_docs", TTRC("Online Documentation")), HELP_DOCS); ED_SHORTCUT_AND_COMMAND("editor/community", TTRC("Community"));
help_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/forum", TTRC("Forum")), HELP_FORUM);
help_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/community", TTRC("Community")), HELP_COMMUNITY); ED_SHORTCUT_AND_COMMAND("editor/copy_system_info", TTRC("Copy System Info"));
help_menu->add_separator(); ED_SHORTCUT_AND_COMMAND("editor/report_a_bug", TTRC("Report a Bug"));
help_menu->add_icon_shortcut(get_editor_theme_native_menu_icon(SNAME("ActionCopy"), global_menu, dark_mode), ED_SHORTCUT_AND_COMMAND("editor/copy_system_info", TTRC("Copy System Info")), HELP_COPY_SYSTEM_INFO); ED_SHORTCUT_AND_COMMAND("editor/suggest_a_feature", TTRC("Suggest a Feature"));
help_menu->set_item_tooltip(-1, TTR("Copies the system info as a single-line text into the clipboard.")); ED_SHORTCUT_AND_COMMAND("editor/send_docs_feedback", TTRC("Send Docs Feedback"));
help_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/report_a_bug", TTRC("Report a Bug")), HELP_REPORT_A_BUG); ED_SHORTCUT_AND_COMMAND("editor/about", TTRC("About Godot..."));
help_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/suggest_a_feature", TTRC("Suggest a Feature")), HELP_SUGGEST_A_FEATURE); ED_SHORTCUT_AND_COMMAND("editor/support_development", TTRC("Support Godot Development"));
help_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/send_docs_feedback", TTRC("Send Docs Feedback")), HELP_SEND_DOCS_FEEDBACK);
help_menu->add_separator();
if (!global_menu || !OS::get_singleton()->has_feature("macos")) {
// On macOS "Quit" and "About" options are in the "app" menu.
help_menu->add_icon_shortcut(get_editor_theme_native_menu_icon(SNAME("Godot"), global_menu, dark_mode), ED_SHORTCUT_AND_COMMAND("editor/about", TTRC("About Godot...")), HELP_ABOUT);
}
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);
// Use the Ctrl modifier so F2 can be used to rename nodes in the scene tree dock. // Use the Ctrl modifier so F2 can be used to rename nodes in the scene tree dock.
ED_SHORTCUT_AND_COMMAND("editor/editor_2d", TTRC("Open 2D Workspace"), KeyModifierMask::CTRL | Key::F1); ED_SHORTCUT_AND_COMMAND("editor/editor_2d", TTRC("Open 2D Workspace"), KeyModifierMask::CTRL | Key::F1);
@@ -8650,6 +8686,74 @@ EditorNode::EditorNode() {
ED_SHORTCUT_AND_COMMAND("editor/editor_next", TTRC("Open the next Editor")); ED_SHORTCUT_AND_COMMAND("editor/editor_next", TTRC("Open the next Editor"));
ED_SHORTCUT_AND_COMMAND("editor/editor_prev", TTRC("Open the previous Editor")); ED_SHORTCUT_AND_COMMAND("editor/editor_prev", TTRC("Open the previous Editor"));
// Editor menu and toolbar.
bool can_expand = bool(EDITOR_GET("interface/editor/expand_to_title")) && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_EXTEND_TO_TITLE);
#ifdef MACOS_ENABLED
if (NativeMenu::get_singleton()->has_system_menu(NativeMenu::APPLICATION_MENU_ID)) {
apple_menu = memnew(PopupMenu);
apple_menu->set_system_menu(NativeMenu::APPLICATION_MENU_ID);
add_child(apple_menu);
apple_menu->add_shortcut(ED_GET_SHORTCUT("editor/editor_settings"), EDITOR_OPEN_SETTINGS);
apple_menu->add_separator();
apple_menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorNode::_menu_option));
}
#endif
if (can_expand) {
// Add spacer to avoid other controls under window minimize/maximize/close buttons (left side).
left_menu_spacer = memnew(Control);
left_menu_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS);
title_bar->add_child(left_menu_spacer);
}
file_menu = memnew(PopupMenu);
file_menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorNode::_menu_option));
file_menu->connect("about_to_popup", callable_mp(this, &EditorNode::_update_file_menu_opened));
_add_to_main_menu(TTRC("Scene"), file_menu);
project_menu = memnew(PopupMenu);
project_menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorNode::_menu_option));
_add_to_main_menu(TTRC("Project"), project_menu);
debug_menu = memnew(PopupMenu);
// Options are added and handled by DebuggerEditorPlugin, do not rebuild.
_add_to_main_menu(TTRC("Debug"), debug_menu);
settings_menu = memnew(PopupMenu);
settings_menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorNode::_menu_option));
_add_to_main_menu(TTRC("Editor"), settings_menu);
help_menu = memnew(PopupMenu);
help_menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorNode::_menu_option));
_add_to_main_menu(TTRC("Help"), help_menu);
_update_main_menu_type();
// Spacer to center 2D / 3D / Script buttons.
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);
project_title = memnew(Label);
project_title->add_theme_font_override(SceneStringName(font), theme->get_font(SNAME("bold"), EditorStringName(EditorFonts)));
project_title->add_theme_font_size_override(SceneStringName(font_size), theme->get_font_size(SNAME("bold_size"), EditorStringName(EditorFonts)));
project_title->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS);
project_title->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
project_title->set_h_size_flags(Control::SIZE_EXPAND_FILL);
project_title->set_mouse_filter(Control::MOUSE_FILTER_PASS);
project_title->set_visible(can_expand && menu_type == MENU_TYPE_GLOBAL);
left_spacer->add_child(project_title);
HBoxContainer *main_editor_button_hb = memnew(HBoxContainer);
main_editor_button_hb->set_mouse_filter(Control::MOUSE_FILTER_STOP);
main_editor_button_hb->set_name("EditorMainScreenButtons");
editor_main_screen->set_button_container(main_editor_button_hb);
title_bar->add_child(main_editor_button_hb);
title_bar->set_center_control(main_editor_button_hb);
// Spacer to center 2D / 3D / Script buttons. // Spacer to center 2D / 3D / Script buttons.
right_spacer = memnew(Control); right_spacer = memnew(Control);
right_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS); right_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS);
@@ -8897,11 +9001,6 @@ EditorNode::EditorNode() {
file_pack_zip->set_title(TTR("Pack Project as ZIP...")); file_pack_zip->set_title(TTR("Pack Project as ZIP..."));
gui_base->add_child(file_pack_zip); gui_base->add_child(file_pack_zip);
file_menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorNode::_menu_option));
file_menu->connect("about_to_popup", callable_mp(this, &EditorNode::_update_file_menu_opened));
settings_menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorNode::_menu_option));
file->connect("file_selected", callable_mp(this, &EditorNode::_dialog_action)); file->connect("file_selected", callable_mp(this, &EditorNode::_dialog_action));
file_templates->connect("file_selected", callable_mp(this, &EditorNode::_dialog_action)); file_templates->connect("file_selected", callable_mp(this, &EditorNode::_dialog_action));
@@ -8973,12 +9072,6 @@ EditorNode::EditorNode() {
add_editor_plugin(VersionControlEditorPlugin::get_singleton()); add_editor_plugin(VersionControlEditorPlugin::get_singleton());
vcs_actions_menu = VersionControlEditorPlugin::get_singleton()->get_version_control_actions_panel();
vcs_actions_menu->connect("index_pressed", callable_mp(this, &EditorNode::_version_control_menu_option));
vcs_actions_menu->add_item(TTRC("Create/Override Version Control Metadata..."), VCS_METADATA);
vcs_actions_menu->add_item(TTRC("Version Control Settings..."), VCS_SETTINGS);
project_menu->set_item_submenu_node(project_menu->get_item_index(PROJECT_VERSION_CONTROL), vcs_actions_menu);
add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor))); add_editor_plugin(memnew(AudioBusesEditorPlugin(audio_bus_editor)));
for (int i = 0; i < EditorPlugins::get_plugin_count(); i++) { for (int i = 0; i < EditorPlugins::get_plugin_count(); i++) {

View File

@@ -710,6 +710,20 @@ private:
bool _is_project_data_missing(); bool _is_project_data_missing();
enum MenuType {
MENU_TYPE_NONE,
MENU_TYPE_GLOBAL,
MENU_TYPE_COMPACT,
MENU_TYPE_FULL,
};
MenuType menu_type = MENU_TYPE_NONE;
Vector<PopupMenu *> main_menu_items;
void _build_file_menu();
void _build_project_menu();
void _build_settings_menu();
void _build_help_menu();
void _update_main_menu_type(); void _update_main_menu_type();
void _add_to_main_menu(const String &p_name, PopupMenu *p_menu); void _add_to_main_menu(const String &p_name, PopupMenu *p_menu);

View File

@@ -487,7 +487,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
EDITOR_SETTING_BASIC(Variant::INT, PROPERTY_HINT_ENUM, "network/connection/check_for_updates", int(default_update_mode), "Disable Update Checks,Check Newest Preview,Check Newest Stable,Check Newest Patch"); // Uses EngineUpdateLabel::UpdateMode. EDITOR_SETTING_BASIC(Variant::INT, PROPERTY_HINT_ENUM, "network/connection/check_for_updates", int(default_update_mode), "Disable Update Checks,Check Newest Preview,Check Newest Stable,Check Newest Patch"); // Uses EngineUpdateLabel::UpdateMode.
} }
EDITOR_SETTING_USAGE(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/use_embedded_menu", false, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED | PROPERTY_USAGE_EDITOR_BASIC_SETTING) EDITOR_SETTING_USAGE(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/use_embedded_menu", false, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_EDITOR_BASIC_SETTING)
EDITOR_SETTING_USAGE(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/use_native_file_dialogs", false, "", PROPERTY_USAGE_DEFAULT) EDITOR_SETTING_USAGE(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/use_native_file_dialogs", false, "", PROPERTY_USAGE_DEFAULT)
EDITOR_SETTING_USAGE(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/expand_to_title", true, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED | PROPERTY_USAGE_EDITOR_BASIC_SETTING) EDITOR_SETTING_USAGE(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/expand_to_title", true, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED | PROPERTY_USAGE_EDITOR_BASIC_SETTING)