diff --git a/editor/editor_dock_manager.cpp b/editor/editor_dock_manager.cpp index 32269f91a10..32ab261204e 100644 --- a/editor/editor_dock_manager.cpp +++ b/editor/editor_dock_manager.cpp @@ -158,17 +158,20 @@ void EditorDockManager::_update_layout() { return; } dock_context_popup->docks_updated(); - _update_docks_menu(); + update_docks_menu(); EditorNode::get_singleton()->save_editor_layout_delayed(); } -void EditorDockManager::_update_docks_menu() { +void EditorDockManager::update_docks_menu() { docks_menu->clear(); docks_menu->reset_size(); const Ref default_icon = docks_menu->get_editor_theme_icon(SNAME("Window")); const Color closed_icon_color_mod = Color(1, 1, 1, 0.5); + 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(); + // Add docks. docks_menu_docks.clear(); int id = 0; @@ -182,7 +185,7 @@ void EditorDockManager::_update_docks_menu() { } else { docks_menu->add_item(dock.value.title, id); } - const Ref icon = dock.value.icon_name ? docks_menu->get_editor_theme_icon(dock.value.icon_name) : dock.value.icon; + const Ref icon = dock.value.icon_name ? docks_menu->get_editor_theme_native_menu_icon(dock.value.icon_name, global_menu, dark_mode) : 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); @@ -613,7 +616,7 @@ void EditorDockManager::load_docks_from_config(Ref p_layout, const S int ofs = p_layout->get_value(p_section, "dock_hsplit_" + itos(i + 1)); hsplits[i]->set_split_offset(ofs * EDSCALE); } - _update_docks_menu(); + update_docks_menu(); } void EditorDockManager::bottom_dock_show_placement_popup(const Rect2i &p_position, Control *p_dock) { @@ -848,7 +851,7 @@ EditorDockManager::EditorDockManager() { docks_menu = memnew(PopupMenu); docks_menu->set_hide_on_item_selection(false); docks_menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorDockManager::_docks_menu_option)); - EditorNode::get_singleton()->get_gui_base()->connect(SceneStringName(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) { diff --git a/editor/editor_dock_manager.h b/editor/editor_dock_manager.h index d750d6b24e9..962c79441d6 100644 --- a/editor/editor_dock_manager.h +++ b/editor/editor_dock_manager.h @@ -113,7 +113,6 @@ private: void _dock_container_update_visibility(TabContainer *p_dock_container); void _update_layout(); - void _update_docks_menu(); void _docks_menu_option(int p_id); void _window_close_request(WindowWrapper *p_wrapper); @@ -133,6 +132,7 @@ private: public: static EditorDockManager *get_singleton() { return singleton; } + void update_docks_menu(); void update_tab_styles(); void set_tab_icon_max_width(int p_max_width); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 2261b14acbe..4e6abeda4f0 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -541,6 +541,9 @@ void EditorNode::_update_theme(bool p_skip_creation) { // 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(); + gui_base->add_theme_style_override(SceneStringName(panel), theme->get_stylebox(SNAME("Background"), EditorStringName(EditorStyles))); 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))); @@ -550,10 +553,10 @@ void EditorNode::_update_theme(bool p_skip_creation) { distraction_free->set_button_icon(theme->get_icon(SNAME("DistractionFree"), EditorStringName(EditorIcons))); distraction_free->add_theme_style_override(SceneStringName(pressed), theme->get_stylebox(CoreStringName(normal), "FlatMenuButton")); - help_menu->set_item_icon(help_menu->get_item_index(HELP_SEARCH), theme->get_icon(SNAME("HelpSearch"), EditorStringName(EditorIcons))); - help_menu->set_item_icon(help_menu->get_item_index(HELP_COPY_SYSTEM_INFO), theme->get_icon(SNAME("ActionCopy"), EditorStringName(EditorIcons))); - help_menu->set_item_icon(help_menu->get_item_index(HELP_ABOUT), theme->get_icon(SNAME("Godot"), EditorStringName(EditorIcons))); - help_menu->set_item_icon(help_menu->get_item_index(HELP_SUPPORT_GODOT_DEVELOPMENT), theme->get_icon(SNAME("Heart"), EditorStringName(EditorIcons))); + help_menu->set_item_icon(help_menu->get_item_index(HELP_SEARCH), help_menu->get_editor_theme_native_menu_icon(SNAME("HelpSearch"), global_menu, dark_mode)); + help_menu->set_item_icon(help_menu->get_item_index(HELP_COPY_SYSTEM_INFO), help_menu->get_editor_theme_native_menu_icon(SNAME("ActionCopy"), global_menu, dark_mode)); + help_menu->set_item_icon(help_menu->get_item_index(HELP_ABOUT), help_menu->get_editor_theme_native_menu_icon(SNAME("Godot"), global_menu, dark_mode)); + help_menu->set_item_icon(help_menu->get_item_index(HELP_SUPPORT_GODOT_DEVELOPMENT), help_menu->get_editor_theme_native_menu_icon(SNAME("Heart"), global_menu, dark_mode)); if (EditorDebuggerNode::get_singleton()->is_visible()) { bottom_panel->add_theme_style_override(SceneStringName(panel), theme->get_stylebox(SNAME("BottomPanelDebuggerOverride"), EditorStringName(EditorStyles))); @@ -563,6 +566,7 @@ void EditorNode::_update_theme(bool p_skip_creation) { } editor_dock_manager->update_tab_styles(); + editor_dock_manager->update_docks_menu(); editor_dock_manager->set_tab_icon_max_width(theme->get_constant(SNAME("class_icon_size"), EditorStringName(Editor))); } @@ -3287,6 +3291,7 @@ void EditorNode::_save_screenshot(NodePath p_path) { void EditorNode::_check_system_theme_changed() { 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; if (follow_system_theme) { @@ -3310,6 +3315,17 @@ void EditorNode::_check_system_theme_changed() { if (system_theme_changed) { _update_theme(); + } else if (global_menu && display_server->is_dark_mode_supported() && display_server->is_dark_mode() != last_dark_mode_state) { + last_dark_mode_state = display_server->is_dark_mode(); + + // Update system menus. + bool dark_mode = DisplayServer::get_singleton()->is_dark_mode(); + + help_menu->set_item_icon(help_menu->get_item_index(HELP_SEARCH), help_menu->get_editor_theme_native_menu_icon(SNAME("HelpSearch"), global_menu, dark_mode)); + help_menu->set_item_icon(help_menu->get_item_index(HELP_COPY_SYSTEM_INFO), help_menu->get_editor_theme_native_menu_icon(SNAME("ActionCopy"), global_menu, dark_mode)); + help_menu->set_item_icon(help_menu->get_item_index(HELP_ABOUT), help_menu->get_editor_theme_native_menu_icon(SNAME("Godot"), global_menu, dark_mode)); + help_menu->set_item_icon(help_menu->get_item_index(HELP_SUPPORT_GODOT_DEVELOPMENT), help_menu->get_editor_theme_native_menu_icon(SNAME("Heart"), global_menu, dark_mode)); + editor_dock_manager->update_docks_menu(); } } @@ -7308,6 +7324,7 @@ EditorNode::EditorNode() { 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) { @@ -7575,13 +7592,13 @@ EditorNode::EditorNode() { ED_SHORTCUT_AND_COMMAND("editor/editor_help", TTRC("Search Help..."), Key::F1); ED_SHORTCUT_OVERRIDE("editor/editor_help", "macos", KeyModifierMask::ALT | Key::SPACE); - help_menu->add_icon_shortcut(theme->get_icon(SNAME("HelpSearch"), EditorStringName(EditorIcons)), ED_GET_SHORTCUT("editor/editor_help"), HELP_SEARCH); + help_menu->add_icon_shortcut(help_menu->get_editor_theme_native_menu_icon(SNAME("HelpSearch"), global_menu, dark_mode), ED_GET_SHORTCUT("editor/editor_help"), HELP_SEARCH); help_menu->add_separator(); help_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/online_docs", TTRC("Online Documentation")), HELP_DOCS); 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); help_menu->add_separator(); - help_menu->add_icon_shortcut(theme->get_icon(SNAME("ActionCopy"), EditorStringName(EditorIcons)), ED_SHORTCUT_AND_COMMAND("editor/copy_system_info", TTRC("Copy System Info")), HELP_COPY_SYSTEM_INFO); + help_menu->add_icon_shortcut(help_menu->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); help_menu->set_item_tooltip(-1, TTR("Copies the system info as a single-line text into the clipboard.")); help_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/report_a_bug", TTRC("Report a Bug")), HELP_REPORT_A_BUG); help_menu->add_shortcut(ED_SHORTCUT_AND_COMMAND("editor/suggest_a_feature", TTRC("Suggest a Feature")), HELP_SUGGEST_A_FEATURE); @@ -7589,9 +7606,9 @@ EditorNode::EditorNode() { 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(theme->get_icon(SNAME("Godot"), EditorStringName(EditorIcons)), ED_SHORTCUT_AND_COMMAND("editor/about", TTRC("About Godot...")), HELP_ABOUT); + help_menu->add_icon_shortcut(help_menu->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(theme->get_icon(SNAME("Heart"), EditorStringName(EditorIcons)), ED_SHORTCUT_AND_COMMAND("editor/support_development", TTRC("Support Godot Development")), HELP_SUPPORT_GODOT_DEVELOPMENT); + help_menu->add_icon_shortcut(help_menu->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); diff --git a/editor/themes/editor_icons.cpp b/editor/themes/editor_icons.cpp index b7da3cfad8a..a415a9191e1 100644 --- a/editor/themes/editor_icons.cpp +++ b/editor/themes/editor_icons.cpp @@ -94,21 +94,37 @@ void editor_register_icons(const Ref &p_theme, bool p_dark_theme, float p // And then some icons are completely excluded from the conversion. // Standard color conversion map. - HashMap color_conversion_map; + HashMap color_conversion_map_light; + HashMap color_conversion_map_dark; // Icons by default are set up for the dark theme, so if the theme is light, // we apply the dark-to-light color conversion map. - if (!p_dark_theme) { - for (KeyValue &E : EditorColorMap::get_color_conversion_map()) { - color_conversion_map[E.key] = E.value; - } + for (KeyValue &E : EditorColorMap::get_color_conversion_map()) { + color_conversion_map_light[E.key] = E.value; } // These colors should be converted even if we are using a dark theme. const Color error_color = p_theme->get_color(SNAME("error_color"), EditorStringName(Editor)); const Color success_color = p_theme->get_color(SNAME("success_color"), EditorStringName(Editor)); const Color warning_color = p_theme->get_color(SNAME("warning_color"), EditorStringName(Editor)); - color_conversion_map[Color::html("#ff5f5f")] = error_color; - color_conversion_map[Color::html("#5fff97")] = success_color; - color_conversion_map[Color::html("#ffdd65")] = warning_color; + color_conversion_map_dark[Color::html("#ff5f5f")] = error_color; + color_conversion_map_dark[Color::html("#5fff97")] = success_color; + color_conversion_map_dark[Color::html("#ffdd65")] = warning_color; + color_conversion_map_light[Color::html("#ff5f5f")] = error_color; + color_conversion_map_light[Color::html("#5fff97")] = success_color; + color_conversion_map_light[Color::html("#ffdd65")] = warning_color; + + HashMap color_conversion_map = p_dark_theme ? color_conversion_map_dark : color_conversion_map_light; + + // The names of the icons used in native menus. + HashSet native_menu_icons; + native_menu_icons.insert("HelpSearch"); + native_menu_icons.insert("ActionCopy"); + native_menu_icons.insert("Heart"); + native_menu_icons.insert("PackedScene"); + native_menu_icons.insert("FileAccess"); + native_menu_icons.insert("Folder"); + native_menu_icons.insert("AnimationTrackList"); + native_menu_icons.insert("Object"); + native_menu_icons.insert("History"); // The names of the icons to exclude from the standard color conversion. HashSet conversion_exceptions = EditorColorMap::get_color_conversion_exceptions(); @@ -141,25 +157,38 @@ void editor_register_icons(const Ref &p_theme, bool p_dark_theme, float p // Generate icons. { for (int i = 0; i < editor_icons_count; i++) { - Ref icon; - const String &editor_icon_name = editor_icons_names[i]; - if (accent_color_icons.has(editor_icon_name)) { - icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name, p_gizmo_handle_scale), 1.0, accent_color_map); - } else { + if (native_menu_icons.has(editor_icon_name)) { float saturation = p_icon_saturation; if (saturation_exceptions.has(editor_icon_name)) { saturation = 1.0; } - if (conversion_exceptions.has(editor_icon_name)) { - icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name, p_gizmo_handle_scale), saturation); - } else { - icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name, p_gizmo_handle_scale), saturation, color_conversion_map); - } - } + Ref icon_dark = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name, p_gizmo_handle_scale), saturation, color_conversion_map_dark); + Ref icon_light = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name, p_gizmo_handle_scale), saturation, color_conversion_map_light); - p_theme->set_icon(editor_icon_name, EditorStringName(EditorIcons), icon); + p_theme->set_icon(editor_icon_name + "Dark", EditorStringName(EditorIcons), icon_dark); + p_theme->set_icon(editor_icon_name + "Light", EditorStringName(EditorIcons), icon_light); + p_theme->set_icon(editor_icon_name, EditorStringName(EditorIcons), p_dark_theme ? icon_dark : icon_light); + } else { + Ref icon; + if (accent_color_icons.has(editor_icon_name)) { + icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name, p_gizmo_handle_scale), 1.0, accent_color_map); + } else { + float saturation = p_icon_saturation; + if (saturation_exceptions.has(editor_icon_name)) { + saturation = 1.0; + } + + if (conversion_exceptions.has(editor_icon_name)) { + icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name, p_gizmo_handle_scale), saturation); + } else { + icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name, p_gizmo_handle_scale), saturation, color_conversion_map); + } + } + + p_theme->set_icon(editor_icon_name, EditorStringName(EditorIcons), icon); + } } } diff --git a/scene/main/window.cpp b/scene/main/window.cpp index d6328972b89..62c26bd836a 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -2372,6 +2372,18 @@ Variant Window::get_theme_item(Theme::DataType p_data_type, const StringName &p_ Ref Window::get_editor_theme_icon(const StringName &p_name) const { return get_theme_icon(p_name, SNAME("EditorIcons")); } + +Ref Window::get_editor_theme_native_menu_icon(const StringName &p_name, bool p_global_menu, bool p_dark_mode) const { + if (!p_global_menu) { + return get_theme_icon(p_name, SNAME("EditorIcons")); + } + if (p_dark_mode && has_theme_icon(String(p_name) + "Dark", SNAME("EditorIcons"))) { + return get_theme_icon(String(p_name) + "Dark", SNAME("EditorIcons")); + } else if (!p_dark_mode && has_theme_icon(String(p_name) + "Light", SNAME("EditorIcons"))) { + return get_theme_icon(String(p_name) + "Light", SNAME("EditorIcons")); + } + return get_theme_icon(p_name, SNAME("EditorIcons")); +} #endif bool Window::has_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { diff --git a/scene/main/window.h b/scene/main/window.h index 285fd95db10..04f2a62c2f8 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -457,6 +457,7 @@ public: Variant get_theme_item(Theme::DataType p_data_type, const StringName &p_name, const StringName &p_theme_type = StringName()) const; #ifdef TOOLS_ENABLED Ref get_editor_theme_icon(const StringName &p_name) const; + Ref get_editor_theme_native_menu_icon(const StringName &p_name, bool p_global_menu, bool p_dark_mode) const; #endif bool has_theme_icon_override(const StringName &p_name) const;