From 635b8a1474843fcdb4bdd3d9c32254c9aebb0836 Mon Sep 17 00:00:00 2001 From: Yuri Sizov Date: Mon, 15 Jan 2024 13:14:55 +0100 Subject: [PATCH] Split theme generation logic into several subroutines This change introduces a new theme configuration struct to be passed to the aforementioned routines to better control reuse of styles and definitions in the generator. Everything not passed and not explicitly shared is scoped so it is not automatically accessible throughout the routine. This should ensure that the decision to share styles is a conscious one. In the future we will try to reduce the number of unique definitions and share most of it. This PR is a stepping stone on this path. This also puts the effort into separating redefinitions of default theme items vs custom types introduced only by the editor. In a few cases where editor-specific definitions need to reference default definitions we simply fetch them from the theme. It's not ideal and hides the dependency a bit, but hopefully these cases will be abstracted properly in due time. --- editor/animation_bezier_editor.cpp | 2 +- editor/animation_track_editor.cpp | 2 +- editor/create_dialog.cpp | 2 +- editor/editor_build_profile.cpp | 2 +- editor/editor_feature_profile.cpp | 2 +- editor/editor_help_search.cpp | 2 +- editor/editor_inspector.cpp | 2 +- editor/editor_node.cpp | 1 + editor/editor_properties.cpp | 8 +- editor/export/export_template_manager.cpp | 2 +- editor/export/project_export.cpp | 2 +- editor/gui/scene_tree_editor.cpp | 8 +- .../plugins/asset_library_editor_plugin.cpp | 1 - editor/plugins/theme_editor_plugin.cpp | 5 +- .../tiles/tile_set_atlas_source_editor.cpp | 2 +- editor/themes/editor_theme_manager.cpp | 3832 +++++++++-------- editor/themes/editor_theme_manager.h | 100 + 17 files changed, 2155 insertions(+), 1820 deletions(-) diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index 69319d1d495..f29b8516737 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -334,7 +334,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) { } } - Color dc = get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor)); + Color dc = get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor)); Ref remove = get_editor_theme_icon(SNAME("Remove")); float remove_hpos = limit - hsep - remove->get_width(); diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 404bfdbd7c9..3c704b34733 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -1921,7 +1921,7 @@ void AnimationTrackEdit::_notification(int p_what) { Color linecolor = color; linecolor.a = 0.2; - Color dc = get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor)); + Color dc = get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor)); // NAMES AND ICONS // diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 22801988157..da0182b1761 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -306,7 +306,7 @@ void CreateDialog::_configure_search_option_item(TreeItem *r_item, const String r_item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_type)); if (!instantiable) { - r_item->set_custom_color(0, search_options->get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + r_item->set_custom_color(0, search_options->get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); } HashMap::Iterator class_doc = EditorHelp::get_doc_data()->class_list.find(p_type); diff --git a/editor/editor_build_profile.cpp b/editor/editor_build_profile.cpp index 0677064f28e..3d10b7949eb 100644 --- a/editor/editor_build_profile.cpp +++ b/editor/editor_build_profile.cpp @@ -601,7 +601,7 @@ void EditorBuildProfileManager::_fill_classes_from(TreeItem *p_parent, const Str bool disabled = edited->is_class_disabled(p_class); if (disabled) { - class_item->set_custom_color(0, class_list->get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + class_item->set_custom_color(0, class_list->get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); } class_item->set_text(0, text); diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp index 8c64ce1c70c..aa44ea380b8 100644 --- a/editor/editor_feature_profile.cpp +++ b/editor/editor_feature_profile.cpp @@ -503,7 +503,7 @@ void EditorFeatureProfileManager::_fill_classes_from(TreeItem *p_parent, const S bool disabled_editor = edited->is_class_editor_disabled(p_class); bool disabled_properties = edited->has_class_properties_disabled(p_class); if (disabled) { - class_item->set_custom_color(0, class_list->get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + class_item->set_custom_color(0, class_list->get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); } else if (disabled_editor && disabled_properties) { text += " " + TTR("(Editor Disabled, Properties Disabled)"); } else if (disabled_properties) { diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index 40c26689b81..b200154ec8c 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -698,5 +698,5 @@ EditorHelpSearch::Runner::Runner(Control *p_icon_service, Tree *p_results_tree, results_tree(p_results_tree), term((p_search_flags & SEARCH_CASE_SENSITIVE) == 0 ? p_term.strip_edges().to_lower() : p_term.strip_edges()), search_flags(p_search_flags), - disabled_color(ui_service->get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))) { + disabled_color(ui_service->get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))) { } diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index b7704da063d..a3530fc9abd 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -1357,7 +1357,7 @@ void EditorInspectorSection::_notification(int p_what) { Ref light_font = get_theme_font(SNAME("main"), EditorStringName(EditorFonts)); int light_font_size = get_theme_font_size(SNAME("main_size"), EditorStringName(EditorFonts)); - Color light_font_color = get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor)); + Color light_font_color = get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor)); // Can we fit the long version of the revertable count text? num_revertable_str = vformat(TTRN("(%d change)", "(%d changes)", revertable_properties.size()), revertable_properties.size()); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 528bc0a758d..521477d4706 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -5978,6 +5978,7 @@ void EditorNode::_bottom_panel_raise_toggled(bool p_pressed) { void EditorNode::_update_renderer_color() { String rendering_method = renderer->get_selected_metadata(); + // TODO: Use theme colors instead of hardcoded values. if (rendering_method == "forward_plus") { renderer->add_theme_color_override("font_color", Color::hex(0x5d8c3fff)); } diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 16f808367f9..f237649c5de 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -992,12 +992,12 @@ void EditorPropertyLayersGrid::_notification(int p_what) { const int bsize = (grid_size.height * 80 / 100) / 2; const int h = bsize * 2 + 1; - Color color = get_theme_color(read_only ? SNAME("disabled_highlight_color") : SNAME("highlight_color"), EditorStringName(Editor)); + Color color = get_theme_color(read_only ? SNAME("highlight_disabled_color") : SNAME("highlight_color"), EditorStringName(Editor)); - Color text_color = get_theme_color(read_only ? SNAME("disabled_font_color") : SNAME("font_color"), EditorStringName(Editor)); + Color text_color = get_theme_color(read_only ? SNAME("font_disabled_color") : SNAME("font_color"), EditorStringName(Editor)); text_color.a *= 0.5; - Color text_color_on = get_theme_color(read_only ? SNAME("disabled_font_color") : SNAME("font_hover_color"), EditorStringName(Editor)); + Color text_color_on = get_theme_color(read_only ? SNAME("font_disabled_color") : SNAME("font_hover_color"), EditorStringName(Editor)); text_color_on.a *= 0.7; const int vofs = (grid_size.height - h) / 2; @@ -2073,7 +2073,7 @@ void EditorPropertyQuaternion::_notification(int p_what) { euler[i]->add_theme_color_override("label_color", colors[i]); } edit_button->set_icon(get_editor_theme_icon(SNAME("Edit"))); - euler_label->add_theme_color_override(SNAME("font_color"), get_theme_color(SNAME("property_color"), EditorStringName(Editor))); + euler_label->add_theme_color_override(SNAME("font_color"), get_theme_color(SNAME("property_color"), SNAME("EditorProperty"))); warning->set_icon(get_editor_theme_icon(SNAME("NodeWarning"))); warning->add_theme_color_override(SNAME("font_color"), get_theme_color(SNAME("warning_color"), EditorStringName(Editor))); } break; diff --git a/editor/export/export_template_manager.cpp b/editor/export/export_template_manager.cpp index f470d4f3fd4..69ad076f8a0 100644 --- a/editor/export/export_template_manager.cpp +++ b/editor/export/export_template_manager.cpp @@ -758,7 +758,7 @@ void ExportTemplateManager::_notification(int p_what) { case NOTIFICATION_THEME_CHANGED: { current_value->add_theme_font_override("font", get_theme_font(SNAME("main"), EditorStringName(EditorFonts))); current_missing_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), EditorStringName(Editor))); - current_installed_label->add_theme_color_override("font_color", get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + current_installed_label->add_theme_color_override("font_color", get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); mirror_options_button->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); } break; diff --git a/editor/export/project_export.cpp b/editor/export/project_export.cpp index a47fdbf222c..63bd87e6cc0 100644 --- a/editor/export/project_export.cpp +++ b/editor/export/project_export.cpp @@ -824,7 +824,7 @@ void ProjectExportDialog::_setup_item_for_file_mode(TreeItem *p_item, EditorExpo p_item->set_cell_mode(1, TreeItem::CELL_MODE_STRING); p_item->set_editable(1, false); p_item->set_selectable(1, false); - p_item->set_custom_color(1, get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + p_item->set_custom_color(1, get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); } else { p_item->set_checked(0, true); p_item->set_cell_mode(1, TreeItem::CELL_MODE_CUSTOM); diff --git a/editor/gui/scene_tree_editor.cpp b/editor/gui/scene_tree_editor.cpp index 7e6f06bf776..7a9df26fa7f 100644 --- a/editor/gui/scene_tree_editor.cpp +++ b/editor/gui/scene_tree_editor.cpp @@ -235,7 +235,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { item->add_button(0, get_editor_theme_icon(SNAME("Script")), BUTTON_SCRIPT); } else { //has no script (or script is a custom type) - _set_item_custom_color(item, get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + _set_item_custom_color(item, get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); item->set_selectable(0, false); if (!scr.is_null()) { // make sure to mark the script if a custom type @@ -267,7 +267,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { item->set_selectable(0, marked_selectable); _set_item_custom_color(item, get_theme_color(SNAME("accent_color"), EditorStringName(Editor))); } else if (!p_node->can_process()) { - _set_item_custom_color(item, get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + _set_item_custom_color(item, get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); } else if (!marked_selectable && !marked_children_selectable) { Node *node = p_node; while (node) { @@ -492,7 +492,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) { } if (!valid) { - _set_item_custom_color(item, get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + _set_item_custom_color(item, get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); item->set_selectable(0, false); } } @@ -718,7 +718,7 @@ bool SceneTreeEditor::_update_filter(TreeItem *p_parent, bool p_scroll_to_select } p_parent->set_selectable(0, true); } else if (keep_for_children) { - p_parent->set_custom_color(0, get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + p_parent->set_custom_color(0, get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); p_parent->set_selectable(0, false); p_parent->deselect(0); } diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 950a75c2214..20129556860 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -417,7 +417,6 @@ void EditorAssetLibraryItemDownload::configure(const String &p_title, int p_asse void EditorAssetLibraryItemDownload::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("AssetLib"))); status->add_theme_color_override("font_color", get_theme_color(SNAME("status_color"), SNAME("AssetLib"))); diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index 145ecf65bc6..8c3fe82f36f 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -852,10 +852,9 @@ bool ThemeItemImportTree::has_selected_items() const { void ThemeItemImportTree::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { select_icons_warning_icon->set_texture(get_editor_theme_icon(SNAME("StatusWarning"))); - select_icons_warning->add_theme_color_override("font_color", get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + select_icons_warning->add_theme_color_override("font_color", get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); import_items_filter->set_right_icon(get_editor_theme_icon(SNAME("Search"))); @@ -2470,7 +2469,7 @@ HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_ item_rename_cancel_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_canceled).bind(p_data_type, p_item_name, item_name_container)); item_rename_cancel_button->hide(); } else { - item_name->add_theme_color_override("font_color", get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))); + item_name->add_theme_color_override("font_color", get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))); Button *item_override_button = memnew(Button); item_override_button->set_icon(get_editor_theme_icon(SNAME("Add"))); diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index 8e65ad3b8e1..e3710adc836 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp @@ -735,7 +735,7 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() { tile_data_editors["probability"] = tile_data_probability_editor; } - Color disabled_color = get_theme_color("disabled_font_color", EditorStringName(Editor)); + Color disabled_color = get_theme_color("font_disabled_color", EditorStringName(Editor)); // --- Physics --- ADD_TILE_DATA_EDITOR_GROUP(TTR("Physics")); diff --git a/editor/themes/editor_theme_manager.cpp b/editor/themes/editor_theme_manager.cpp index 5a67531f861..f243da3c183 100644 --- a/editor/themes/editor_theme_manager.cpp +++ b/editor/themes/editor_theme_manager.cpp @@ -84,213 +84,20 @@ Ref make_line_stylebox(Color p_color, int p_thickness = 1, float p return style; } -static void populate_editor_theme(const Ref &theme, const Ref &p_old_theme) { - // Controls may rely on the scale for their internal drawing logic. - theme->set_default_base_scale(EDSCALE); +// Theme generation and population routines. - // Theme settings - Color accent_color = EDITOR_GET("interface/theme/accent_color"); - Color base_color = EDITOR_GET("interface/theme/base_color"); - float contrast = EDITOR_GET("interface/theme/contrast"); - bool increase_scrollbar_touch_area = EDITOR_GET("interface/touchscreen/increase_scrollbar_touch_area"); - const float gizmo_handle_scale = EDITOR_GET("interface/touchscreen/scale_gizmo_handles"); - bool draw_extra_borders = EDITOR_GET("interface/theme/draw_extra_borders"); - float icon_saturation = EDITOR_GET("interface/theme/icon_saturation"); - float relationship_line_opacity = EDITOR_GET("interface/theme/relationship_line_opacity"); +Ref EditorThemeManager::_create_base_theme(const Ref &p_old_theme) { + OS::get_singleton()->benchmark_begin_measure("EditorTheme", "Create Base Theme"); - String preset = EDITOR_GET("interface/theme/preset"); + Ref theme = memnew(EditorTheme); + ThemeConfiguration config = _create_theme_config(theme); + _create_shared_styles(theme, config); - int border_size = EDITOR_GET("interface/theme/border_size"); - int corner_radius = EDITOR_GET("interface/theme/corner_radius"); - - Color preset_accent_color; - Color preset_base_color; - float preset_contrast = 0; - bool preset_draw_extra_borders = false; - - const float default_contrast = 0.3; - - // Please use alphabetical order if you're adding a new theme here - // (after "Custom") - - if (preset == "Custom") { - accent_color = EDITOR_GET("interface/theme/accent_color"); - base_color = EDITOR_GET("interface/theme/base_color"); - contrast = EDITOR_GET("interface/theme/contrast"); - } else if (preset == "Breeze Dark") { - preset_accent_color = Color(0.26, 0.76, 1.00); - preset_base_color = Color(0.24, 0.26, 0.28); - preset_contrast = default_contrast; - } else if (preset == "Godot 2") { - preset_accent_color = Color(0.53, 0.67, 0.89); - preset_base_color = Color(0.24, 0.23, 0.27); - preset_contrast = default_contrast; - } else if (preset == "Gray") { - preset_accent_color = Color(0.44, 0.73, 0.98); - preset_base_color = Color(0.24, 0.24, 0.24); - preset_contrast = default_contrast; - } else if (preset == "Light") { - preset_accent_color = Color(0.18, 0.50, 1.00); - preset_base_color = Color(0.9, 0.9, 0.9); - // A negative contrast rate looks better for light themes, since it better follows the natural order of UI "elevation". - preset_contrast = -0.06; - } else if (preset == "Solarized (Dark)") { - preset_accent_color = Color(0.15, 0.55, 0.82); - preset_base_color = Color(0.04, 0.23, 0.27); - preset_contrast = default_contrast; - } else if (preset == "Solarized (Light)") { - preset_accent_color = Color(0.15, 0.55, 0.82); - preset_base_color = Color(0.89, 0.86, 0.79); - // A negative contrast rate looks better for light themes, since it better follows the natural order of UI "elevation". - preset_contrast = -0.06; - } else if (preset == "Black (OLED)") { - preset_accent_color = Color(0.45, 0.75, 1.0); - preset_base_color = Color(0, 0, 0); - // The contrast rate value is irrelevant on a fully black theme. - preset_contrast = 0.0; - preset_draw_extra_borders = true; - } else { // Default - preset_accent_color = Color(0.44, 0.73, 0.98); - preset_base_color = Color(0.21, 0.24, 0.29); - preset_contrast = default_contrast; - } - - if (preset != "Custom") { - accent_color = preset_accent_color; - base_color = preset_base_color; - contrast = preset_contrast; - draw_extra_borders = preset_draw_extra_borders; - EditorSettings::get_singleton()->set_initial_value("interface/theme/accent_color", accent_color); - EditorSettings::get_singleton()->set_initial_value("interface/theme/base_color", base_color); - EditorSettings::get_singleton()->set_initial_value("interface/theme/contrast", contrast); - EditorSettings::get_singleton()->set_initial_value("interface/theme/draw_extra_borders", draw_extra_borders); - } - - EditorSettings::get_singleton()->set_manually("interface/theme/preset", preset); - EditorSettings::get_singleton()->set_manually("interface/theme/accent_color", accent_color); - EditorSettings::get_singleton()->set_manually("interface/theme/base_color", base_color); - EditorSettings::get_singleton()->set_manually("interface/theme/contrast", contrast); - EditorSettings::get_singleton()->set_manually("interface/theme/draw_extra_borders", draw_extra_borders); - - // Colors - bool dark_theme = EditorSettings::get_singleton()->is_dark_theme(); - - // Ensure base colors are in the 0..1 luminance range to avoid 8-bit integer overflow or text rendering issues. - // Some places in the editor use 8-bit integer colors. - const Color dark_color_1 = base_color.lerp(Color(0, 0, 0, 1), contrast).clamp(); - const Color dark_color_2 = base_color.lerp(Color(0, 0, 0, 1), contrast * 1.5).clamp(); - const Color dark_color_3 = base_color.lerp(Color(0, 0, 0, 1), contrast * 2).clamp(); - - // Only used when the Draw Extra Borders editor setting is enabled. - const Color extra_border_color_1 = Color(0.5, 0.5, 0.5); - const Color extra_border_color_2 = dark_theme ? Color(0.3, 0.3, 0.3) : Color(0.7, 0.7, 0.7); - - const Color background_color = dark_color_2; - - // White (dark theme) or black (light theme), will be used to generate the rest of the colors - const Color mono_color = dark_theme ? Color(1, 1, 1) : Color(0, 0, 0); - - const Color contrast_color_1 = base_color.lerp(mono_color, MAX(contrast, default_contrast)); - const Color contrast_color_2 = base_color.lerp(mono_color, MAX(contrast * 1.5, default_contrast * 1.5)); - - const Color font_color = mono_color.lerp(base_color, 0.25); - const Color font_hover_color = mono_color.lerp(base_color, 0.125); - const Color font_focus_color = mono_color.lerp(base_color, 0.125); - const Color font_hover_pressed_color = font_hover_color.lerp(accent_color, 0.74); - const Color font_disabled_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.35); - const Color font_readonly_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.65); - const Color font_placeholder_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.6); - const Color font_outline_color = Color(0, 0, 0, 0); - const Color selection_color = accent_color * Color(1, 1, 1, 0.4); - const Color disabled_color = mono_color.inverted().lerp(base_color, 0.7); - const Color disabled_bg_color = mono_color.inverted().lerp(base_color, 0.9); - - const Color icon_normal_color = Color(1, 1, 1); - Color icon_hover_color = icon_normal_color * (dark_theme ? 1.15 : 1.45); - icon_hover_color.a = 1.0; - Color icon_focus_color = icon_hover_color; - Color icon_disabled_color = Color(icon_normal_color, 0.4); - // Make the pressed icon 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. - Color icon_pressed_color = accent_color * (dark_theme ? 1.15 : 3.5); - icon_pressed_color.a = 1.0; - - const Color separator_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.1); - const Color highlight_color = Color(accent_color.r, accent_color.g, accent_color.b, 0.275); - const Color disabled_highlight_color = highlight_color.lerp(dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.5); - - // Can't save single float in theme, so using Color. - theme->set_color("icon_saturation", EditorStringName(Editor), Color(icon_saturation, icon_saturation, icon_saturation)); - theme->set_color("accent_color", EditorStringName(Editor), accent_color); - theme->set_color("highlight_color", EditorStringName(Editor), highlight_color); - theme->set_color("disabled_highlight_color", EditorStringName(Editor), disabled_highlight_color); - theme->set_color("base_color", EditorStringName(Editor), base_color); - theme->set_color("dark_color_1", EditorStringName(Editor), dark_color_1); - theme->set_color("dark_color_2", EditorStringName(Editor), dark_color_2); - theme->set_color("dark_color_3", EditorStringName(Editor), dark_color_3); - theme->set_color("contrast_color_1", EditorStringName(Editor), contrast_color_1); - theme->set_color("contrast_color_2", EditorStringName(Editor), contrast_color_2); - theme->set_color("box_selection_fill_color", EditorStringName(Editor), accent_color * Color(1, 1, 1, 0.3)); - theme->set_color("box_selection_stroke_color", EditorStringName(Editor), accent_color * Color(1, 1, 1, 0.8)); - - theme->set_color("axis_x_color", EditorStringName(Editor), Color(0.96, 0.20, 0.32)); - theme->set_color("axis_y_color", EditorStringName(Editor), Color(0.53, 0.84, 0.01)); - theme->set_color("axis_z_color", EditorStringName(Editor), Color(0.16, 0.55, 0.96)); - theme->set_color("axis_w_color", EditorStringName(Editor), Color(0.55, 0.55, 0.55)); - - const float prop_color_saturation = accent_color.get_s() * 0.75; - const float prop_color_value = accent_color.get_v(); - - theme->set_color("property_color_x", EditorStringName(Editor), Color().from_hsv(0.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value)); - theme->set_color("property_color_y", EditorStringName(Editor), Color().from_hsv(1.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value)); - theme->set_color("property_color_z", EditorStringName(Editor), Color().from_hsv(2.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value)); - theme->set_color("property_color_w", EditorStringName(Editor), Color().from_hsv(1.5 / 3.0 + 0.05, prop_color_saturation, prop_color_value)); - - theme->set_color("font_color", EditorStringName(Editor), font_color); - theme->set_color("highlighted_font_color", EditorStringName(Editor), font_hover_color); - theme->set_color("disabled_font_color", EditorStringName(Editor), font_disabled_color); - theme->set_color("readonly_font_color", EditorStringName(Editor), font_readonly_color); - - theme->set_color("mono_color", EditorStringName(Editor), mono_color); - - Color success_color = Color(0.45, 0.95, 0.5); - Color warning_color = Color(1, 0.87, 0.4); - Color error_color = Color(1, 0.47, 0.42); - Color property_color = font_color.lerp(Color(0.5, 0.5, 0.5), 0.5); - Color readonly_color = property_color.lerp(dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.25); - Color readonly_warning_color = error_color.lerp(dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.25); - - if (!dark_theme) { - // Darken some colors to be readable on a light background. - success_color = success_color.lerp(mono_color, 0.35); - warning_color = warning_color.lerp(mono_color, 0.35); - error_color = error_color.lerp(mono_color, 0.25); - } - - theme->set_color("success_color", EditorStringName(Editor), success_color); - theme->set_color("warning_color", EditorStringName(Editor), warning_color); - theme->set_color("error_color", EditorStringName(Editor), error_color); - theme->set_color("property_color", EditorStringName(Editor), property_color); - theme->set_color("readonly_color", EditorStringName(Editor), readonly_color); - - if (!dark_theme) { - theme->set_color("highend_color", EditorStringName(Editor), Color::hex(0xad1128ff)); - } else { - theme->set_color("highend_color", EditorStringName(Editor), Color(1.0, 0.0, 0.0)); - } - - const int thumb_size = EDITOR_GET("filesystem/file_dialog/thumbnail_size"); - theme->set_constant("scale", EditorStringName(Editor), EDSCALE); - theme->set_constant("thumb_size", EditorStringName(Editor), thumb_size); - theme->set_constant("class_icon_size", EditorStringName(Editor), 16 * EDSCALE); - theme->set_constant("dark_theme", EditorStringName(Editor), dark_theme); - theme->set_constant("color_picker_button_height", EditorStringName(Editor), 28 * EDSCALE); - theme->set_constant("gizmo_handle_scale", EditorStringName(Editor), gizmo_handle_scale); - theme->set_constant("window_border_margin", EditorStringName(Editor), 8); - theme->set_constant("top_bar_separation", EditorStringName(Editor), 8 * EDSCALE); + // 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 the settings are comparable to the old theme, then just copy them over. + // 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; @@ -306,1610 +113,2040 @@ static void populate_editor_theme(const Ref &theme, const Ref &p_o 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, gizmo_handle_scale) && - prev_dark_theme == dark_theme && - prev_accent_color == accent_color && - prev_icon_saturation == icon_saturation); + 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, thumb_size); + regenerate_thumb_icons = !Math::is_equal_approx(prev_thumb_size, config.thumb_size); } - editor_configure_icons(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, dark_theme, icon_saturation, thumb_size, false); + editor_register_icons(theme, config.dark_theme, config.icon_saturation, config.thumb_size, false); } if (regenerate_thumb_icons) { - editor_register_icons(theme, dark_theme, icon_saturation, thumb_size, true); + editor_register_icons(theme, config.dark_theme, config.icon_saturation, config.thumb_size, true); } - // Register editor fonts. + // External function, see editor_fonts.cpp. editor_register_fonts(theme); - // Ensure borders are visible when using an editor scale below 100%. - const int border_width = CLAMP(border_size, 0, 2) * MAX(1, EDSCALE); - const int corner_width = CLAMP(corner_radius, 0, 6); - const int default_margin_size = 4; - const int margin_size_extra = default_margin_size + CLAMP(border_size, 0, 2); - - // Styleboxes - // This is the most commonly used stylebox, variations should be made as duplicate of this - Ref style_default = make_flat_stylebox(base_color, default_margin_size, default_margin_size, default_margin_size, default_margin_size, corner_width); - style_default->set_border_width_all(border_width); - style_default->set_border_color(base_color); - - // Button and widgets - const float extra_spacing = EDITOR_GET("interface/theme/additional_spacing"); - - const Vector2 widget_default_margin = Vector2(extra_spacing + 6, extra_spacing + default_margin_size + 1) * EDSCALE; - - Ref style_widget = style_default->duplicate(); - style_widget->set_content_margin_individual(widget_default_margin.x, widget_default_margin.y, widget_default_margin.x, widget_default_margin.y); - style_widget->set_bg_color(dark_color_1); - if (draw_extra_borders) { - style_widget->set_border_width_all(Math::round(EDSCALE)); - style_widget->set_border_color(extra_border_color_1); - } else { - style_widget->set_border_color(dark_color_2); - } - - Ref style_widget_disabled = style_widget->duplicate(); - if (draw_extra_borders) { - style_widget_disabled->set_border_color(extra_border_color_2); - } else { - style_widget_disabled->set_border_color(disabled_color); - } - style_widget_disabled->set_bg_color(disabled_bg_color); - - Ref style_widget_focus = style_widget->duplicate(); - style_widget_focus->set_draw_center(false); - style_widget_focus->set_border_width_all(Math::round(2 * MAX(1, EDSCALE))); - style_widget_focus->set_border_color(accent_color); - - Ref style_widget_pressed = style_widget->duplicate(); - style_widget_pressed->set_bg_color(dark_color_1.darkened(0.125)); - - Ref style_widget_hover = style_widget->duplicate(); - style_widget_hover->set_bg_color(mono_color * Color(1, 1, 1, 0.11)); - if (draw_extra_borders) { - style_widget_hover->set_border_color(extra_border_color_1); - } else { - style_widget_hover->set_border_color(mono_color * Color(1, 1, 1, 0.05)); - } - - // Style for windows, popups, etc.. - Ref style_popup = style_default->duplicate(); - const int popup_margin_size = default_margin_size * EDSCALE * 3; - style_popup->set_content_margin_all(popup_margin_size); - style_popup->set_border_color(contrast_color_1); - const Color shadow_color = Color(0, 0, 0, dark_theme ? 0.3 : 0.1); - style_popup->set_shadow_color(shadow_color); - style_popup->set_shadow_size(4 * EDSCALE); - // Popups are separate windows by default in the editor. Windows currently don't support per-pixel transparency - // in 4.0, and even if it was, it may not always work in practice (e.g. running with compositing disabled). - style_popup->set_corner_radius_all(0); - - Ref style_popup_separator(memnew(StyleBoxLine)); - style_popup_separator->set_color(separator_color); - style_popup_separator->set_grow_begin(popup_margin_size - MAX(Math::round(EDSCALE), border_width)); - style_popup_separator->set_grow_end(popup_margin_size - MAX(Math::round(EDSCALE), border_width)); - style_popup_separator->set_thickness(MAX(Math::round(EDSCALE), border_width)); - - Ref style_popup_labeled_separator_left(memnew(StyleBoxLine)); - style_popup_labeled_separator_left->set_grow_begin(popup_margin_size - MAX(Math::round(EDSCALE), border_width)); - style_popup_labeled_separator_left->set_color(separator_color); - style_popup_labeled_separator_left->set_thickness(MAX(Math::round(EDSCALE), border_width)); - - Ref style_popup_labeled_separator_right(memnew(StyleBoxLine)); - style_popup_labeled_separator_right->set_grow_end(popup_margin_size - MAX(Math::round(EDSCALE), border_width)); - style_popup_labeled_separator_right->set_color(separator_color); - style_popup_labeled_separator_right->set_thickness(MAX(Math::round(EDSCALE), border_width)); - - Ref style_empty = make_empty_stylebox(default_margin_size, default_margin_size, default_margin_size, default_margin_size); - - // TabBar - - Ref style_tab_base = style_widget->duplicate(); - - style_tab_base->set_border_width_all(0); - // Don't round the top corners to avoid creating a small blank space between the tabs and the main panel. - // This also makes the top highlight look better. - style_tab_base->set_corner_radius(CORNER_BOTTOM_LEFT, 0); - style_tab_base->set_corner_radius(CORNER_BOTTOM_RIGHT, 0); - - // When using a border width greater than 0, visually line up the left of the selected tab with the underlying panel. - style_tab_base->set_expand_margin(SIDE_LEFT, -border_width); - - style_tab_base->set_content_margin(SIDE_LEFT, widget_default_margin.x + 5 * EDSCALE); - style_tab_base->set_content_margin(SIDE_RIGHT, widget_default_margin.x + 5 * EDSCALE); - style_tab_base->set_content_margin(SIDE_BOTTOM, widget_default_margin.y); - style_tab_base->set_content_margin(SIDE_TOP, widget_default_margin.y); - - Ref style_tab_selected = style_tab_base->duplicate(); - - style_tab_selected->set_bg_color(base_color); - // Add a highlight line at the top of the selected tab. - style_tab_selected->set_border_width(SIDE_TOP, Math::round(2 * EDSCALE)); - // Make the highlight line prominent, but not too prominent as to not be distracting. - Color tab_highlight = dark_color_2.lerp(accent_color, 0.75); - style_tab_selected->set_border_color(tab_highlight); - style_tab_selected->set_corner_radius_all(0); - - Ref style_tab_hovered = style_tab_base->duplicate(); - - style_tab_hovered->set_bg_color(dark_color_1.lerp(base_color, 0.4)); - // Hovered tab has a subtle highlight between normal and selected states. - style_tab_hovered->set_corner_radius_all(0); - - Ref style_tab_unselected = style_tab_base->duplicate(); - style_tab_unselected->set_expand_margin(SIDE_BOTTOM, 0); - style_tab_unselected->set_bg_color(dark_color_1); - // Add some spacing between unselected tabs to make them easier to distinguish from each other - style_tab_unselected->set_border_color(Color(0, 0, 0, 0)); - - Ref style_tab_disabled = style_tab_base->duplicate(); - style_tab_disabled->set_expand_margin(SIDE_BOTTOM, 0); - style_tab_disabled->set_bg_color(disabled_bg_color); - style_tab_disabled->set_border_color(disabled_bg_color); - - Ref style_tab_focus = style_widget_focus->duplicate(); - - // Editor background - Color background_color_opaque = background_color; - background_color_opaque.a = 1.0; - theme->set_color("background", EditorStringName(Editor), background_color_opaque); - theme->set_stylebox("Background", EditorStringName(EditorStyles), make_flat_stylebox(background_color_opaque, default_margin_size, default_margin_size, default_margin_size, default_margin_size)); - - // Focus - theme->set_stylebox("Focus", EditorStringName(EditorStyles), style_widget_focus); - // Use a less opaque color to be less distracting for the 2D and 3D editor viewports. - Ref style_widget_focus_viewport = style_widget_focus->duplicate(); - style_widget_focus_viewport->set_border_color(accent_color * Color(1, 1, 1, 0.5)); - theme->set_stylebox("FocusViewport", EditorStringName(EditorStyles), style_widget_focus_viewport); - - // Menu - Ref style_menu = style_widget->duplicate(); - style_menu->set_draw_center(false); - style_menu->set_border_width_all(0); - theme->set_stylebox("panel", "PanelContainer", style_menu); - theme->set_stylebox("MenuPanel", EditorStringName(EditorStyles), style_menu); - - // CanvasItem Editor - Ref style_canvas_editor_info = make_flat_stylebox(Color(0.0, 0.0, 0.0, 0.2)); - style_canvas_editor_info->set_expand_margin_all(4 * EDSCALE); - theme->set_stylebox("CanvasItemInfoOverlay", EditorStringName(EditorStyles), style_canvas_editor_info); - - // 2D and 3D contextual toolbar. - // Use a custom stylebox to make contextual menu items stand out from the rest. - // This helps with editor usability as contextual menu items change when selecting nodes, - // even though it may not be immediately obvious at first. - Ref toolbar_stylebox = memnew(StyleBoxFlat); - toolbar_stylebox->set_bg_color(accent_color * Color(1, 1, 1, 0.1)); - toolbar_stylebox->set_anti_aliased(false); - // Add an underline to the StyleBox, but prevent its minimum vertical size from changing. - toolbar_stylebox->set_border_color(accent_color); - toolbar_stylebox->set_border_width(SIDE_BOTTOM, Math::round(2 * EDSCALE)); - toolbar_stylebox->set_content_margin(SIDE_BOTTOM, 0); - toolbar_stylebox->set_expand_margin_individual(4 * EDSCALE, 2 * EDSCALE, 4 * EDSCALE, 4 * EDSCALE); - theme->set_stylebox("ContextualToolbar", EditorStringName(EditorStyles), toolbar_stylebox); - - // Script Editor - theme->set_stylebox("ScriptEditorPanel", EditorStringName(EditorStyles), make_empty_stylebox(default_margin_size, 0, default_margin_size, default_margin_size)); - theme->set_stylebox("ScriptEditorPanelFloating", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0)); - - theme->set_stylebox("ScriptEditor", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0)); - - // Launch Pad and Play buttons - Ref style_launch_pad = make_flat_stylebox(dark_color_1, 2 * EDSCALE, 0, 2 * EDSCALE, 0, corner_width); - style_launch_pad->set_corner_radius_all(corner_radius * EDSCALE); - theme->set_stylebox("LaunchPadNormal", EditorStringName(EditorStyles), style_launch_pad); - Ref style_launch_pad_movie = style_launch_pad->duplicate(); - style_launch_pad_movie->set_bg_color(accent_color * Color(1, 1, 1, 0.1)); - style_launch_pad_movie->set_border_color(accent_color); - style_launch_pad_movie->set_border_width_all(Math::round(2 * EDSCALE)); - theme->set_stylebox("LaunchPadMovieMode", EditorStringName(EditorStyles), style_launch_pad_movie); - - theme->set_stylebox("MovieWriterButtonNormal", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0)); - Ref style_write_movie_button = style_widget_pressed->duplicate(); - style_write_movie_button->set_bg_color(accent_color); - style_write_movie_button->set_corner_radius_all(corner_radius * EDSCALE); - style_write_movie_button->set_content_margin(SIDE_TOP, 0); - style_write_movie_button->set_content_margin(SIDE_BOTTOM, 0); - style_write_movie_button->set_content_margin(SIDE_LEFT, 0); - style_write_movie_button->set_content_margin(SIDE_RIGHT, 0); - style_write_movie_button->set_expand_margin(SIDE_RIGHT, 2 * EDSCALE); - theme->set_stylebox("MovieWriterButtonPressed", EditorStringName(EditorStyles), style_write_movie_button); - - // MenuButton - theme->set_stylebox("normal", "MenuButton", style_menu); - theme->set_stylebox("hover", "MenuButton", style_widget_hover); - theme->set_stylebox("pressed", "MenuButton", style_menu); - theme->set_stylebox("focus", "MenuButton", style_menu); - theme->set_stylebox("disabled", "MenuButton", style_menu); - - theme->set_color("font_color", "MenuButton", font_color); - theme->set_color("font_hover_color", "MenuButton", font_hover_color); - theme->set_color("font_hover_pressed_color", "MenuButton", font_hover_pressed_color); - theme->set_color("font_focus_color", "MenuButton", font_focus_color); - theme->set_color("font_outline_color", "MenuButton", font_outline_color); - - theme->set_constant("outline_size", "MenuButton", 0); - - theme->set_stylebox("MenuHover", EditorStringName(EditorStyles), style_widget_hover); - - // Buttons - theme->set_stylebox("normal", "Button", style_widget); - theme->set_stylebox("hover", "Button", style_widget_hover); - theme->set_stylebox("pressed", "Button", style_widget_pressed); - theme->set_stylebox("focus", "Button", style_widget_focus); - theme->set_stylebox("disabled", "Button", style_widget_disabled); - - theme->set_color("font_color", "Button", font_color); - theme->set_color("font_hover_color", "Button", font_hover_color); - theme->set_color("font_hover_pressed_color", "Button", font_hover_pressed_color); - theme->set_color("font_focus_color", "Button", font_focus_color); - theme->set_color("font_pressed_color", "Button", accent_color); - theme->set_color("font_disabled_color", "Button", font_disabled_color); - theme->set_color("font_outline_color", "Button", font_outline_color); - - theme->set_color("icon_normal_color", "Button", icon_normal_color); - theme->set_color("icon_hover_color", "Button", icon_hover_color); - theme->set_color("icon_focus_color", "Button", icon_focus_color); - theme->set_color("icon_pressed_color", "Button", icon_pressed_color); - theme->set_color("icon_disabled_color", "Button", icon_disabled_color); - - theme->set_constant("h_separation", "Button", 4 * EDSCALE); - theme->set_constant("outline_size", "Button", 0); - - // Flat button variations. - - Ref style_flat_button = make_empty_stylebox(); - for (int i = 0; i < 4; i++) { - style_flat_button->set_content_margin((Side)i, style_widget->get_margin((Side)i) + style_widget->get_border_width((Side)i)); - } - - Ref style_flat_button_pressed = style_widget_pressed->duplicate(); - Color flat_pressed_color = dark_color_1.lightened(0.24).lerp(accent_color, 0.2) * Color(0.8, 0.8, 0.8, 0.85); - if (dark_theme) { - flat_pressed_color = dark_color_1.lerp(accent_color, 0.12) * Color(0.6, 0.6, 0.6, 0.85); - } - style_flat_button_pressed->set_bg_color(flat_pressed_color); - - theme->set_stylebox("normal", "FlatButton", style_flat_button); - theme->set_stylebox("hover", "FlatButton", style_flat_button); - theme->set_stylebox("pressed", "FlatButton", style_flat_button_pressed); - theme->set_stylebox("disabled", "FlatButton", style_flat_button); - - theme->set_stylebox("normal", "FlatMenuButton", style_flat_button); - theme->set_stylebox("hover", "FlatMenuButton", style_flat_button); - theme->set_stylebox("pressed", "FlatMenuButton", style_flat_button_pressed); - theme->set_stylebox("disabled", "FlatMenuButton", style_flat_button); - - const float ACTION_BUTTON_EXTRA_MARGIN = 32 * EDSCALE; - - theme->set_type_variation("InspectorActionButton", "Button"); - Color color_inspector_action = dark_color_1.lerp(mono_color, 0.12); - color_inspector_action.a = 0.5; - Ref style_inspector_action = style_widget->duplicate(); - style_inspector_action->set_bg_color(color_inspector_action); - style_inspector_action->set_content_margin(SIDE_RIGHT, ACTION_BUTTON_EXTRA_MARGIN); - theme->set_stylebox("normal", "InspectorActionButton", style_inspector_action); - style_inspector_action = style_widget_hover->duplicate(); - style_inspector_action->set_content_margin(SIDE_RIGHT, ACTION_BUTTON_EXTRA_MARGIN); - theme->set_stylebox("hover", "InspectorActionButton", style_inspector_action); - style_inspector_action = style_widget_pressed->duplicate(); - style_inspector_action->set_content_margin(SIDE_RIGHT, ACTION_BUTTON_EXTRA_MARGIN); - theme->set_stylebox("pressed", "InspectorActionButton", style_inspector_action); - style_inspector_action = style_widget_disabled->duplicate(); - style_inspector_action->set_content_margin(SIDE_RIGHT, ACTION_BUTTON_EXTRA_MARGIN); - theme->set_stylebox("disabled", "InspectorActionButton", style_inspector_action); - theme->set_constant("h_separation", "InspectorActionButton", ACTION_BUTTON_EXTRA_MARGIN); - - // Variation for Editor Log filter buttons - theme->set_type_variation("EditorLogFilterButton", "Button"); - // When pressed, don't tint the icons with the accent color, just leave them normal. - theme->set_color("icon_pressed_color", "EditorLogFilterButton", icon_normal_color); - // When unpressed, dim the icons. - theme->set_color("icon_normal_color", "EditorLogFilterButton", icon_disabled_color); - // When pressed, add a small bottom border to the buttons to better show their active state, - // similar to active tabs. - - Ref editor_log_button_pressed = style_flat_button_pressed->duplicate(); - editor_log_button_pressed->set_border_width(SIDE_BOTTOM, 2 * EDSCALE); - editor_log_button_pressed->set_border_color(accent_color); - theme->set_stylebox("pressed", "EditorLogFilterButton", editor_log_button_pressed); - - // Buttons in material previews - const Color dim_light_color = icon_normal_color.darkened(0.24); - const Color dim_light_highlighted_color = icon_normal_color.darkened(0.18); - Ref sb_empty_borderless = make_empty_stylebox(); - - theme->set_type_variation("PreviewLightButton", "Button"); - // When pressed, don't use the accent color tint. When unpressed, dim the icon. - theme->set_color("icon_normal_color", "PreviewLightButton", dim_light_color); - theme->set_color("icon_focus_color", "PreviewLightButton", dim_light_color); - theme->set_color("icon_pressed_color", "PreviewLightButton", icon_normal_color); - theme->set_color("icon_hover_pressed_color", "PreviewLightButton", icon_normal_color); - // Unpressed icon is dim, so use a dim highlight. - theme->set_color("icon_hover_color", "PreviewLightButton", dim_light_highlighted_color); - - theme->set_stylebox("normal", "PreviewLightButton", sb_empty_borderless); - theme->set_stylebox("hover", "PreviewLightButton", sb_empty_borderless); - theme->set_stylebox("focus", "PreviewLightButton", sb_empty_borderless); - theme->set_stylebox("pressed", "PreviewLightButton", sb_empty_borderless); - - // ProjectTag - { - theme->set_type_variation("ProjectTag", "Button"); - - Ref tag = style_widget->duplicate(); - tag->set_bg_color(dark_theme ? tag->get_bg_color().lightened(0.2) : tag->get_bg_color().darkened(0.2)); - tag->set_corner_radius(CORNER_TOP_LEFT, 0); - tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0); - tag->set_corner_radius(CORNER_TOP_RIGHT, 4); - tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4); - theme->set_stylebox("normal", "ProjectTag", tag); - - tag = style_widget_hover->duplicate(); - tag->set_corner_radius(CORNER_TOP_LEFT, 0); - tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0); - tag->set_corner_radius(CORNER_TOP_RIGHT, 4); - tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4); - theme->set_stylebox("hover", "ProjectTag", tag); - - tag = style_widget_pressed->duplicate(); - tag->set_corner_radius(CORNER_TOP_LEFT, 0); - tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0); - tag->set_corner_radius(CORNER_TOP_RIGHT, 4); - tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4); - theme->set_stylebox("pressed", "ProjectTag", tag); - } - - // MenuBar - theme->set_stylebox("normal", "MenuBar", style_widget); - theme->set_stylebox("hover", "MenuBar", style_widget_hover); - theme->set_stylebox("pressed", "MenuBar", style_widget_pressed); - theme->set_stylebox("disabled", "MenuBar", style_widget_disabled); - - theme->set_color("font_color", "MenuBar", font_color); - theme->set_color("font_hover_color", "MenuBar", font_hover_color); - theme->set_color("font_hover_pressed_color", "MenuBar", font_hover_pressed_color); - theme->set_color("font_focus_color", "MenuBar", font_focus_color); - theme->set_color("font_pressed_color", "MenuBar", accent_color); - theme->set_color("font_disabled_color", "MenuBar", font_disabled_color); - theme->set_color("font_outline_color", "MenuBar", font_outline_color); - - theme->set_color("icon_normal_color", "MenuBar", icon_normal_color); - theme->set_color("icon_hover_color", "MenuBar", icon_hover_color); - theme->set_color("icon_focus_color", "MenuBar", icon_focus_color); - theme->set_color("icon_pressed_color", "MenuBar", icon_pressed_color); - theme->set_color("icon_disabled_color", "MenuBar", icon_disabled_color); - - theme->set_constant("h_separation", "MenuBar", 4 * EDSCALE); - theme->set_constant("outline_size", "MenuBar", 0); - - // OptionButton - Ref style_option_button_focus = style_widget_focus->duplicate(); - Ref style_option_button_normal = style_widget->duplicate(); - Ref style_option_button_hover = style_widget_hover->duplicate(); - Ref style_option_button_pressed = style_widget_pressed->duplicate(); - Ref style_option_button_disabled = style_widget_disabled->duplicate(); - - style_option_button_focus->set_content_margin(SIDE_RIGHT, 4 * EDSCALE); - style_option_button_normal->set_content_margin(SIDE_RIGHT, 4 * EDSCALE); - style_option_button_hover->set_content_margin(SIDE_RIGHT, 4 * EDSCALE); - style_option_button_pressed->set_content_margin(SIDE_RIGHT, 4 * EDSCALE); - style_option_button_disabled->set_content_margin(SIDE_RIGHT, 4 * EDSCALE); - - theme->set_stylebox("focus", "OptionButton", style_option_button_focus); - theme->set_stylebox("normal", "OptionButton", style_widget); - theme->set_stylebox("hover", "OptionButton", style_widget_hover); - theme->set_stylebox("pressed", "OptionButton", style_widget_pressed); - theme->set_stylebox("disabled", "OptionButton", style_widget_disabled); - - theme->set_stylebox("normal_mirrored", "OptionButton", style_option_button_normal); - theme->set_stylebox("hover_mirrored", "OptionButton", style_option_button_hover); - theme->set_stylebox("pressed_mirrored", "OptionButton", style_option_button_pressed); - theme->set_stylebox("disabled_mirrored", "OptionButton", style_option_button_disabled); - - theme->set_color("font_color", "OptionButton", font_color); - theme->set_color("font_hover_color", "OptionButton", font_hover_color); - theme->set_color("font_hover_pressed_color", "OptionButton", font_hover_pressed_color); - theme->set_color("font_focus_color", "OptionButton", font_focus_color); - theme->set_color("font_pressed_color", "OptionButton", accent_color); - theme->set_color("font_disabled_color", "OptionButton", font_disabled_color); - theme->set_color("font_outline_color", "OptionButton", font_outline_color); - - theme->set_color("icon_normal_color", "OptionButton", icon_normal_color); - theme->set_color("icon_hover_color", "OptionButton", icon_hover_color); - theme->set_color("icon_focus_color", "OptionButton", icon_focus_color); - theme->set_color("icon_pressed_color", "OptionButton", icon_pressed_color); - theme->set_color("icon_disabled_color", "OptionButton", icon_disabled_color); - - theme->set_icon("arrow", "OptionButton", theme->get_icon(SNAME("GuiOptionArrow"), EditorStringName(EditorIcons))); - theme->set_constant("arrow_margin", "OptionButton", widget_default_margin.x - 2 * EDSCALE); - theme->set_constant("modulate_arrow", "OptionButton", true); - theme->set_constant("h_separation", "OptionButton", 4 * EDSCALE); - theme->set_constant("outline_size", "OptionButton", 0); - - // CheckButton - theme->set_stylebox("normal", "CheckButton", style_menu); - theme->set_stylebox("pressed", "CheckButton", style_menu); - theme->set_stylebox("disabled", "CheckButton", style_menu); - theme->set_stylebox("hover", "CheckButton", style_menu); - theme->set_stylebox("hover_pressed", "CheckButton", style_menu); - - theme->set_icon("checked", "CheckButton", theme->get_icon(SNAME("GuiToggleOn"), EditorStringName(EditorIcons))); - theme->set_icon("checked_disabled", "CheckButton", theme->get_icon(SNAME("GuiToggleOnDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("unchecked", "CheckButton", theme->get_icon(SNAME("GuiToggleOff"), EditorStringName(EditorIcons))); - theme->set_icon("unchecked_disabled", "CheckButton", theme->get_icon(SNAME("GuiToggleOffDisabled"), EditorStringName(EditorIcons))); - - theme->set_icon("checked_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOnMirrored"), EditorStringName(EditorIcons))); - theme->set_icon("checked_disabled_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOnDisabledMirrored"), EditorStringName(EditorIcons))); - theme->set_icon("unchecked_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOffMirrored"), EditorStringName(EditorIcons))); - theme->set_icon("unchecked_disabled_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOffDisabledMirrored"), EditorStringName(EditorIcons))); - - theme->set_color("font_color", "CheckButton", font_color); - theme->set_color("font_hover_color", "CheckButton", font_hover_color); - theme->set_color("font_hover_pressed_color", "CheckButton", font_hover_pressed_color); - theme->set_color("font_focus_color", "CheckButton", font_focus_color); - theme->set_color("font_pressed_color", "CheckButton", accent_color); - theme->set_color("font_disabled_color", "CheckButton", font_disabled_color); - theme->set_color("font_outline_color", "CheckButton", font_outline_color); - - theme->set_color("icon_normal_color", "CheckButton", icon_normal_color); - theme->set_color("icon_hover_color", "CheckButton", icon_hover_color); - theme->set_color("icon_focus_color", "CheckButton", icon_focus_color); - theme->set_color("icon_pressed_color", "CheckButton", icon_pressed_color); - theme->set_color("icon_disabled_color", "CheckButton", icon_disabled_color); - - theme->set_constant("h_separation", "CheckButton", 8 * EDSCALE); - theme->set_constant("check_v_offset", "CheckButton", 0); - theme->set_constant("outline_size", "CheckButton", 0); - - // Checkbox - Ref sb_checkbox = style_menu->duplicate(); - sb_checkbox->set_content_margin_all(default_margin_size * EDSCALE); - - theme->set_stylebox("normal", "CheckBox", sb_checkbox); - theme->set_stylebox("pressed", "CheckBox", sb_checkbox); - theme->set_stylebox("disabled", "CheckBox", sb_checkbox); - theme->set_stylebox("hover", "CheckBox", sb_checkbox); - theme->set_stylebox("hover_pressed", "CheckBox", sb_checkbox); - theme->set_icon("checked", "CheckBox", theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons))); - theme->set_icon("unchecked", "CheckBox", theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons))); - theme->set_icon("radio_checked", "CheckBox", theme->get_icon(SNAME("GuiRadioChecked"), EditorStringName(EditorIcons))); - theme->set_icon("radio_unchecked", "CheckBox", theme->get_icon(SNAME("GuiRadioUnchecked"), EditorStringName(EditorIcons))); - theme->set_icon("checked_disabled", "CheckBox", theme->get_icon(SNAME("GuiCheckedDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("unchecked_disabled", "CheckBox", theme->get_icon(SNAME("GuiUncheckedDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("radio_checked_disabled", "CheckBox", theme->get_icon(SNAME("GuiRadioCheckedDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("radio_unchecked_disabled", "CheckBox", theme->get_icon(SNAME("GuiRadioUncheckedDisabled"), EditorStringName(EditorIcons))); - - theme->set_color("font_color", "CheckBox", font_color); - theme->set_color("font_hover_color", "CheckBox", font_hover_color); - theme->set_color("font_hover_pressed_color", "CheckBox", font_hover_pressed_color); - theme->set_color("font_focus_color", "CheckBox", font_focus_color); - theme->set_color("font_pressed_color", "CheckBox", accent_color); - theme->set_color("font_disabled_color", "CheckBox", font_disabled_color); - theme->set_color("font_outline_color", "CheckBox", font_outline_color); - - theme->set_color("icon_normal_color", "CheckBox", icon_normal_color); - theme->set_color("icon_hover_color", "CheckBox", icon_hover_color); - theme->set_color("icon_focus_color", "CheckBox", icon_focus_color); - theme->set_color("icon_pressed_color", "CheckBox", icon_pressed_color); - theme->set_color("icon_disabled_color", "CheckBox", icon_disabled_color); - - theme->set_constant("h_separation", "CheckBox", 8 * EDSCALE); - theme->set_constant("check_v_offset", "CheckBox", 0); - theme->set_constant("outline_size", "CheckBox", 0); - - // PopupDialog - theme->set_stylebox("panel", "PopupDialog", style_popup); - - // PopupMenu - Ref style_popup_menu = style_popup->duplicate(); - // Use 1 pixel for the sides, since if 0 is used, the highlight of hovered items is drawn - // on top of the popup border. This causes a 'gap' in the panel border when an item is highlighted, - // and it looks weird. 1px solves this. - style_popup_menu->set_content_margin_individual(EDSCALE, 2 * EDSCALE, EDSCALE, 2 * EDSCALE); - // Always display a border for PopupMenus so they can be distinguished from their background. - style_popup_menu->set_border_width_all(EDSCALE); - if (draw_extra_borders) { - style_popup_menu->set_border_color(extra_border_color_2); - } else { - style_popup_menu->set_border_color(dark_color_2); - } - theme->set_stylebox("panel", "PopupMenu", style_popup_menu); - - Ref style_menu_hover = style_widget_hover->duplicate(); - // Don't use rounded corners for hover highlights since the StyleBox touches the PopupMenu's edges. - style_menu_hover->set_corner_radius_all(0); - theme->set_stylebox("hover", "PopupMenu", style_menu_hover); - - theme->set_stylebox("separator", "PopupMenu", style_popup_separator); - theme->set_stylebox("labeled_separator_left", "PopupMenu", style_popup_labeled_separator_left); - theme->set_stylebox("labeled_separator_right", "PopupMenu", style_popup_labeled_separator_right); - - theme->set_color("font_color", "PopupMenu", font_color); - theme->set_color("font_hover_color", "PopupMenu", font_hover_color); - theme->set_color("font_accelerator_color", "PopupMenu", font_disabled_color); - theme->set_color("font_disabled_color", "PopupMenu", font_disabled_color); - theme->set_color("font_separator_color", "PopupMenu", font_disabled_color); - theme->set_color("font_outline_color", "PopupMenu", font_outline_color); - theme->set_icon("checked", "PopupMenu", theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons))); - theme->set_icon("unchecked", "PopupMenu", theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons))); - theme->set_icon("radio_checked", "PopupMenu", theme->get_icon(SNAME("GuiRadioChecked"), EditorStringName(EditorIcons))); - theme->set_icon("radio_unchecked", "PopupMenu", theme->get_icon(SNAME("GuiRadioUnchecked"), EditorStringName(EditorIcons))); - theme->set_icon("checked_disabled", "PopupMenu", theme->get_icon(SNAME("GuiCheckedDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("unchecked_disabled", "PopupMenu", theme->get_icon(SNAME("GuiUncheckedDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("radio_checked_disabled", "PopupMenu", theme->get_icon(SNAME("GuiRadioCheckedDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("radio_unchecked_disabled", "PopupMenu", theme->get_icon(SNAME("GuiRadioUncheckedDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("submenu", "PopupMenu", theme->get_icon(SNAME("ArrowRight"), EditorStringName(EditorIcons))); - theme->set_icon("submenu_mirrored", "PopupMenu", theme->get_icon(SNAME("ArrowLeft"), EditorStringName(EditorIcons))); - theme->set_icon("visibility_hidden", "PopupMenu", theme->get_icon(SNAME("GuiVisibilityHidden"), EditorStringName(EditorIcons))); - theme->set_icon("visibility_visible", "PopupMenu", theme->get_icon(SNAME("GuiVisibilityVisible"), EditorStringName(EditorIcons))); - theme->set_icon("visibility_xray", "PopupMenu", theme->get_icon(SNAME("GuiVisibilityXray"), EditorStringName(EditorIcons))); - - // Force the v_separation to be even so that the spacing on top and bottom is even. - // If the vsep is odd and cannot be split into 2 even groups (of pixels), then it will be lopsided. - // We add 2 to the vsep to give it some extra spacing which looks a bit more modern (see Windows, for example). - const int vsep_base = extra_spacing + default_margin_size + 6; - const int force_even_vsep = vsep_base + (vsep_base % 2); - theme->set_constant("v_separation", "PopupMenu", force_even_vsep * EDSCALE); - theme->set_constant("outline_size", "PopupMenu", 0); - theme->set_constant("item_start_padding", "PopupMenu", default_margin_size * 1.5 * EDSCALE); - theme->set_constant("item_end_padding", "PopupMenu", default_margin_size * 1.5 * EDSCALE); - - // Sub-inspectors - for (int i = 0; i < 16; i++) { - Color si_base_color = accent_color; - - 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 = accent_color.lerp(si_base_color, float(EDITOR_GET("docks/property_editor/subresource_hue_tint"))); - - // Sub-inspector background. - Ref sub_inspector_bg = style_default->duplicate(); - sub_inspector_bg->set_bg_color(dark_color_1.lerp(si_base_color, 0.08)); - sub_inspector_bg->set_border_width_all(2 * EDSCALE); - sub_inspector_bg->set_border_color(si_base_color * Color(0.7, 0.7, 0.7, 0.8)); - sub_inspector_bg->set_content_margin_all(4 * EDSCALE); - sub_inspector_bg->set_corner_radius(CORNER_TOP_LEFT, 0); - sub_inspector_bg->set_corner_radius(CORNER_TOP_RIGHT, 0); - - theme->set_stylebox("sub_inspector_bg" + itos(i), EditorStringName(Editor), sub_inspector_bg); - - // EditorProperty background while it has a sub-inspector open. - Ref bg_color = make_flat_stylebox(si_base_color * Color(0.7, 0.7, 0.7, 0.8), 0, 0, 0, 0, corner_radius); - bg_color->set_anti_aliased(false); - bg_color->set_corner_radius(CORNER_BOTTOM_LEFT, 0); - bg_color->set_corner_radius(CORNER_BOTTOM_RIGHT, 0); - - theme->set_stylebox("sub_inspector_property_bg" + itos(i), EditorStringName(Editor), bg_color); - } - - theme->set_color("sub_inspector_property_color", EditorStringName(Editor), dark_theme ? Color(1, 1, 1, 1) : Color(0, 0, 0, 1)); - - // EditorSpinSlider. - theme->set_color("label_color", "EditorSpinSlider", font_color); - theme->set_color("read_only_label_color", "EditorSpinSlider", font_readonly_color); - - Ref editor_spin_label_bg = style_default->duplicate(); - editor_spin_label_bg->set_bg_color(dark_color_3); - editor_spin_label_bg->set_border_width_all(0); - theme->set_stylebox("label_bg", "EditorSpinSlider", editor_spin_label_bg); - - // EditorProperty - Ref style_property_bg = style_default->duplicate(); - style_property_bg->set_bg_color(highlight_color); - style_property_bg->set_border_width_all(0); - - Ref style_property_child_bg = style_default->duplicate(); - style_property_child_bg->set_bg_color(dark_color_2); - style_property_child_bg->set_border_width_all(0); - - theme->set_constant("font_offset", "EditorProperty", 8 * EDSCALE); - theme->set_stylebox("bg_selected", "EditorProperty", style_property_bg); - theme->set_stylebox("bg", "EditorProperty", Ref(memnew(StyleBoxEmpty))); - theme->set_stylebox("child_bg", "EditorProperty", style_property_child_bg); - theme->set_constant("v_separation", "EditorProperty", (extra_spacing + default_margin_size) * EDSCALE); - theme->set_color("warning_color", "EditorProperty", warning_color); - theme->set_color("property_color", "EditorProperty", property_color); - theme->set_color("readonly_color", "EditorProperty", readonly_color); - theme->set_color("readonly_warning_color", "EditorProperty", readonly_warning_color); - - Ref style_property_group_note = style_default->duplicate(); - Color property_group_note_color = accent_color; - property_group_note_color.a = 0.1; - style_property_group_note->set_bg_color(property_group_note_color); - theme->set_stylebox("bg_group_note", "EditorProperty", style_property_group_note); - - // EditorInspectorSection - Color inspector_section_color = font_color.lerp(Color(0.5, 0.5, 0.5), 0.35); - theme->set_color("font_color", "EditorInspectorSection", inspector_section_color); - - Color inspector_indent_color = accent_color; - inspector_indent_color.a = 0.2; - Ref inspector_indent_style = make_flat_stylebox(inspector_indent_color, 2.0 * EDSCALE, 0, 2.0 * EDSCALE, 0); - theme->set_stylebox("indent_box", "EditorInspectorSection", inspector_indent_style); - theme->set_constant("indent_size", "EditorInspectorSection", 6.0 * EDSCALE); - - theme->set_constant("inspector_margin", EditorStringName(Editor), 12 * EDSCALE); - - // Tree & ItemList background - Ref style_tree_bg = style_default->duplicate(); - // Make Trees easier to distinguish from other controls by using a darker background color. - style_tree_bg->set_bg_color(dark_color_1.lerp(dark_color_2, 0.5)); - if (draw_extra_borders) { - style_tree_bg->set_border_width_all(Math::round(EDSCALE)); - style_tree_bg->set_border_color(extra_border_color_2); - } else { - style_tree_bg->set_border_color(dark_color_3); - } - - theme->set_stylebox("panel", "Tree", style_tree_bg); - theme->set_stylebox("panel", "EditorValidationPanel", style_tree_bg); - - // Tree - theme->set_icon("checked", "Tree", theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons))); - theme->set_icon("checked_disabled", "Tree", theme->get_icon(SNAME("GuiCheckedDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("indeterminate", "Tree", theme->get_icon(SNAME("GuiIndeterminate"), EditorStringName(EditorIcons))); - theme->set_icon("indeterminate_disabled", "Tree", theme->get_icon(SNAME("GuiIndeterminateDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("unchecked", "Tree", theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons))); - theme->set_icon("unchecked_disabled", "Tree", theme->get_icon(SNAME("GuiUncheckedDisabled"), EditorStringName(EditorIcons))); - theme->set_icon("arrow", "Tree", theme->get_icon(SNAME("GuiTreeArrowDown"), EditorStringName(EditorIcons))); - theme->set_icon("arrow_collapsed", "Tree", theme->get_icon(SNAME("GuiTreeArrowRight"), EditorStringName(EditorIcons))); - theme->set_icon("arrow_collapsed_mirrored", "Tree", theme->get_icon(SNAME("GuiTreeArrowLeft"), EditorStringName(EditorIcons))); - theme->set_icon("updown", "Tree", theme->get_icon(SNAME("GuiTreeUpdown"), EditorStringName(EditorIcons))); - theme->set_icon("select_arrow", "Tree", theme->get_icon(SNAME("GuiDropdown"), EditorStringName(EditorIcons))); - theme->set_stylebox("focus", "Tree", style_widget_focus); - theme->set_stylebox("custom_button", "Tree", make_empty_stylebox()); - theme->set_stylebox("custom_button_pressed", "Tree", make_empty_stylebox()); - theme->set_stylebox("custom_button_hover", "Tree", style_widget); - theme->set_color("custom_button_font_highlight", "Tree", font_hover_color); - theme->set_color("font_color", "Tree", font_color); - theme->set_color("font_selected_color", "Tree", mono_color); - theme->set_color("font_disabled_color", "Tree", font_disabled_color); - theme->set_color("font_outline_color", "Tree", font_outline_color); - theme->set_color("title_button_color", "Tree", font_color); - theme->set_color("drop_position_color", "Tree", accent_color); - theme->set_constant("v_separation", "Tree", widget_default_margin.y - EDSCALE); - theme->set_constant("h_separation", "Tree", 6 * EDSCALE); - theme->set_constant("guide_width", "Tree", border_width); - theme->set_constant("item_margin", "Tree", 3 * default_margin_size * EDSCALE); - theme->set_constant("inner_item_margin_bottom", "Tree", (default_margin_size + extra_spacing) * EDSCALE); - theme->set_constant("inner_item_margin_left", "Tree", (default_margin_size + extra_spacing) * EDSCALE); - theme->set_constant("inner_item_margin_right", "Tree", (default_margin_size + extra_spacing) * EDSCALE); - theme->set_constant("inner_item_margin_top", "Tree", (default_margin_size + extra_spacing) * EDSCALE); - theme->set_constant("button_margin", "Tree", default_margin_size * EDSCALE); - theme->set_constant("scroll_border", "Tree", 40 * EDSCALE); - theme->set_constant("scroll_speed", "Tree", 12); - theme->set_constant("outline_size", "Tree", 0); - theme->set_constant("scrollbar_margin_left", "Tree", 0); - theme->set_constant("scrollbar_margin_top", "Tree", 0); - theme->set_constant("scrollbar_margin_right", "Tree", 0); - theme->set_constant("scrollbar_margin_bottom", "Tree", 0); - theme->set_constant("scrollbar_h_separation", "Tree", 1 * EDSCALE); - theme->set_constant("scrollbar_v_separation", "Tree", 1 * EDSCALE); - - const Color guide_color = mono_color * Color(1, 1, 1, 0.05); - Color relationship_line_color = mono_color * Color(1, 1, 1, relationship_line_opacity); - - theme->set_constant("draw_guides", "Tree", relationship_line_opacity < 0.01); - theme->set_color("guide_color", "Tree", guide_color); - - int relationship_line_width = 1; - Color parent_line_color = mono_color * Color(1, 1, 1, CLAMP(relationship_line_opacity + 0.45, 0.0, 1.0)); - Color children_line_color = mono_color * Color(1, 1, 1, CLAMP(relationship_line_opacity + 0.25, 0.0, 1.0)); - theme->set_constant("draw_relationship_lines", "Tree", relationship_line_opacity >= 0.01); - theme->set_constant("relationship_line_width", "Tree", relationship_line_width); - theme->set_constant("parent_hl_line_width", "Tree", relationship_line_width * 2); - theme->set_constant("children_hl_line_width", "Tree", relationship_line_width); - theme->set_constant("parent_hl_line_margin", "Tree", relationship_line_width * 3); - theme->set_color("relationship_line_color", "Tree", relationship_line_color); - theme->set_color("parent_hl_line_color", "Tree", parent_line_color); - theme->set_color("children_hl_line_color", "Tree", children_line_color); - - Ref style_tree_btn = style_default->duplicate(); - style_tree_btn->set_bg_color(highlight_color); - style_tree_btn->set_border_width_all(0); - theme->set_stylebox("button_pressed", "Tree", style_tree_btn); - - Ref style_tree_hover = style_default->duplicate(); - style_tree_hover->set_bg_color(highlight_color * Color(1, 1, 1, 0.4)); - style_tree_hover->set_border_width_all(0); - theme->set_stylebox("hover", "Tree", style_tree_hover); - - Ref style_tree_focus = style_default->duplicate(); - style_tree_focus->set_bg_color(highlight_color); - style_tree_focus->set_border_width_all(0); - theme->set_stylebox("selected_focus", "Tree", style_tree_focus); - - Ref style_tree_selected = style_tree_focus->duplicate(); - theme->set_stylebox("selected", "Tree", style_tree_selected); - - Ref style_tree_cursor = style_default->duplicate(); - style_tree_cursor->set_draw_center(false); - style_tree_cursor->set_border_width_all(MAX(1, border_width)); - style_tree_cursor->set_border_color(contrast_color_1); - - Ref style_tree_title = style_default->duplicate(); - style_tree_title->set_bg_color(dark_color_3); - style_tree_title->set_border_width_all(0); - theme->set_stylebox("cursor", "Tree", style_tree_cursor); - theme->set_stylebox("cursor_unfocused", "Tree", style_tree_cursor); - theme->set_stylebox("title_button_normal", "Tree", style_tree_title); - theme->set_stylebox("title_button_hover", "Tree", style_tree_title); - theme->set_stylebox("title_button_pressed", "Tree", style_tree_title); - - Color prop_category_color = dark_color_1.lerp(mono_color, 0.12); - Color prop_section_color = dark_color_1.lerp(mono_color, 0.09); - Color prop_subsection_color = dark_color_1.lerp(mono_color, 0.06); - theme->set_color("prop_category", EditorStringName(Editor), prop_category_color); - theme->set_color("prop_section", EditorStringName(Editor), prop_section_color); - theme->set_color("prop_subsection", EditorStringName(Editor), prop_subsection_color); - theme->set_color("drop_position_color", "Tree", accent_color); - - // EditorInspectorCategory - Ref category_bg = style_default->duplicate(); - category_bg->set_bg_color(prop_category_color); - category_bg->set_border_color(prop_category_color); - theme->set_stylebox("bg", "EditorInspectorCategory", category_bg); - - // ItemList - Ref style_itemlist_bg = style_default->duplicate(); - style_itemlist_bg->set_bg_color(dark_color_1); - - if (draw_extra_borders) { - style_itemlist_bg->set_border_width_all(Math::round(EDSCALE)); - style_itemlist_bg->set_border_color(extra_border_color_2); - } else { - style_itemlist_bg->set_border_width_all(border_width); - style_itemlist_bg->set_border_color(dark_color_3); - } - - Ref style_itemlist_cursor = style_default->duplicate(); - style_itemlist_cursor->set_draw_center(false); - style_itemlist_cursor->set_border_width_all(border_width); - style_itemlist_cursor->set_border_color(highlight_color); - - Ref style_itemlist_hover = style_tree_selected->duplicate(); - style_itemlist_hover->set_bg_color(highlight_color * Color(1, 1, 1, 0.3)); - style_itemlist_hover->set_border_width_all(0); - - theme->set_stylebox("panel", "ItemList", style_itemlist_bg); - theme->set_stylebox("focus", "ItemList", style_widget_focus); - theme->set_stylebox("cursor", "ItemList", style_itemlist_cursor); - theme->set_stylebox("cursor_unfocused", "ItemList", style_itemlist_cursor); - theme->set_stylebox("selected_focus", "ItemList", style_tree_focus); - theme->set_stylebox("selected", "ItemList", style_tree_selected); - theme->set_stylebox("hovered", "ItemList", style_itemlist_hover); - theme->set_color("font_color", "ItemList", font_color); - theme->set_color("font_hovered_color", "ItemList", mono_color); - theme->set_color("font_selected_color", "ItemList", mono_color); - theme->set_color("font_outline_color", "ItemList", font_outline_color); - theme->set_color("guide_color", "ItemList", guide_color); - theme->set_constant("v_separation", "ItemList", force_even_vsep * 0.5 * EDSCALE); - theme->set_constant("h_separation", "ItemList", 6 * EDSCALE); - theme->set_constant("icon_margin", "ItemList", 6 * EDSCALE); - theme->set_constant("line_separation", "ItemList", 3 * EDSCALE); - theme->set_constant("outline_size", "ItemList", 0); - - // TabBar & TabContainer - Ref style_tabbar_background = make_flat_stylebox(dark_color_1, 0, 0, 0, 0, corner_radius * EDSCALE); - style_tabbar_background->set_corner_radius(CORNER_BOTTOM_LEFT, 0); - style_tabbar_background->set_corner_radius(CORNER_BOTTOM_RIGHT, 0); - theme->set_stylebox("tabbar_background", "TabContainer", style_tabbar_background); - - theme->set_stylebox("tab_selected", "TabContainer", style_tab_selected); - theme->set_stylebox("tab_hovered", "TabContainer", style_tab_hovered); - theme->set_stylebox("tab_unselected", "TabContainer", style_tab_unselected); - theme->set_stylebox("tab_disabled", "TabContainer", style_tab_disabled); - theme->set_stylebox("tab_focus", "TabContainer", style_tab_focus); - theme->set_stylebox("tab_selected", "TabBar", style_tab_selected); - theme->set_stylebox("tab_hovered", "TabBar", style_tab_hovered); - theme->set_stylebox("tab_unselected", "TabBar", style_tab_unselected); - theme->set_stylebox("tab_disabled", "TabBar", style_tab_disabled); - theme->set_stylebox("tab_focus", "TabBar", style_tab_focus); - theme->set_stylebox("button_pressed", "TabBar", style_menu); - theme->set_stylebox("button_highlight", "TabBar", style_menu); - theme->set_color("font_selected_color", "TabContainer", font_color); - theme->set_color("font_hovered_color", "TabContainer", font_color); - theme->set_color("font_unselected_color", "TabContainer", font_disabled_color); - theme->set_color("font_outline_color", "TabContainer", font_outline_color); - theme->set_color("font_selected_color", "TabBar", font_color); - theme->set_color("font_hovered_color", "TabBar", font_color); - theme->set_color("font_unselected_color", "TabBar", font_disabled_color); - theme->set_color("font_outline_color", "TabBar", font_outline_color); - theme->set_color("drop_mark_color", "TabContainer", tab_highlight); - theme->set_color("drop_mark_color", "TabBar", tab_highlight); - theme->set_icon("menu", "TabContainer", theme->get_icon(SNAME("GuiTabMenu"), EditorStringName(EditorIcons))); - theme->set_icon("menu_highlight", "TabContainer", theme->get_icon(SNAME("GuiTabMenuHl"), EditorStringName(EditorIcons))); - theme->set_icon("close", "TabBar", theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons))); - theme->set_icon("increment", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowRight"), EditorStringName(EditorIcons))); - theme->set_icon("decrement", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowLeft"), EditorStringName(EditorIcons))); - theme->set_icon("increment", "TabBar", theme->get_icon(SNAME("GuiScrollArrowRight"), EditorStringName(EditorIcons))); - theme->set_icon("decrement", "TabBar", theme->get_icon(SNAME("GuiScrollArrowLeft"), EditorStringName(EditorIcons))); - theme->set_icon("increment_highlight", "TabBar", theme->get_icon(SNAME("GuiScrollArrowRightHl"), EditorStringName(EditorIcons))); - theme->set_icon("decrement_highlight", "TabBar", theme->get_icon(SNAME("GuiScrollArrowLeftHl"), EditorStringName(EditorIcons))); - theme->set_icon("increment_highlight", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowRightHl"), EditorStringName(EditorIcons))); - theme->set_icon("decrement_highlight", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowLeftHl"), EditorStringName(EditorIcons))); - theme->set_icon("drop_mark", "TabContainer", theme->get_icon(SNAME("GuiTabDropMark"), EditorStringName(EditorIcons))); - theme->set_icon("drop_mark", "TabBar", theme->get_icon(SNAME("GuiTabDropMark"), EditorStringName(EditorIcons))); - theme->set_constant("side_margin", "TabContainer", 0); - theme->set_constant("outline_size", "TabContainer", 0); - theme->set_constant("h_separation", "TabBar", 4 * EDSCALE); - theme->set_constant("outline_size", "TabBar", 0); - - // Content of each tab. - Ref style_content_panel = style_default->duplicate(); - style_content_panel->set_border_color(dark_color_3); - style_content_panel->set_border_width_all(border_width); - style_content_panel->set_border_width(Side::SIDE_TOP, 0); - style_content_panel->set_corner_radius(CORNER_TOP_LEFT, 0); - style_content_panel->set_corner_radius(CORNER_TOP_RIGHT, 0); - // Compensate for the border. - style_content_panel->set_content_margin_individual(margin_size_extra * EDSCALE, (2 + margin_size_extra) * EDSCALE, margin_size_extra * EDSCALE, margin_size_extra * EDSCALE); - theme->set_stylebox("panel", "TabContainer", style_content_panel); - - // Bottom panel. - Ref style_bottom_panel = style_content_panel->duplicate(); - style_bottom_panel->set_corner_radius_all(corner_radius * EDSCALE); - theme->set_stylebox("BottomPanel", EditorStringName(EditorStyles), style_bottom_panel); - - // TabContainerOdd can be used on tabs against the base color background (e.g. nested tabs). - theme->set_type_variation("TabContainerOdd", "TabContainer"); - - Ref style_tab_selected_odd = style_tab_selected->duplicate(); - style_tab_selected_odd->set_bg_color(disabled_bg_color); - theme->set_stylebox("tab_selected", "TabContainerOdd", style_tab_selected_odd); - - Ref style_content_panel_odd = style_content_panel->duplicate(); - style_content_panel_odd->set_bg_color(disabled_bg_color); - theme->set_stylebox("panel", "TabContainerOdd", style_content_panel_odd); - - // This stylebox is used in 3d and 2d viewports (no borders). - Ref style_content_panel_vp = style_content_panel->duplicate(); - style_content_panel_vp->set_content_margin_individual(border_width * 2, default_margin_size * EDSCALE, border_width * 2, border_width * 2); - theme->set_stylebox("Content", EditorStringName(EditorStyles), style_content_panel_vp); - - // This stylebox is used by preview tabs in the Theme Editor. - Ref style_theme_preview_tab = style_tab_selected_odd->duplicate(); - style_theme_preview_tab->set_expand_margin(SIDE_BOTTOM, 5 * EDSCALE); - theme->set_stylebox("ThemeEditorPreviewFG", EditorStringName(EditorStyles), style_theme_preview_tab); - Ref style_theme_preview_bg_tab = style_tab_unselected->duplicate(); - style_theme_preview_bg_tab->set_expand_margin(SIDE_BOTTOM, 2 * EDSCALE); - theme->set_stylebox("ThemeEditorPreviewBG", EditorStringName(EditorStyles), style_theme_preview_bg_tab); - - Ref style_texture_region_bg = style_tree_bg->duplicate(); - style_texture_region_bg->set_content_margin_all(0); - theme->set_stylebox("TextureRegionPreviewBG", EditorStringName(EditorStyles), style_texture_region_bg); - theme->set_stylebox("TextureRegionPreviewFG", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0)); - - // Separators - theme->set_stylebox("separator", "HSeparator", make_line_stylebox(separator_color, MAX(Math::round(EDSCALE), border_width))); - theme->set_stylebox("separator", "VSeparator", make_line_stylebox(separator_color, MAX(Math::round(EDSCALE), border_width), 0, 0, true)); - - // Debugger - - Ref style_panel_debugger = style_content_panel->duplicate(); - style_panel_debugger->set_border_width(SIDE_BOTTOM, 0); - theme->set_stylebox("DebuggerPanel", EditorStringName(EditorStyles), style_panel_debugger); - - Ref style_panel_invisible_top = style_content_panel->duplicate(); - int stylebox_offset = theme->get_font(SNAME("tab_selected"), SNAME("TabContainer"))->get_height(theme->get_font_size(SNAME("tab_selected"), SNAME("TabContainer"))) + theme->get_stylebox(SNAME("tab_selected"), SNAME("TabContainer"))->get_minimum_size().height + theme->get_stylebox(SNAME("panel"), SNAME("TabContainer"))->get_content_margin(SIDE_TOP); - style_panel_invisible_top->set_expand_margin(SIDE_TOP, -stylebox_offset); - style_panel_invisible_top->set_content_margin(SIDE_TOP, 0); - theme->set_stylebox("BottomPanelDebuggerOverride", EditorStringName(EditorStyles), style_panel_invisible_top); - - // LineEdit - - Ref style_line_edit = style_widget->duplicate(); - // The original style_widget style has an extra 1 pixel offset that makes LineEdits not align with Buttons, - // so this compensates for that. - style_line_edit->set_content_margin(SIDE_TOP, style_line_edit->get_content_margin(SIDE_TOP) - 1 * EDSCALE); - - // Don't round the bottom corners to make the line look sharper. - style_line_edit->set_corner_radius(CORNER_BOTTOM_LEFT, 0); - style_line_edit->set_corner_radius(CORNER_BOTTOM_RIGHT, 0); - - if (draw_extra_borders) { - style_line_edit->set_border_width_all(Math::round(EDSCALE)); - style_line_edit->set_border_color(extra_border_color_1); - } else { - // Add a bottom line to make LineEdits more visible, especially in sectioned inspectors - // such as the Project Settings. - style_line_edit->set_border_width(SIDE_BOTTOM, Math::round(2 * EDSCALE)); - style_line_edit->set_border_color(dark_color_2); - } - - Ref style_line_edit_disabled = style_line_edit->duplicate(); - style_line_edit_disabled->set_border_color(disabled_color); - style_line_edit_disabled->set_bg_color(disabled_bg_color); - - theme->set_stylebox("normal", "LineEdit", style_line_edit); - theme->set_stylebox("focus", "LineEdit", style_widget_focus); - theme->set_stylebox("read_only", "LineEdit", style_line_edit_disabled); - theme->set_icon("clear", "LineEdit", theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons))); - theme->set_color("font_color", "LineEdit", font_color); - theme->set_color("font_selected_color", "LineEdit", mono_color); - theme->set_color("font_uneditable_color", "LineEdit", font_readonly_color); - theme->set_color("font_placeholder_color", "LineEdit", font_placeholder_color); - theme->set_color("font_outline_color", "LineEdit", font_outline_color); - theme->set_color("caret_color", "LineEdit", font_color); - theme->set_color("selection_color", "LineEdit", selection_color); - theme->set_color("clear_button_color", "LineEdit", font_color); - theme->set_color("clear_button_color_pressed", "LineEdit", accent_color); - - theme->set_constant("minimum_character_width", "LineEdit", 4); - theme->set_constant("outline_size", "LineEdit", 0); - theme->set_constant("caret_width", "LineEdit", 1); - - // TextEdit - theme->set_stylebox("normal", "TextEdit", style_line_edit); - theme->set_stylebox("focus", "TextEdit", style_widget_focus); - theme->set_stylebox("read_only", "TextEdit", style_line_edit_disabled); - theme->set_icon("tab", "TextEdit", theme->get_icon(SNAME("GuiTab"), EditorStringName(EditorIcons))); - theme->set_icon("space", "TextEdit", theme->get_icon(SNAME("GuiSpace"), EditorStringName(EditorIcons))); - theme->set_color("font_color", "TextEdit", font_color); - theme->set_color("font_readonly_color", "TextEdit", font_readonly_color); - theme->set_color("font_placeholder_color", "TextEdit", font_placeholder_color); - theme->set_color("font_outline_color", "TextEdit", font_outline_color); - theme->set_color("caret_color", "TextEdit", font_color); - theme->set_color("selection_color", "TextEdit", selection_color); - theme->set_color("background_color", "TextEdit", Color(0, 0, 0, 0)); - - theme->set_constant("line_spacing", "TextEdit", 4 * EDSCALE); - theme->set_constant("outline_size", "TextEdit", 0); - theme->set_constant("caret_width", "TextEdit", 1); - - theme->set_icon("h_grabber", "SplitContainer", theme->get_icon(SNAME("GuiHsplitter"), EditorStringName(EditorIcons))); - theme->set_icon("v_grabber", "SplitContainer", theme->get_icon(SNAME("GuiVsplitter"), EditorStringName(EditorIcons))); - theme->set_icon("grabber", "VSplitContainer", theme->get_icon(SNAME("GuiVsplitter"), EditorStringName(EditorIcons))); - theme->set_icon("grabber", "HSplitContainer", theme->get_icon(SNAME("GuiHsplitter"), EditorStringName(EditorIcons))); - - theme->set_constant("separation", "SplitContainer", default_margin_size * 2 * EDSCALE); - theme->set_constant("separation", "HSplitContainer", default_margin_size * 2 * EDSCALE); - theme->set_constant("separation", "VSplitContainer", default_margin_size * 2 * EDSCALE); - - theme->set_constant("minimum_grab_thickness", "SplitContainer", 6 * EDSCALE); - theme->set_constant("minimum_grab_thickness", "HSplitContainer", 6 * EDSCALE); - theme->set_constant("minimum_grab_thickness", "VSplitContainer", 6 * EDSCALE); - - // Containers - theme->set_constant("separation", "BoxContainer", default_margin_size * EDSCALE); - theme->set_constant("separation", "HBoxContainer", default_margin_size * EDSCALE); - theme->set_constant("separation", "VBoxContainer", default_margin_size * EDSCALE); - theme->set_constant("margin_left", "MarginContainer", 0); - theme->set_constant("margin_top", "MarginContainer", 0); - theme->set_constant("margin_right", "MarginContainer", 0); - theme->set_constant("margin_bottom", "MarginContainer", 0); - theme->set_constant("h_separation", "GridContainer", default_margin_size * EDSCALE); - theme->set_constant("v_separation", "GridContainer", default_margin_size * EDSCALE); - theme->set_constant("h_separation", "FlowContainer", default_margin_size * EDSCALE); - theme->set_constant("v_separation", "FlowContainer", default_margin_size * EDSCALE); - theme->set_constant("h_separation", "HFlowContainer", default_margin_size * EDSCALE); - theme->set_constant("v_separation", "HFlowContainer", default_margin_size * EDSCALE); - theme->set_constant("h_separation", "VFlowContainer", default_margin_size * EDSCALE); - theme->set_constant("v_separation", "VFlowContainer", default_margin_size * EDSCALE); - - // Custom theme type for MarginContainer with 4px margins. - theme->set_type_variation("MarginContainer4px", "MarginContainer"); - theme->set_constant("margin_left", "MarginContainer4px", 4 * EDSCALE); - theme->set_constant("margin_top", "MarginContainer4px", 4 * EDSCALE); - theme->set_constant("margin_right", "MarginContainer4px", 4 * EDSCALE); - theme->set_constant("margin_bottom", "MarginContainer4px", 4 * EDSCALE); - - // Window - - // Prevent corner artifacts between window title and body. - Ref style_window_title = style_default->duplicate(); - style_window_title->set_corner_radius(CORNER_TOP_LEFT, 0); - style_window_title->set_corner_radius(CORNER_TOP_RIGHT, 0); - // Prevent visible line between window title and body. - style_window_title->set_expand_margin(SIDE_BOTTOM, 2 * EDSCALE); - - Ref style_window = style_popup->duplicate(); - style_window->set_border_color(base_color); - style_window->set_border_width(SIDE_TOP, 24 * EDSCALE); - style_window->set_expand_margin(SIDE_TOP, 24 * EDSCALE); - theme->set_stylebox("embedded_border", "Window", style_window); - theme->set_stylebox("embedded_unfocused_border", "Window", style_window); - - theme->set_color("title_color", "Window", font_color); - theme->set_icon("close", "Window", theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons))); - theme->set_icon("close_pressed", "Window", theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons))); - theme->set_constant("close_h_offset", "Window", 22 * EDSCALE); - theme->set_constant("close_v_offset", "Window", 20 * EDSCALE); - theme->set_constant("title_height", "Window", 24 * EDSCALE); - theme->set_constant("resize_margin", "Window", 4 * EDSCALE); - theme->set_font("title_font", "Window", theme->get_font(SNAME("title"), EditorStringName(EditorFonts))); - theme->set_font_size("title_font_size", "Window", theme->get_font_size(SNAME("title_size"), EditorStringName(EditorFonts))); - - // Complex window (currently only Editor Settings and Project Settings) - Ref style_complex_window = style_window->duplicate(); - style_complex_window->set_bg_color(dark_color_2); - style_complex_window->set_border_color(dark_color_2); - theme->set_stylebox("panel", "EditorSettingsDialog", style_complex_window); - theme->set_stylebox("panel", "ProjectSettingsEditor", style_complex_window); - theme->set_stylebox("panel", "EditorAbout", style_complex_window); - - // AcceptDialog - theme->set_stylebox("panel", "AcceptDialog", style_window_title); - theme->set_constant("buttons_separation", "AcceptDialog", 8 * EDSCALE); - - // HScrollBar - Ref empty_icon = memnew(ImageTexture); - - if (increase_scrollbar_touch_area) { - theme->set_stylebox("scroll", "HScrollBar", make_line_stylebox(separator_color, 50)); - } else { - theme->set_stylebox("scroll", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, -5, 1, -5, 1)); - } - theme->set_stylebox("scroll_focus", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1)); - theme->set_stylebox("grabber", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabber"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1)); - theme->set_stylebox("grabber_highlight", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberHl"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1)); - theme->set_stylebox("grabber_pressed", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberPressed"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1)); - - theme->set_icon("increment", "HScrollBar", empty_icon); - theme->set_icon("increment_highlight", "HScrollBar", empty_icon); - theme->set_icon("increment_pressed", "HScrollBar", empty_icon); - theme->set_icon("decrement", "HScrollBar", empty_icon); - theme->set_icon("decrement_highlight", "HScrollBar", empty_icon); - theme->set_icon("decrement_pressed", "HScrollBar", empty_icon); - - // VScrollBar - if (increase_scrollbar_touch_area) { - theme->set_stylebox("scroll", "VScrollBar", make_line_stylebox(separator_color, 50, 1, 1, true)); - } else { - theme->set_stylebox("scroll", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, -5, 1, -5)); - } - theme->set_stylebox("scroll_focus", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1)); - theme->set_stylebox("grabber", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabber"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1)); - theme->set_stylebox("grabber_highlight", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberHl"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1)); - theme->set_stylebox("grabber_pressed", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberPressed"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1)); - - theme->set_icon("increment", "VScrollBar", empty_icon); - theme->set_icon("increment_highlight", "VScrollBar", empty_icon); - theme->set_icon("increment_pressed", "VScrollBar", empty_icon); - theme->set_icon("decrement", "VScrollBar", empty_icon); - theme->set_icon("decrement_highlight", "VScrollBar", empty_icon); - theme->set_icon("decrement_pressed", "VScrollBar", empty_icon); - - // HSlider - theme->set_icon("grabber_highlight", "HSlider", theme->get_icon(SNAME("GuiSliderGrabberHl"), EditorStringName(EditorIcons))); - theme->set_icon("grabber", "HSlider", theme->get_icon(SNAME("GuiSliderGrabber"), EditorStringName(EditorIcons))); - theme->set_stylebox("slider", "HSlider", make_flat_stylebox(dark_color_3, 0, default_margin_size / 2, 0, default_margin_size / 2, corner_width)); - theme->set_stylebox("grabber_area", "HSlider", make_flat_stylebox(contrast_color_1, 0, default_margin_size / 2, 0, default_margin_size / 2, corner_width)); - theme->set_stylebox("grabber_area_highlight", "HSlider", make_flat_stylebox(contrast_color_1, 0, default_margin_size / 2, 0, default_margin_size / 2)); - theme->set_constant("center_grabber", "HSlider", 0); - theme->set_constant("grabber_offset", "HSlider", 0); - - // VSlider - theme->set_icon("grabber", "VSlider", theme->get_icon(SNAME("GuiSliderGrabber"), EditorStringName(EditorIcons))); - theme->set_icon("grabber_highlight", "VSlider", theme->get_icon(SNAME("GuiSliderGrabberHl"), EditorStringName(EditorIcons))); - theme->set_stylebox("slider", "VSlider", make_flat_stylebox(dark_color_3, default_margin_size / 2, 0, default_margin_size / 2, 0, corner_width)); - theme->set_stylebox("grabber_area", "VSlider", make_flat_stylebox(contrast_color_1, default_margin_size / 2, 0, default_margin_size / 2, 0, corner_width)); - theme->set_stylebox("grabber_area_highlight", "VSlider", make_flat_stylebox(contrast_color_1, default_margin_size / 2, 0, default_margin_size / 2, 0)); - theme->set_constant("center_grabber", "VSlider", 0); - theme->set_constant("grabber_offset", "VSlider", 0); - - // RichTextLabel - theme->set_color("default_color", "RichTextLabel", font_color); - theme->set_color("font_shadow_color", "RichTextLabel", Color(0, 0, 0, 0)); - theme->set_color("font_outline_color", "RichTextLabel", font_outline_color); - theme->set_color("selection_color", "RichTextLabel", selection_color); - theme->set_constant("shadow_offset_x", "RichTextLabel", 1 * EDSCALE); - theme->set_constant("shadow_offset_y", "RichTextLabel", 1 * EDSCALE); - theme->set_constant("shadow_outline_size", "RichTextLabel", 1 * EDSCALE); - theme->set_constant("outline_size", "RichTextLabel", 0); - theme->set_stylebox("focus", "RichTextLabel", make_empty_stylebox()); - theme->set_stylebox("normal", "RichTextLabel", style_tree_bg); - - // Editor help. - Ref style_editor_help = style_default->duplicate(); - style_editor_help->set_bg_color(dark_color_2); - style_editor_help->set_border_color(dark_color_3); - theme->set_stylebox("background", "EditorHelp", style_editor_help); - - theme->set_color("title_color", "EditorHelp", accent_color); - theme->set_color("headline_color", "EditorHelp", mono_color); - theme->set_color("text_color", "EditorHelp", font_color); - theme->set_color("comment_color", "EditorHelp", font_color * Color(1, 1, 1, 0.6)); - theme->set_color("symbol_color", "EditorHelp", font_color * Color(1, 1, 1, 0.6)); - theme->set_color("value_color", "EditorHelp", font_color * Color(1, 1, 1, 0.6)); - theme->set_color("qualifier_color", "EditorHelp", font_color * Color(1, 1, 1, 0.8)); - theme->set_color("type_color", "EditorHelp", accent_color.lerp(font_color, 0.5)); - theme->set_color("selection_color", "EditorHelp", selection_color); - theme->set_color("link_color", "EditorHelp", accent_color.lerp(mono_color, 0.8)); - theme->set_color("code_color", "EditorHelp", accent_color.lerp(mono_color, 0.6)); - theme->set_color("kbd_color", "EditorHelp", accent_color.lerp(property_color, 0.6)); - theme->set_color("code_bg_color", "EditorHelp", dark_color_3); - theme->set_color("kbd_bg_color", "EditorHelp", dark_color_1); - theme->set_color("param_bg_color", "EditorHelp", dark_color_1); - theme->set_constant("line_separation", "EditorHelp", Math::round(6 * EDSCALE)); - theme->set_constant("table_h_separation", "EditorHelp", 16 * EDSCALE); - theme->set_constant("table_v_separation", "EditorHelp", 6 * EDSCALE); - theme->set_constant("text_highlight_h_padding", "EditorHelp", 1 * EDSCALE); - theme->set_constant("text_highlight_v_padding", "EditorHelp", 2 * EDSCALE); - - // Panel - theme->set_stylebox("panel", "Panel", make_flat_stylebox(dark_color_1, 6, 4, 6, 4, corner_width)); - theme->set_stylebox("PanelForeground", EditorStringName(EditorStyles), style_default); - - // Label - theme->set_stylebox("normal", "Label", style_empty); - theme->set_color("font_color", "Label", font_color); - theme->set_color("font_shadow_color", "Label", Color(0, 0, 0, 0)); - theme->set_color("font_outline_color", "Label", font_outline_color); - theme->set_constant("shadow_offset_x", "Label", 1 * EDSCALE); - theme->set_constant("shadow_offset_y", "Label", 1 * EDSCALE); - theme->set_constant("shadow_outline_size", "Label", 1 * EDSCALE); - theme->set_constant("line_spacing", "Label", 3 * EDSCALE); - theme->set_constant("outline_size", "Label", 0); - - // LinkButton - theme->set_stylebox("focus", "LinkButton", style_empty); - theme->set_color("font_color", "LinkButton", font_color); - theme->set_color("font_hover_color", "LinkButton", font_hover_color); - theme->set_color("font_hover_pressed_color", "LinkButton", font_hover_pressed_color); - theme->set_color("font_focus_color", "LinkButton", font_focus_color); - theme->set_color("font_pressed_color", "LinkButton", accent_color); - theme->set_color("font_disabled_color", "LinkButton", font_disabled_color); - theme->set_color("font_outline_color", "LinkButton", font_outline_color); - - theme->set_constant("outline_size", "LinkButton", 0); - - theme->set_type_variation("HeaderSmallLink", "LinkButton"); - theme->set_font("font", "HeaderSmallLink", theme->get_font(SNAME("font"), SNAME("HeaderSmall"))); - theme->set_font_size("font_size", "HeaderSmallLink", theme->get_font_size(SNAME("font_size"), SNAME("HeaderSmall"))); - - // TooltipPanel + TooltipLabel - // TooltipPanel is also used for custom tooltips, while TooltipLabel - // is only relevant for default tooltips. - Ref style_tooltip = style_popup->duplicate(); - style_tooltip->set_shadow_size(0); - style_tooltip->set_content_margin_all(default_margin_size * EDSCALE * 0.5); - style_tooltip->set_bg_color(dark_color_3 * Color(0.8, 0.8, 0.8, 0.9)); - style_tooltip->set_border_width_all(0); - theme->set_color("font_color", "TooltipLabel", font_hover_color); - theme->set_color("font_shadow_color", "TooltipLabel", Color(0, 0, 0, 0)); - theme->set_stylebox("panel", "TooltipPanel", style_tooltip); - - // PopupPanel - theme->set_stylebox("panel", "PopupPanel", style_popup); - - Ref control_editor_popup_style = style_popup->duplicate(); - control_editor_popup_style->set_shadow_size(0); - control_editor_popup_style->set_content_margin(SIDE_LEFT, default_margin_size * EDSCALE); - control_editor_popup_style->set_content_margin(SIDE_TOP, default_margin_size * EDSCALE); - control_editor_popup_style->set_content_margin(SIDE_RIGHT, default_margin_size * EDSCALE); - control_editor_popup_style->set_content_margin(SIDE_BOTTOM, default_margin_size * EDSCALE); - control_editor_popup_style->set_border_width_all(0); - - theme->set_stylebox("panel", "ControlEditorPopupPanel", control_editor_popup_style); - theme->set_type_variation("ControlEditorPopupPanel", "PopupPanel"); - - // SpinBox - theme->set_icon("updown", "SpinBox", theme->get_icon(SNAME("GuiSpinboxUpdown"), EditorStringName(EditorIcons))); - theme->set_icon("updown_disabled", "SpinBox", theme->get_icon(SNAME("GuiSpinboxUpdownDisabled"), EditorStringName(EditorIcons))); - - // ProgressBar - theme->set_stylebox("background", "ProgressBar", make_stylebox(theme->get_icon(SNAME("GuiProgressBar"), EditorStringName(EditorIcons)), 4, 4, 4, 4, 0, 0, 0, 0)); - theme->set_stylebox("fill", "ProgressBar", make_stylebox(theme->get_icon(SNAME("GuiProgressFill"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 2, 1, 2, 1)); - theme->set_color("font_color", "ProgressBar", font_color); - theme->set_color("font_outline_color", "ProgressBar", font_outline_color); - theme->set_constant("outline_size", "ProgressBar", 0); - - // GraphEdit - theme->set_stylebox("panel", "GraphEdit", style_tree_bg); - Ref graph_toolbar_style = make_flat_stylebox(dark_color_1 * Color(1, 1, 1, 0.6), 4, 2, 4, 2, 3); - theme->set_stylebox("menu_panel", "GraphEdit", graph_toolbar_style); - - if (dark_theme) { - theme->set_color("grid_major", "GraphEdit", Color(1.0, 1.0, 1.0, 0.1)); - theme->set_color("grid_minor", "GraphEdit", Color(1.0, 1.0, 1.0, 0.05)); - } else { - theme->set_color("grid_major", "GraphEdit", Color(0.0, 0.0, 0.0, 0.15)); - theme->set_color("grid_minor", "GraphEdit", Color(0.0, 0.0, 0.0, 0.07)); - } - theme->set_color("selection_fill", "GraphEdit", theme->get_color(SNAME("box_selection_fill_color"), EditorStringName(Editor))); - theme->set_color("selection_stroke", "GraphEdit", theme->get_color(SNAME("box_selection_stroke_color"), EditorStringName(Editor))); - theme->set_color("activity", "GraphEdit", accent_color); - - theme->set_icon("zoom_out", "GraphEdit", theme->get_icon(SNAME("ZoomLess"), EditorStringName(EditorIcons))); - theme->set_icon("zoom_in", "GraphEdit", theme->get_icon(SNAME("ZoomMore"), EditorStringName(EditorIcons))); - theme->set_icon("zoom_reset", "GraphEdit", theme->get_icon(SNAME("ZoomReset"), EditorStringName(EditorIcons))); - theme->set_icon("grid_toggle", "GraphEdit", theme->get_icon(SNAME("GridToggle"), EditorStringName(EditorIcons))); - theme->set_icon("minimap_toggle", "GraphEdit", theme->get_icon(SNAME("GridMinimap"), EditorStringName(EditorIcons))); - theme->set_icon("snapping_toggle", "GraphEdit", theme->get_icon(SNAME("SnapGrid"), EditorStringName(EditorIcons))); - theme->set_icon("layout", "GraphEdit", theme->get_icon(SNAME("GridLayout"), EditorStringName(EditorIcons))); - - // GraphEditMinimap - Ref style_minimap_bg = make_flat_stylebox(dark_color_1, 0, 0, 0, 0); - style_minimap_bg->set_border_color(dark_color_3); - style_minimap_bg->set_border_width_all(1); - theme->set_stylebox("panel", "GraphEditMinimap", style_minimap_bg); - - Ref style_minimap_camera; - Ref style_minimap_node; - if (dark_theme) { - style_minimap_camera = make_flat_stylebox(Color(0.65, 0.65, 0.65, 0.2), 0, 0, 0, 0); - style_minimap_camera->set_border_color(Color(0.65, 0.65, 0.65, 0.45)); - style_minimap_node = make_flat_stylebox(Color(1, 1, 1), 0, 0, 0, 0); - } else { - style_minimap_camera = make_flat_stylebox(Color(0.38, 0.38, 0.38, 0.2), 0, 0, 0, 0); - style_minimap_camera->set_border_color(Color(0.38, 0.38, 0.38, 0.45)); - style_minimap_node = make_flat_stylebox(Color(0, 0, 0), 0, 0, 0, 0); - } - style_minimap_camera->set_border_width_all(1); - style_minimap_node->set_anti_aliased(false); - theme->set_stylebox("camera", "GraphEditMinimap", style_minimap_camera); - theme->set_stylebox("node", "GraphEditMinimap", style_minimap_node); - - Color minimap_resizer_color; - if (dark_theme) { - minimap_resizer_color = Color(1, 1, 1, 0.65); - } else { - minimap_resizer_color = Color(0, 0, 0, 0.65); - } - theme->set_icon("resizer", "GraphEditMinimap", theme->get_icon(SNAME("GuiResizerTopLeft"), EditorStringName(EditorIcons))); - theme->set_color("resizer_color", "GraphEditMinimap", minimap_resizer_color); - - // GraphNode - - const int gn_margin_top = 2; - const int gn_margin_side = 2; - const int gn_margin_bottom = 2; - - Color graphnode_bg = dark_color_3; - if (!dark_theme) { - graphnode_bg = prop_section_color; - } - const Color graph_node_selected_border_color = graphnode_bg.lerp(accent_color, 0.275); - - const Color graphnode_frame_bg = graphnode_bg.lerp(style_tree_bg->get_bg_color(), 0.3); - - Ref graphn_sb_panel = make_flat_stylebox(graphnode_frame_bg, gn_margin_side, gn_margin_top, gn_margin_side, gn_margin_bottom, corner_width); - graphn_sb_panel->set_border_width_all(border_width); - graphn_sb_panel->set_border_color(graphnode_bg); - graphn_sb_panel->set_corner_radius_individual(0, 0, corner_radius * EDSCALE, corner_radius * EDSCALE); - graphn_sb_panel->set_expand_margin(SIDE_TOP, 17 * EDSCALE); - - Ref graphn_sb_panel_selected = make_flat_stylebox(graphnode_frame_bg, gn_margin_side, gn_margin_top, gn_margin_side, gn_margin_bottom, corner_width); - graphn_sb_panel_selected->set_border_width_all(2 * EDSCALE + border_width); - graphn_sb_panel_selected->set_border_color(graph_node_selected_border_color); - graphn_sb_panel_selected->set_corner_radius_individual(0, 0, corner_radius * EDSCALE, corner_radius * EDSCALE); - graphn_sb_panel_selected->set_expand_margin(SIDE_TOP, 17 * EDSCALE); - - const int gn_titlebar_margin_left = 12; - const int gn_titlebar_margin_right = 4; // The rest is for the close button. - Ref graphn_sb_titlebar = make_flat_stylebox(graphnode_bg, gn_titlebar_margin_left, gn_margin_top, gn_titlebar_margin_right, 0, corner_width); - graphn_sb_titlebar->set_expand_margin(SIDE_TOP, 2 * EDSCALE); - graphn_sb_titlebar->set_corner_radius_individual(corner_radius * EDSCALE, corner_radius * EDSCALE, 0, 0); - - Ref graphn_sb_titlebar_selected = make_flat_stylebox(graph_node_selected_border_color, gn_titlebar_margin_left, gn_margin_top, gn_titlebar_margin_right, 0, corner_width); - graphn_sb_titlebar_selected->set_corner_radius_individual(corner_radius * EDSCALE, corner_radius * EDSCALE, 0, 0); - graphn_sb_titlebar_selected->set_expand_margin(SIDE_TOP, 2 * EDSCALE); - Ref graphn_sb_slot = make_empty_stylebox(12, 0, 12, 0); - - theme->set_stylebox("panel", "GraphElement", graphn_sb_panel); - theme->set_stylebox("panel_selected", "GraphElement", graphn_sb_panel_selected); - theme->set_stylebox("titlebar", "GraphElement", graphn_sb_titlebar); - theme->set_stylebox("titlebar_selected", "GraphElement", graphn_sb_titlebar_selected); - - // GraphNode's title Label. - theme->set_type_variation("GraphNodeTitleLabel", "Label"); - - theme->set_stylebox("normal", "GraphNodeTitleLabel", make_empty_stylebox(0, 0, 0, 0)); - theme->set_color("font_color", "GraphNodeTitleLabel", font_color); - theme->set_constant("line_spacing", "GraphNodeTitleLabel", 3 * EDSCALE); - - Color graphnode_decoration_color = dark_color_1.inverted(); - - theme->set_color("resizer_color", "GraphElement", graphnode_decoration_color); - theme->set_icon("resizer", "GraphElement", theme->get_icon(SNAME("GuiResizer"), EditorStringName(EditorIcons))); - - // GraphNode. - theme->set_stylebox("panel", "GraphNode", graphn_sb_panel); - theme->set_stylebox("panel_selected", "GraphNode", graphn_sb_panel_selected); - theme->set_stylebox("titlebar", "GraphNode", graphn_sb_titlebar); - theme->set_stylebox("titlebar_selected", "GraphNode", graphn_sb_titlebar_selected); - theme->set_stylebox("slot", "GraphNode", graphn_sb_slot); - - theme->set_color("resizer_color", "GraphNode", graphnode_decoration_color); - - theme->set_constant("port_h_offset", "GraphNode", 0); - theme->set_constant("separation", "GraphNode", 1 * EDSCALE); - - Ref port_icon = theme->get_icon(SNAME("GuiGraphNodePort"), EditorStringName(EditorIcons)); - // The true size is 24x24 This is necessary for sharp port icons at high zoom levels in GraphEdit (up to ~200%). - port_icon->set_size_override(Size2(12, 12)); - theme->set_icon("port", "GraphNode", port_icon); - - // StateMachine graph - theme->set_stylebox("panel", "GraphStateMachine", style_tree_bg); - theme->set_stylebox("error_panel", "GraphStateMachine", style_tree_bg); - theme->set_color("error_color", "GraphStateMachine", error_color); - - const int sm_margin_side = 10 * EDSCALE; - - Ref sm_node_style = make_flat_stylebox(dark_color_3 * Color(1, 1, 1, 0.7), sm_margin_side, 24 * EDSCALE, sm_margin_side, gn_margin_bottom, corner_width); - sm_node_style->set_border_width_all(border_width); - sm_node_style->set_border_color(graphnode_bg); - - Ref sm_node_selected_style = make_flat_stylebox(graphnode_bg * Color(1, 1, 1, 0.9), sm_margin_side, 24 * EDSCALE, sm_margin_side, gn_margin_bottom, corner_width); - sm_node_selected_style->set_border_width_all(2 * EDSCALE + border_width); - sm_node_selected_style->set_border_color(accent_color * Color(1, 1, 1, 0.9)); - sm_node_selected_style->set_shadow_size(8 * EDSCALE); - sm_node_selected_style->set_shadow_color(shadow_color); - - Ref sm_node_playing_style = sm_node_selected_style->duplicate(); - sm_node_playing_style->set_border_color(warning_color); - sm_node_playing_style->set_shadow_color(warning_color * Color(1, 1, 1, 0.2)); - - theme->set_stylebox("node_frame", "GraphStateMachine", sm_node_style); - theme->set_stylebox("node_frame_selected", "GraphStateMachine", sm_node_selected_style); - theme->set_stylebox("node_frame_playing", "GraphStateMachine", sm_node_playing_style); - - Ref sm_node_start_style = sm_node_style->duplicate(); - sm_node_start_style->set_border_width_all(1 * EDSCALE); - sm_node_start_style->set_border_color(success_color.lightened(0.24)); - theme->set_stylebox("node_frame_start", "GraphStateMachine", sm_node_start_style); - - Ref sm_node_end_style = sm_node_style->duplicate(); - sm_node_end_style->set_border_width_all(1 * EDSCALE); - sm_node_end_style->set_border_color(error_color); - theme->set_stylebox("node_frame_end", "GraphStateMachine", sm_node_end_style); - - theme->set_font("node_title_font", "GraphStateMachine", theme->get_font(SNAME("font"), SNAME("Label"))); - theme->set_font_size("node_title_font_size", "GraphStateMachine", theme->get_font_size(SNAME("font_size"), SNAME("Label"))); - theme->set_color("node_title_font_color", "GraphStateMachine", font_color); - - theme->set_color("transition_color", "GraphStateMachine", font_color); - theme->set_color("transition_disabled_color", "GraphStateMachine", font_color * Color(1, 1, 1, 0.2)); - theme->set_color("transition_icon_color", "GraphStateMachine", Color(1, 1, 1)); - theme->set_color("transition_icon_disabled_color", "GraphStateMachine", Color(1, 1, 1, 0.2)); - theme->set_color("highlight_color", "GraphStateMachine", accent_color); - theme->set_color("highlight_disabled_color", "GraphStateMachine", accent_color * Color(1, 1, 1, 0.6)); - theme->set_color("guideline_color", "GraphStateMachine", font_color * Color(1, 1, 1, 0.3)); - - theme->set_color("playback_color", "GraphStateMachine", font_color); - theme->set_color("playback_background_color", "GraphStateMachine", font_color * Color(1, 1, 1, 0.3)); - - // GridContainer - theme->set_constant("v_separation", "GridContainer", Math::round(widget_default_margin.y - 2 * EDSCALE)); - - // FileDialog - theme->set_icon("folder", "FileDialog", theme->get_icon(SNAME("Folder"), EditorStringName(EditorIcons))); - theme->set_icon("parent_folder", "FileDialog", theme->get_icon(SNAME("ArrowUp"), EditorStringName(EditorIcons))); - theme->set_icon("back_folder", "FileDialog", theme->get_icon(SNAME("Back"), EditorStringName(EditorIcons))); - theme->set_icon("forward_folder", "FileDialog", theme->get_icon(SNAME("Forward"), EditorStringName(EditorIcons))); - theme->set_icon("reload", "FileDialog", theme->get_icon(SNAME("Reload"), EditorStringName(EditorIcons))); - theme->set_icon("toggle_hidden", "FileDialog", theme->get_icon(SNAME("GuiVisibilityVisible"), EditorStringName(EditorIcons))); - // Use a different color for folder icons to make them easier to distinguish from files. - // On a light theme, the icon will be dark, so we need to lighten it before blending it with the accent color. - theme->set_color("folder_icon_color", "FileDialog", (dark_theme ? Color(1, 1, 1) : Color(4.25, 4.25, 4.25)).lerp(accent_color, 0.7)); - theme->set_color("files_disabled", "FileDialog", font_disabled_color); - - // ColorPicker - theme->set_constant("margin", "ColorPicker", default_margin_size); - theme->set_constant("sv_width", "ColorPicker", 256 * EDSCALE); - theme->set_constant("sv_height", "ColorPicker", 256 * EDSCALE); - theme->set_constant("h_width", "ColorPicker", 30 * EDSCALE); - theme->set_constant("label_width", "ColorPicker", 10 * EDSCALE); - theme->set_constant("center_slider_grabbers", "ColorPicker", 1); - theme->set_icon("screen_picker", "ColorPicker", theme->get_icon(SNAME("ColorPick"), EditorStringName(EditorIcons))); - theme->set_icon("shape_circle", "ColorPicker", theme->get_icon(SNAME("PickerShapeCircle"), EditorStringName(EditorIcons))); - theme->set_icon("shape_rect", "ColorPicker", theme->get_icon(SNAME("PickerShapeRectangle"), EditorStringName(EditorIcons))); - theme->set_icon("shape_rect_wheel", "ColorPicker", theme->get_icon(SNAME("PickerShapeRectangleWheel"), EditorStringName(EditorIcons))); - theme->set_icon("add_preset", "ColorPicker", theme->get_icon(SNAME("Add"), EditorStringName(EditorIcons))); - theme->set_icon("sample_bg", "ColorPicker", theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons))); - theme->set_icon("sample_revert", "ColorPicker", theme->get_icon(SNAME("Reload"), EditorStringName(EditorIcons))); - theme->set_icon("overbright_indicator", "ColorPicker", theme->get_icon(SNAME("OverbrightIndicator"), EditorStringName(EditorIcons))); - theme->set_icon("bar_arrow", "ColorPicker", theme->get_icon(SNAME("ColorPickerBarArrow"), EditorStringName(EditorIcons))); - theme->set_icon("picker_cursor", "ColorPicker", theme->get_icon(SNAME("PickerCursor"), EditorStringName(EditorIcons))); - - // ColorPickerButton - theme->set_icon("bg", "ColorPickerButton", theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons))); - - // ColorPresetButton - Ref preset_sb = make_flat_stylebox(Color(1, 1, 1), 2, 2, 2, 2, 2); - theme->set_stylebox("preset_fg", "ColorPresetButton", preset_sb); - theme->set_icon("preset_bg", "ColorPresetButton", theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons))); - theme->set_icon("overbright_indicator", "ColorPresetButton", theme->get_icon(SNAME("OverbrightIndicator"), EditorStringName(EditorIcons))); - - // Information on 3D viewport - Ref style_info_3d_viewport = style_default->duplicate(); - style_info_3d_viewport->set_bg_color(style_info_3d_viewport->get_bg_color() * Color(1, 1, 1, 0.5)); - style_info_3d_viewport->set_border_width_all(0); - theme->set_stylebox("Information3dViewport", EditorStringName(EditorStyles), style_info_3d_viewport); - - // Asset Library. - theme->set_stylebox("bg", "AssetLib", style_empty); - theme->set_stylebox("panel", "AssetLib", style_content_panel); - theme->set_color("status_color", "AssetLib", Color(0.5, 0.5, 0.5)); - theme->set_icon("dismiss", "AssetLib", theme->get_icon(SNAME("Close"), EditorStringName(EditorIcons))); - - // Theme editor. - theme->set_color("preview_picker_overlay_color", "ThemeEditor", Color(0.1, 0.1, 0.1, 0.25)); - Color theme_preview_picker_bg_color = accent_color; - theme_preview_picker_bg_color.a = 0.2; - Ref theme_preview_picker_sb = make_flat_stylebox(theme_preview_picker_bg_color, 0, 0, 0, 0); - theme_preview_picker_sb->set_border_color(accent_color); - theme_preview_picker_sb->set_border_width_all(1.0 * EDSCALE); - theme->set_stylebox("preview_picker_overlay", "ThemeEditor", theme_preview_picker_sb); - Color theme_preview_picker_label_bg_color = accent_color; - theme_preview_picker_label_bg_color.set_v(0.5); - Ref theme_preview_picker_label_sb = make_flat_stylebox(theme_preview_picker_label_bg_color, 4.0, 1.0, 4.0, 3.0); - theme->set_stylebox("preview_picker_label", "ThemeEditor", theme_preview_picker_label_sb); - - // Dictionary editor add item. - // Expand to the left and right by 4px to compensate for the dictionary editor margins. - Ref style_dictionary_add_item = make_flat_stylebox(prop_subsection_color, 0, 4, 0, 4, corner_radius); - style_dictionary_add_item->set_expand_margin(SIDE_LEFT, 4 * EDSCALE); - style_dictionary_add_item->set_expand_margin(SIDE_RIGHT, 4 * EDSCALE); - theme->set_stylebox("DictionaryAddItem", EditorStringName(EditorStyles), style_dictionary_add_item); - - Ref vshader_label_style = make_empty_stylebox(2, 1, 2, 1); - theme->set_stylebox("label_style", "VShaderEditor", vshader_label_style); - - // Project manager. - theme->set_stylebox("search_panel", "ProjectManager", style_tree_bg); - theme->set_constant("sidebar_button_icon_separation", "ProjectManager", int(6 * EDSCALE)); - - // adaptive script theme constants - // for comments and elements with lower relevance - const Color dim_color = Color(font_color, 0.5); - - const float mono_value = mono_color.r; - const Color alpha1 = Color(mono_value, mono_value, mono_value, 0.07); - const Color alpha2 = Color(mono_value, mono_value, mono_value, 0.14); - const Color alpha3 = Color(mono_value, mono_value, mono_value, 0.27); - - const Color symbol_color = dark_theme ? Color(0.67, 0.79, 1) : Color(0, 0, 0.61); - const Color keyword_color = dark_theme ? Color(1.0, 0.44, 0.52) : Color(0.9, 0.135, 0.51); - const Color control_flow_keyword_color = dark_theme ? Color(1.0, 0.55, 0.8) : Color(0.743, 0.12, 0.8); - const Color base_type_color = dark_theme ? Color(0.26, 1.0, 0.76) : Color(0, 0.6, 0.2); - const Color engine_type_color = dark_theme ? Color(0.56, 1, 0.86) : Color(0.11, 0.55, 0.4); - const Color user_type_color = dark_theme ? Color(0.78, 1, 0.93) : Color(0.18, 0.45, 0.4); - const Color comment_color = dark_theme ? dim_color : Color(0.08, 0.08, 0.08, 0.5); - const Color doc_comment_color = dark_theme ? Color(0.6, 0.7, 0.8, 0.8) : Color(0.15, 0.15, 0.4, 0.7); - const Color string_color = dark_theme ? Color(1, 0.93, 0.63) : Color(0.6, 0.42, 0); - - // Use the brightest background color on a light theme (which generally uses a negative contrast rate). - const Color te_background_color = dark_theme ? background_color : dark_color_3; - const Color completion_background_color = dark_theme ? base_color : background_color; - const Color completion_selected_color = alpha1; - const Color completion_existing_color = alpha2; - // Same opacity as the scroll grabber editor icon. - const Color completion_scroll_color = Color(mono_value, mono_value, mono_value, 0.29); - const Color completion_scroll_hovered_color = Color(mono_value, mono_value, mono_value, 0.4); - const Color completion_font_color = font_color; - const Color text_color = font_color; - const Color line_number_color = dim_color; - const Color safe_line_number_color = dark_theme ? (dim_color * Color(1, 1.2, 1, 1.5)) : Color(0, 0.4, 0, 0.75); - const Color caret_color = mono_color; - const Color caret_background_color = mono_color.inverted(); - const Color text_selected_color = Color(0, 0, 0, 0); - const Color brace_mismatch_color = dark_theme ? error_color : Color(1, 0.08, 0, 1); - const Color current_line_color = alpha1; - const Color line_length_guideline_color = dark_theme ? base_color : background_color; - const Color word_highlighted_color = alpha1; - const Color number_color = dark_theme ? Color(0.63, 1, 0.88) : Color(0, 0.55, 0.28, 1); - const Color function_color = dark_theme ? Color(0.34, 0.7, 1.0) : Color(0, 0.225, 0.9, 1); - const Color member_variable_color = dark_theme ? Color(0.34, 0.7, 1.0).lerp(mono_color, 0.6) : Color(0, 0.4, 0.68, 1); - const Color mark_color = Color(error_color.r, error_color.g, error_color.b, 0.3); - const Color bookmark_color = Color(0.08, 0.49, 0.98); - const Color breakpoint_color = dark_theme ? error_color : Color(1, 0.27, 0.2, 1); - const Color executing_line_color = Color(0.98, 0.89, 0.27); - const Color code_folding_color = alpha3; - const Color folded_code_region_color = Color(0.68, 0.46, 0.77, 0.2); - const Color search_result_color = alpha1; - const Color search_result_border_color = dark_theme ? Color(0.41, 0.61, 0.91, 0.38) : Color(0, 0.4, 1, 0.38); - - EditorSettings *setting = EditorSettings::get_singleton(); - String text_editor_color_theme = setting->get("text_editor/theme/color_theme"); - if (text_editor_color_theme == "Default") { - setting->set_initial_value("text_editor/theme/highlighting/symbol_color", symbol_color, true); - setting->set_initial_value("text_editor/theme/highlighting/keyword_color", keyword_color, true); - setting->set_initial_value("text_editor/theme/highlighting/control_flow_keyword_color", control_flow_keyword_color, true); - setting->set_initial_value("text_editor/theme/highlighting/base_type_color", base_type_color, true); - setting->set_initial_value("text_editor/theme/highlighting/engine_type_color", engine_type_color, true); - setting->set_initial_value("text_editor/theme/highlighting/user_type_color", user_type_color, true); - setting->set_initial_value("text_editor/theme/highlighting/comment_color", comment_color, true); - setting->set_initial_value("text_editor/theme/highlighting/doc_comment_color", doc_comment_color, true); - setting->set_initial_value("text_editor/theme/highlighting/string_color", string_color, true); - setting->set_initial_value("text_editor/theme/highlighting/background_color", te_background_color, true); - setting->set_initial_value("text_editor/theme/highlighting/completion_background_color", completion_background_color, true); - setting->set_initial_value("text_editor/theme/highlighting/completion_selected_color", completion_selected_color, true); - setting->set_initial_value("text_editor/theme/highlighting/completion_existing_color", completion_existing_color, true); - setting->set_initial_value("text_editor/theme/highlighting/completion_scroll_color", completion_scroll_color, true); - setting->set_initial_value("text_editor/theme/highlighting/completion_scroll_hovered_color", completion_scroll_hovered_color, true); - setting->set_initial_value("text_editor/theme/highlighting/completion_font_color", completion_font_color, true); - setting->set_initial_value("text_editor/theme/highlighting/text_color", text_color, true); - setting->set_initial_value("text_editor/theme/highlighting/line_number_color", line_number_color, true); - setting->set_initial_value("text_editor/theme/highlighting/safe_line_number_color", safe_line_number_color, true); - setting->set_initial_value("text_editor/theme/highlighting/caret_color", caret_color, true); - setting->set_initial_value("text_editor/theme/highlighting/caret_background_color", caret_background_color, true); - setting->set_initial_value("text_editor/theme/highlighting/text_selected_color", text_selected_color, true); - setting->set_initial_value("text_editor/theme/highlighting/selection_color", selection_color, true); - setting->set_initial_value("text_editor/theme/highlighting/brace_mismatch_color", brace_mismatch_color, true); - setting->set_initial_value("text_editor/theme/highlighting/current_line_color", current_line_color, true); - setting->set_initial_value("text_editor/theme/highlighting/line_length_guideline_color", line_length_guideline_color, true); - setting->set_initial_value("text_editor/theme/highlighting/word_highlighted_color", word_highlighted_color, true); - setting->set_initial_value("text_editor/theme/highlighting/number_color", number_color, true); - setting->set_initial_value("text_editor/theme/highlighting/function_color", function_color, true); - setting->set_initial_value("text_editor/theme/highlighting/member_variable_color", member_variable_color, true); - setting->set_initial_value("text_editor/theme/highlighting/mark_color", mark_color, true); - setting->set_initial_value("text_editor/theme/highlighting/bookmark_color", bookmark_color, true); - setting->set_initial_value("text_editor/theme/highlighting/breakpoint_color", breakpoint_color, true); - setting->set_initial_value("text_editor/theme/highlighting/executing_line_color", executing_line_color, true); - setting->set_initial_value("text_editor/theme/highlighting/code_folding_color", code_folding_color, true); - setting->set_initial_value("text_editor/theme/highlighting/folded_code_region_color", folded_code_region_color, true); - setting->set_initial_value("text_editor/theme/highlighting/search_result_color", search_result_color, true); - setting->set_initial_value("text_editor/theme/highlighting/search_result_border_color", search_result_border_color, true); - } else if (text_editor_color_theme == "Godot 2") { - setting->load_text_editor_theme(); - } - - // Now theme is loaded, apply it to CodeEdit. - theme->set_font("font", "CodeEdit", theme->get_font(SNAME("source"), EditorStringName(EditorFonts))); - theme->set_font_size("font_size", "CodeEdit", theme->get_font_size(SNAME("source_size"), EditorStringName(EditorFonts))); - - Ref code_edit_stylebox = make_flat_stylebox(EDITOR_GET("text_editor/theme/highlighting/background_color"), widget_default_margin.x, widget_default_margin.y, widget_default_margin.x, widget_default_margin.y, corner_radius); - theme->set_stylebox("normal", "CodeEdit", code_edit_stylebox); - theme->set_stylebox("read_only", "CodeEdit", code_edit_stylebox); - theme->set_stylebox("focus", "CodeEdit", Ref(memnew(StyleBoxEmpty))); - - theme->set_icon("tab", "CodeEdit", theme->get_icon(SNAME("GuiTab"), EditorStringName(EditorIcons))); - theme->set_icon("space", "CodeEdit", theme->get_icon(SNAME("GuiSpace"), EditorStringName(EditorIcons))); - theme->set_icon("folded", "CodeEdit", theme->get_icon(SNAME("CodeFoldedRightArrow"), EditorStringName(EditorIcons))); - theme->set_icon("can_fold", "CodeEdit", theme->get_icon(SNAME("CodeFoldDownArrow"), EditorStringName(EditorIcons))); - theme->set_icon("folded_code_region", "CodeEdit", theme->get_icon(SNAME("CodeRegionFoldedRightArrow"), EditorStringName(EditorIcons))); - theme->set_icon("can_fold_code_region", "CodeEdit", theme->get_icon(SNAME("CodeRegionFoldDownArrow"), EditorStringName(EditorIcons))); - theme->set_icon("executing_line", "CodeEdit", theme->get_icon(SNAME("TextEditorPlay"), EditorStringName(EditorIcons))); - theme->set_icon("breakpoint", "CodeEdit", theme->get_icon(SNAME("Breakpoint"), EditorStringName(EditorIcons))); - - theme->set_constant("line_spacing", "CodeEdit", EDITOR_GET("text_editor/appearance/whitespace/line_spacing")); - - theme->set_color("background_color", "CodeEdit", Color(0, 0, 0, 0)); - theme->set_color("completion_background_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_background_color")); - theme->set_color("completion_selected_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_selected_color")); - theme->set_color("completion_existing_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_existing_color")); - theme->set_color("completion_scroll_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_scroll_color")); - theme->set_color("completion_scroll_hovered_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_scroll_hovered_color")); - theme->set_color("font_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/text_color")); - theme->set_color("line_number_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/line_number_color")); - theme->set_color("caret_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/caret_color")); - theme->set_color("font_selected_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/text_selected_color")); - theme->set_color("selection_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/selection_color")); - theme->set_color("brace_mismatch_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/brace_mismatch_color")); - theme->set_color("current_line_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/current_line_color")); - theme->set_color("line_length_guideline_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/line_length_guideline_color")); - theme->set_color("word_highlighted_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/word_highlighted_color")); - theme->set_color("bookmark_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/bookmark_color")); - theme->set_color("breakpoint_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/breakpoint_color")); - theme->set_color("executing_line_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/executing_line_color")); - theme->set_color("code_folding_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/code_folding_color")); - theme->set_color("folded_code_region_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/folded_code_region_color")); - theme->set_color("search_result_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/search_result_color")); - theme->set_color("search_result_border_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/search_result_border_color")); -} - -Ref EditorThemeManager::_create_base_theme(const Ref &p_old_theme) { - OS::get_singleton()->benchmark_begin_measure("EditorTheme", "Create Base Theme"); - - Ref theme = memnew(EditorTheme); - populate_editor_theme(theme, p_old_theme); + _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"); return theme; } +EditorThemeManager::ThemeConfiguration EditorThemeManager::_create_theme_config(const Ref &p_theme) { + ThemeConfiguration config; + + // Basic properties. + + config.preset = EDITOR_GET("interface/theme/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"); + config.contrast = EDITOR_GET("interface/theme/contrast"); + config.icon_saturation = EDITOR_GET("interface/theme/icon_saturation"); + + // Extra properties. + + config.extra_spacing = EDITOR_GET("interface/theme/additional_spacing"); + // Ensure borders are visible when using an editor scale below 100%. + config.border_width = CLAMP((int)EDITOR_GET("interface/theme/border_size"), 0, 2) * MAX(1, EDSCALE); + config.corner_radius = CLAMP((int)EDITOR_GET("interface/theme/corner_radius"), 0, 6); + + config.draw_extra_borders = EDITOR_GET("interface/theme/draw_extra_borders"); + config.relationship_line_opacity = EDITOR_GET("interface/theme/relationship_line_opacity"); + config.thumb_size = EDITOR_GET("filesystem/file_dialog/thumbnail_size"); + config.class_icon_size = 16 * EDSCALE; + 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.default_contrast = 0.3; // Make sure to keep this in sync with the editor settings definition. + + // Generated properties. + + config.base_margin = 4; + config.increased_margin = config.base_margin + config.extra_spacing; + config.popup_margin = config.base_margin * 3 * EDSCALE; + config.window_border_margin = config.base_margin * 2; + config.top_bar_separation = config.base_margin * 2 * EDSCALE; + // Force the v_separation to be even so that the spacing on top and bottom is even. + // If the vsep is odd and cannot be split into 2 even groups (of pixels), then it will be lopsided. + // We add 2 to the vsep to give it some extra spacing which looks a bit more modern (see Windows, for example). + const int separation_base = config.increased_margin + 6; + config.forced_even_separation = separation_base + (separation_base % 2); + + if (config.preset != "Custom") { + Color preset_accent_color; + Color preset_base_color; + float preset_contrast = 0; + bool preset_draw_extra_borders = false; + + // Please use alphabetical order if you're adding a new theme here. + if (config.preset == "Breeze Dark") { + preset_accent_color = Color(0.26, 0.76, 1.00); + preset_base_color = Color(0.24, 0.26, 0.28); + preset_contrast = config.default_contrast; + } else if (config.preset == "Godot 2") { + preset_accent_color = Color(0.53, 0.67, 0.89); + preset_base_color = Color(0.24, 0.23, 0.27); + preset_contrast = config.default_contrast; + } else if (config.preset == "Gray") { + preset_accent_color = Color(0.44, 0.73, 0.98); + preset_base_color = Color(0.24, 0.24, 0.24); + preset_contrast = config.default_contrast; + } else if (config.preset == "Light") { + preset_accent_color = Color(0.18, 0.50, 1.00); + preset_base_color = Color(0.9, 0.9, 0.9); + // A negative contrast rate looks better for light themes, since it better follows the natural order of UI "elevation". + preset_contrast = -0.06; + } else if (config.preset == "Solarized (Dark)") { + preset_accent_color = Color(0.15, 0.55, 0.82); + preset_base_color = Color(0.04, 0.23, 0.27); + preset_contrast = config.default_contrast; + } else if (config.preset == "Solarized (Light)") { + preset_accent_color = Color(0.15, 0.55, 0.82); + preset_base_color = Color(0.89, 0.86, 0.79); + // A negative contrast rate looks better for light themes, since it better follows the natural order of UI "elevation". + preset_contrast = -0.06; + } else if (config.preset == "Black (OLED)") { + preset_accent_color = Color(0.45, 0.75, 1.0); + preset_base_color = Color(0, 0, 0); + // The contrast rate value is irrelevant on a fully black theme. + preset_contrast = 0.0; + preset_draw_extra_borders = true; + } else { // Default + preset_accent_color = Color(0.44, 0.73, 0.98); + preset_base_color = Color(0.21, 0.24, 0.29); + preset_contrast = config.default_contrast; + } + + config.accent_color = preset_accent_color; + config.base_color = preset_base_color; + config.contrast = preset_contrast; + config.draw_extra_borders = preset_draw_extra_borders; + + EditorSettings::get_singleton()->set_initial_value("interface/theme/accent_color", config.accent_color); + EditorSettings::get_singleton()->set_initial_value("interface/theme/base_color", config.base_color); + EditorSettings::get_singleton()->set_initial_value("interface/theme/contrast", config.contrast); + EditorSettings::get_singleton()->set_initial_value("interface/theme/draw_extra_borders", config.draw_extra_borders); + } + + // Enforce values in case they were adjusted or overridden. + EditorSettings::get_singleton()->set_manually("interface/theme/preset", config.preset); + EditorSettings::get_singleton()->set_manually("interface/theme/accent_color", config.accent_color); + EditorSettings::get_singleton()->set_manually("interface/theme/base_color", config.base_color); + EditorSettings::get_singleton()->set_manually("interface/theme/contrast", config.contrast); + EditorSettings::get_singleton()->set_manually("interface/theme/draw_extra_borders", config.draw_extra_borders); + + return config; +} + +void EditorThemeManager::_create_shared_styles(const Ref &p_theme, ThemeConfiguration &p_config) { + // Colors. + { + // Base colors. + + p_theme->set_color("base_color", EditorStringName(Editor), p_config.base_color); + p_theme->set_color("accent_color", EditorStringName(Editor), p_config.accent_color); + + // White (dark theme) or black (light theme), will be used to generate the rest of the colors + p_config.mono_color = p_config.dark_theme ? Color(1, 1, 1) : Color(0, 0, 0); + + // Ensure base colors are in the 0..1 luminance range to avoid 8-bit integer overflow or text rendering issues. + // Some places in the editor use 8-bit integer colors. + p_config.dark_color_1 = p_config.base_color.lerp(Color(0, 0, 0, 1), p_config.contrast).clamp(); + p_config.dark_color_2 = p_config.base_color.lerp(Color(0, 0, 0, 1), p_config.contrast * 1.5).clamp(); + p_config.dark_color_3 = p_config.base_color.lerp(Color(0, 0, 0, 1), p_config.contrast * 2).clamp(); + + p_config.contrast_color_1 = p_config.base_color.lerp(p_config.mono_color, MAX(p_config.contrast, p_config.default_contrast)); + p_config.contrast_color_2 = p_config.base_color.lerp(p_config.mono_color, MAX(p_config.contrast * 1.5, p_config.default_contrast * 1.5)); + + p_config.highlight_color = Color(p_config.accent_color.r, p_config.accent_color.g, p_config.accent_color.b, 0.275); + p_config.highlight_disabled_color = p_config.highlight_color.lerp(p_config.dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.5); + + p_config.success_color = Color(0.45, 0.95, 0.5); + p_config.warning_color = Color(1, 0.87, 0.4); + p_config.error_color = Color(1, 0.47, 0.42); + if (!p_config.dark_theme) { + // Darken some colors to be readable on a light background. + p_config.success_color = p_config.success_color.lerp(p_config.mono_color, 0.35); + p_config.warning_color = p_config.warning_color.lerp(p_config.mono_color, 0.35); + p_config.error_color = p_config.error_color.lerp(p_config.mono_color, 0.25); + } + + p_theme->set_color("mono_color", EditorStringName(Editor), p_config.mono_color); + p_theme->set_color("dark_color_1", EditorStringName(Editor), p_config.dark_color_1); + p_theme->set_color("dark_color_2", EditorStringName(Editor), p_config.dark_color_2); + p_theme->set_color("dark_color_3", EditorStringName(Editor), p_config.dark_color_3); + p_theme->set_color("contrast_color_1", EditorStringName(Editor), p_config.contrast_color_1); + p_theme->set_color("contrast_color_2", EditorStringName(Editor), p_config.contrast_color_2); + p_theme->set_color("highlight_color", EditorStringName(Editor), p_config.highlight_color); + p_theme->set_color("highlight_disabled_color", EditorStringName(Editor), p_config.highlight_disabled_color); + p_theme->set_color("success_color", EditorStringName(Editor), p_config.success_color); + p_theme->set_color("warning_color", EditorStringName(Editor), p_config.warning_color); + p_theme->set_color("error_color", EditorStringName(Editor), p_config.error_color); + + // Only used when the Draw Extra Borders editor setting is enabled. + p_config.extra_border_color_1 = Color(0.5, 0.5, 0.5); + p_config.extra_border_color_2 = p_config.dark_theme ? Color(0.3, 0.3, 0.3) : Color(0.7, 0.7, 0.7); + + p_theme->set_color("extra_border_color_1", EditorStringName(Editor), p_config.extra_border_color_1); + p_theme->set_color("extra_border_color_2", EditorStringName(Editor), p_config.extra_border_color_2); + + // Font colors. + + p_config.font_color = p_config.mono_color.lerp(p_config.base_color, 0.25); + p_config.font_focus_color = p_config.mono_color.lerp(p_config.base_color, 0.125); + p_config.font_hover_color = p_config.mono_color.lerp(p_config.base_color, 0.125); + p_config.font_pressed_color = p_config.accent_color; + p_config.font_hover_pressed_color = p_config.font_hover_color.lerp(p_config.accent_color, 0.74); + p_config.font_disabled_color = Color(p_config.mono_color.r, p_config.mono_color.g, p_config.mono_color.b, 0.35); + p_config.font_readonly_color = Color(p_config.mono_color.r, p_config.mono_color.g, p_config.mono_color.b, 0.65); + p_config.font_placeholder_color = Color(p_config.mono_color.r, p_config.mono_color.g, p_config.mono_color.b, 0.6); + p_config.font_outline_color = Color(0, 0, 0, 0); + + p_theme->set_color("font_color", EditorStringName(Editor), p_config.font_color); + p_theme->set_color("font_focus_color", EditorStringName(Editor), p_config.font_focus_color); + p_theme->set_color("font_hover_color", EditorStringName(Editor), p_config.font_hover_color); + p_theme->set_color("font_pressed_color", EditorStringName(Editor), p_config.font_pressed_color); + p_theme->set_color("font_hover_pressed_color", EditorStringName(Editor), p_config.font_hover_pressed_color); + p_theme->set_color("font_disabled_color", EditorStringName(Editor), p_config.font_disabled_color); + p_theme->set_color("font_readonly_color", EditorStringName(Editor), p_config.font_readonly_color); + p_theme->set_color("font_placeholder_color", EditorStringName(Editor), p_config.font_placeholder_color); + p_theme->set_color("font_outline_color", EditorStringName(Editor), p_config.font_outline_color); + + // Icon colors. + + p_config.icon_normal_color = Color(1, 1, 1); + p_config.icon_focus_color = p_config.icon_normal_color * (p_config.dark_theme ? 1.15 : 1.45); + p_config.icon_focus_color.a = 1.0; + p_config.icon_hover_color = p_config.icon_focus_color; + // Make the pressed icon 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. + p_config.icon_pressed_color = p_config.accent_color * (p_config.dark_theme ? 1.15 : 3.5); + p_config.icon_pressed_color.a = 1.0; + p_config.icon_disabled_color = Color(p_config.icon_normal_color, 0.4); + + p_theme->set_color("icon_normal_color", EditorStringName(Editor), p_config.icon_normal_color); + p_theme->set_color("icon_focus_color", EditorStringName(Editor), p_config.icon_focus_color); + p_theme->set_color("icon_hover_color", EditorStringName(Editor), p_config.icon_hover_color); + p_theme->set_color("icon_pressed_color", EditorStringName(Editor), p_config.icon_pressed_color); + p_theme->set_color("icon_disabled_color", EditorStringName(Editor), p_config.icon_disabled_color); + + // Additional GUI colors. + + p_config.shadow_color = Color(0, 0, 0, p_config.dark_theme ? 0.3 : 0.1); + p_config.selection_color = p_config.accent_color * Color(1, 1, 1, 0.4); + p_config.disabled_border_color = p_config.mono_color.inverted().lerp(p_config.base_color, 0.7); + p_config.disabled_bg_color = p_config.mono_color.inverted().lerp(p_config.base_color, 0.9); + p_config.separator_color = Color(p_config.mono_color.r, p_config.mono_color.g, p_config.mono_color.b, 0.1); + + p_theme->set_color("selection_color", EditorStringName(Editor), p_config.selection_color); + p_theme->set_color("disabled_border_color", EditorStringName(Editor), p_config.disabled_border_color); + p_theme->set_color("disabled_bg_color", EditorStringName(Editor), p_config.disabled_bg_color); + p_theme->set_color("separator_color", EditorStringName(Editor), p_config.separator_color); + + // Additional editor colors. + + p_theme->set_color("box_selection_fill_color", EditorStringName(Editor), p_config.accent_color * Color(1, 1, 1, 0.3)); + p_theme->set_color("box_selection_stroke_color", EditorStringName(Editor), p_config.accent_color * Color(1, 1, 1, 0.8)); + + p_theme->set_color("axis_x_color", EditorStringName(Editor), Color(0.96, 0.20, 0.32)); + p_theme->set_color("axis_y_color", EditorStringName(Editor), Color(0.53, 0.84, 0.01)); + p_theme->set_color("axis_z_color", EditorStringName(Editor), Color(0.16, 0.55, 0.96)); + p_theme->set_color("axis_w_color", EditorStringName(Editor), Color(0.55, 0.55, 0.55)); + + const float prop_color_saturation = p_config.accent_color.get_s() * 0.75; + const float prop_color_value = p_config.accent_color.get_v(); + + p_theme->set_color("property_color_x", EditorStringName(Editor), Color().from_hsv(0.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value)); + p_theme->set_color("property_color_y", EditorStringName(Editor), Color().from_hsv(1.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value)); + p_theme->set_color("property_color_z", EditorStringName(Editor), Color().from_hsv(2.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value)); + p_theme->set_color("property_color_w", EditorStringName(Editor), Color().from_hsv(1.5 / 3.0 + 0.05, prop_color_saturation, prop_color_value)); + + // Special colors for rendering methods. + + p_theme->set_color("forward_plus_color", EditorStringName(Editor), Color::hex(0x5d8c3fff)); + p_theme->set_color("mobile_color", EditorStringName(Editor), Color::hex(0xa5557dff)); + p_theme->set_color("gl_compatibility_color", EditorStringName(Editor), Color::hex(0x5586a4ff)); + + if (p_config.dark_theme) { + p_theme->set_color("highend_color", EditorStringName(Editor), Color(1.0, 0.0, 0.0)); + } else { + p_theme->set_color("highend_color", EditorStringName(Editor), Color::hex(0xad1128ff)); + } + } + + // Constants. + { + // Can't save single float in theme, so using Color. + p_theme->set_color("icon_saturation", EditorStringName(Editor), Color(p_config.icon_saturation, p_config.icon_saturation, p_config.icon_saturation)); + + // Controls may rely on the scale for their internal drawing logic. + p_theme->set_default_base_scale(EDSCALE); + p_theme->set_constant("scale", EditorStringName(Editor), EDSCALE); + + p_theme->set_constant("thumb_size", EditorStringName(Editor), p_config.thumb_size); + p_theme->set_constant("class_icon_size", EditorStringName(Editor), p_config.class_icon_size); + p_theme->set_constant("color_picker_button_height", EditorStringName(Editor), p_config.color_picker_button_height); + p_theme->set_constant("gizmo_handle_scale", EditorStringName(Editor), p_config.gizmo_handle_scale); + + p_theme->set_constant("base_margin", EditorStringName(Editor), p_config.base_margin); + p_theme->set_constant("increased_margin", EditorStringName(Editor), p_config.increased_margin); + p_theme->set_constant("window_border_margin", EditorStringName(Editor), p_config.window_border_margin); + p_theme->set_constant("top_bar_separation", EditorStringName(Editor), p_config.top_bar_separation); + + p_theme->set_constant("dark_theme", EditorStringName(Editor), p_config.dark_theme); + } + + // Styleboxes. + { + // This is the basic stylebox, used as a base for most other styleboxes (through `duplicate()`). + p_config.base_style = make_flat_stylebox(p_config.base_color, p_config.base_margin, p_config.base_margin, p_config.base_margin, p_config.base_margin, p_config.corner_radius); + p_config.base_style->set_border_width_all(p_config.border_width); + p_config.base_style->set_border_color(p_config.base_color); + + p_config.base_empty_style = make_empty_stylebox(p_config.base_margin, p_config.base_margin, p_config.base_margin, p_config.base_margin); + + // Button styles. + { + p_config.widget_margin = Vector2(p_config.increased_margin + 2, p_config.increased_margin + 1) * EDSCALE; + + p_config.button_style = p_config.base_style->duplicate(); + p_config.button_style->set_content_margin_individual(p_config.widget_margin.x, p_config.widget_margin.y, p_config.widget_margin.x, p_config.widget_margin.y); + p_config.button_style->set_bg_color(p_config.dark_color_1); + if (p_config.draw_extra_borders) { + p_config.button_style->set_border_width_all(Math::round(EDSCALE)); + p_config.button_style->set_border_color(p_config.extra_border_color_1); + } else { + p_config.button_style->set_border_color(p_config.dark_color_2); + } + + p_config.button_style_disabled = p_config.button_style->duplicate(); + p_config.button_style_disabled->set_bg_color(p_config.disabled_bg_color); + if (p_config.draw_extra_borders) { + p_config.button_style_disabled->set_border_color(p_config.extra_border_color_2); + } else { + p_config.button_style_disabled->set_border_color(p_config.disabled_border_color); + } + + p_config.button_style_focus = p_config.button_style->duplicate(); + p_config.button_style_focus->set_draw_center(false); + p_config.button_style_focus->set_border_width_all(Math::round(2 * MAX(1, EDSCALE))); + p_config.button_style_focus->set_border_color(p_config.accent_color); + + p_config.button_style_pressed = p_config.button_style->duplicate(); + p_config.button_style_pressed->set_bg_color(p_config.dark_color_1.darkened(0.125)); + + p_config.button_style_hover = p_config.button_style->duplicate(); + p_config.button_style_hover->set_bg_color(p_config.mono_color * Color(1, 1, 1, 0.11)); + if (p_config.draw_extra_borders) { + p_config.button_style_hover->set_border_color(p_config.extra_border_color_1); + } else { + p_config.button_style_hover->set_border_color(p_config.mono_color * Color(1, 1, 1, 0.05)); + } + } + + // Windows and popups. + { + p_config.popup_style = p_config.base_style->duplicate(); + p_config.popup_style->set_content_margin_all(p_config.popup_margin); + p_config.popup_style->set_border_color(p_config.contrast_color_1); + p_config.popup_style->set_shadow_color(p_config.shadow_color); + p_config.popup_style->set_shadow_size(4 * EDSCALE); + // Popups are separate windows by default in the editor. Windows currently don't support per-pixel transparency + // in 4.0, and even if it was, it may not always work in practice (e.g. running with compositing disabled). + p_config.popup_style->set_corner_radius_all(0); + + p_config.window_style = p_config.popup_style->duplicate(); + p_config.window_style->set_border_color(p_config.base_color); + p_config.window_style->set_border_width(SIDE_TOP, 24 * EDSCALE); + p_config.window_style->set_expand_margin(SIDE_TOP, 24 * EDSCALE); + + // Prevent corner artifacts between window title and body. + p_config.dialog_style = p_config.base_style->duplicate(); + p_config.dialog_style->set_corner_radius(CORNER_TOP_LEFT, 0); + p_config.dialog_style->set_corner_radius(CORNER_TOP_RIGHT, 0); + // Prevent visible line between window title and body. + p_config.dialog_style->set_expand_margin(SIDE_BOTTOM, 2 * EDSCALE); + } + + // Panels. + { + p_config.panel_container_style = p_config.button_style->duplicate(); + p_config.panel_container_style->set_draw_center(false); + p_config.panel_container_style->set_border_width_all(0); + + // Content panel for tabs and similar containers. + + // Compensate for the border. + const int content_panel_margin = p_config.base_margin * EDSCALE + p_config.border_width; + + p_config.content_panel_style = p_config.base_style->duplicate(); + p_config.content_panel_style->set_border_color(p_config.dark_color_3); + p_config.content_panel_style->set_border_width_all(p_config.border_width); + p_config.content_panel_style->set_border_width(Side::SIDE_TOP, 0); + p_config.content_panel_style->set_corner_radius(CORNER_TOP_LEFT, 0); + p_config.content_panel_style->set_corner_radius(CORNER_TOP_RIGHT, 0); + p_config.content_panel_style->set_content_margin_individual(content_panel_margin, 2 * EDSCALE + content_panel_margin, content_panel_margin, content_panel_margin); + + // Trees and similarly inset panels. + + p_config.tree_panel_style = p_config.base_style->duplicate(); + // Make Trees easier to distinguish from other controls by using a darker background color. + p_config.tree_panel_style->set_bg_color(p_config.dark_color_1.lerp(p_config.dark_color_2, 0.5)); + if (p_config.draw_extra_borders) { + p_config.tree_panel_style->set_border_width_all(Math::round(EDSCALE)); + p_config.tree_panel_style->set_border_color(p_config.extra_border_color_2); + } else { + p_config.tree_panel_style->set_border_color(p_config.dark_color_3); + } + } + } +} + +void EditorThemeManager::_populate_standard_styles(const Ref &p_theme, ThemeConfiguration &p_config) { + // Panels. + { + // Panel. + p_theme->set_stylebox("panel", "Panel", make_flat_stylebox(p_config.dark_color_1, 6, 4, 6, 4, p_config.corner_radius)); + + // PanelContainer. + p_theme->set_stylebox("panel", "PanelContainer", p_config.panel_container_style); + + // TooltipPanel & TooltipLabel. + { + // TooltipPanel is also used for custom tooltips, while TooltipLabel + // is only relevant for default tooltips. + + p_theme->set_color("font_color", "TooltipLabel", p_config.font_hover_color); + p_theme->set_color("font_shadow_color", "TooltipLabel", Color(0, 0, 0, 0)); + + Ref style_tooltip = p_config.popup_style->duplicate(); + style_tooltip->set_shadow_size(0); + style_tooltip->set_content_margin_all(p_config.base_margin * EDSCALE * 0.5); + style_tooltip->set_bg_color(p_config.dark_color_3 * Color(0.8, 0.8, 0.8, 0.9)); + style_tooltip->set_border_width_all(0); + p_theme->set_stylebox("panel", "TooltipPanel", style_tooltip); + } + + // PopupPanel + p_theme->set_stylebox("panel", "PopupPanel", p_config.popup_style); + } + + // Buttons. + { + // Button. + + p_theme->set_stylebox("normal", "Button", p_config.button_style); + p_theme->set_stylebox("hover", "Button", p_config.button_style_hover); + p_theme->set_stylebox("pressed", "Button", p_config.button_style_pressed); + p_theme->set_stylebox("focus", "Button", p_config.button_style_focus); + p_theme->set_stylebox("disabled", "Button", p_config.button_style_disabled); + + p_theme->set_color("font_color", "Button", p_config.font_color); + p_theme->set_color("font_hover_color", "Button", p_config.font_hover_color); + p_theme->set_color("font_hover_pressed_color", "Button", p_config.font_hover_pressed_color); + p_theme->set_color("font_focus_color", "Button", p_config.font_focus_color); + p_theme->set_color("font_pressed_color", "Button", p_config.font_pressed_color); + p_theme->set_color("font_disabled_color", "Button", p_config.font_disabled_color); + p_theme->set_color("font_outline_color", "Button", p_config.font_outline_color); + + p_theme->set_color("icon_normal_color", "Button", p_config.icon_normal_color); + p_theme->set_color("icon_hover_color", "Button", p_config.icon_hover_color); + p_theme->set_color("icon_focus_color", "Button", p_config.icon_focus_color); + p_theme->set_color("icon_pressed_color", "Button", p_config.icon_pressed_color); + p_theme->set_color("icon_disabled_color", "Button", p_config.icon_disabled_color); + + p_theme->set_constant("h_separation", "Button", 4 * EDSCALE); + p_theme->set_constant("outline_size", "Button", 0); + + // MenuButton. + + p_theme->set_stylebox("normal", "MenuButton", p_config.panel_container_style); + p_theme->set_stylebox("hover", "MenuButton", p_config.button_style_hover); + p_theme->set_stylebox("pressed", "MenuButton", p_config.panel_container_style); + p_theme->set_stylebox("focus", "MenuButton", p_config.panel_container_style); + p_theme->set_stylebox("disabled", "MenuButton", p_config.panel_container_style); + + p_theme->set_color("font_color", "MenuButton", p_config.font_color); + p_theme->set_color("font_hover_color", "MenuButton", p_config.font_hover_color); + p_theme->set_color("font_hover_pressed_color", "MenuButton", p_config.font_hover_pressed_color); + p_theme->set_color("font_focus_color", "MenuButton", p_config.font_focus_color); + p_theme->set_color("font_outline_color", "MenuButton", p_config.font_outline_color); + + p_theme->set_constant("outline_size", "MenuButton", 0); + + // MenuBar. + + p_theme->set_stylebox("normal", "MenuBar", p_config.button_style); + p_theme->set_stylebox("hover", "MenuBar", p_config.button_style_hover); + p_theme->set_stylebox("pressed", "MenuBar", p_config.button_style_pressed); + p_theme->set_stylebox("disabled", "MenuBar", p_config.button_style_disabled); + + p_theme->set_color("font_color", "MenuBar", p_config.font_color); + p_theme->set_color("font_hover_color", "MenuBar", p_config.font_hover_color); + p_theme->set_color("font_hover_pressed_color", "MenuBar", p_config.font_hover_pressed_color); + p_theme->set_color("font_focus_color", "MenuBar", p_config.font_focus_color); + p_theme->set_color("font_pressed_color", "MenuBar", p_config.font_pressed_color); + p_theme->set_color("font_disabled_color", "MenuBar", p_config.font_disabled_color); + p_theme->set_color("font_outline_color", "MenuBar", p_config.font_outline_color); + + p_theme->set_color("icon_normal_color", "MenuBar", p_config.icon_normal_color); + p_theme->set_color("icon_hover_color", "MenuBar", p_config.icon_hover_color); + p_theme->set_color("icon_focus_color", "MenuBar", p_config.icon_focus_color); + p_theme->set_color("icon_pressed_color", "MenuBar", p_config.icon_pressed_color); + p_theme->set_color("icon_disabled_color", "MenuBar", p_config.icon_disabled_color); + + p_theme->set_constant("h_separation", "MenuBar", 4 * EDSCALE); + p_theme->set_constant("outline_size", "MenuBar", 0); + + // OptionButton. + { + Ref option_button_focus_style = p_config.button_style_focus->duplicate(); + Ref option_button_normal_style = p_config.button_style->duplicate(); + Ref option_button_hover_style = p_config.button_style_hover->duplicate(); + Ref option_button_pressed_style = p_config.button_style_pressed->duplicate(); + Ref option_button_disabled_style = p_config.button_style_disabled->duplicate(); + + option_button_focus_style->set_content_margin(SIDE_RIGHT, 4 * EDSCALE); + option_button_normal_style->set_content_margin(SIDE_RIGHT, 4 * EDSCALE); + option_button_hover_style->set_content_margin(SIDE_RIGHT, 4 * EDSCALE); + option_button_pressed_style->set_content_margin(SIDE_RIGHT, 4 * EDSCALE); + option_button_disabled_style->set_content_margin(SIDE_RIGHT, 4 * EDSCALE); + + p_theme->set_stylebox("focus", "OptionButton", option_button_focus_style); + p_theme->set_stylebox("normal", "OptionButton", p_config.button_style); + p_theme->set_stylebox("hover", "OptionButton", p_config.button_style_hover); + p_theme->set_stylebox("pressed", "OptionButton", p_config.button_style_pressed); + p_theme->set_stylebox("disabled", "OptionButton", p_config.button_style_disabled); + + p_theme->set_stylebox("normal_mirrored", "OptionButton", option_button_normal_style); + p_theme->set_stylebox("hover_mirrored", "OptionButton", option_button_hover_style); + p_theme->set_stylebox("pressed_mirrored", "OptionButton", option_button_pressed_style); + p_theme->set_stylebox("disabled_mirrored", "OptionButton", option_button_disabled_style); + + p_theme->set_color("font_color", "OptionButton", p_config.font_color); + p_theme->set_color("font_hover_color", "OptionButton", p_config.font_hover_color); + p_theme->set_color("font_hover_pressed_color", "OptionButton", p_config.font_hover_pressed_color); + p_theme->set_color("font_focus_color", "OptionButton", p_config.font_focus_color); + p_theme->set_color("font_pressed_color", "OptionButton", p_config.font_pressed_color); + p_theme->set_color("font_disabled_color", "OptionButton", p_config.font_disabled_color); + p_theme->set_color("font_outline_color", "OptionButton", p_config.font_outline_color); + + p_theme->set_color("icon_normal_color", "OptionButton", p_config.icon_normal_color); + p_theme->set_color("icon_hover_color", "OptionButton", p_config.icon_hover_color); + p_theme->set_color("icon_focus_color", "OptionButton", p_config.icon_focus_color); + p_theme->set_color("icon_pressed_color", "OptionButton", p_config.icon_pressed_color); + p_theme->set_color("icon_disabled_color", "OptionButton", p_config.icon_disabled_color); + + p_theme->set_icon("arrow", "OptionButton", p_theme->get_icon(SNAME("GuiOptionArrow"), EditorStringName(EditorIcons))); + p_theme->set_constant("arrow_margin", "OptionButton", p_config.widget_margin.x - 2 * EDSCALE); + p_theme->set_constant("modulate_arrow", "OptionButton", true); + p_theme->set_constant("h_separation", "OptionButton", 4 * EDSCALE); + p_theme->set_constant("outline_size", "OptionButton", 0); + } + + // CheckButton. + + p_theme->set_stylebox("normal", "CheckButton", p_config.panel_container_style); + p_theme->set_stylebox("pressed", "CheckButton", p_config.panel_container_style); + p_theme->set_stylebox("disabled", "CheckButton", p_config.panel_container_style); + p_theme->set_stylebox("hover", "CheckButton", p_config.panel_container_style); + p_theme->set_stylebox("hover_pressed", "CheckButton", p_config.panel_container_style); + + p_theme->set_icon("checked", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOn"), EditorStringName(EditorIcons))); + p_theme->set_icon("checked_disabled", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOnDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("unchecked", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOff"), EditorStringName(EditorIcons))); + p_theme->set_icon("unchecked_disabled", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOffDisabled"), EditorStringName(EditorIcons))); + + p_theme->set_icon("checked_mirrored", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOnMirrored"), EditorStringName(EditorIcons))); + p_theme->set_icon("checked_disabled_mirrored", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOnDisabledMirrored"), EditorStringName(EditorIcons))); + p_theme->set_icon("unchecked_mirrored", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOffMirrored"), EditorStringName(EditorIcons))); + p_theme->set_icon("unchecked_disabled_mirrored", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOffDisabledMirrored"), EditorStringName(EditorIcons))); + + p_theme->set_color("font_color", "CheckButton", p_config.font_color); + p_theme->set_color("font_hover_color", "CheckButton", p_config.font_hover_color); + p_theme->set_color("font_hover_pressed_color", "CheckButton", p_config.font_hover_pressed_color); + p_theme->set_color("font_focus_color", "CheckButton", p_config.font_focus_color); + p_theme->set_color("font_pressed_color", "CheckButton", p_config.font_pressed_color); + p_theme->set_color("font_disabled_color", "CheckButton", p_config.font_disabled_color); + p_theme->set_color("font_outline_color", "CheckButton", p_config.font_outline_color); + + p_theme->set_color("icon_normal_color", "CheckButton", p_config.icon_normal_color); + p_theme->set_color("icon_hover_color", "CheckButton", p_config.icon_hover_color); + p_theme->set_color("icon_focus_color", "CheckButton", p_config.icon_focus_color); + p_theme->set_color("icon_pressed_color", "CheckButton", p_config.icon_pressed_color); + p_theme->set_color("icon_disabled_color", "CheckButton", p_config.icon_disabled_color); + + p_theme->set_constant("h_separation", "CheckButton", 8 * EDSCALE); + p_theme->set_constant("check_v_offset", "CheckButton", 0); + p_theme->set_constant("outline_size", "CheckButton", 0); + + // CheckBox. + { + Ref checkbox_style = p_config.panel_container_style->duplicate(); + checkbox_style->set_content_margin_all(p_config.base_margin * EDSCALE); + + p_theme->set_stylebox("normal", "CheckBox", checkbox_style); + p_theme->set_stylebox("pressed", "CheckBox", checkbox_style); + p_theme->set_stylebox("disabled", "CheckBox", checkbox_style); + p_theme->set_stylebox("hover", "CheckBox", checkbox_style); + p_theme->set_stylebox("hover_pressed", "CheckBox", checkbox_style); + p_theme->set_icon("checked", "CheckBox", p_theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons))); + p_theme->set_icon("unchecked", "CheckBox", p_theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons))); + p_theme->set_icon("radio_checked", "CheckBox", p_theme->get_icon(SNAME("GuiRadioChecked"), EditorStringName(EditorIcons))); + p_theme->set_icon("radio_unchecked", "CheckBox", p_theme->get_icon(SNAME("GuiRadioUnchecked"), EditorStringName(EditorIcons))); + p_theme->set_icon("checked_disabled", "CheckBox", p_theme->get_icon(SNAME("GuiCheckedDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("unchecked_disabled", "CheckBox", p_theme->get_icon(SNAME("GuiUncheckedDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("radio_checked_disabled", "CheckBox", p_theme->get_icon(SNAME("GuiRadioCheckedDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("radio_unchecked_disabled", "CheckBox", p_theme->get_icon(SNAME("GuiRadioUncheckedDisabled"), EditorStringName(EditorIcons))); + + p_theme->set_color("font_color", "CheckBox", p_config.font_color); + p_theme->set_color("font_hover_color", "CheckBox", p_config.font_hover_color); + p_theme->set_color("font_hover_pressed_color", "CheckBox", p_config.font_hover_pressed_color); + p_theme->set_color("font_focus_color", "CheckBox", p_config.font_focus_color); + p_theme->set_color("font_pressed_color", "CheckBox", p_config.font_pressed_color); + p_theme->set_color("font_disabled_color", "CheckBox", p_config.font_disabled_color); + p_theme->set_color("font_outline_color", "CheckBox", p_config.font_outline_color); + + p_theme->set_color("icon_normal_color", "CheckBox", p_config.icon_normal_color); + p_theme->set_color("icon_hover_color", "CheckBox", p_config.icon_hover_color); + p_theme->set_color("icon_focus_color", "CheckBox", p_config.icon_focus_color); + p_theme->set_color("icon_pressed_color", "CheckBox", p_config.icon_pressed_color); + p_theme->set_color("icon_disabled_color", "CheckBox", p_config.icon_disabled_color); + + p_theme->set_constant("h_separation", "CheckBox", 8 * EDSCALE); + p_theme->set_constant("check_v_offset", "CheckBox", 0); + p_theme->set_constant("outline_size", "CheckBox", 0); + } + + // LinkButton. + + p_theme->set_stylebox("focus", "LinkButton", p_config.base_empty_style); + p_theme->set_color("font_color", "LinkButton", p_config.font_color); + p_theme->set_color("font_hover_color", "LinkButton", p_config.font_hover_color); + p_theme->set_color("font_hover_pressed_color", "LinkButton", p_config.font_hover_pressed_color); + p_theme->set_color("font_focus_color", "LinkButton", p_config.font_focus_color); + p_theme->set_color("font_pressed_color", "LinkButton", p_config.font_pressed_color); + p_theme->set_color("font_disabled_color", "LinkButton", p_config.font_disabled_color); + p_theme->set_color("font_outline_color", "LinkButton", p_config.font_outline_color); + + p_theme->set_constant("outline_size", "LinkButton", 0); + } + + // Tree & ItemList. + { + Ref style_tree_focus = p_config.base_style->duplicate(); + style_tree_focus->set_bg_color(p_config.highlight_color); + style_tree_focus->set_border_width_all(0); + + Ref style_tree_selected = style_tree_focus->duplicate(); + + const Color guide_color = p_config.mono_color * Color(1, 1, 1, 0.05); + + // Tree. + { + p_theme->set_icon("checked", "Tree", p_theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons))); + p_theme->set_icon("checked_disabled", "Tree", p_theme->get_icon(SNAME("GuiCheckedDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("indeterminate", "Tree", p_theme->get_icon(SNAME("GuiIndeterminate"), EditorStringName(EditorIcons))); + p_theme->set_icon("indeterminate_disabled", "Tree", p_theme->get_icon(SNAME("GuiIndeterminateDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("unchecked", "Tree", p_theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons))); + p_theme->set_icon("unchecked_disabled", "Tree", p_theme->get_icon(SNAME("GuiUncheckedDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("arrow", "Tree", p_theme->get_icon(SNAME("GuiTreeArrowDown"), EditorStringName(EditorIcons))); + p_theme->set_icon("arrow_collapsed", "Tree", p_theme->get_icon(SNAME("GuiTreeArrowRight"), EditorStringName(EditorIcons))); + p_theme->set_icon("arrow_collapsed_mirrored", "Tree", p_theme->get_icon(SNAME("GuiTreeArrowLeft"), EditorStringName(EditorIcons))); + p_theme->set_icon("updown", "Tree", p_theme->get_icon(SNAME("GuiTreeUpdown"), EditorStringName(EditorIcons))); + p_theme->set_icon("select_arrow", "Tree", p_theme->get_icon(SNAME("GuiDropdown"), EditorStringName(EditorIcons))); + + p_theme->set_stylebox("panel", "Tree", p_config.tree_panel_style); + p_theme->set_stylebox("focus", "Tree", p_config.button_style_focus); + p_theme->set_stylebox("custom_button", "Tree", make_empty_stylebox()); + p_theme->set_stylebox("custom_button_pressed", "Tree", make_empty_stylebox()); + p_theme->set_stylebox("custom_button_hover", "Tree", p_config.button_style); + + p_theme->set_color("custom_button_font_highlight", "Tree", p_config.font_hover_color); + p_theme->set_color("font_color", "Tree", p_config.font_color); + p_theme->set_color("font_selected_color", "Tree", p_config.mono_color); + p_theme->set_color("font_disabled_color", "Tree", p_config.font_disabled_color); + p_theme->set_color("font_outline_color", "Tree", p_config.font_outline_color); + p_theme->set_color("title_button_color", "Tree", p_config.font_color); + p_theme->set_color("drop_position_color", "Tree", p_config.accent_color); + + p_theme->set_constant("v_separation", "Tree", p_config.widget_margin.y - EDSCALE); + p_theme->set_constant("h_separation", "Tree", 6 * EDSCALE); + p_theme->set_constant("guide_width", "Tree", p_config.border_width); + p_theme->set_constant("item_margin", "Tree", 3 * p_config.base_margin * EDSCALE); + p_theme->set_constant("inner_item_margin_bottom", "Tree", p_config.increased_margin * EDSCALE); + p_theme->set_constant("inner_item_margin_left", "Tree", p_config.increased_margin * EDSCALE); + p_theme->set_constant("inner_item_margin_right", "Tree", p_config.increased_margin * EDSCALE); + p_theme->set_constant("inner_item_margin_top", "Tree", p_config.increased_margin * EDSCALE); + p_theme->set_constant("button_margin", "Tree", p_config.base_margin * EDSCALE); + p_theme->set_constant("scroll_border", "Tree", 40 * EDSCALE); + p_theme->set_constant("scroll_speed", "Tree", 12); + p_theme->set_constant("outline_size", "Tree", 0); + p_theme->set_constant("scrollbar_margin_left", "Tree", 0); + p_theme->set_constant("scrollbar_margin_top", "Tree", 0); + p_theme->set_constant("scrollbar_margin_right", "Tree", 0); + p_theme->set_constant("scrollbar_margin_bottom", "Tree", 0); + p_theme->set_constant("scrollbar_h_separation", "Tree", 1 * EDSCALE); + p_theme->set_constant("scrollbar_v_separation", "Tree", 1 * EDSCALE); + + Color relationship_line_color = p_config.mono_color * Color(1, 1, 1, p_config.relationship_line_opacity); + + p_theme->set_constant("draw_guides", "Tree", p_config.relationship_line_opacity < 0.01); + p_theme->set_color("guide_color", "Tree", guide_color); + + int relationship_line_width = 1; + Color parent_line_color = p_config.mono_color * Color(1, 1, 1, CLAMP(p_config.relationship_line_opacity + 0.45, 0.0, 1.0)); + Color children_line_color = p_config.mono_color * Color(1, 1, 1, CLAMP(p_config.relationship_line_opacity + 0.25, 0.0, 1.0)); + + p_theme->set_constant("draw_relationship_lines", "Tree", p_config.relationship_line_opacity >= 0.01); + p_theme->set_constant("relationship_line_width", "Tree", relationship_line_width); + p_theme->set_constant("parent_hl_line_width", "Tree", relationship_line_width * 2); + p_theme->set_constant("children_hl_line_width", "Tree", relationship_line_width); + p_theme->set_constant("parent_hl_line_margin", "Tree", relationship_line_width * 3); + p_theme->set_color("relationship_line_color", "Tree", relationship_line_color); + p_theme->set_color("parent_hl_line_color", "Tree", parent_line_color); + p_theme->set_color("children_hl_line_color", "Tree", children_line_color); + p_theme->set_color("drop_position_color", "Tree", p_config.accent_color); + + Ref style_tree_btn = p_config.base_style->duplicate(); + style_tree_btn->set_bg_color(p_config.highlight_color); + style_tree_btn->set_border_width_all(0); + p_theme->set_stylebox("button_pressed", "Tree", style_tree_btn); + + Ref style_tree_hover = p_config.base_style->duplicate(); + style_tree_hover->set_bg_color(p_config.highlight_color * Color(1, 1, 1, 0.4)); + style_tree_hover->set_border_width_all(0); + p_theme->set_stylebox("hover", "Tree", style_tree_hover); + + p_theme->set_stylebox("selected_focus", "Tree", style_tree_focus); + p_theme->set_stylebox("selected", "Tree", style_tree_selected); + + Ref style_tree_cursor = p_config.base_style->duplicate(); + style_tree_cursor->set_draw_center(false); + style_tree_cursor->set_border_width_all(MAX(1, p_config.border_width)); + style_tree_cursor->set_border_color(p_config.contrast_color_1); + + Ref style_tree_title = p_config.base_style->duplicate(); + style_tree_title->set_bg_color(p_config.dark_color_3); + style_tree_title->set_border_width_all(0); + p_theme->set_stylebox("cursor", "Tree", style_tree_cursor); + p_theme->set_stylebox("cursor_unfocused", "Tree", style_tree_cursor); + p_theme->set_stylebox("title_button_normal", "Tree", style_tree_title); + p_theme->set_stylebox("title_button_hover", "Tree", style_tree_title); + p_theme->set_stylebox("title_button_pressed", "Tree", style_tree_title); + } + + // ItemList. + { + Ref style_itemlist_bg = p_config.base_style->duplicate(); + style_itemlist_bg->set_bg_color(p_config.dark_color_1); + + if (p_config.draw_extra_borders) { + style_itemlist_bg->set_border_width_all(Math::round(EDSCALE)); + style_itemlist_bg->set_border_color(p_config.extra_border_color_2); + } else { + style_itemlist_bg->set_border_width_all(p_config.border_width); + style_itemlist_bg->set_border_color(p_config.dark_color_3); + } + + Ref style_itemlist_cursor = p_config.base_style->duplicate(); + style_itemlist_cursor->set_draw_center(false); + style_itemlist_cursor->set_border_width_all(p_config.border_width); + style_itemlist_cursor->set_border_color(p_config.highlight_color); + + Ref style_itemlist_hover = style_tree_selected->duplicate(); + style_itemlist_hover->set_bg_color(p_config.highlight_color * Color(1, 1, 1, 0.3)); + style_itemlist_hover->set_border_width_all(0); + + p_theme->set_stylebox("panel", "ItemList", style_itemlist_bg); + p_theme->set_stylebox("focus", "ItemList", p_config.button_style_focus); + p_theme->set_stylebox("cursor", "ItemList", style_itemlist_cursor); + p_theme->set_stylebox("cursor_unfocused", "ItemList", style_itemlist_cursor); + p_theme->set_stylebox("selected_focus", "ItemList", style_tree_focus); + p_theme->set_stylebox("selected", "ItemList", style_tree_selected); + p_theme->set_stylebox("hovered", "ItemList", style_itemlist_hover); + p_theme->set_color("font_color", "ItemList", p_config.font_color); + p_theme->set_color("font_hovered_color", "ItemList", p_config.mono_color); + p_theme->set_color("font_selected_color", "ItemList", p_config.mono_color); + p_theme->set_color("font_outline_color", "ItemList", p_config.font_outline_color); + p_theme->set_color("guide_color", "ItemList", guide_color); + p_theme->set_constant("v_separation", "ItemList", p_config.forced_even_separation * 0.5 * EDSCALE); + p_theme->set_constant("h_separation", "ItemList", 6 * EDSCALE); + p_theme->set_constant("icon_margin", "ItemList", 6 * EDSCALE); + p_theme->set_constant("line_separation", "ItemList", 3 * EDSCALE); + p_theme->set_constant("outline_size", "ItemList", 0); + } + } + + // TabBar & TabContainer. + { + Ref style_tab_base = p_config.button_style->duplicate(); + + style_tab_base->set_border_width_all(0); + // Don't round the top corners to avoid creating a small blank space between the tabs and the main panel. + // This also makes the top highlight look better. + style_tab_base->set_corner_radius(CORNER_BOTTOM_LEFT, 0); + style_tab_base->set_corner_radius(CORNER_BOTTOM_RIGHT, 0); + + // When using a border width greater than 0, visually line up the left of the selected tab with the underlying panel. + style_tab_base->set_expand_margin(SIDE_LEFT, -p_config.border_width); + + style_tab_base->set_content_margin(SIDE_LEFT, p_config.widget_margin.x + 5 * EDSCALE); + style_tab_base->set_content_margin(SIDE_RIGHT, p_config.widget_margin.x + 5 * EDSCALE); + style_tab_base->set_content_margin(SIDE_BOTTOM, p_config.widget_margin.y); + style_tab_base->set_content_margin(SIDE_TOP, p_config.widget_margin.y); + + Ref style_tab_selected = style_tab_base->duplicate(); + + style_tab_selected->set_bg_color(p_config.base_color); + // Add a highlight line at the top of the selected tab. + style_tab_selected->set_border_width(SIDE_TOP, Math::round(2 * EDSCALE)); + // Make the highlight line prominent, but not too prominent as to not be distracting. + Color tab_highlight = p_config.dark_color_2.lerp(p_config.accent_color, 0.75); + style_tab_selected->set_border_color(tab_highlight); + style_tab_selected->set_corner_radius_all(0); + + Ref style_tab_hovered = style_tab_base->duplicate(); + + style_tab_hovered->set_bg_color(p_config.dark_color_1.lerp(p_config.base_color, 0.4)); + // Hovered tab has a subtle highlight between normal and selected states. + style_tab_hovered->set_corner_radius_all(0); + + Ref style_tab_unselected = style_tab_base->duplicate(); + style_tab_unselected->set_expand_margin(SIDE_BOTTOM, 0); + style_tab_unselected->set_bg_color(p_config.dark_color_1); + // Add some spacing between unselected tabs to make them easier to distinguish from each other + style_tab_unselected->set_border_color(Color(0, 0, 0, 0)); + + Ref style_tab_disabled = style_tab_base->duplicate(); + style_tab_disabled->set_expand_margin(SIDE_BOTTOM, 0); + style_tab_disabled->set_bg_color(p_config.disabled_bg_color); + style_tab_disabled->set_border_color(p_config.disabled_bg_color); + + Ref style_tab_focus = p_config.button_style_focus->duplicate(); + + Ref style_tabbar_background = make_flat_stylebox(p_config.dark_color_1, 0, 0, 0, 0, p_config.corner_radius * EDSCALE); + style_tabbar_background->set_corner_radius(CORNER_BOTTOM_LEFT, 0); + style_tabbar_background->set_corner_radius(CORNER_BOTTOM_RIGHT, 0); + p_theme->set_stylebox("tabbar_background", "TabContainer", style_tabbar_background); + p_theme->set_stylebox("panel", "TabContainer", p_config.content_panel_style); + + p_theme->set_stylebox("tab_selected", "TabContainer", style_tab_selected); + p_theme->set_stylebox("tab_hovered", "TabContainer", style_tab_hovered); + p_theme->set_stylebox("tab_unselected", "TabContainer", style_tab_unselected); + p_theme->set_stylebox("tab_disabled", "TabContainer", style_tab_disabled); + p_theme->set_stylebox("tab_focus", "TabContainer", style_tab_focus); + p_theme->set_stylebox("tab_selected", "TabBar", style_tab_selected); + p_theme->set_stylebox("tab_hovered", "TabBar", style_tab_hovered); + p_theme->set_stylebox("tab_unselected", "TabBar", style_tab_unselected); + p_theme->set_stylebox("tab_disabled", "TabBar", style_tab_disabled); + p_theme->set_stylebox("tab_focus", "TabBar", style_tab_focus); + p_theme->set_stylebox("button_pressed", "TabBar", p_config.panel_container_style); + p_theme->set_stylebox("button_highlight", "TabBar", p_config.panel_container_style); + + p_theme->set_color("font_selected_color", "TabContainer", p_config.font_color); + p_theme->set_color("font_hovered_color", "TabContainer", p_config.font_color); + p_theme->set_color("font_unselected_color", "TabContainer", p_config.font_disabled_color); + p_theme->set_color("font_outline_color", "TabContainer", p_config.font_outline_color); + p_theme->set_color("font_selected_color", "TabBar", p_config.font_color); + p_theme->set_color("font_hovered_color", "TabBar", p_config.font_color); + p_theme->set_color("font_unselected_color", "TabBar", p_config.font_disabled_color); + p_theme->set_color("font_outline_color", "TabBar", p_config.font_outline_color); + p_theme->set_color("drop_mark_color", "TabContainer", tab_highlight); + p_theme->set_color("drop_mark_color", "TabBar", tab_highlight); + + p_theme->set_icon("menu", "TabContainer", p_theme->get_icon(SNAME("GuiTabMenu"), EditorStringName(EditorIcons))); + p_theme->set_icon("menu_highlight", "TabContainer", p_theme->get_icon(SNAME("GuiTabMenuHl"), EditorStringName(EditorIcons))); + p_theme->set_icon("close", "TabBar", p_theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons))); + p_theme->set_icon("increment", "TabContainer", p_theme->get_icon(SNAME("GuiScrollArrowRight"), EditorStringName(EditorIcons))); + p_theme->set_icon("decrement", "TabContainer", p_theme->get_icon(SNAME("GuiScrollArrowLeft"), EditorStringName(EditorIcons))); + p_theme->set_icon("increment", "TabBar", p_theme->get_icon(SNAME("GuiScrollArrowRight"), EditorStringName(EditorIcons))); + p_theme->set_icon("decrement", "TabBar", p_theme->get_icon(SNAME("GuiScrollArrowLeft"), EditorStringName(EditorIcons))); + p_theme->set_icon("increment_highlight", "TabBar", p_theme->get_icon(SNAME("GuiScrollArrowRightHl"), EditorStringName(EditorIcons))); + p_theme->set_icon("decrement_highlight", "TabBar", p_theme->get_icon(SNAME("GuiScrollArrowLeftHl"), EditorStringName(EditorIcons))); + p_theme->set_icon("increment_highlight", "TabContainer", p_theme->get_icon(SNAME("GuiScrollArrowRightHl"), EditorStringName(EditorIcons))); + p_theme->set_icon("decrement_highlight", "TabContainer", p_theme->get_icon(SNAME("GuiScrollArrowLeftHl"), EditorStringName(EditorIcons))); + p_theme->set_icon("drop_mark", "TabContainer", p_theme->get_icon(SNAME("GuiTabDropMark"), EditorStringName(EditorIcons))); + p_theme->set_icon("drop_mark", "TabBar", p_theme->get_icon(SNAME("GuiTabDropMark"), EditorStringName(EditorIcons))); + + p_theme->set_constant("side_margin", "TabContainer", 0); + p_theme->set_constant("outline_size", "TabContainer", 0); + p_theme->set_constant("h_separation", "TabBar", 4 * EDSCALE); + p_theme->set_constant("outline_size", "TabBar", 0); + } + + // Separators. + p_theme->set_stylebox("separator", "HSeparator", make_line_stylebox(p_config.separator_color, MAX(Math::round(EDSCALE), p_config.border_width))); + p_theme->set_stylebox("separator", "VSeparator", make_line_stylebox(p_config.separator_color, MAX(Math::round(EDSCALE), p_config.border_width), 0, 0, true)); + + // LineEdit & TextEdit. + { + Ref text_editor_style = p_config.button_style->duplicate(); + // The original button_style style has an extra 1 pixel offset that makes LineEdits not align with Buttons, + // so this compensates for that. + text_editor_style->set_content_margin(SIDE_TOP, text_editor_style->get_content_margin(SIDE_TOP) - 1 * EDSCALE); + + // Don't round the bottom corners to make the line look sharper. + text_editor_style->set_corner_radius(CORNER_BOTTOM_LEFT, 0); + text_editor_style->set_corner_radius(CORNER_BOTTOM_RIGHT, 0); + + if (p_config.draw_extra_borders) { + text_editor_style->set_border_width_all(Math::round(EDSCALE)); + text_editor_style->set_border_color(p_config.extra_border_color_1); + } else { + // Add a bottom line to make LineEdits more visible, especially in sectioned inspectors + // such as the Project Settings. + text_editor_style->set_border_width(SIDE_BOTTOM, Math::round(2 * EDSCALE)); + text_editor_style->set_border_color(p_config.dark_color_2); + } + + Ref text_editor_disabled_style = text_editor_style->duplicate(); + text_editor_disabled_style->set_border_color(p_config.disabled_border_color); + text_editor_disabled_style->set_bg_color(p_config.disabled_bg_color); + + // LineEdit. + + p_theme->set_stylebox("normal", "LineEdit", text_editor_style); + p_theme->set_stylebox("focus", "LineEdit", p_config.button_style_focus); + p_theme->set_stylebox("read_only", "LineEdit", text_editor_disabled_style); + + p_theme->set_icon("clear", "LineEdit", p_theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons))); + + p_theme->set_color("font_color", "LineEdit", p_config.font_color); + p_theme->set_color("font_selected_color", "LineEdit", p_config.mono_color); + p_theme->set_color("font_uneditable_color", "LineEdit", p_config.font_readonly_color); + p_theme->set_color("font_placeholder_color", "LineEdit", p_config.font_placeholder_color); + p_theme->set_color("font_outline_color", "LineEdit", p_config.font_outline_color); + p_theme->set_color("caret_color", "LineEdit", p_config.font_color); + p_theme->set_color("selection_color", "LineEdit", p_config.selection_color); + p_theme->set_color("clear_button_color", "LineEdit", p_config.font_color); + p_theme->set_color("clear_button_color_pressed", "LineEdit", p_config.accent_color); + + p_theme->set_constant("minimum_character_width", "LineEdit", 4); + p_theme->set_constant("outline_size", "LineEdit", 0); + p_theme->set_constant("caret_width", "LineEdit", 1); + + // TextEdit. + + p_theme->set_stylebox("normal", "TextEdit", text_editor_style); + p_theme->set_stylebox("focus", "TextEdit", p_config.button_style_focus); + p_theme->set_stylebox("read_only", "TextEdit", text_editor_disabled_style); + + p_theme->set_icon("tab", "TextEdit", p_theme->get_icon(SNAME("GuiTab"), EditorStringName(EditorIcons))); + p_theme->set_icon("space", "TextEdit", p_theme->get_icon(SNAME("GuiSpace"), EditorStringName(EditorIcons))); + + p_theme->set_color("font_color", "TextEdit", p_config.font_color); + p_theme->set_color("font_readonly_color", "TextEdit", p_config.font_readonly_color); + p_theme->set_color("font_placeholder_color", "TextEdit", p_config.font_placeholder_color); + p_theme->set_color("font_outline_color", "TextEdit", p_config.font_outline_color); + p_theme->set_color("caret_color", "TextEdit", p_config.font_color); + p_theme->set_color("selection_color", "TextEdit", p_config.selection_color); + p_theme->set_color("background_color", "TextEdit", Color(0, 0, 0, 0)); + + p_theme->set_constant("line_spacing", "TextEdit", 4 * EDSCALE); + p_theme->set_constant("outline_size", "TextEdit", 0); + p_theme->set_constant("caret_width", "TextEdit", 1); + } + + // Containers. + { + p_theme->set_constant("separation", "BoxContainer", p_config.base_margin * EDSCALE); + p_theme->set_constant("separation", "HBoxContainer", p_config.base_margin * EDSCALE); + p_theme->set_constant("separation", "VBoxContainer", p_config.base_margin * EDSCALE); + p_theme->set_constant("margin_left", "MarginContainer", 0); + p_theme->set_constant("margin_top", "MarginContainer", 0); + p_theme->set_constant("margin_right", "MarginContainer", 0); + p_theme->set_constant("margin_bottom", "MarginContainer", 0); + p_theme->set_constant("h_separation", "GridContainer", p_config.base_margin * EDSCALE); + p_theme->set_constant("v_separation", "GridContainer", p_config.base_margin * EDSCALE); + p_theme->set_constant("h_separation", "FlowContainer", p_config.base_margin * EDSCALE); + p_theme->set_constant("v_separation", "FlowContainer", p_config.base_margin * EDSCALE); + p_theme->set_constant("h_separation", "HFlowContainer", p_config.base_margin * EDSCALE); + p_theme->set_constant("v_separation", "HFlowContainer", p_config.base_margin * EDSCALE); + p_theme->set_constant("h_separation", "VFlowContainer", p_config.base_margin * EDSCALE); + p_theme->set_constant("v_separation", "VFlowContainer", p_config.base_margin * EDSCALE); + + // SplitContainer. + + p_theme->set_icon("h_grabber", "SplitContainer", p_theme->get_icon(SNAME("GuiHsplitter"), EditorStringName(EditorIcons))); + p_theme->set_icon("v_grabber", "SplitContainer", p_theme->get_icon(SNAME("GuiVsplitter"), EditorStringName(EditorIcons))); + p_theme->set_icon("grabber", "VSplitContainer", p_theme->get_icon(SNAME("GuiVsplitter"), EditorStringName(EditorIcons))); + p_theme->set_icon("grabber", "HSplitContainer", p_theme->get_icon(SNAME("GuiHsplitter"), EditorStringName(EditorIcons))); + + p_theme->set_constant("separation", "SplitContainer", p_config.base_margin * 2 * EDSCALE); + p_theme->set_constant("separation", "HSplitContainer", p_config.base_margin * 2 * EDSCALE); + p_theme->set_constant("separation", "VSplitContainer", p_config.base_margin * 2 * EDSCALE); + + p_theme->set_constant("minimum_grab_thickness", "SplitContainer", 6 * EDSCALE); + p_theme->set_constant("minimum_grab_thickness", "HSplitContainer", 6 * EDSCALE); + p_theme->set_constant("minimum_grab_thickness", "VSplitContainer", 6 * EDSCALE); + + // GridContainer. + p_theme->set_constant("v_separation", "GridContainer", Math::round(p_config.widget_margin.y - 2 * EDSCALE)); + } + + // Window and dialogs. + { + // Window. + + p_theme->set_stylebox("embedded_border", "Window", p_config.window_style); + p_theme->set_stylebox("embedded_unfocused_border", "Window", p_config.window_style); + + p_theme->set_color("title_color", "Window", p_config.font_color); + p_theme->set_icon("close", "Window", p_theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons))); + p_theme->set_icon("close_pressed", "Window", p_theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons))); + p_theme->set_constant("close_h_offset", "Window", 22 * EDSCALE); + p_theme->set_constant("close_v_offset", "Window", 20 * EDSCALE); + p_theme->set_constant("title_height", "Window", 24 * EDSCALE); + p_theme->set_constant("resize_margin", "Window", 4 * EDSCALE); + p_theme->set_font("title_font", "Window", p_theme->get_font(SNAME("title"), EditorStringName(EditorFonts))); + p_theme->set_font_size("title_font_size", "Window", p_theme->get_font_size(SNAME("title_size"), EditorStringName(EditorFonts))); + + // AcceptDialog. + p_theme->set_stylebox("panel", "AcceptDialog", p_config.dialog_style); + p_theme->set_constant("buttons_separation", "AcceptDialog", 8 * EDSCALE); + + // FileDialog. + p_theme->set_icon("folder", "FileDialog", p_theme->get_icon(SNAME("Folder"), EditorStringName(EditorIcons))); + p_theme->set_icon("parent_folder", "FileDialog", p_theme->get_icon(SNAME("ArrowUp"), EditorStringName(EditorIcons))); + p_theme->set_icon("back_folder", "FileDialog", p_theme->get_icon(SNAME("Back"), EditorStringName(EditorIcons))); + p_theme->set_icon("forward_folder", "FileDialog", p_theme->get_icon(SNAME("Forward"), EditorStringName(EditorIcons))); + p_theme->set_icon("reload", "FileDialog", p_theme->get_icon(SNAME("Reload"), EditorStringName(EditorIcons))); + p_theme->set_icon("toggle_hidden", "FileDialog", p_theme->get_icon(SNAME("GuiVisibilityVisible"), EditorStringName(EditorIcons))); + // Use a different color for folder icons to make them easier to distinguish from files. + // On a light theme, the icon will be dark, so we need to lighten it before blending it with the accent color. + p_theme->set_color("folder_icon_color", "FileDialog", (p_config.dark_theme ? Color(1, 1, 1) : Color(4.25, 4.25, 4.25)).lerp(p_config.accent_color, 0.7)); + p_theme->set_color("files_disabled", "FileDialog", p_config.font_disabled_color); + + // PopupDialog. + p_theme->set_stylebox("panel", "PopupDialog", p_config.popup_style); + + // PopupMenu. + { + Ref style_popup_menu = p_config.popup_style->duplicate(); + // Use 1 pixel for the sides, since if 0 is used, the highlight of hovered items is drawn + // on top of the popup border. This causes a 'gap' in the panel border when an item is highlighted, + // and it looks weird. 1px solves this. + style_popup_menu->set_content_margin_individual(EDSCALE, 2 * EDSCALE, EDSCALE, 2 * EDSCALE); + // Always display a border for PopupMenus so they can be distinguished from their background. + style_popup_menu->set_border_width_all(EDSCALE); + if (p_config.draw_extra_borders) { + style_popup_menu->set_border_color(p_config.extra_border_color_2); + } else { + style_popup_menu->set_border_color(p_config.dark_color_2); + } + p_theme->set_stylebox("panel", "PopupMenu", style_popup_menu); + + Ref style_menu_hover = p_config.button_style_hover->duplicate(); + // Don't use rounded corners for hover highlights since the StyleBox touches the PopupMenu's edges. + style_menu_hover->set_corner_radius_all(0); + p_theme->set_stylebox("hover", "PopupMenu", style_menu_hover); + + Ref style_popup_separator(memnew(StyleBoxLine)); + style_popup_separator->set_color(p_config.separator_color); + style_popup_separator->set_grow_begin(p_config.popup_margin - MAX(Math::round(EDSCALE), p_config.border_width)); + style_popup_separator->set_grow_end(p_config.popup_margin - MAX(Math::round(EDSCALE), p_config.border_width)); + style_popup_separator->set_thickness(MAX(Math::round(EDSCALE), p_config.border_width)); + + Ref style_popup_labeled_separator_left(memnew(StyleBoxLine)); + style_popup_labeled_separator_left->set_grow_begin(p_config.popup_margin - MAX(Math::round(EDSCALE), p_config.border_width)); + style_popup_labeled_separator_left->set_color(p_config.separator_color); + style_popup_labeled_separator_left->set_thickness(MAX(Math::round(EDSCALE), p_config.border_width)); + + Ref style_popup_labeled_separator_right(memnew(StyleBoxLine)); + style_popup_labeled_separator_right->set_grow_end(p_config.popup_margin - MAX(Math::round(EDSCALE), p_config.border_width)); + style_popup_labeled_separator_right->set_color(p_config.separator_color); + style_popup_labeled_separator_right->set_thickness(MAX(Math::round(EDSCALE), p_config.border_width)); + + p_theme->set_stylebox("separator", "PopupMenu", style_popup_separator); + p_theme->set_stylebox("labeled_separator_left", "PopupMenu", style_popup_labeled_separator_left); + p_theme->set_stylebox("labeled_separator_right", "PopupMenu", style_popup_labeled_separator_right); + + p_theme->set_color("font_color", "PopupMenu", p_config.font_color); + p_theme->set_color("font_hover_color", "PopupMenu", p_config.font_hover_color); + p_theme->set_color("font_accelerator_color", "PopupMenu", p_config.font_disabled_color); + p_theme->set_color("font_disabled_color", "PopupMenu", p_config.font_disabled_color); + p_theme->set_color("font_separator_color", "PopupMenu", p_config.font_disabled_color); + p_theme->set_color("font_outline_color", "PopupMenu", p_config.font_outline_color); + + p_theme->set_icon("checked", "PopupMenu", p_theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons))); + p_theme->set_icon("unchecked", "PopupMenu", p_theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons))); + p_theme->set_icon("radio_checked", "PopupMenu", p_theme->get_icon(SNAME("GuiRadioChecked"), EditorStringName(EditorIcons))); + p_theme->set_icon("radio_unchecked", "PopupMenu", p_theme->get_icon(SNAME("GuiRadioUnchecked"), EditorStringName(EditorIcons))); + p_theme->set_icon("checked_disabled", "PopupMenu", p_theme->get_icon(SNAME("GuiCheckedDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("unchecked_disabled", "PopupMenu", p_theme->get_icon(SNAME("GuiUncheckedDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("radio_checked_disabled", "PopupMenu", p_theme->get_icon(SNAME("GuiRadioCheckedDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("radio_unchecked_disabled", "PopupMenu", p_theme->get_icon(SNAME("GuiRadioUncheckedDisabled"), EditorStringName(EditorIcons))); + p_theme->set_icon("submenu", "PopupMenu", p_theme->get_icon(SNAME("ArrowRight"), EditorStringName(EditorIcons))); + p_theme->set_icon("submenu_mirrored", "PopupMenu", p_theme->get_icon(SNAME("ArrowLeft"), EditorStringName(EditorIcons))); + p_theme->set_icon("visibility_hidden", "PopupMenu", p_theme->get_icon(SNAME("GuiVisibilityHidden"), EditorStringName(EditorIcons))); + p_theme->set_icon("visibility_visible", "PopupMenu", p_theme->get_icon(SNAME("GuiVisibilityVisible"), EditorStringName(EditorIcons))); + p_theme->set_icon("visibility_xray", "PopupMenu", p_theme->get_icon(SNAME("GuiVisibilityXray"), EditorStringName(EditorIcons))); + + p_theme->set_constant("v_separation", "PopupMenu", p_config.forced_even_separation * EDSCALE); + p_theme->set_constant("outline_size", "PopupMenu", 0); + p_theme->set_constant("item_start_padding", "PopupMenu", p_config.base_margin * 1.5 * EDSCALE); + p_theme->set_constant("item_end_padding", "PopupMenu", p_config.base_margin * 1.5 * EDSCALE); + } + } + + // Sliders and scrollbars. + { + Ref empty_icon = memnew(ImageTexture); + + // HScrollBar. + + if (p_config.increase_scrollbar_touch_area) { + p_theme->set_stylebox("scroll", "HScrollBar", make_line_stylebox(p_config.separator_color, 50)); + } else { + p_theme->set_stylebox("scroll", "HScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, -5, 1, -5, 1)); + } + p_theme->set_stylebox("scroll_focus", "HScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1)); + p_theme->set_stylebox("grabber", "HScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollGrabber"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1)); + p_theme->set_stylebox("grabber_highlight", "HScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollGrabberHl"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1)); + p_theme->set_stylebox("grabber_pressed", "HScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollGrabberPressed"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1)); + + p_theme->set_icon("increment", "HScrollBar", empty_icon); + p_theme->set_icon("increment_highlight", "HScrollBar", empty_icon); + p_theme->set_icon("increment_pressed", "HScrollBar", empty_icon); + p_theme->set_icon("decrement", "HScrollBar", empty_icon); + p_theme->set_icon("decrement_highlight", "HScrollBar", empty_icon); + p_theme->set_icon("decrement_pressed", "HScrollBar", empty_icon); + + // VScrollBar. + + if (p_config.increase_scrollbar_touch_area) { + p_theme->set_stylebox("scroll", "VScrollBar", make_line_stylebox(p_config.separator_color, 50, 1, 1, true)); + } else { + p_theme->set_stylebox("scroll", "VScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, -5, 1, -5)); + } + p_theme->set_stylebox("scroll_focus", "VScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1)); + p_theme->set_stylebox("grabber", "VScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollGrabber"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1)); + p_theme->set_stylebox("grabber_highlight", "VScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollGrabberHl"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1)); + p_theme->set_stylebox("grabber_pressed", "VScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollGrabberPressed"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1)); + + p_theme->set_icon("increment", "VScrollBar", empty_icon); + p_theme->set_icon("increment_highlight", "VScrollBar", empty_icon); + p_theme->set_icon("increment_pressed", "VScrollBar", empty_icon); + p_theme->set_icon("decrement", "VScrollBar", empty_icon); + p_theme->set_icon("decrement_highlight", "VScrollBar", empty_icon); + p_theme->set_icon("decrement_pressed", "VScrollBar", empty_icon); + + // HSlider. + p_theme->set_icon("grabber_highlight", "HSlider", p_theme->get_icon(SNAME("GuiSliderGrabberHl"), EditorStringName(EditorIcons))); + p_theme->set_icon("grabber", "HSlider", p_theme->get_icon(SNAME("GuiSliderGrabber"), EditorStringName(EditorIcons))); + p_theme->set_stylebox("slider", "HSlider", make_flat_stylebox(p_config.dark_color_3, 0, p_config.base_margin / 2, 0, p_config.base_margin / 2, p_config.corner_radius)); + p_theme->set_stylebox("grabber_area", "HSlider", make_flat_stylebox(p_config.contrast_color_1, 0, p_config.base_margin / 2, 0, p_config.base_margin / 2, p_config.corner_radius)); + p_theme->set_stylebox("grabber_area_highlight", "HSlider", make_flat_stylebox(p_config.contrast_color_1, 0, p_config.base_margin / 2, 0, p_config.base_margin / 2)); + p_theme->set_constant("center_grabber", "HSlider", 0); + p_theme->set_constant("grabber_offset", "HSlider", 0); + + // VSlider. + p_theme->set_icon("grabber", "VSlider", p_theme->get_icon(SNAME("GuiSliderGrabber"), EditorStringName(EditorIcons))); + p_theme->set_icon("grabber_highlight", "VSlider", p_theme->get_icon(SNAME("GuiSliderGrabberHl"), EditorStringName(EditorIcons))); + p_theme->set_stylebox("slider", "VSlider", make_flat_stylebox(p_config.dark_color_3, p_config.base_margin / 2, 0, p_config.base_margin / 2, 0, p_config.corner_radius)); + p_theme->set_stylebox("grabber_area", "VSlider", make_flat_stylebox(p_config.contrast_color_1, p_config.base_margin / 2, 0, p_config.base_margin / 2, 0, p_config.corner_radius)); + p_theme->set_stylebox("grabber_area_highlight", "VSlider", make_flat_stylebox(p_config.contrast_color_1, p_config.base_margin / 2, 0, p_config.base_margin / 2, 0)); + p_theme->set_constant("center_grabber", "VSlider", 0); + p_theme->set_constant("grabber_offset", "VSlider", 0); + } + + // Labels. + { + // RichTextLabel. + + p_theme->set_stylebox("normal", "RichTextLabel", p_config.tree_panel_style); + p_theme->set_stylebox("focus", "RichTextLabel", make_empty_stylebox()); + + p_theme->set_color("default_color", "RichTextLabel", p_config.font_color); + p_theme->set_color("font_shadow_color", "RichTextLabel", Color(0, 0, 0, 0)); + p_theme->set_color("font_outline_color", "RichTextLabel", p_config.font_outline_color); + p_theme->set_color("selection_color", "RichTextLabel", p_config.selection_color); + + p_theme->set_constant("shadow_offset_x", "RichTextLabel", 1 * EDSCALE); + p_theme->set_constant("shadow_offset_y", "RichTextLabel", 1 * EDSCALE); + p_theme->set_constant("shadow_outline_size", "RichTextLabel", 1 * EDSCALE); + p_theme->set_constant("outline_size", "RichTextLabel", 0); + + // Label. + + p_theme->set_stylebox("normal", "Label", p_config.base_empty_style); + + p_theme->set_color("font_color", "Label", p_config.font_color); + p_theme->set_color("font_shadow_color", "Label", Color(0, 0, 0, 0)); + p_theme->set_color("font_outline_color", "Label", p_config.font_outline_color); + + p_theme->set_constant("shadow_offset_x", "Label", 1 * EDSCALE); + p_theme->set_constant("shadow_offset_y", "Label", 1 * EDSCALE); + p_theme->set_constant("shadow_outline_size", "Label", 1 * EDSCALE); + p_theme->set_constant("line_spacing", "Label", 3 * EDSCALE); + p_theme->set_constant("outline_size", "Label", 0); + } + + // SpinBox. + p_theme->set_icon("updown", "SpinBox", p_theme->get_icon(SNAME("GuiSpinboxUpdown"), EditorStringName(EditorIcons))); + p_theme->set_icon("updown_disabled", "SpinBox", p_theme->get_icon(SNAME("GuiSpinboxUpdownDisabled"), EditorStringName(EditorIcons))); + + // ProgressBar. + p_theme->set_stylebox("background", "ProgressBar", make_stylebox(p_theme->get_icon(SNAME("GuiProgressBar"), EditorStringName(EditorIcons)), 4, 4, 4, 4, 0, 0, 0, 0)); + p_theme->set_stylebox("fill", "ProgressBar", make_stylebox(p_theme->get_icon(SNAME("GuiProgressFill"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 2, 1, 2, 1)); + p_theme->set_color("font_color", "ProgressBar", p_config.font_color); + p_theme->set_color("font_outline_color", "ProgressBar", p_config.font_outline_color); + p_theme->set_constant("outline_size", "ProgressBar", 0); + + // GraphEdit and related nodes. + { + // GraphEdit. + + p_theme->set_stylebox("panel", "GraphEdit", p_config.tree_panel_style); + p_theme->set_stylebox("menu_panel", "GraphEdit", make_flat_stylebox(p_config.dark_color_1 * Color(1, 1, 1, 0.6), 4, 2, 4, 2, 3)); + + if (p_config.dark_theme) { + p_theme->set_color("grid_major", "GraphEdit", Color(1.0, 1.0, 1.0, 0.1)); + p_theme->set_color("grid_minor", "GraphEdit", Color(1.0, 1.0, 1.0, 0.05)); + } else { + p_theme->set_color("grid_major", "GraphEdit", Color(0.0, 0.0, 0.0, 0.15)); + p_theme->set_color("grid_minor", "GraphEdit", Color(0.0, 0.0, 0.0, 0.07)); + } + p_theme->set_color("selection_fill", "GraphEdit", p_theme->get_color(SNAME("box_selection_fill_color"), EditorStringName(Editor))); + p_theme->set_color("selection_stroke", "GraphEdit", p_theme->get_color(SNAME("box_selection_stroke_color"), EditorStringName(Editor))); + p_theme->set_color("activity", "GraphEdit", p_config.accent_color); + + p_theme->set_icon("zoom_out", "GraphEdit", p_theme->get_icon(SNAME("ZoomLess"), EditorStringName(EditorIcons))); + p_theme->set_icon("zoom_in", "GraphEdit", p_theme->get_icon(SNAME("ZoomMore"), EditorStringName(EditorIcons))); + p_theme->set_icon("zoom_reset", "GraphEdit", p_theme->get_icon(SNAME("ZoomReset"), EditorStringName(EditorIcons))); + p_theme->set_icon("grid_toggle", "GraphEdit", p_theme->get_icon(SNAME("GridToggle"), EditorStringName(EditorIcons))); + p_theme->set_icon("minimap_toggle", "GraphEdit", p_theme->get_icon(SNAME("GridMinimap"), EditorStringName(EditorIcons))); + p_theme->set_icon("snapping_toggle", "GraphEdit", p_theme->get_icon(SNAME("SnapGrid"), EditorStringName(EditorIcons))); + p_theme->set_icon("layout", "GraphEdit", p_theme->get_icon(SNAME("GridLayout"), EditorStringName(EditorIcons))); + + // GraphEditMinimap. + { + Ref style_minimap_bg = make_flat_stylebox(p_config.dark_color_1, 0, 0, 0, 0); + style_minimap_bg->set_border_color(p_config.dark_color_3); + style_minimap_bg->set_border_width_all(1); + p_theme->set_stylebox("panel", "GraphEditMinimap", style_minimap_bg); + + Ref style_minimap_camera; + Ref style_minimap_node; + if (p_config.dark_theme) { + style_minimap_camera = make_flat_stylebox(Color(0.65, 0.65, 0.65, 0.2), 0, 0, 0, 0); + style_minimap_camera->set_border_color(Color(0.65, 0.65, 0.65, 0.45)); + style_minimap_node = make_flat_stylebox(Color(1, 1, 1), 0, 0, 0, 0); + } else { + style_minimap_camera = make_flat_stylebox(Color(0.38, 0.38, 0.38, 0.2), 0, 0, 0, 0); + style_minimap_camera->set_border_color(Color(0.38, 0.38, 0.38, 0.45)); + style_minimap_node = make_flat_stylebox(Color(0, 0, 0), 0, 0, 0, 0); + } + style_minimap_camera->set_border_width_all(1); + style_minimap_node->set_anti_aliased(false); + p_theme->set_stylebox("camera", "GraphEditMinimap", style_minimap_camera); + p_theme->set_stylebox("node", "GraphEditMinimap", style_minimap_node); + + const Color minimap_resizer_color = p_config.dark_theme ? Color(1, 1, 1, 0.65) : Color(0, 0, 0, 0.65); + p_theme->set_icon("resizer", "GraphEditMinimap", p_theme->get_icon(SNAME("GuiResizerTopLeft"), EditorStringName(EditorIcons))); + p_theme->set_color("resizer_color", "GraphEditMinimap", minimap_resizer_color); + } + + // GraphElement & GraphNode. + { + const int gn_margin_top = 2; + const int gn_margin_side = 2; + const int gn_margin_bottom = 2; + + const Color gn_bg_color = p_config.dark_theme ? p_config.dark_color_3 : p_config.dark_color_1.lerp(p_config.mono_color, 0.09); + const Color gn_selected_border_color = gn_bg_color.lerp(p_config.accent_color, 0.275); + const Color gn_frame_bg = gn_bg_color.lerp(p_config.tree_panel_style->get_bg_color(), 0.3); + + Ref gn_panel_style = make_flat_stylebox(gn_frame_bg, gn_margin_side, gn_margin_top, gn_margin_side, gn_margin_bottom, p_config.corner_radius); + gn_panel_style->set_border_width_all(p_config.border_width); + gn_panel_style->set_border_color(gn_bg_color); + gn_panel_style->set_corner_radius_individual(0, 0, p_config.corner_radius * EDSCALE, p_config.corner_radius * EDSCALE); + gn_panel_style->set_expand_margin(SIDE_TOP, 17 * EDSCALE); + + Ref gn_panel_selected_style = make_flat_stylebox(gn_frame_bg, gn_margin_side, gn_margin_top, gn_margin_side, gn_margin_bottom, p_config.corner_radius); + gn_panel_selected_style->set_border_width_all(2 * EDSCALE + p_config.border_width); + gn_panel_selected_style->set_border_color(gn_selected_border_color); + gn_panel_selected_style->set_corner_radius_individual(0, 0, p_config.corner_radius * EDSCALE, p_config.corner_radius * EDSCALE); + gn_panel_selected_style->set_expand_margin(SIDE_TOP, 17 * EDSCALE); + + const int gn_titlebar_margin_left = 12; + const int gn_titlebar_margin_right = 4; // The rest is for the close button. + + Ref gn_titlebar_style = make_flat_stylebox(gn_bg_color, gn_titlebar_margin_left, gn_margin_top, gn_titlebar_margin_right, 0, p_config.corner_radius); + gn_titlebar_style->set_expand_margin(SIDE_TOP, 2 * EDSCALE); + gn_titlebar_style->set_corner_radius_individual(p_config.corner_radius * EDSCALE, p_config.corner_radius * EDSCALE, 0, 0); + + Ref gn_titlebar_selected_style = make_flat_stylebox(gn_selected_border_color, gn_titlebar_margin_left, gn_margin_top, gn_titlebar_margin_right, 0, p_config.corner_radius); + gn_titlebar_selected_style->set_corner_radius_individual(p_config.corner_radius * EDSCALE, p_config.corner_radius * EDSCALE, 0, 0); + gn_titlebar_selected_style->set_expand_margin(SIDE_TOP, 2 * EDSCALE); + + Color gn_decoration_color = p_config.dark_color_1.inverted(); + + // GraphElement. + + p_theme->set_stylebox("panel", "GraphElement", gn_panel_style); + p_theme->set_stylebox("panel_selected", "GraphElement", gn_panel_selected_style); + p_theme->set_stylebox("titlebar", "GraphElement", gn_titlebar_style); + p_theme->set_stylebox("titlebar_selected", "GraphElement", gn_titlebar_selected_style); + + p_theme->set_color("resizer_color", "GraphElement", gn_decoration_color); + p_theme->set_icon("resizer", "GraphElement", p_theme->get_icon(SNAME("GuiResizer"), EditorStringName(EditorIcons))); + + // GraphNode. + + Ref gn_slot_style = make_empty_stylebox(12, 0, 12, 0); + + p_theme->set_stylebox("panel", "GraphNode", gn_panel_style); + p_theme->set_stylebox("panel_selected", "GraphNode", gn_panel_selected_style); + p_theme->set_stylebox("titlebar", "GraphNode", gn_titlebar_style); + p_theme->set_stylebox("titlebar_selected", "GraphNode", gn_titlebar_selected_style); + p_theme->set_stylebox("slot", "GraphNode", gn_slot_style); + + p_theme->set_color("resizer_color", "GraphNode", gn_decoration_color); + + p_theme->set_constant("port_h_offset", "GraphNode", 0); + p_theme->set_constant("separation", "GraphNode", 1 * EDSCALE); + + Ref port_icon = p_theme->get_icon(SNAME("GuiGraphNodePort"), EditorStringName(EditorIcons)); + // The true size is 24x24 This is necessary for sharp port icons at high zoom levels in GraphEdit (up to ~200%). + port_icon->set_size_override(Size2(12, 12)); + p_theme->set_icon("port", "GraphNode", port_icon); + + // GraphNode's title Label. + p_theme->set_type_variation("GraphNodeTitleLabel", "Label"); + p_theme->set_stylebox("normal", "GraphNodeTitleLabel", make_empty_stylebox(0, 0, 0, 0)); + p_theme->set_color("font_color", "GraphNodeTitleLabel", p_config.font_color); + p_theme->set_constant("line_spacing", "GraphNodeTitleLabel", 3 * EDSCALE); + } + } + + // ColorPicker and related nodes. + { + // ColorPicker. + + p_theme->set_constant("margin", "ColorPicker", p_config.base_margin); + p_theme->set_constant("sv_width", "ColorPicker", 256 * EDSCALE); + p_theme->set_constant("sv_height", "ColorPicker", 256 * EDSCALE); + p_theme->set_constant("h_width", "ColorPicker", 30 * EDSCALE); + p_theme->set_constant("label_width", "ColorPicker", 10 * EDSCALE); + p_theme->set_constant("center_slider_grabbers", "ColorPicker", 1); + + p_theme->set_icon("screen_picker", "ColorPicker", p_theme->get_icon(SNAME("ColorPick"), EditorStringName(EditorIcons))); + p_theme->set_icon("shape_circle", "ColorPicker", p_theme->get_icon(SNAME("PickerShapeCircle"), EditorStringName(EditorIcons))); + p_theme->set_icon("shape_rect", "ColorPicker", p_theme->get_icon(SNAME("PickerShapeRectangle"), EditorStringName(EditorIcons))); + p_theme->set_icon("shape_rect_wheel", "ColorPicker", p_theme->get_icon(SNAME("PickerShapeRectangleWheel"), EditorStringName(EditorIcons))); + p_theme->set_icon("add_preset", "ColorPicker", p_theme->get_icon(SNAME("Add"), EditorStringName(EditorIcons))); + p_theme->set_icon("sample_bg", "ColorPicker", p_theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons))); + p_theme->set_icon("sample_revert", "ColorPicker", p_theme->get_icon(SNAME("Reload"), EditorStringName(EditorIcons))); + p_theme->set_icon("overbright_indicator", "ColorPicker", p_theme->get_icon(SNAME("OverbrightIndicator"), EditorStringName(EditorIcons))); + p_theme->set_icon("bar_arrow", "ColorPicker", p_theme->get_icon(SNAME("ColorPickerBarArrow"), EditorStringName(EditorIcons))); + p_theme->set_icon("picker_cursor", "ColorPicker", p_theme->get_icon(SNAME("PickerCursor"), EditorStringName(EditorIcons))); + + // ColorPickerButton. + p_theme->set_icon("bg", "ColorPickerButton", p_theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons))); + + // ColorPresetButton. + p_theme->set_stylebox("preset_fg", "ColorPresetButton", make_flat_stylebox(Color(1, 1, 1), 2, 2, 2, 2, 2)); + p_theme->set_icon("preset_bg", "ColorPresetButton", p_theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons))); + p_theme->set_icon("overbright_indicator", "ColorPresetButton", p_theme->get_icon(SNAME("OverbrightIndicator"), EditorStringName(EditorIcons))); + } +} + +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); + p_theme->set_constant("sidebar_button_icon_separation", "ProjectManager", int(6 * EDSCALE)); + + // ProjectTag. + { + p_theme->set_type_variation("ProjectTag", "Button"); + + Ref tag = p_config.button_style->duplicate(); + tag->set_bg_color(p_config.dark_theme ? tag->get_bg_color().lightened(0.2) : tag->get_bg_color().darkened(0.2)); + tag->set_corner_radius(CORNER_TOP_LEFT, 0); + tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0); + tag->set_corner_radius(CORNER_TOP_RIGHT, 4); + tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4); + p_theme->set_stylebox("normal", "ProjectTag", tag); + + tag = p_config.button_style_hover->duplicate(); + tag->set_corner_radius(CORNER_TOP_LEFT, 0); + tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0); + tag->set_corner_radius(CORNER_TOP_RIGHT, 4); + tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4); + p_theme->set_stylebox("hover", "ProjectTag", tag); + + tag = p_config.button_style_pressed->duplicate(); + tag->set_corner_radius(CORNER_TOP_LEFT, 0); + tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0); + tag->set_corner_radius(CORNER_TOP_RIGHT, 4); + tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4); + p_theme->set_stylebox("pressed", "ProjectTag", tag); + } + } + + // Editor and main screen. + { + // Editor background. + Color background_color_opaque = p_config.dark_color_2; + background_color_opaque.a = 1.0; + p_theme->set_color("background", EditorStringName(Editor), background_color_opaque); + p_theme->set_stylebox("Background", EditorStringName(EditorStyles), make_flat_stylebox(background_color_opaque, p_config.base_margin, p_config.base_margin, p_config.base_margin, p_config.base_margin)); + + p_theme->set_stylebox("PanelForeground", EditorStringName(EditorStyles), p_config.base_style); + + // Editor focus. + p_theme->set_stylebox("Focus", EditorStringName(EditorStyles), p_config.button_style_focus); + // Use a less opaque color to be less distracting for the 2D and 3D editor viewports. + Ref style_widget_focus_viewport = p_config.button_style_focus->duplicate(); + style_widget_focus_viewport->set_border_color(p_config.accent_color * Color(1, 1, 1, 0.5)); + p_theme->set_stylebox("FocusViewport", EditorStringName(EditorStyles), style_widget_focus_viewport); + + // This stylebox is used in 3d and 2d viewports (no borders). + Ref style_content_panel_vp = p_config.content_panel_style->duplicate(); + style_content_panel_vp->set_content_margin_individual(p_config.border_width * 2, p_config.base_margin * EDSCALE, p_config.border_width * 2, p_config.border_width * 2); + p_theme->set_stylebox("Content", EditorStringName(EditorStyles), style_content_panel_vp); + + // 2D/CanvasItem editor + Ref style_canvas_editor_info = make_flat_stylebox(Color(0.0, 0.0, 0.0, 0.2)); + style_canvas_editor_info->set_expand_margin_all(4 * EDSCALE); + p_theme->set_stylebox("CanvasItemInfoOverlay", EditorStringName(EditorStyles), style_canvas_editor_info); + + // 3D/Spatial editor. + Ref style_info_3d_viewport = p_config.base_style->duplicate(); + style_info_3d_viewport->set_bg_color(style_info_3d_viewport->get_bg_color() * Color(1, 1, 1, 0.5)); + style_info_3d_viewport->set_border_width_all(0); + p_theme->set_stylebox("Information3dViewport", EditorStringName(EditorStyles), style_info_3d_viewport); + + // 2D and 3D contextual toolbar. + // Use a custom stylebox to make contextual menu items stand out from the rest. + // This helps with editor usability as contextual menu items change when selecting nodes, + // even though it may not be immediately obvious at first. + Ref toolbar_stylebox = memnew(StyleBoxFlat); + toolbar_stylebox->set_bg_color(p_config.accent_color * Color(1, 1, 1, 0.1)); + toolbar_stylebox->set_anti_aliased(false); + // Add an underline to the StyleBox, but prevent its minimum vertical size from changing. + toolbar_stylebox->set_border_color(p_config.accent_color); + toolbar_stylebox->set_border_width(SIDE_BOTTOM, Math::round(2 * EDSCALE)); + toolbar_stylebox->set_content_margin(SIDE_BOTTOM, 0); + toolbar_stylebox->set_expand_margin_individual(4 * EDSCALE, 2 * EDSCALE, 4 * EDSCALE, 4 * EDSCALE); + p_theme->set_stylebox("ContextualToolbar", EditorStringName(EditorStyles), toolbar_stylebox); + + // Script editor. + p_theme->set_stylebox("ScriptEditorPanel", EditorStringName(EditorStyles), make_empty_stylebox(p_config.base_margin, 0, p_config.base_margin, p_config.base_margin)); + p_theme->set_stylebox("ScriptEditorPanelFloating", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0)); + p_theme->set_stylebox("ScriptEditor", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0)); + + // Bottom panel. + Ref style_bottom_panel = p_config.content_panel_style->duplicate(); + style_bottom_panel->set_corner_radius_all(p_config.corner_radius * EDSCALE); + p_theme->set_stylebox("BottomPanel", EditorStringName(EditorStyles), style_bottom_panel); + + // Main menu. + p_theme->set_stylebox("MenuHover", EditorStringName(EditorStyles), p_config.button_style_hover); + } + + // Editor GUI widgets. + { + // EditorSpinSlider. + p_theme->set_color("label_color", "EditorSpinSlider", p_config.font_color); + p_theme->set_color("read_only_label_color", "EditorSpinSlider", p_config.font_readonly_color); + + Ref editor_spin_label_bg = p_config.base_style->duplicate(); + editor_spin_label_bg->set_bg_color(p_config.dark_color_3); + editor_spin_label_bg->set_border_width_all(0); + p_theme->set_stylebox("label_bg", "EditorSpinSlider", editor_spin_label_bg); + + // Launch Pad and Play buttons + Ref style_launch_pad = make_flat_stylebox(p_config.dark_color_1, 2 * EDSCALE, 0, 2 * EDSCALE, 0, p_config.corner_radius); + style_launch_pad->set_corner_radius_all(p_config.corner_radius * EDSCALE); + p_theme->set_stylebox("LaunchPadNormal", EditorStringName(EditorStyles), style_launch_pad); + Ref style_launch_pad_movie = style_launch_pad->duplicate(); + style_launch_pad_movie->set_bg_color(p_config.accent_color * Color(1, 1, 1, 0.1)); + style_launch_pad_movie->set_border_color(p_config.accent_color); + style_launch_pad_movie->set_border_width_all(Math::round(2 * EDSCALE)); + p_theme->set_stylebox("LaunchPadMovieMode", EditorStringName(EditorStyles), style_launch_pad_movie); + + p_theme->set_stylebox("MovieWriterButtonNormal", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0)); + Ref style_write_movie_button = p_config.button_style_pressed->duplicate(); + style_write_movie_button->set_bg_color(p_config.accent_color); + style_write_movie_button->set_corner_radius_all(p_config.corner_radius * EDSCALE); + style_write_movie_button->set_content_margin(SIDE_TOP, 0); + style_write_movie_button->set_content_margin(SIDE_BOTTOM, 0); + style_write_movie_button->set_content_margin(SIDE_LEFT, 0); + style_write_movie_button->set_content_margin(SIDE_RIGHT, 0); + style_write_movie_button->set_expand_margin(SIDE_RIGHT, 2 * EDSCALE); + p_theme->set_stylebox("MovieWriterButtonPressed", EditorStringName(EditorStyles), style_write_movie_button); + } + + // Standard GUI variations. + { + // Custom theme type for MarginContainer with 4px margins. + p_theme->set_type_variation("MarginContainer4px", "MarginContainer"); + p_theme->set_constant("margin_left", "MarginContainer4px", 4 * EDSCALE); + p_theme->set_constant("margin_top", "MarginContainer4px", 4 * EDSCALE); + p_theme->set_constant("margin_right", "MarginContainer4px", 4 * EDSCALE); + p_theme->set_constant("margin_bottom", "MarginContainer4px", 4 * EDSCALE); + + // Header LinkButton variation. + p_theme->set_type_variation("HeaderSmallLink", "LinkButton"); + p_theme->set_font("font", "HeaderSmallLink", p_theme->get_font(SNAME("font"), SNAME("HeaderSmall"))); + p_theme->set_font_size("font_size", "HeaderSmallLink", p_theme->get_font_size(SNAME("font_size"), SNAME("HeaderSmall"))); + + // Flat button variations. + { + Ref style_flat_button = make_empty_stylebox(); + for (int i = 0; i < 4; i++) { + style_flat_button->set_content_margin((Side)i, p_config.button_style->get_margin((Side)i) + p_config.button_style->get_border_width((Side)i)); + } + + Ref style_flat_button_pressed = p_config.button_style_pressed->duplicate(); + Color flat_pressed_color = p_config.dark_color_1.lightened(0.24).lerp(p_config.accent_color, 0.2) * Color(0.8, 0.8, 0.8, 0.85); + if (p_config.dark_theme) { + flat_pressed_color = p_config.dark_color_1.lerp(p_config.accent_color, 0.12) * Color(0.6, 0.6, 0.6, 0.85); + } + style_flat_button_pressed->set_bg_color(flat_pressed_color); + + p_theme->set_stylebox("normal", "FlatButton", style_flat_button); + p_theme->set_stylebox("hover", "FlatButton", style_flat_button); + p_theme->set_stylebox("pressed", "FlatButton", style_flat_button_pressed); + p_theme->set_stylebox("disabled", "FlatButton", style_flat_button); + + p_theme->set_stylebox("normal", "FlatMenuButton", style_flat_button); + p_theme->set_stylebox("hover", "FlatMenuButton", style_flat_button); + p_theme->set_stylebox("pressed", "FlatMenuButton", style_flat_button_pressed); + p_theme->set_stylebox("disabled", "FlatMenuButton", style_flat_button); + + // Variation for Editor Log filter buttons. + + p_theme->set_type_variation("EditorLogFilterButton", "Button"); + // When pressed, don't tint the icons with the accent color, just leave them normal. + p_theme->set_color("icon_pressed_color", "EditorLogFilterButton", p_config.icon_normal_color); + // When unpressed, dim the icons. + p_theme->set_color("icon_normal_color", "EditorLogFilterButton", p_config.icon_disabled_color); + + // When pressed, add a small bottom border to the buttons to better show their active state, + // similar to active tabs. + Ref editor_log_button_pressed = style_flat_button_pressed->duplicate(); + editor_log_button_pressed->set_border_width(SIDE_BOTTOM, 2 * EDSCALE); + editor_log_button_pressed->set_border_color(p_config.accent_color); + p_theme->set_stylebox("pressed", "EditorLogFilterButton", editor_log_button_pressed); + } + + // Complex editor windows. + { + Ref style_complex_window = p_config.window_style->duplicate(); + style_complex_window->set_bg_color(p_config.dark_color_2); + style_complex_window->set_border_color(p_config.dark_color_2); + p_theme->set_stylebox("panel", "EditorSettingsDialog", style_complex_window); + p_theme->set_stylebox("panel", "ProjectSettingsEditor", style_complex_window); + p_theme->set_stylebox("panel", "EditorAbout", style_complex_window); + } + + // InspectorActionButton. + { + p_theme->set_type_variation("InspectorActionButton", "Button"); + + const float action_extra_margin = 32 * EDSCALE; + p_theme->set_constant("h_separation", "InspectorActionButton", action_extra_margin); + + Color color_inspector_action = p_config.dark_color_1.lerp(p_config.mono_color, 0.12); + color_inspector_action.a = 0.5; + Ref style_inspector_action = p_config.button_style->duplicate(); + style_inspector_action->set_bg_color(color_inspector_action); + style_inspector_action->set_content_margin(SIDE_RIGHT, action_extra_margin); + p_theme->set_stylebox("normal", "InspectorActionButton", style_inspector_action); + + style_inspector_action = p_config.button_style_hover->duplicate(); + style_inspector_action->set_content_margin(SIDE_RIGHT, action_extra_margin); + p_theme->set_stylebox("hover", "InspectorActionButton", style_inspector_action); + + style_inspector_action = p_config.button_style_pressed->duplicate(); + style_inspector_action->set_content_margin(SIDE_RIGHT, action_extra_margin); + p_theme->set_stylebox("pressed", "InspectorActionButton", style_inspector_action); + + style_inspector_action = p_config.button_style_disabled->duplicate(); + style_inspector_action->set_content_margin(SIDE_RIGHT, action_extra_margin); + p_theme->set_stylebox("disabled", "InspectorActionButton", style_inspector_action); + } + + // Buttons in material previews. + { + const Color dim_light_color = p_config.icon_normal_color.darkened(0.24); + const Color dim_light_highlighted_color = p_config.icon_normal_color.darkened(0.18); + Ref sb_empty_borderless = make_empty_stylebox(); + + p_theme->set_type_variation("PreviewLightButton", "Button"); + // When pressed, don't use the accent color tint. When unpressed, dim the icon. + p_theme->set_color("icon_normal_color", "PreviewLightButton", dim_light_color); + p_theme->set_color("icon_focus_color", "PreviewLightButton", dim_light_color); + p_theme->set_color("icon_pressed_color", "PreviewLightButton", p_config.icon_normal_color); + p_theme->set_color("icon_hover_pressed_color", "PreviewLightButton", p_config.icon_normal_color); + // Unpressed icon is dim, so use a dim highlight. + p_theme->set_color("icon_hover_color", "PreviewLightButton", dim_light_highlighted_color); + + p_theme->set_stylebox("normal", "PreviewLightButton", sb_empty_borderless); + p_theme->set_stylebox("hover", "PreviewLightButton", sb_empty_borderless); + p_theme->set_stylebox("focus", "PreviewLightButton", sb_empty_borderless); + p_theme->set_stylebox("pressed", "PreviewLightButton", sb_empty_borderless); + } + + // TabContainerOdd variation. + { + // Can be used on tabs against the base color background (e.g. nested tabs). + p_theme->set_type_variation("TabContainerOdd", "TabContainer"); + + Ref style_tab_selected_odd = p_theme->get_stylebox(SNAME("tab_selected"), SNAME("TabContainer"))->duplicate(); + style_tab_selected_odd->set_bg_color(p_config.disabled_bg_color); + p_theme->set_stylebox("tab_selected", "TabContainerOdd", style_tab_selected_odd); + + Ref style_content_panel_odd = p_config.content_panel_style->duplicate(); + style_content_panel_odd->set_bg_color(p_config.disabled_bg_color); + p_theme->set_stylebox("panel", "TabContainerOdd", style_content_panel_odd); + } + + // EditorValidationPanel. + p_theme->set_stylebox("panel", "EditorValidationPanel", p_config.tree_panel_style); + + // ControlEditor. + { + p_theme->set_type_variation("ControlEditorPopupPanel", "PopupPanel"); + + Ref control_editor_popup_style = p_config.popup_style->duplicate(); + control_editor_popup_style->set_shadow_size(0); + control_editor_popup_style->set_content_margin(SIDE_LEFT, p_config.base_margin * EDSCALE); + control_editor_popup_style->set_content_margin(SIDE_TOP, p_config.base_margin * EDSCALE); + control_editor_popup_style->set_content_margin(SIDE_RIGHT, p_config.base_margin * EDSCALE); + control_editor_popup_style->set_content_margin(SIDE_BOTTOM, p_config.base_margin * EDSCALE); + control_editor_popup_style->set_border_width_all(0); + + p_theme->set_stylebox("panel", "ControlEditorPopupPanel", control_editor_popup_style); + } + } + + // Editor inspector. + { + // Sub-inspectors. + for (int i = 0; i < 16; i++) { + Color si_base_color = p_config.accent_color; + + 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"))); + + // Sub-inspector background. + Ref sub_inspector_bg = p_config.base_style->duplicate(); + sub_inspector_bg->set_bg_color(p_config.dark_color_1.lerp(si_base_color, 0.08)); + sub_inspector_bg->set_border_width_all(2 * EDSCALE); + sub_inspector_bg->set_border_color(si_base_color * Color(0.7, 0.7, 0.7, 0.8)); + sub_inspector_bg->set_content_margin_all(4 * EDSCALE); + sub_inspector_bg->set_corner_radius(CORNER_TOP_LEFT, 0); + sub_inspector_bg->set_corner_radius(CORNER_TOP_RIGHT, 0); + + p_theme->set_stylebox("sub_inspector_bg" + itos(i), EditorStringName(Editor), sub_inspector_bg); + + // EditorProperty background while it has a sub-inspector open. + Ref bg_color = make_flat_stylebox(si_base_color * Color(0.7, 0.7, 0.7, 0.8), 0, 0, 0, 0, p_config.corner_radius); + bg_color->set_anti_aliased(false); + bg_color->set_corner_radius(CORNER_BOTTOM_LEFT, 0); + bg_color->set_corner_radius(CORNER_BOTTOM_RIGHT, 0); + + p_theme->set_stylebox("sub_inspector_property_bg" + itos(i), EditorStringName(Editor), bg_color); + } + + p_theme->set_color("sub_inspector_property_color", EditorStringName(Editor), p_config.dark_theme ? Color(1, 1, 1, 1) : Color(0, 0, 0, 1)); + + // EditorProperty. + + Ref style_property_bg = p_config.base_style->duplicate(); + style_property_bg->set_bg_color(p_config.highlight_color); + style_property_bg->set_border_width_all(0); + + Ref style_property_child_bg = p_config.base_style->duplicate(); + 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_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); + p_theme->set_constant("v_separation", "EditorProperty", p_config.increased_margin * EDSCALE); + + const Color property_color = p_config.font_color.lerp(Color(0.5, 0.5, 0.5), 0.5); + const Color readonly_color = property_color.lerp(p_config.dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.25); + const Color readonly_warning_color = p_config.error_color.lerp(p_config.dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.25); + + p_theme->set_color("property_color", "EditorProperty", property_color); + p_theme->set_color("readonly_color", "EditorProperty", readonly_color); + p_theme->set_color("warning_color", "EditorProperty", p_config.warning_color); + p_theme->set_color("readonly_warning_color", "EditorProperty", readonly_warning_color); + + Ref style_property_group_note = p_config.base_style->duplicate(); + Color property_group_note_color = p_config.accent_color; + property_group_note_color.a = 0.1; + style_property_group_note->set_bg_color(property_group_note_color); + p_theme->set_stylebox("bg_group_note", "EditorProperty", style_property_group_note); + + // EditorInspectorSection. + + Color inspector_section_color = p_config.font_color.lerp(Color(0.5, 0.5, 0.5), 0.35); + p_theme->set_color("font_color", "EditorInspectorSection", inspector_section_color); + + Color inspector_indent_color = p_config.accent_color; + inspector_indent_color.a = 0.2; + Ref inspector_indent_style = make_flat_stylebox(inspector_indent_color, 2.0 * EDSCALE, 0, 2.0 * EDSCALE, 0); + p_theme->set_stylebox("indent_box", "EditorInspectorSection", inspector_indent_style); + p_theme->set_constant("indent_size", "EditorInspectorSection", 6.0 * EDSCALE); + + Color prop_category_color = p_config.dark_color_1.lerp(p_config.mono_color, 0.12); + Color prop_section_color = p_config.dark_color_1.lerp(p_config.mono_color, 0.09); + Color prop_subsection_color = p_config.dark_color_1.lerp(p_config.mono_color, 0.06); + + p_theme->set_color("prop_category", EditorStringName(Editor), prop_category_color); + p_theme->set_color("prop_section", EditorStringName(Editor), prop_section_color); + p_theme->set_color("prop_subsection", EditorStringName(Editor), prop_subsection_color); + + // EditorInspectorCategory. + + Ref category_bg = p_config.base_style->duplicate(); + category_bg->set_bg_color(prop_category_color); + category_bg->set_border_color(prop_category_color); + p_theme->set_stylebox("bg", "EditorInspectorCategory", category_bg); + + p_theme->set_constant("inspector_margin", EditorStringName(Editor), 12 * EDSCALE); + + // Dictionary editor. + + // Expand to the left and right by 4px to compensate for the dictionary editor margins. + Ref style_dictionary_add_item = make_flat_stylebox(prop_subsection_color, 0, 4, 0, 4, p_config.corner_radius); + style_dictionary_add_item->set_expand_margin(SIDE_LEFT, 4 * EDSCALE); + style_dictionary_add_item->set_expand_margin(SIDE_RIGHT, 4 * EDSCALE); + p_theme->set_stylebox("DictionaryAddItem", EditorStringName(EditorStyles), style_dictionary_add_item); + } + + // Editor help. + { + Ref style_editor_help = p_config.base_style->duplicate(); + style_editor_help->set_bg_color(p_config.dark_color_2); + style_editor_help->set_border_color(p_config.dark_color_3); + p_theme->set_stylebox("background", "EditorHelp", style_editor_help); + + const Color kbd_color = p_config.font_color.lerp(Color(0.5, 0.5, 0.5), 0.5); + + p_theme->set_color("title_color", "EditorHelp", p_config.accent_color); + p_theme->set_color("headline_color", "EditorHelp", p_config.mono_color); + p_theme->set_color("text_color", "EditorHelp", p_config.font_color); + p_theme->set_color("comment_color", "EditorHelp", p_config.font_color * Color(1, 1, 1, 0.6)); + p_theme->set_color("symbol_color", "EditorHelp", p_config.font_color * Color(1, 1, 1, 0.6)); + p_theme->set_color("value_color", "EditorHelp", p_config.font_color * Color(1, 1, 1, 0.6)); + p_theme->set_color("qualifier_color", "EditorHelp", p_config.font_color * Color(1, 1, 1, 0.8)); + p_theme->set_color("type_color", "EditorHelp", p_config.accent_color.lerp(p_config.font_color, 0.5)); + p_theme->set_color("selection_color", "EditorHelp", p_config.selection_color); + p_theme->set_color("link_color", "EditorHelp", p_config.accent_color.lerp(p_config.mono_color, 0.8)); + p_theme->set_color("code_color", "EditorHelp", p_config.accent_color.lerp(p_config.mono_color, 0.6)); + p_theme->set_color("kbd_color", "EditorHelp", p_config.accent_color.lerp(kbd_color, 0.6)); + p_theme->set_color("code_bg_color", "EditorHelp", p_config.dark_color_3); + p_theme->set_color("kbd_bg_color", "EditorHelp", p_config.dark_color_1); + p_theme->set_color("param_bg_color", "EditorHelp", p_config.dark_color_1); + p_theme->set_constant("line_separation", "EditorHelp", Math::round(6 * EDSCALE)); + p_theme->set_constant("table_h_separation", "EditorHelp", 16 * EDSCALE); + p_theme->set_constant("table_v_separation", "EditorHelp", 6 * EDSCALE); + p_theme->set_constant("text_highlight_h_padding", "EditorHelp", 1 * EDSCALE); + p_theme->set_constant("text_highlight_v_padding", "EditorHelp", 2 * EDSCALE); + } + + // Asset Library. + p_theme->set_stylebox("bg", "AssetLib", p_config.base_empty_style); + p_theme->set_stylebox("panel", "AssetLib", p_config.content_panel_style); + p_theme->set_color("status_color", "AssetLib", Color(0.5, 0.5, 0.5)); // FIXME: Use a defined color instead. + p_theme->set_icon("dismiss", "AssetLib", p_theme->get_icon(SNAME("Close"), EditorStringName(EditorIcons))); + + // Debugger. + { + Ref debugger_panel_style = p_config.content_panel_style->duplicate(); + debugger_panel_style->set_border_width(SIDE_BOTTOM, 0); + p_theme->set_stylebox("DebuggerPanel", EditorStringName(EditorStyles), debugger_panel_style); + + // This pattern of get_font()->get_height(get_font_size()) is used quite a lot and is very verbose. + // FIXME: Introduce Theme::get_font_height() / Control::get_theme_font_height() / Window::get_theme_font_height(). + const int offset_i1 = p_theme->get_font(SNAME("tab_selected"), SNAME("TabContainer"))->get_height(p_theme->get_font_size(SNAME("tab_selected"), SNAME("TabContainer"))); + const int offset_i2 = p_theme->get_stylebox(SNAME("tab_selected"), SNAME("TabContainer"))->get_minimum_size().height; + const int offset_i3 = p_theme->get_stylebox(SNAME("panel"), SNAME("TabContainer"))->get_content_margin(SIDE_TOP); + const int invisible_top_offset = offset_i1 + offset_i2 + offset_i3; + + Ref invisible_top_panel_style = p_config.content_panel_style->duplicate(); + invisible_top_panel_style->set_expand_margin(SIDE_TOP, -invisible_top_offset); + invisible_top_panel_style->set_content_margin(SIDE_TOP, 0); + p_theme->set_stylebox("BottomPanelDebuggerOverride", EditorStringName(EditorStyles), invisible_top_panel_style); + } + + // Resource and node editors. + { + // TextureRegion editor. + Ref style_texture_region_bg = p_config.tree_panel_style->duplicate(); + style_texture_region_bg->set_content_margin_all(0); + p_theme->set_stylebox("TextureRegionPreviewBG", EditorStringName(EditorStyles), style_texture_region_bg); + p_theme->set_stylebox("TextureRegionPreviewFG", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0)); + + // Theme editor. + { + p_theme->set_color("preview_picker_overlay_color", "ThemeEditor", Color(0.1, 0.1, 0.1, 0.25)); + + Color theme_preview_picker_bg_color = p_config.accent_color; + theme_preview_picker_bg_color.a = 0.2; + Ref theme_preview_picker_sb = make_flat_stylebox(theme_preview_picker_bg_color, 0, 0, 0, 0); + theme_preview_picker_sb->set_border_color(p_config.accent_color); + theme_preview_picker_sb->set_border_width_all(1.0 * EDSCALE); + p_theme->set_stylebox("preview_picker_overlay", "ThemeEditor", theme_preview_picker_sb); + + Color theme_preview_picker_label_bg_color = p_config.accent_color; + theme_preview_picker_label_bg_color.set_v(0.5); + Ref theme_preview_picker_label_sb = make_flat_stylebox(theme_preview_picker_label_bg_color, 4.0, 1.0, 4.0, 3.0); + p_theme->set_stylebox("preview_picker_label", "ThemeEditor", theme_preview_picker_label_sb); + + Ref style_theme_preview_tab = p_theme->get_stylebox(SNAME("tab_selected"), SNAME("TabContainerOdd"))->duplicate(); + style_theme_preview_tab->set_expand_margin(SIDE_BOTTOM, 5 * EDSCALE); + p_theme->set_stylebox("ThemeEditorPreviewFG", EditorStringName(EditorStyles), style_theme_preview_tab); + + Ref style_theme_preview_bg_tab = p_theme->get_stylebox(SNAME("tab_unselected"), SNAME("TabContainer"))->duplicate(); + style_theme_preview_bg_tab->set_expand_margin(SIDE_BOTTOM, 2 * EDSCALE); + p_theme->set_stylebox("ThemeEditorPreviewBG", EditorStringName(EditorStyles), style_theme_preview_bg_tab); + } + + // VisualShader editor. + p_theme->set_stylebox("label_style", "VShaderEditor", make_empty_stylebox(2, 1, 2, 1)); + + // StateMachine graph. + { + p_theme->set_stylebox("panel", "GraphStateMachine", p_config.tree_panel_style); + p_theme->set_stylebox("error_panel", "GraphStateMachine", p_config.tree_panel_style); + p_theme->set_color("error_color", "GraphStateMachine", p_config.error_color); + + const int sm_margin_side = 10 * EDSCALE; + const int sm_margin_bottom = 2; + const Color sm_bg_color = p_config.dark_theme ? p_config.dark_color_3 : p_config.dark_color_1.lerp(p_config.mono_color, 0.09); + + Ref sm_node_style = make_flat_stylebox(p_config.dark_color_3 * Color(1, 1, 1, 0.7), sm_margin_side, 24 * EDSCALE, sm_margin_side, sm_margin_bottom, p_config.corner_radius); + sm_node_style->set_border_width_all(p_config.border_width); + sm_node_style->set_border_color(sm_bg_color); + + Ref sm_node_selected_style = make_flat_stylebox(sm_bg_color * Color(1, 1, 1, 0.9), sm_margin_side, 24 * EDSCALE, sm_margin_side, sm_margin_bottom, p_config.corner_radius); + sm_node_selected_style->set_border_width_all(2 * EDSCALE + p_config.border_width); + sm_node_selected_style->set_border_color(p_config.accent_color * Color(1, 1, 1, 0.9)); + sm_node_selected_style->set_shadow_size(8 * EDSCALE); + sm_node_selected_style->set_shadow_color(p_config.shadow_color); + + Ref sm_node_playing_style = sm_node_selected_style->duplicate(); + sm_node_playing_style->set_border_color(p_config.warning_color); + sm_node_playing_style->set_shadow_color(p_config.warning_color * Color(1, 1, 1, 0.2)); + + p_theme->set_stylebox("node_frame", "GraphStateMachine", sm_node_style); + p_theme->set_stylebox("node_frame_selected", "GraphStateMachine", sm_node_selected_style); + p_theme->set_stylebox("node_frame_playing", "GraphStateMachine", sm_node_playing_style); + + Ref sm_node_start_style = sm_node_style->duplicate(); + sm_node_start_style->set_border_width_all(1 * EDSCALE); + sm_node_start_style->set_border_color(p_config.success_color.lightened(0.24)); + p_theme->set_stylebox("node_frame_start", "GraphStateMachine", sm_node_start_style); + + Ref sm_node_end_style = sm_node_style->duplicate(); + sm_node_end_style->set_border_width_all(1 * EDSCALE); + sm_node_end_style->set_border_color(p_config.error_color); + p_theme->set_stylebox("node_frame_end", "GraphStateMachine", sm_node_end_style); + + p_theme->set_font("node_title_font", "GraphStateMachine", p_theme->get_font(SNAME("font"), SNAME("Label"))); + p_theme->set_font_size("node_title_font_size", "GraphStateMachine", p_theme->get_font_size(SNAME("font_size"), SNAME("Label"))); + p_theme->set_color("node_title_font_color", "GraphStateMachine", p_config.font_color); + + p_theme->set_color("transition_color", "GraphStateMachine", p_config.font_color); + p_theme->set_color("transition_disabled_color", "GraphStateMachine", p_config.font_color * Color(1, 1, 1, 0.2)); + p_theme->set_color("transition_icon_color", "GraphStateMachine", Color(1, 1, 1)); + p_theme->set_color("transition_icon_disabled_color", "GraphStateMachine", Color(1, 1, 1, 0.2)); + p_theme->set_color("highlight_color", "GraphStateMachine", p_config.accent_color); + p_theme->set_color("highlight_disabled_color", "GraphStateMachine", p_config.accent_color * Color(1, 1, 1, 0.6)); + p_theme->set_color("guideline_color", "GraphStateMachine", p_config.font_color * Color(1, 1, 1, 0.3)); + + p_theme->set_color("playback_color", "GraphStateMachine", p_config.font_color); + p_theme->set_color("playback_background_color", "GraphStateMachine", p_config.font_color * Color(1, 1, 1, 0.3)); + } + } +} + +void EditorThemeManager::_generate_text_editor_defaults(ThemeConfiguration &p_config) { + // Adaptive colors for comments and elements with lower relevance. + const Color dim_color = Color(p_config.font_color, 0.5); + const float mono_value = p_config.mono_color.r; + const Color alpha1 = Color(mono_value, mono_value, mono_value, 0.07); + const Color alpha2 = Color(mono_value, mono_value, mono_value, 0.14); + const Color alpha3 = Color(mono_value, mono_value, mono_value, 0.27); + + /* clang-format off */ + // Syntax highlight token colors. + const Color symbol_color = p_config.dark_theme ? Color(0.67, 0.79, 1) : Color(0, 0, 0.61); + const Color keyword_color = p_config.dark_theme ? Color(1.0, 0.44, 0.52) : Color(0.9, 0.135, 0.51); + const Color control_flow_keyword_color = p_config.dark_theme ? Color(1.0, 0.55, 0.8) : Color(0.743, 0.12, 0.8); + const Color base_type_color = p_config.dark_theme ? Color(0.26, 1.0, 0.76) : Color(0, 0.6, 0.2); + const Color engine_type_color = p_config.dark_theme ? Color(0.56, 1, 0.86) : Color(0.11, 0.55, 0.4); + const Color user_type_color = p_config.dark_theme ? Color(0.78, 1, 0.93) : Color(0.18, 0.45, 0.4); + const Color comment_color = p_config.dark_theme ? dim_color : Color(0.08, 0.08, 0.08, 0.5); + const Color doc_comment_color = p_config.dark_theme ? Color(0.6, 0.7, 0.8, 0.8) : Color(0.15, 0.15, 0.4, 0.7); + const Color string_color = p_config.dark_theme ? Color(1, 0.93, 0.63) : Color(0.6, 0.42, 0); + + // Use the brightest background color on a light theme (which generally uses a negative contrast rate). + const Color te_background_color = p_config.dark_theme ? p_config.dark_color_2 : p_config.dark_color_3; + const Color completion_background_color = p_config.dark_theme ? p_config.base_color : p_config.dark_color_2; + const Color completion_selected_color = alpha1; + const Color completion_existing_color = alpha2; + // Same opacity as the scroll grabber editor icon. + const Color completion_scroll_color = Color(mono_value, mono_value, mono_value, 0.29); + const Color completion_scroll_hovered_color = Color(mono_value, mono_value, mono_value, 0.4); + const Color completion_font_color = p_config.font_color; + const Color text_color = p_config.font_color; + const Color line_number_color = dim_color; + const Color safe_line_number_color = p_config.dark_theme ? (dim_color * Color(1, 1.2, 1, 1.5)) : Color(0, 0.4, 0, 0.75); + const Color caret_color = p_config.mono_color; + const Color caret_background_color = p_config.mono_color.inverted(); + const Color text_selected_color = Color(0, 0, 0, 0); + const Color selection_color = p_config.selection_color; + const Color brace_mismatch_color = p_config.dark_theme ? p_config.error_color : Color(1, 0.08, 0, 1); + const Color current_line_color = alpha1; + const Color line_length_guideline_color = p_config.dark_theme ? p_config.base_color : p_config.dark_color_2; + const Color word_highlighted_color = alpha1; + const Color number_color = p_config.dark_theme ? Color(0.63, 1, 0.88) : Color(0, 0.55, 0.28, 1); + const Color function_color = p_config.dark_theme ? Color(0.34, 0.7, 1.0) : Color(0, 0.225, 0.9, 1); + const Color member_variable_color = p_config.dark_theme ? Color(0.34, 0.7, 1.0).lerp(p_config.mono_color, 0.6) : Color(0, 0.4, 0.68, 1); + const Color mark_color = Color(p_config.error_color.r, p_config.error_color.g, p_config.error_color.b, 0.3); + const Color bookmark_color = Color(0.08, 0.49, 0.98); + const Color breakpoint_color = p_config.dark_theme ? p_config.error_color : Color(1, 0.27, 0.2, 1); + const Color executing_line_color = Color(0.98, 0.89, 0.27); + const Color code_folding_color = alpha3; + const Color folded_code_region_color = Color(0.68, 0.46, 0.77, 0.2); + const Color search_result_color = alpha1; + const Color search_result_border_color = p_config.dark_theme ? Color(0.41, 0.61, 0.91, 0.38) : Color(0, 0.4, 1, 0.38); + /* clang-format on */ + + EditorSettings *setting = EditorSettings::get_singleton(); + + /* clang-format off */ + setting->set_initial_value("text_editor/theme/highlighting/symbol_color", symbol_color, true); + setting->set_initial_value("text_editor/theme/highlighting/keyword_color", keyword_color, true); + setting->set_initial_value("text_editor/theme/highlighting/control_flow_keyword_color", control_flow_keyword_color, true); + setting->set_initial_value("text_editor/theme/highlighting/base_type_color", base_type_color, true); + setting->set_initial_value("text_editor/theme/highlighting/engine_type_color", engine_type_color, true); + setting->set_initial_value("text_editor/theme/highlighting/user_type_color", user_type_color, true); + setting->set_initial_value("text_editor/theme/highlighting/comment_color", comment_color, true); + setting->set_initial_value("text_editor/theme/highlighting/doc_comment_color", doc_comment_color, true); + setting->set_initial_value("text_editor/theme/highlighting/string_color", string_color, true); + setting->set_initial_value("text_editor/theme/highlighting/background_color", te_background_color, true); + setting->set_initial_value("text_editor/theme/highlighting/completion_background_color", completion_background_color, true); + setting->set_initial_value("text_editor/theme/highlighting/completion_selected_color", completion_selected_color, true); + setting->set_initial_value("text_editor/theme/highlighting/completion_existing_color", completion_existing_color, true); + setting->set_initial_value("text_editor/theme/highlighting/completion_scroll_color", completion_scroll_color, true); + setting->set_initial_value("text_editor/theme/highlighting/completion_scroll_hovered_color", completion_scroll_hovered_color, true); + setting->set_initial_value("text_editor/theme/highlighting/completion_font_color", completion_font_color, true); + setting->set_initial_value("text_editor/theme/highlighting/text_color", text_color, true); + setting->set_initial_value("text_editor/theme/highlighting/line_number_color", line_number_color, true); + setting->set_initial_value("text_editor/theme/highlighting/safe_line_number_color", safe_line_number_color, true); + setting->set_initial_value("text_editor/theme/highlighting/caret_color", caret_color, true); + setting->set_initial_value("text_editor/theme/highlighting/caret_background_color", caret_background_color, true); + setting->set_initial_value("text_editor/theme/highlighting/text_selected_color", text_selected_color, true); + setting->set_initial_value("text_editor/theme/highlighting/selection_color", selection_color, true); + setting->set_initial_value("text_editor/theme/highlighting/brace_mismatch_color", brace_mismatch_color, true); + setting->set_initial_value("text_editor/theme/highlighting/current_line_color", current_line_color, true); + setting->set_initial_value("text_editor/theme/highlighting/line_length_guideline_color", line_length_guideline_color, true); + setting->set_initial_value("text_editor/theme/highlighting/word_highlighted_color", word_highlighted_color, true); + setting->set_initial_value("text_editor/theme/highlighting/number_color", number_color, true); + setting->set_initial_value("text_editor/theme/highlighting/function_color", function_color, true); + setting->set_initial_value("text_editor/theme/highlighting/member_variable_color", member_variable_color, true); + setting->set_initial_value("text_editor/theme/highlighting/mark_color", mark_color, true); + setting->set_initial_value("text_editor/theme/highlighting/bookmark_color", bookmark_color, true); + setting->set_initial_value("text_editor/theme/highlighting/breakpoint_color", breakpoint_color, true); + setting->set_initial_value("text_editor/theme/highlighting/executing_line_color", executing_line_color, true); + setting->set_initial_value("text_editor/theme/highlighting/code_folding_color", code_folding_color, true); + setting->set_initial_value("text_editor/theme/highlighting/folded_code_region_color", folded_code_region_color, true); + setting->set_initial_value("text_editor/theme/highlighting/search_result_color", search_result_color, true); + setting->set_initial_value("text_editor/theme/highlighting/search_result_border_color", search_result_border_color, true); + /* clang-format on */ +} + +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); + } else if (text_editor_color_theme == "Godot 2") { + EditorSettings::get_singleton()->load_text_editor_theme(); + } + + // Now theme is loaded, apply it to CodeEdit. + p_theme->set_font("font", "CodeEdit", p_theme->get_font(SNAME("source"), EditorStringName(EditorFonts))); + p_theme->set_font_size("font_size", "CodeEdit", p_theme->get_font_size(SNAME("source_size"), EditorStringName(EditorFonts))); + + /* clang-format off */ + p_theme->set_icon("tab", "CodeEdit", p_theme->get_icon(SNAME("GuiTab"), EditorStringName(EditorIcons))); + p_theme->set_icon("space", "CodeEdit", p_theme->get_icon(SNAME("GuiSpace"), EditorStringName(EditorIcons))); + p_theme->set_icon("folded", "CodeEdit", p_theme->get_icon(SNAME("CodeFoldedRightArrow"), EditorStringName(EditorIcons))); + p_theme->set_icon("can_fold", "CodeEdit", p_theme->get_icon(SNAME("CodeFoldDownArrow"), EditorStringName(EditorIcons))); + p_theme->set_icon("folded_code_region", "CodeEdit", p_theme->get_icon(SNAME("CodeRegionFoldedRightArrow"), EditorStringName(EditorIcons))); + p_theme->set_icon("can_fold_code_region", "CodeEdit", p_theme->get_icon(SNAME("CodeRegionFoldDownArrow"), EditorStringName(EditorIcons))); + p_theme->set_icon("executing_line", "CodeEdit", p_theme->get_icon(SNAME("TextEditorPlay"), EditorStringName(EditorIcons))); + p_theme->set_icon("breakpoint", "CodeEdit", p_theme->get_icon(SNAME("Breakpoint"), EditorStringName(EditorIcons))); + /* clang-format on */ + + p_theme->set_constant("line_spacing", "CodeEdit", EDITOR_GET("text_editor/appearance/whitespace/line_spacing")); + + const Color background_color = EDITOR_GET("text_editor/theme/highlighting/background_color"); + 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_color("background_color", "CodeEdit", Color(0, 0, 0, 0)); // Unset any color, we use a stylebox. + + /* clang-format off */ + p_theme->set_color("completion_background_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_background_color")); + p_theme->set_color("completion_selected_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_selected_color")); + p_theme->set_color("completion_existing_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_existing_color")); + p_theme->set_color("completion_scroll_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_scroll_color")); + p_theme->set_color("completion_scroll_hovered_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_scroll_hovered_color")); + p_theme->set_color("font_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/text_color")); + p_theme->set_color("line_number_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/line_number_color")); + p_theme->set_color("caret_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/caret_color")); + p_theme->set_color("font_selected_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/text_selected_color")); + p_theme->set_color("selection_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/selection_color")); + p_theme->set_color("brace_mismatch_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/brace_mismatch_color")); + p_theme->set_color("current_line_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/current_line_color")); + p_theme->set_color("line_length_guideline_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/line_length_guideline_color")); + p_theme->set_color("word_highlighted_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/word_highlighted_color")); + p_theme->set_color("bookmark_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/bookmark_color")); + p_theme->set_color("breakpoint_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/breakpoint_color")); + p_theme->set_color("executing_line_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/executing_line_color")); + p_theme->set_color("code_folding_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/code_folding_color")); + p_theme->set_color("folded_code_region_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/folded_code_region_color")); + p_theme->set_color("search_result_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/search_result_color")); + p_theme->set_color("search_result_border_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/search_result_border_color")); + /* clang-format on */ +} + +// Public interface for theme generation. + Ref EditorThemeManager::generate_theme(const Ref &p_old_theme) { OS::get_singleton()->benchmark_begin_measure("EditorTheme", "Generate Theme"); @@ -1933,17 +2170,16 @@ bool EditorThemeManager::is_generated_theme_outdated() { // without a restart, so there is no point regenerating the theme. // TODO: We can use this information more intelligently to do partial theme updates and speed things up. - return - EditorSettings::get_singleton()->check_changed_settings_in_group("interface/theme") || - 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("text_editor/theme") || - EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/help/help") || - 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"); + return EditorSettings::get_singleton()->check_changed_settings_in_group("interface/theme") || + 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("text_editor/theme") || + EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/help/help") || + 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"); } void EditorThemeManager::initialize() { diff --git a/editor/themes/editor_theme_manager.h b/editor/themes/editor_theme_manager.h index bd06aeba0d5..71fab5b39f6 100644 --- a/editor/themes/editor_theme_manager.h +++ b/editor/themes/editor_theme_manager.h @@ -31,11 +31,111 @@ #ifndef EDITOR_THEME_MANAGER_H #define EDITOR_THEME_MANAGER_H +#include "scene/resources/style_box_flat.h" #include "scene/resources/theme.h" class EditorThemeManager { + struct ThemeConfiguration { + // Basic properties. + + String preset; + bool dark_theme = false; + + Color base_color; + Color accent_color; + float contrast = 1.0; + float icon_saturation = 1.0; + + // Extra properties. + + float extra_spacing = 0.0; + int border_width = 0; + int corner_radius = 3; + + bool draw_extra_borders = false; + float relationship_line_opacity = 1.0; + int thumb_size = 16; + int class_icon_size = 16; + bool increase_scrollbar_touch_area = false; + float gizmo_handle_scale = 1.0; + int color_picker_button_height = 28; + + float default_contrast = 1.0; + + // Generated properties. + + int base_margin = 4; + int increased_margin = 4; + + int popup_margin = 12; + int window_border_margin = 8; + int top_bar_separation = 8; + int forced_even_separation = 0; + + Color mono_color; + Color dark_color_1; + Color dark_color_2; + Color dark_color_3; + Color contrast_color_1; + Color contrast_color_2; + Color highlight_color; + Color highlight_disabled_color; + Color success_color; + Color warning_color; + Color error_color; + Color extra_border_color_1; + Color extra_border_color_2; + + Color font_color; + Color font_focus_color; + Color font_hover_color; + Color font_pressed_color; + Color font_hover_pressed_color; + Color font_disabled_color; + Color font_readonly_color; + Color font_placeholder_color; + Color font_outline_color; + + Color icon_normal_color; + Color icon_focus_color; + Color icon_hover_color; + Color icon_pressed_color; + Color icon_disabled_color; + + Color shadow_color; + Color selection_color; + Color disabled_border_color; + Color disabled_bg_color; + Color separator_color; + + Ref base_style; + Ref base_empty_style; + + Ref button_style; + Ref button_style_disabled; + Ref button_style_focus; + Ref button_style_pressed; + Ref button_style_hover; + + Ref popup_style; + Ref window_style; + Ref dialog_style; + Ref panel_container_style; + Ref content_panel_style; + Ref tree_panel_style; + + Vector2 widget_margin; + }; 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 _generate_text_editor_defaults(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);