diff --git a/editor/debugger/editor_performance_profiler.cpp b/editor/debugger/editor_performance_profiler.cpp index af723cc731af..37e13b59cc65 100644 --- a/editor/debugger/editor_performance_profiler.cpp +++ b/editor/debugger/editor_performance_profiler.cpp @@ -31,9 +31,9 @@ #include "editor_performance_profiler.h" #include "editor/editor_property_name_processor.h" -#include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/themes/editor_scale.h" +#include "editor/themes/editor_theme_manager.h" #include "main/performance.h" EditorPerformanceProfiler::Monitor::Monitor() {} @@ -122,7 +122,7 @@ void EditorPerformanceProfiler::_monitor_draw() { } Size2i cell_size = Size2i(monitor_draw->get_size()) / Size2i(columns, rows); float spacing = float(POINT_SEPARATION) / float(columns); - float value_multiplier = EditorSettings::get_singleton()->is_dark_theme() ? 1.4f : 0.55f; + float value_multiplier = EditorThemeManager::is_dark_theme() ? 1.4f : 0.55f; float hue_shift = 1.0f / float(monitors.size()); for (int i = 0; i < active.size(); i++) { diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index 50845b445863..61a4b341b92f 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -41,6 +41,7 @@ #include "editor/filesystem_dock.h" #include "editor/gui/editor_file_dialog.h" #include "editor/themes/editor_scale.h" +#include "editor/themes/editor_theme_manager.h" #include "scene/gui/separator.h" #include "scene/resources/font.h" #include "servers/audio_server.h" @@ -84,9 +85,9 @@ void EditorAudioBus::_notification(int p_what) { disabled_vu = get_editor_theme_icon(SNAME("BusVuFrozen")); - Color solo_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(1.0, 0.89, 0.22) : Color(1.0, 0.92, 0.44); - Color mute_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(1.0, 0.16, 0.16) : Color(1.0, 0.44, 0.44); - Color bypass_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(0.13, 0.8, 1.0) : Color(0.44, 0.87, 1.0); + Color solo_color = EditorThemeManager::is_dark_theme() ? Color(1.0, 0.89, 0.22) : Color(1.0, 0.92, 0.44); + Color mute_color = EditorThemeManager::is_dark_theme() ? Color(1.0, 0.16, 0.16) : Color(1.0, 0.44, 0.44); + Color bypass_color = EditorThemeManager::is_dark_theme() ? Color(0.13, 0.8, 1.0) : Color(0.44, 0.87, 1.0); solo->set_icon(get_editor_theme_icon(SNAME("AudioBusSolo"))); solo->add_theme_color_override("icon_pressed_color", solo_color); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 521477d4706e..87d55318061c 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -808,7 +808,7 @@ void EditorNode::_update_update_spinner() { // as this feature should only be enabled for troubleshooting purposes. // Make the icon modulate color overbright because icons are not completely white on a dark theme. // On a light theme, icons are dark, so we need to modulate them with an even brighter color. - const bool dark_theme = EditorSettings::get_singleton()->is_dark_theme(); + const bool dark_theme = EditorThemeManager::is_dark_theme(); update_spinner->set_self_modulate(theme->get_color(SNAME("error_color"), EditorStringName(Editor)) * (dark_theme ? Color(1.1, 1.1, 1.1) : Color(4.25, 4.25, 4.25))); } else { update_spinner->set_tooltip_text(TTR("Spins when the editor window redraws.")); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index b56543118578..25510122f40d 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -1278,14 +1278,6 @@ void EditorSettings::load_favorites_and_recent_dirs() { } } -bool EditorSettings::is_dark_theme() { - int AUTO_COLOR = 0; - int LIGHT_COLOR = 2; - Color base_color = get("interface/theme/base_color"); - int icon_font_color_setting = get("interface/theme/icon_and_font_color"); - return (icon_font_color_setting == AUTO_COLOR && base_color.get_luminance() < 0.5) || icon_font_color_setting == LIGHT_COLOR; -} - void EditorSettings::list_text_editor_themes() { String themes = "Default,Godot 2,Custom"; diff --git a/editor/editor_settings.h b/editor/editor_settings.h index c3ce790e0e7b..2e280ac9d6ec 100644 --- a/editor/editor_settings.h +++ b/editor/editor_settings.h @@ -158,8 +158,6 @@ class EditorSettings : public Resource { Vector get_recent_dirs() const; void load_favorites_and_recent_dirs(); - bool is_dark_theme(); - void list_text_editor_themes(); void load_text_editor_theme(); bool import_text_editor_theme(String p_file); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index a46dffb1f38d..189f728fe410 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -53,6 +53,7 @@ #include "editor/scene_tree_dock.h" #include "editor/shader_create_dialog.h" #include "editor/themes/editor_scale.h" +#include "editor/themes/editor_theme_manager.h" #include "scene/gui/item_list.h" #include "scene/gui/label.h" #include "scene/gui/line_edit.h" @@ -625,7 +626,7 @@ void FileSystemDock::_notification(int p_what) { // Update editor dark theme & always show folders states from editor settings, redraw if needed. bool do_redraw = false; - bool new_editor_is_dark_theme = EditorSettings::get_singleton()->is_dark_theme(); + bool new_editor_is_dark_theme = EditorThemeManager::is_dark_theme(); if (new_editor_is_dark_theme != editor_is_dark_theme) { editor_is_dark_theme = new_editor_is_dark_theme; do_redraw = true; @@ -3763,7 +3764,7 @@ FileSystemDock::FileSystemDock() { assigned_folder_colors = ProjectSettings::get_singleton()->get_setting("file_customization/folder_colors"); - editor_is_dark_theme = EditorSettings::get_singleton()->is_dark_theme(); + editor_is_dark_theme = EditorThemeManager::is_dark_theme(); VBoxContainer *top_vbc = memnew(VBoxContainer); add_child(top_vbc); diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index cdfc85cf6f72..8cf104725ada 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -36,10 +36,10 @@ #include "core/version.h" #include "editor/editor_file_system.h" #include "editor/editor_node.h" -#include "editor/editor_settings.h" #include "editor/gui/editor_toaster.h" #include "editor/import/resource_importer_texture_settings.h" #include "editor/themes/editor_scale.h" +#include "editor/themes/editor_theme_manager.h" #include "scene/resources/compressed_texture.h" void ResourceImporterTexture::_texture_reimport_roughness(const Ref &p_tex, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_channel) { @@ -696,7 +696,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String editor_meta["editor_scale"] = EDSCALE; } if (convert_editor_colors) { - editor_meta["editor_dark_theme"] = EditorSettings::get_singleton()->is_dark_theme(); + editor_meta["editor_dark_theme"] = EditorThemeManager::is_dark_theme(); } _save_editor_meta(editor_meta, p_save_path + ".editor.meta"); @@ -755,7 +755,7 @@ bool ResourceImporterTexture::are_import_settings_valid(const String &p_path) co if (editor_meta.has("editor_scale") && (float)editor_meta["editor_scale"] != EDSCALE) { return false; } - if (editor_meta.has("editor_dark_theme") && (bool)editor_meta["editor_dark_theme"] != EditorSettings::get_singleton()->is_dark_theme()) { + if (editor_meta.has("editor_dark_theme") && (bool)editor_meta["editor_dark_theme"] != EditorThemeManager::is_dark_theme()) { return false; } } diff --git a/editor/plugins/bone_map_editor_plugin.cpp b/editor/plugins/bone_map_editor_plugin.cpp index 38573fbaa734..3256b90aba5d 100644 --- a/editor/plugins/bone_map_editor_plugin.cpp +++ b/editor/plugins/bone_map_editor_plugin.cpp @@ -36,6 +36,7 @@ #include "editor/import/3d/post_import_plugin_skeleton_track_organizer.h" #include "editor/import/3d/scene_import_settings.h" #include "editor/themes/editor_scale.h" +#include "editor/themes/editor_theme_manager.h" #include "scene/gui/aspect_ratio_container.h" #include "scene/gui/separator.h" #include "scene/gui/texture_rect.h" @@ -52,7 +53,7 @@ void BoneMapperButton::fetch_textures() { set_offset(SIDE_BOTTOM, 0); // Hack to avoid handle color darkening... - set_modulate(EditorSettings::get_singleton()->is_dark_theme() ? Color(1, 1, 1) : Color(4.25, 4.25, 4.25)); + set_modulate(EditorThemeManager::is_dark_theme() ? Color(1, 1, 1) : Color(4.25, 4.25, 4.25)); circle = memnew(TextureRect); circle->set_texture(get_editor_theme_icon(SNAME("BoneMapperHandleCircle"))); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 6c776ad9b3d9..3722d6bebabb 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -45,6 +45,7 @@ #include "editor/plugins/script_editor_plugin.h" #include "editor/scene_tree_dock.h" #include "editor/themes/editor_scale.h" +#include "editor/themes/editor_theme_manager.h" #include "scene/2d/polygon_2d.h" #include "scene/2d/skeleton_2d.h" #include "scene/2d/sprite_2d.h" @@ -3898,7 +3899,7 @@ void CanvasItemEditor::_update_editor_settings() { // to distinguish from the other key icons at the top. On a light theme, // the icon will be dark, so we need to lighten it before blending it // with the red color. - const Color key_auto_color = EditorSettings::get_singleton()->is_dark_theme() ? Color(1, 1, 1) : Color(4.25, 4.25, 4.25); + const Color key_auto_color = EditorThemeManager::is_dark_theme() ? Color(1, 1, 1) : Color(4.25, 4.25, 4.25); key_auto_insert_button->add_theme_color_override("icon_pressed_color", key_auto_color.lerp(Color(1, 0, 0), 0.55)); animation_menu->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); diff --git a/editor/plugins/particle_process_material_editor_plugin.cpp b/editor/plugins/particle_process_material_editor_plugin.cpp index e696da3f5ead..d6ec3921d5fc 100644 --- a/editor/plugins/particle_process_material_editor_plugin.cpp +++ b/editor/plugins/particle_process_material_editor_plugin.cpp @@ -34,6 +34,7 @@ #include "editor/editor_settings.h" #include "editor/editor_string_names.h" #include "editor/gui/editor_spin_slider.h" +#include "editor/themes/editor_theme_manager.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" #include "scene/gui/label.h" @@ -352,7 +353,7 @@ void ParticleProcessMaterialMinMaxPropertyEditor::_notification(int p_what) { min_edit->add_theme_color_override(SNAME("label_color"), get_theme_color(SNAME("property_color_x"), EditorStringName(Editor))); max_edit->add_theme_color_override(SNAME("label_color"), get_theme_color(SNAME("property_color_y"), EditorStringName(Editor))); - const bool dark_theme = EditorSettings::get_singleton()->is_dark_theme(); + const bool dark_theme = EditorThemeManager::is_dark_theme(); const Color accent_color = get_theme_color(SNAME("accent_color"), EditorStringName(Editor)); background_color = dark_theme ? Color(0.3, 0.3, 0.3) : Color(0.7, 0.7, 0.7); normal_color = dark_theme ? Color(0.5, 0.5, 0.5) : Color(0.8, 0.8, 0.8); diff --git a/editor/themes/editor_fonts.cpp b/editor/themes/editor_fonts.cpp index fc3631653cb8..ee613877027d 100644 --- a/editor/themes/editor_fonts.cpp +++ b/editor/themes/editor_fonts.cpp @@ -107,7 +107,6 @@ Ref make_bold_font(const Ref &p_font, double p_embolden, Ty } void editor_register_fonts(const Ref &p_theme) { - OS::get_singleton()->benchmark_begin_measure("EditorTheme", "Register Fonts"); Ref dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); TextServer::FontAntialiasing font_antialiasing = (TextServer::FontAntialiasing)(int)EDITOR_GET("interface/editor/font_antialiasing"); @@ -444,6 +443,4 @@ void editor_register_fonts(const Ref &p_theme) { p_theme->set_font_size("status_source_size", EditorStringName(EditorFonts), default_font_size); p_theme->set_font("status_source", EditorStringName(EditorFonts), mono_other_fc); - - OS::get_singleton()->benchmark_end_measure("EditorTheme", "Register Fonts"); } diff --git a/editor/themes/editor_icons.cpp b/editor/themes/editor_icons.cpp index bb767747f36d..f318b640d085 100644 --- a/editor/themes/editor_icons.cpp +++ b/editor/themes/editor_icons.cpp @@ -78,9 +78,8 @@ Ref editor_generate_icon(int p_index, float p_scale, float p_satur return ImageTexture::create_from_image(img); } -float get_gizmo_handle_scale(const String &gizmo_handle_name = "") { - const float scale_gizmo_handles_for_touch = EDITOR_GET("interface/touchscreen/scale_gizmo_handles"); - if (scale_gizmo_handles_for_touch > 1.0f) { +float get_gizmo_handle_scale(const String &p_gizmo_handle_name, float p_gizmo_handle_scale) { + if (p_gizmo_handle_scale > 1.0f) { // The names of the icons that require additional scaling. static HashSet gizmo_to_scale; if (gizmo_to_scale.is_empty()) { @@ -92,18 +91,15 @@ float get_gizmo_handle_scale(const String &gizmo_handle_name = "") { gizmo_to_scale.insert("EditorPathSmoothHandle"); } - if (gizmo_to_scale.has(gizmo_handle_name)) { - return EDSCALE * scale_gizmo_handles_for_touch; + if (gizmo_to_scale.has(p_gizmo_handle_name)) { + return EDSCALE * p_gizmo_handle_scale; } } return EDSCALE; } -void editor_register_icons(const Ref &p_theme, bool p_dark_theme, float p_icon_saturation, int p_thumb_size, bool p_only_thumbs) { - const String benchmark_key = vformat("Generate Icons (%s)", (p_only_thumbs ? "Only Thumbs" : "All")); - OS::get_singleton()->benchmark_begin_measure("EditorTheme", benchmark_key); - +void editor_register_icons(const Ref &p_theme, bool p_dark_theme, float p_icon_saturation, int p_thumb_size, float p_gizmo_handle_scale) { // Before we register the icons, we adjust their colors and saturation. // Most icons follow the standard rules for color conversion to follow the editor // theme's polarity (dark/light). We also adjust the saturation for most icons, @@ -158,13 +154,13 @@ void editor_register_icons(const Ref &p_theme, bool p_dark_theme, float p accent_color_icons.insert("PlayOverlay"); // Generate icons. - if (!p_only_thumbs) { + { 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), 1.0, accent_color_map); + 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)) { @@ -172,9 +168,9 @@ void editor_register_icons(const Ref &p_theme, bool p_dark_theme, float p } if (conversion_exceptions.has(editor_icon_name)) { - icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name), saturation); + 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), saturation, color_conversion_map); + icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name, p_gizmo_handle_scale), saturation, color_conversion_map); } } @@ -231,7 +227,6 @@ void editor_register_icons(const Ref &p_theme, bool p_dark_theme, float p p_theme->set_icon(editor_icons_names[index], EditorStringName(EditorIcons), icon); } } - OS::get_singleton()->benchmark_end_measure("EditorTheme", benchmark_key); } void editor_copy_icons(const Ref &p_theme, const Ref &p_old_theme) { diff --git a/editor/themes/editor_icons.h b/editor/themes/editor_icons.h index 2094ebf27c15..447057b5e433 100644 --- a/editor/themes/editor_icons.h +++ b/editor/themes/editor_icons.h @@ -34,7 +34,7 @@ #include "scene/resources/theme.h" void editor_configure_icons(bool p_dark_theme); -void editor_register_icons(const Ref &p_theme, bool p_dark_theme, float p_icon_saturation, int p_thumb_size, bool p_only_thumbs = false); +void editor_register_icons(const Ref &p_theme, bool p_dark_theme, float p_icon_saturation, int p_thumb_size, float p_gizmo_handle_scale); void editor_copy_icons(const Ref &p_theme, const Ref &p_old_theme); String get_default_project_icon(); diff --git a/editor/themes/editor_theme.h b/editor/themes/editor_theme.h index 41a60fdf9636..2cc7ad287e19 100644 --- a/editor/themes/editor_theme.h +++ b/editor/themes/editor_theme.h @@ -38,6 +38,10 @@ class EditorTheme : public Theme { static Vector editor_theme_types; + uint32_t generated_hash = 0; + uint32_t generated_fonts_hash = 0; + uint32_t generated_icons_hash = 0; + public: virtual Color get_color(const StringName &p_name, const StringName &p_theme_type) const override; virtual int get_constant(const StringName &p_name, const StringName &p_theme_type) const override; @@ -46,6 +50,15 @@ class EditorTheme : public Theme { virtual Ref get_icon(const StringName &p_name, const StringName &p_theme_type) const override; virtual Ref get_stylebox(const StringName &p_name, const StringName &p_theme_type) const override; + void set_generated_hash(uint32_t p_hash) { generated_hash = p_hash; } + uint32_t get_generated_hash() const { return generated_hash; } + + void set_generated_fonts_hash(uint32_t p_hash) { generated_fonts_hash = p_hash; } + uint32_t get_generated_fonts_hash() const { return generated_fonts_hash; } + + void set_generated_icons_hash(uint32_t p_hash) { generated_icons_hash = p_hash; } + uint32_t get_generated_icons_hash() const { return generated_icons_hash; } + static void initialize(); static void finalize(); }; diff --git a/editor/themes/editor_theme_manager.cpp b/editor/themes/editor_theme_manager.cpp index 4ce323c763fe..5eb287cc43a4 100644 --- a/editor/themes/editor_theme_manager.cpp +++ b/editor/themes/editor_theme_manager.cpp @@ -45,7 +45,81 @@ #include "scene/resources/style_box_texture.h" #include "scene/resources/texture.h" -// Helper methods. +// Theme configuration. + +uint32_t EditorThemeManager::ThemeConfiguration::hash() { + uint32_t hash = hash_murmur3_one_float(EDSCALE); + + // Basic properties. + + hash = hash_murmur3_one_32(preset.hash(), hash); + hash = hash_murmur3_one_32(spacing_preset.hash(), hash); + + hash = hash_murmur3_one_32(base_color.to_rgba32(), hash); + hash = hash_murmur3_one_32(accent_color.to_rgba32(), hash); + hash = hash_murmur3_one_float(contrast, hash); + hash = hash_murmur3_one_float(icon_saturation, hash); + + // Extra properties. + + hash = hash_murmur3_one_32(base_spacing, hash); + hash = hash_murmur3_one_32(extra_spacing, hash); + hash = hash_murmur3_one_32(border_width, hash); + hash = hash_murmur3_one_32(corner_radius, hash); + + hash = hash_murmur3_one_32((int)draw_extra_borders, hash); + hash = hash_murmur3_one_float(relationship_line_opacity, hash); + hash = hash_murmur3_one_32(thumb_size, hash); + hash = hash_murmur3_one_32(class_icon_size, hash); + hash = hash_murmur3_one_32((int)increase_scrollbar_touch_area, hash); + hash = hash_murmur3_one_float(gizmo_handle_scale, hash); + hash = hash_murmur3_one_32(color_picker_button_height, hash); + hash = hash_murmur3_one_float(subresource_hue_tint, hash); + + hash = hash_murmur3_one_float(default_contrast, hash); + + // Generated properties. + + hash = hash_murmur3_one_32((int)dark_theme, hash); + + return hash; +} + +uint32_t EditorThemeManager::ThemeConfiguration::hash_fonts() { + uint32_t hash = hash_murmur3_one_float(EDSCALE); + + // TODO: Implement the hash based on what editor_register_fonts() uses. + + return hash; +} + +uint32_t EditorThemeManager::ThemeConfiguration::hash_icons() { + uint32_t hash = hash_murmur3_one_float(EDSCALE); + + hash = hash_murmur3_one_32(accent_color.to_rgba32(), hash); + hash = hash_murmur3_one_float(icon_saturation, hash); + + hash = hash_murmur3_one_32(thumb_size, hash); + hash = hash_murmur3_one_float(gizmo_handle_scale, hash); + + hash = hash_murmur3_one_32((int)dark_theme, hash); + + return hash; +} + +// Benchmarks. + +int EditorThemeManager::benchmark_run = 0; + +String EditorThemeManager::get_benchmark_key() { + if (benchmark_run == 0) { + return "EditorTheme (Startup)"; + } + + return vformat("EditorTheme (Run %d)", benchmark_run); +} + +// Generation helper methods. Ref make_stylebox(Ref p_texture, float p_left, float p_top, float p_right, float p_bottom, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1, bool p_draw_center = true) { Ref style(memnew(StyleBoxTexture)); @@ -86,73 +160,71 @@ Ref make_line_stylebox(Color p_color, int p_thickness = 1, float p // Theme generation and population routines. -Ref EditorThemeManager::_create_base_theme(const Ref &p_old_theme) { - OS::get_singleton()->benchmark_begin_measure("EditorTheme", "Create Base Theme"); +Ref EditorThemeManager::_create_base_theme(const Ref &p_old_theme) { + OS::get_singleton()->benchmark_begin_measure(get_benchmark_key(), "Create Base Theme"); Ref theme = memnew(EditorTheme); ThemeConfiguration config = _create_theme_config(theme); + theme->set_generated_hash(config.hash()); + theme->set_generated_fonts_hash(config.hash_fonts()); + theme->set_generated_icons_hash(config.hash_icons()); + + print_verbose(vformat("EditorTheme: Generating new theme for the config '%d'.", theme->get_generated_hash())); + _create_shared_styles(theme, config); - // FIXME: Make the comparison more robust and fix imprecision issues by hashing affecting values. - // TODO: Refactor the icons check into their respective file, and add a similar check for fonts. - - // Register editor icons. - // If settings are comparable to the old theme, then just copy existing icons over. - // Otherwise, regenerate them. Also check if we need to regenerate "thumb" icons. - bool keep_old_icons = false; - bool regenerate_thumb_icons = true; - if (p_old_theme != nullptr) { - // We check editor scale, theme dark/light mode, icon saturation, and accent color. - - // That doesn't really work as expected, since theme constants are integers, and scales are floats. - // So this check will never work when changing between 100-199% values. - const float prev_scale = (float)p_old_theme->get_constant(SNAME("scale"), EditorStringName(Editor)); - const bool prev_dark_theme = (bool)p_old_theme->get_constant(SNAME("dark_theme"), EditorStringName(Editor)); - const Color prev_accent_color = p_old_theme->get_color(SNAME("accent_color"), EditorStringName(Editor)); - const float prev_icon_saturation = p_old_theme->get_color(SNAME("icon_saturation"), EditorStringName(Editor)).r; - const float prev_gizmo_handle_scale = (float)p_old_theme->get_constant(SNAME("gizmo_handle_scale"), EditorStringName(Editor)); - - keep_old_icons = (Math::is_equal_approx(prev_scale, EDSCALE) && - Math::is_equal_approx(prev_gizmo_handle_scale, config.gizmo_handle_scale) && - prev_dark_theme == config.dark_theme && - prev_accent_color == config.accent_color && - prev_icon_saturation == config.icon_saturation); - - const double prev_thumb_size = (double)p_old_theme->get_constant(SNAME("thumb_size"), EditorStringName(Editor)); - - regenerate_thumb_icons = !Math::is_equal_approx(prev_thumb_size, config.thumb_size); - } + // Register icons. + { + OS::get_singleton()->benchmark_begin_measure(get_benchmark_key(), "Register Icons"); + + // External functions, see editor_icons.cpp. + editor_configure_icons(config.dark_theme); - // External functions, see editor_icons.cpp. - editor_configure_icons(config.dark_theme); - if (keep_old_icons) { - editor_copy_icons(theme, p_old_theme); - } else { - editor_register_icons(theme, config.dark_theme, config.icon_saturation, config.thumb_size, false); + // If settings are comparable to the old theme, then just copy existing icons over. + // Otherwise, regenerate them. + bool keep_old_icons = (p_old_theme != nullptr && theme->get_generated_icons_hash() == p_old_theme->get_generated_icons_hash()); + if (keep_old_icons) { + print_verbose("EditorTheme: Can keep old icons, copying."); + editor_copy_icons(theme, p_old_theme); + } else { + print_verbose("EditorTheme: Generating new icons."); + editor_register_icons(theme, config.dark_theme, config.icon_saturation, config.thumb_size, config.gizmo_handle_scale); + } + + OS::get_singleton()->benchmark_end_measure(get_benchmark_key(), "Register Icons"); } - if (regenerate_thumb_icons) { - editor_register_icons(theme, config.dark_theme, config.icon_saturation, config.thumb_size, true); + + // Register fonts. + { + OS::get_singleton()->benchmark_begin_measure(get_benchmark_key(), "Register Fonts"); + + // TODO: Check if existing font definitions from the old theme are usable and copy them. + + // External function, see editor_fonts.cpp. + print_verbose("EditorTheme: Generating new fonts."); + editor_register_fonts(theme); + + OS::get_singleton()->benchmark_end_measure(get_benchmark_key(), "Register Fonts"); } - // External function, see editor_fonts.cpp. - editor_register_fonts(theme); + // TODO: Check if existing style definitions from the old theme are usable and copy them. + print_verbose("EditorTheme: Generating new styles."); _populate_standard_styles(theme, config); _populate_editor_styles(theme, config); _populate_text_editor_styles(theme, config); - OS::get_singleton()->benchmark_end_measure("EditorTheme", "Create Base Theme"); + OS::get_singleton()->benchmark_end_measure(get_benchmark_key(), "Create Base Theme"); return theme; } -EditorThemeManager::ThemeConfiguration EditorThemeManager::_create_theme_config(const Ref &p_theme) { +EditorThemeManager::ThemeConfiguration EditorThemeManager::_create_theme_config(const Ref &p_theme) { ThemeConfiguration config; // Basic properties. config.preset = EDITOR_GET("interface/theme/preset"); config.spacing_preset = EDITOR_GET("interface/theme/spacing_preset"); - config.dark_theme = EditorSettings::get_singleton()->is_dark_theme(); config.base_color = EDITOR_GET("interface/theme/base_color"); config.accent_color = EDITOR_GET("interface/theme/accent_color"); @@ -174,6 +246,7 @@ EditorThemeManager::ThemeConfiguration EditorThemeManager::_create_theme_config( config.increase_scrollbar_touch_area = EDITOR_GET("interface/touchscreen/increase_scrollbar_touch_area"); config.gizmo_handle_scale = EDITOR_GET("interface/touchscreen/scale_gizmo_handles"); config.color_picker_button_height = 28 * EDSCALE; + config.subresource_hue_tint = EDITOR_GET("docks/property_editor/subresource_hue_tint"); config.default_contrast = 0.3; // Make sure to keep this in sync with the editor settings definition. @@ -275,6 +348,8 @@ EditorThemeManager::ThemeConfiguration EditorThemeManager::_create_theme_config( // Generated properties. + config.dark_theme = is_dark_theme(); + config.base_margin = config.base_spacing; config.increased_margin = config.base_spacing + config.extra_spacing; config.separation_margin = (config.base_spacing + config.extra_spacing / 2) * EDSCALE; @@ -292,7 +367,7 @@ EditorThemeManager::ThemeConfiguration EditorThemeManager::_create_theme_config( return config; } -void EditorThemeManager::_create_shared_styles(const Ref &p_theme, ThemeConfiguration &p_config) { +void EditorThemeManager::_create_shared_styles(const Ref &p_theme, ThemeConfiguration &p_config) { // Colors. { // Base colors. @@ -556,7 +631,7 @@ void EditorThemeManager::_create_shared_styles(const Ref &p_theme, ThemeC } } -void EditorThemeManager::_populate_standard_styles(const Ref &p_theme, ThemeConfiguration &p_config) { +void EditorThemeManager::_populate_standard_styles(const Ref &p_theme, ThemeConfiguration &p_config) { // Panels. { // Panel. @@ -1508,7 +1583,7 @@ void EditorThemeManager::_populate_standard_styles(const Ref &p_theme, Th } } -void EditorThemeManager::_populate_editor_styles(const Ref &p_theme, ThemeConfiguration &p_config) { +void EditorThemeManager::_populate_editor_styles(const Ref &p_theme, ThemeConfiguration &p_config) { // Project manager. { p_theme->set_stylebox("search_panel", "ProjectManager", p_config.tree_panel_style); @@ -1789,7 +1864,7 @@ void EditorThemeManager::_populate_editor_styles(const Ref &p_theme, Them float hue_rotate = (i * 2 % 16) / 16.0; si_base_color.set_hsv(Math::fmod(float(si_base_color.get_h() + hue_rotate), float(1.0)), si_base_color.get_s(), si_base_color.get_v()); - si_base_color = p_config.accent_color.lerp(si_base_color, float(EDITOR_GET("docks/property_editor/subresource_hue_tint"))); + si_base_color = p_config.accent_color.lerp(si_base_color, p_config.subresource_hue_tint); // Sub-inspector background. Ref sub_inspector_bg = p_config.base_style->duplicate(); @@ -1823,7 +1898,7 @@ void EditorThemeManager::_populate_editor_styles(const Ref &p_theme, Them style_property_child_bg->set_bg_color(p_config.dark_color_2); style_property_child_bg->set_border_width_all(0); - p_theme->set_stylebox("bg", "EditorProperty", Ref(memnew(StyleBoxEmpty))); + p_theme->set_stylebox("bg", "EditorProperty", memnew(StyleBoxEmpty)); p_theme->set_stylebox("bg_selected", "EditorProperty", style_property_bg); p_theme->set_stylebox("child_bg", "EditorProperty", style_property_child_bg); p_theme->set_constant("font_offset", "EditorProperty", 8 * EDSCALE); @@ -2126,7 +2201,7 @@ void EditorThemeManager::_generate_text_editor_defaults(ThemeConfiguration &p_co /* clang-format on */ } -void EditorThemeManager::_populate_text_editor_styles(const Ref &p_theme, ThemeConfiguration &p_config) { +void EditorThemeManager::_populate_text_editor_styles(const Ref &p_theme, ThemeConfiguration &p_config) { String text_editor_color_theme = EditorSettings::get_singleton()->get("text_editor/theme/color_theme"); if (text_editor_color_theme == "Default") { _generate_text_editor_defaults(p_config); @@ -2155,7 +2230,7 @@ void EditorThemeManager::_populate_text_editor_styles(const Ref &p_theme, Ref code_edit_stylebox = make_flat_stylebox(background_color, p_config.widget_margin.x, p_config.widget_margin.y, p_config.widget_margin.x, p_config.widget_margin.y, p_config.corner_radius); p_theme->set_stylebox("normal", "CodeEdit", code_edit_stylebox); p_theme->set_stylebox("read_only", "CodeEdit", code_edit_stylebox); - p_theme->set_stylebox("focus", "CodeEdit", Ref(memnew(StyleBoxEmpty))); + p_theme->set_stylebox("focus", "CodeEdit", memnew(StyleBoxEmpty)); p_theme->set_color("background_color", "CodeEdit", Color(0, 0, 0, 0)); // Unset any color, we use a stylebox. @@ -2186,10 +2261,12 @@ void EditorThemeManager::_populate_text_editor_styles(const Ref &p_theme, // Public interface for theme generation. -Ref EditorThemeManager::generate_theme(const Ref &p_old_theme) { - OS::get_singleton()->benchmark_begin_measure("EditorTheme", "Generate Theme"); +Ref EditorThemeManager::generate_theme(const Ref &p_old_theme) { + OS::get_singleton()->benchmark_begin_measure(get_benchmark_key(), "Generate Theme"); - Ref theme = _create_base_theme(p_old_theme); + Ref theme = _create_base_theme(p_old_theme); + + OS::get_singleton()->benchmark_begin_measure(get_benchmark_key(), "Merge Custom Theme"); const String custom_theme_path = EDITOR_GET("interface/theme/custom_theme"); if (!custom_theme_path.is_empty()) { @@ -2199,7 +2276,11 @@ Ref EditorThemeManager::generate_theme(const Ref &p_old_theme) { } } - OS::get_singleton()->benchmark_end_measure("EditorTheme", "Generate Theme"); + OS::get_singleton()->benchmark_end_measure(get_benchmark_key(), "Merge Custom Theme"); + + OS::get_singleton()->benchmark_end_measure(get_benchmark_key(), "Generate Theme"); + benchmark_run++; + return theme; } @@ -2213,12 +2294,25 @@ bool EditorThemeManager::is_generated_theme_outdated() { EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/font") || EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/main_font") || EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/code_font") || + EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/increase_scrollbar_touch_area") || + EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/scale_gizmo_handles") || EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/theme") || EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/help/help") || + EditorSettings::get_singleton()->check_changed_settings_in_group("docks/property_editor/subresource_hue_tint") || EditorSettings::get_singleton()->check_changed_settings_in_group("filesystem/file_dialog/thumbnail_size") || - EditorSettings::get_singleton()->check_changed_settings_in_group("run/output/font_size") || - EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/increase_scrollbar_touch_area") || - EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/scale_gizmo_handles"); + EditorSettings::get_singleton()->check_changed_settings_in_group("run/output/font_size"); +} + +bool EditorThemeManager::is_dark_theme() { + // Light color mode for icons and fonts means it's a dark theme, and vice versa. + int icon_font_color_setting = EDITOR_GET("interface/theme/icon_and_font_color"); + + if (icon_font_color_setting == ColorMode::AUTO_COLOR) { + Color base_color = EDITOR_GET("interface/theme/base_color"); + return base_color.get_luminance() < 0.5; + } + + return icon_font_color_setting == ColorMode::LIGHT_COLOR; } void EditorThemeManager::initialize() { diff --git a/editor/themes/editor_theme_manager.h b/editor/themes/editor_theme_manager.h index 86188ec244c1..0b30a9c853d3 100644 --- a/editor/themes/editor_theme_manager.h +++ b/editor/themes/editor_theme_manager.h @@ -31,16 +31,25 @@ #ifndef EDITOR_THEME_MANAGER_H #define EDITOR_THEME_MANAGER_H +#include "editor/themes/editor_theme.h" #include "scene/resources/style_box_flat.h" -#include "scene/resources/theme.h" class EditorThemeManager { + static int benchmark_run; + + static String get_benchmark_key(); + + enum ColorMode { + AUTO_COLOR, + DARK_COLOR, + LIGHT_COLOR, + }; + struct ThemeConfiguration { // Basic properties. String preset; String spacing_preset; - bool dark_theme = false; Color base_color; Color accent_color; @@ -61,11 +70,14 @@ class EditorThemeManager { bool increase_scrollbar_touch_area = false; float gizmo_handle_scale = 1.0; int color_picker_button_height = 28; + float subresource_hue_tint = 0.0; float default_contrast = 1.0; // Generated properties. + bool dark_theme = false; + int base_margin = 4; int increased_margin = 4; int separation_margin = 4; @@ -127,22 +139,28 @@ class EditorThemeManager { Ref tree_panel_style; Vector2 widget_margin; + + uint32_t hash(); + uint32_t hash_fonts(); + uint32_t hash_icons(); }; - static Ref _create_base_theme(const Ref &p_old_theme = nullptr); - static ThemeConfiguration _create_theme_config(const Ref &p_theme); + static Ref _create_base_theme(const Ref &p_old_theme = nullptr); + static ThemeConfiguration _create_theme_config(const Ref &p_theme); - static void _create_shared_styles(const Ref &p_theme, ThemeConfiguration &p_config); - static void _populate_standard_styles(const Ref &p_theme, ThemeConfiguration &p_config); - static void _populate_editor_styles(const Ref &p_theme, ThemeConfiguration &p_config); + static void _create_shared_styles(const Ref &p_theme, ThemeConfiguration &p_config); + static void _populate_standard_styles(const Ref &p_theme, ThemeConfiguration &p_config); + static void _populate_editor_styles(const Ref &p_theme, ThemeConfiguration &p_config); static void _generate_text_editor_defaults(ThemeConfiguration &p_config); - static void _populate_text_editor_styles(const Ref &p_theme, ThemeConfiguration &p_config); + static void _populate_text_editor_styles(const Ref &p_theme, ThemeConfiguration &p_config); public: - static Ref generate_theme(const Ref &p_old_theme = nullptr); + static Ref generate_theme(const Ref &p_old_theme = nullptr); static bool is_generated_theme_outdated(); + static bool is_dark_theme(); + static void initialize(); static void finalize(); }; diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index 3df07f979449..1f07def21c85 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -35,6 +35,7 @@ #include "core/config/project_settings.h" #include "editor/editor_settings.h" +#include "editor/themes/editor_theme_manager.h" Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_line) { Dictionary color_map; @@ -790,7 +791,7 @@ void GDScriptSyntaxHighlighter::_update_cache() { const String text_edit_color_theme = EDITOR_GET("text_editor/theme/color_theme"); const bool godot_2_theme = text_edit_color_theme == "Godot 2"; - if (godot_2_theme || EditorSettings::get_singleton()->is_dark_theme()) { + if (godot_2_theme || EditorThemeManager::is_dark_theme()) { function_definition_color = Color(0.4, 0.9, 1.0); global_function_color = Color(0.64, 0.64, 0.96); node_path_color = Color(0.72, 0.77, 0.49);