1/**************************************************************************/
2/* editor_themes.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#include "editor_themes.h"
32
33#include "core/error/error_macros.h"
34#include "core/io/resource_loader.h"
35#include "editor/editor_fonts.h"
36#include "editor/editor_icons.gen.h"
37#include "editor/editor_scale.h"
38#include "editor/editor_settings.h"
39#include "editor/editor_string_names.h"
40#include "scene/resources/image_texture.h"
41#include "scene/resources/style_box_flat.h"
42#include "scene/resources/style_box_line.h"
43#include "scene/resources/style_box_texture.h"
44#include "scene/theme/theme_db.h"
45
46#include "modules/modules_enabled.gen.h" // For svg.
47#ifdef MODULE_SVG_ENABLED
48#include "modules/svg/image_loader_svg.h"
49#endif
50
51HashMap<Color, Color> EditorColorMap::color_conversion_map;
52HashSet<StringName> EditorColorMap::color_conversion_exceptions;
53
54void EditorColorMap::add_conversion_color_pair(const String p_from_color, const String p_to_color) {
55 color_conversion_map[Color::html(p_from_color)] = Color::html(p_to_color);
56}
57
58void EditorColorMap::add_conversion_exception(const StringName p_icon_name) {
59 color_conversion_exceptions.insert(p_icon_name);
60}
61
62void EditorColorMap::create() {
63 // Some of the colors below are listed for completeness sake.
64 // This can be a basis for proper palette validation later.
65
66 // Convert: FROM TO
67 add_conversion_color_pair("#478cbf", "#478cbf"); // Godot Blue
68 add_conversion_color_pair("#414042", "#414042"); // Godot Gray
69
70 add_conversion_color_pair("#ffffff", "#414141"); // Pure white
71 add_conversion_color_pair("#000000", "#bfbfbf"); // Pure black
72 // Keep pure RGB colors as is, but list them for explicitness.
73 add_conversion_color_pair("#ff0000", "#ff0000"); // Pure red
74 add_conversion_color_pair("#00ff00", "#00ff00"); // Pure green
75 add_conversion_color_pair("#0000ff", "#0000ff"); // Pure blue
76
77 // GUI Colors
78 add_conversion_color_pair("#e0e0e0", "#5a5a5a"); // Common icon color
79 add_conversion_color_pair("#fefefe", "#fefefe"); // Forced light color
80 add_conversion_color_pair("#808080", "#808080"); // GUI disabled color
81 add_conversion_color_pair("#b3b3b3", "#363636"); // GUI disabled light color
82 add_conversion_color_pair("#699ce8", "#699ce8"); // GUI highlight color
83 add_conversion_color_pair("#f9f9f9", "#606060"); // Scrollbar grabber highlight color
84
85 add_conversion_color_pair("#c38ef1", "#a85de9"); // Animation
86 add_conversion_color_pair("#8da5f3", "#3d64dd"); // 2D
87 add_conversion_color_pair("#4b70ea", "#1a3eac"); // 2D Dark
88 add_conversion_color_pair("#7582a8", "#6d83c8"); // 2D Abstract
89 add_conversion_color_pair("#fc7f7f", "#cd3838"); // 3D
90 add_conversion_color_pair("#b56d6d", "#be6a6a"); // 3D Abstract
91 add_conversion_color_pair("#8eef97", "#2fa139"); // GUI Control
92 add_conversion_color_pair("#76ad7b", "#64a66a"); // GUI Control Abstract
93
94 add_conversion_color_pair("#5fb2ff", "#0079f0"); // Selection (blue)
95 add_conversion_color_pair("#003e7a", "#2b74bb"); // Selection (darker blue)
96 add_conversion_color_pair("#f7f5cf", "#615f3a"); // Gizmo (yellow)
97
98 // Rainbow
99 add_conversion_color_pair("#ff4545", "#ff2929"); // Red
100 add_conversion_color_pair("#ffe345", "#ffe337"); // Yellow
101 add_conversion_color_pair("#80ff45", "#74ff34"); // Green
102 add_conversion_color_pair("#45ffa2", "#2cff98"); // Aqua
103 add_conversion_color_pair("#45d7ff", "#22ccff"); // Blue
104 add_conversion_color_pair("#8045ff", "#702aff"); // Purple
105 add_conversion_color_pair("#ff4596", "#ff2781"); // Pink
106
107 // Audio gradients
108 add_conversion_color_pair("#e1da5b", "#d6cf4b"); // Yellow
109
110 add_conversion_color_pair("#62aeff", "#1678e0"); // Frozen gradient top
111 add_conversion_color_pair("#75d1e6", "#41acc5"); // Frozen gradient middle
112 add_conversion_color_pair("#84ffee", "#49ccba"); // Frozen gradient bottom
113
114 add_conversion_color_pair("#f70000", "#c91616"); // Color track red
115 add_conversion_color_pair("#eec315", "#d58c0b"); // Color track orange
116 add_conversion_color_pair("#dbee15", "#b7d10a"); // Color track yellow
117 add_conversion_color_pair("#288027", "#218309"); // Color track green
118
119 // Other objects
120 add_conversion_color_pair("#ffca5f", "#fea900"); // Mesh resource (orange)
121 add_conversion_color_pair("#2998ff", "#68b6ff"); // Shape resource (blue)
122 add_conversion_color_pair("#a2d2ff", "#4998e3"); // Shape resource (light blue)
123 add_conversion_color_pair("#69c4d4", "#29a3cc"); // Input event highlight (light blue)
124
125 // Animation editor tracks
126 // The property track icon color is set by the common icon color.
127 add_conversion_color_pair("#ea7940", "#bd5e2c"); // 3D Position track
128 add_conversion_color_pair("#ff2b88", "#bd165f"); // 3D Rotation track
129 add_conversion_color_pair("#eac840", "#bd9d1f"); // 3D Scale track
130 add_conversion_color_pair("#3cf34e", "#16a827"); // Call Method track
131 add_conversion_color_pair("#2877f6", "#236be6"); // Bezier Curve track
132 add_conversion_color_pair("#eae440", "#9f9722"); // Audio Playback track
133 add_conversion_color_pair("#a448f0", "#9853ce"); // Animation Playback track
134 add_conversion_color_pair("#5ad5c4", "#0a9c88"); // Blend Shape track
135
136 // Control layouts
137 add_conversion_color_pair("#d6d6d6", "#474747"); // Highlighted part
138 add_conversion_color_pair("#474747", "#d6d6d6"); // Background part
139 add_conversion_color_pair("#919191", "#6e6e6e"); // Border part
140
141 // TileSet editor icons
142 add_conversion_color_pair("#fce00e", "#aa8d24"); // New Single Tile
143 add_conversion_color_pair("#0e71fc", "#0350bd"); // New Autotile
144 add_conversion_color_pair("#c6ced4", "#828f9b"); // New Atlas
145
146 // Variant types
147 add_conversion_color_pair("#41ecad", "#25e3a0"); // Variant
148 add_conversion_color_pair("#6f91f0", "#6d8eeb"); // bool
149 add_conversion_color_pair("#5abbef", "#4fb2e9"); // int/uint
150 add_conversion_color_pair("#35d4f4", "#27ccf0"); // float
151 add_conversion_color_pair("#4593ec", "#4690e7"); // String
152 add_conversion_color_pair("#ee5677", "#ee7991"); // AABB
153 add_conversion_color_pair("#e0e0e0", "#5a5a5a"); // Array
154 add_conversion_color_pair("#e1ec41", "#b2bb19"); // Basis
155 add_conversion_color_pair("#54ed9e", "#57e99f"); // Dictionary
156 add_conversion_color_pair("#417aec", "#6993ec"); // NodePath
157 add_conversion_color_pair("#55f3e3", "#12d5c3"); // Object
158 add_conversion_color_pair("#f74949", "#f77070"); // Plane
159 add_conversion_color_pair("#44bd44", "#46b946"); // Projection
160 add_conversion_color_pair("#ec418e", "#ec69a3"); // Quaternion
161 add_conversion_color_pair("#f1738f", "#ee758e"); // Rect2
162 add_conversion_color_pair("#41ec80", "#2ce573"); // RID
163 add_conversion_color_pair("#b9ec41", "#96ce1a"); // Transform2D
164 add_conversion_color_pair("#f68f45", "#f49047"); // Transform3D
165 add_conversion_color_pair("#ac73f1", "#ad76ee"); // Vector2
166 add_conversion_color_pair("#de66f0", "#dc6aed"); // Vector3
167 add_conversion_color_pair("#f066bd", "#ed6abd"); // Vector4
168
169 // Visual shaders
170 add_conversion_color_pair("#77ce57", "#67c046"); // Vector funcs
171 add_conversion_color_pair("#ea686c", "#d95256"); // Vector transforms
172 add_conversion_color_pair("#eac968", "#d9b64f"); // Textures and cubemaps
173 add_conversion_color_pair("#cf68ea", "#c050dd"); // Functions and expressions
174
175 // These icons should not be converted.
176 add_conversion_exception("EditorPivot");
177 add_conversion_exception("EditorHandle");
178 add_conversion_exception("Editor3DHandle");
179 add_conversion_exception("EditorBoneHandle");
180 add_conversion_exception("Godot");
181 add_conversion_exception("Sky");
182 add_conversion_exception("EditorControlAnchor");
183 add_conversion_exception("DefaultProjectIcon");
184 add_conversion_exception("ZoomMore");
185 add_conversion_exception("ZoomLess");
186 add_conversion_exception("ZoomReset");
187 add_conversion_exception("LockViewport");
188 add_conversion_exception("GroupViewport");
189 add_conversion_exception("StatusError");
190 add_conversion_exception("StatusSuccess");
191 add_conversion_exception("StatusWarning");
192 add_conversion_exception("OverbrightIndicator");
193 add_conversion_exception("MaterialPreviewCube");
194 add_conversion_exception("MaterialPreviewSphere");
195 add_conversion_exception("MaterialPreviewLight1");
196 add_conversion_exception("MaterialPreviewLight2");
197
198 // GUI
199 add_conversion_exception("GuiChecked");
200 add_conversion_exception("GuiRadioChecked");
201 add_conversion_exception("GuiIndeterminate");
202 add_conversion_exception("GuiCloseCustomizable");
203 add_conversion_exception("GuiGraphNodePort");
204 add_conversion_exception("GuiResizer");
205 add_conversion_exception("GuiMiniCheckerboard");
206
207 /// Code Editor.
208 add_conversion_exception("GuiTab");
209 add_conversion_exception("GuiSpace");
210 add_conversion_exception("CodeFoldedRightArrow");
211 add_conversion_exception("CodeFoldDownArrow");
212 add_conversion_exception("CodeRegionFoldedRightArrow");
213 add_conversion_exception("CodeRegionFoldDownArrow");
214 add_conversion_exception("TextEditorPlay");
215 add_conversion_exception("Breakpoint");
216}
217
218Vector<StringName> EditorTheme::editor_theme_types;
219
220// TODO: Refactor these and corresponding Theme methods to use the bool get_xxx(r_value) pattern internally.
221
222// Keep in sync with Theme::get_color.
223Color EditorTheme::get_color(const StringName &p_name, const StringName &p_theme_type) const {
224 if (color_map.has(p_theme_type) && color_map[p_theme_type].has(p_name)) {
225 return color_map[p_theme_type][p_name];
226 } else {
227 if (editor_theme_types.has(p_theme_type)) {
228 WARN_PRINT(vformat("Trying to access a non-existing editor theme color '%s' in '%s'.", p_name, p_theme_type));
229 }
230 return Color();
231 }
232}
233
234// Keep in sync with Theme::get_constant.
235int EditorTheme::get_constant(const StringName &p_name, const StringName &p_theme_type) const {
236 if (constant_map.has(p_theme_type) && constant_map[p_theme_type].has(p_name)) {
237 return constant_map[p_theme_type][p_name];
238 } else {
239 if (editor_theme_types.has(p_theme_type)) {
240 WARN_PRINT(vformat("Trying to access a non-existing editor theme constant '%s' in '%s'.", p_name, p_theme_type));
241 }
242 return 0;
243 }
244}
245
246// Keep in sync with Theme::get_font.
247Ref<Font> EditorTheme::get_font(const StringName &p_name, const StringName &p_theme_type) const {
248 if (font_map.has(p_theme_type) && font_map[p_theme_type].has(p_name) && font_map[p_theme_type][p_name].is_valid()) {
249 return font_map[p_theme_type][p_name];
250 } else if (has_default_font()) {
251 if (editor_theme_types.has(p_theme_type)) {
252 WARN_PRINT(vformat("Trying to access a non-existing editor theme font '%s' in '%s'.", p_name, p_theme_type));
253 }
254 return default_font;
255 } else {
256 if (editor_theme_types.has(p_theme_type)) {
257 WARN_PRINT(vformat("Trying to access a non-existing editor theme font '%s' in '%s'.", p_name, p_theme_type));
258 }
259 return ThemeDB::get_singleton()->get_fallback_font();
260 }
261}
262
263// Keep in sync with Theme::get_font_size.
264int EditorTheme::get_font_size(const StringName &p_name, const StringName &p_theme_type) const {
265 if (font_size_map.has(p_theme_type) && font_size_map[p_theme_type].has(p_name) && (font_size_map[p_theme_type][p_name] > 0)) {
266 return font_size_map[p_theme_type][p_name];
267 } else if (has_default_font_size()) {
268 if (editor_theme_types.has(p_theme_type)) {
269 WARN_PRINT(vformat("Trying to access a non-existing editor theme font size '%s' in '%s'.", p_name, p_theme_type));
270 }
271 return default_font_size;
272 } else {
273 if (editor_theme_types.has(p_theme_type)) {
274 WARN_PRINT(vformat("Trying to access a non-existing editor theme font size '%s' in '%s'.", p_name, p_theme_type));
275 }
276 return ThemeDB::get_singleton()->get_fallback_font_size();
277 }
278}
279
280// Keep in sync with Theme::get_icon.
281Ref<Texture2D> EditorTheme::get_icon(const StringName &p_name, const StringName &p_theme_type) const {
282 if (icon_map.has(p_theme_type) && icon_map[p_theme_type].has(p_name) && icon_map[p_theme_type][p_name].is_valid()) {
283 return icon_map[p_theme_type][p_name];
284 } else {
285 if (editor_theme_types.has(p_theme_type)) {
286 WARN_PRINT(vformat("Trying to access a non-existing editor theme icon '%s' in '%s'.", p_name, p_theme_type));
287 }
288 return ThemeDB::get_singleton()->get_fallback_icon();
289 }
290}
291
292// Keep in sync with Theme::get_stylebox.
293Ref<StyleBox> EditorTheme::get_stylebox(const StringName &p_name, const StringName &p_theme_type) const {
294 if (style_map.has(p_theme_type) && style_map[p_theme_type].has(p_name) && style_map[p_theme_type][p_name].is_valid()) {
295 return style_map[p_theme_type][p_name];
296 } else {
297 if (editor_theme_types.has(p_theme_type)) {
298 WARN_PRINT(vformat("Trying to access a non-existing editor theme stylebox '%s' in '%s'.", p_name, p_theme_type));
299 }
300 return ThemeDB::get_singleton()->get_fallback_stylebox();
301 }
302}
303
304EditorTheme::EditorTheme() {
305 if (editor_theme_types.is_empty()) {
306 editor_theme_types.append(EditorStringName(Editor));
307 editor_theme_types.append(EditorStringName(EditorFonts));
308 editor_theme_types.append(EditorStringName(EditorIcons));
309 editor_theme_types.append(EditorStringName(EditorStyles));
310 }
311}
312
313// Editor theme generatior.
314
315static Ref<StyleBoxTexture> make_stylebox(Ref<Texture2D> p_texture, float p_left, float p_top, float p_right, float p_bottom, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1, bool p_draw_center = true) {
316 Ref<StyleBoxTexture> style(memnew(StyleBoxTexture));
317 style->set_texture(p_texture);
318 style->set_texture_margin_individual(p_left * EDSCALE, p_top * EDSCALE, p_right * EDSCALE, p_bottom * EDSCALE);
319 style->set_content_margin_individual((p_left + p_margin_left) * EDSCALE, (p_top + p_margin_top) * EDSCALE, (p_right + p_margin_right) * EDSCALE, (p_bottom + p_margin_bottom) * EDSCALE);
320 style->set_draw_center(p_draw_center);
321 return style;
322}
323
324static Ref<StyleBoxEmpty> make_empty_stylebox(float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) {
325 Ref<StyleBoxEmpty> style(memnew(StyleBoxEmpty));
326 style->set_content_margin_individual(p_margin_left * EDSCALE, p_margin_top * EDSCALE, p_margin_right * EDSCALE, p_margin_bottom * EDSCALE);
327 return style;
328}
329
330static Ref<StyleBoxFlat> make_flat_stylebox(Color p_color, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1, int p_corner_width = 0) {
331 Ref<StyleBoxFlat> style(memnew(StyleBoxFlat));
332 style->set_bg_color(p_color);
333 // Adjust level of detail based on the corners' effective sizes.
334 style->set_corner_detail(Math::ceil(0.8 * p_corner_width * EDSCALE));
335 style->set_corner_radius_all(p_corner_width * EDSCALE);
336 style->set_content_margin_individual(p_margin_left * EDSCALE, p_margin_top * EDSCALE, p_margin_right * EDSCALE, p_margin_bottom * EDSCALE);
337 // Work around issue about antialiased edges being blurrier (GH-35279).
338 style->set_anti_aliased(false);
339 return style;
340}
341
342static Ref<StyleBoxLine> make_line_stylebox(Color p_color, int p_thickness = 1, float p_grow_begin = 1, float p_grow_end = 1, bool p_vertical = false) {
343 Ref<StyleBoxLine> style(memnew(StyleBoxLine));
344 style->set_color(p_color);
345 style->set_grow_begin(p_grow_begin);
346 style->set_grow_end(p_grow_end);
347 style->set_thickness(p_thickness);
348 style->set_vertical(p_vertical);
349 return style;
350}
351
352// See also `generate_icon()` in `scene/theme/default_theme.cpp`.
353static Ref<ImageTexture> editor_generate_icon(int p_index, float p_scale, float p_saturation, const HashMap<Color, Color> &p_convert_colors = HashMap<Color, Color>()) {
354 Ref<Image> img = memnew(Image);
355
356#ifdef MODULE_SVG_ENABLED
357 // Upsample icon generation only if the editor scale isn't an integer multiplier.
358 // Generating upsampled icons is slower, and the benefit is hardly visible
359 // with integer editor scales.
360 const bool upsample = !Math::is_equal_approx(Math::round(p_scale), p_scale);
361 Error err = ImageLoaderSVG::create_image_from_string(img, editor_icons_sources[p_index], p_scale, upsample, p_convert_colors);
362 ERR_FAIL_COND_V_MSG(err != OK, Ref<ImageTexture>(), "Failed generating icon, unsupported or invalid SVG data in editor theme.");
363 if (p_saturation != 1.0) {
364 img->adjust_bcs(1.0, 1.0, p_saturation);
365 }
366#else
367 // If the SVG module is disabled, we can't really display the UI well, but at least we won't crash.
368 // 16 pixels is used as it's the most common base size for Godot icons.
369 img = Image::create_empty(16 * p_scale, 16 * p_scale, false, Image::FORMAT_RGBA8);
370#endif
371
372 return ImageTexture::create_from_image(img);
373}
374
375float get_gizmo_handle_scale(const String &gizmo_handle_name = "") {
376 const float scale_gizmo_handles_for_touch = EDITOR_GET("interface/touchscreen/scale_gizmo_handles");
377 if (scale_gizmo_handles_for_touch > 1.0f) {
378 // The names of the icons that require additional scaling.
379 static HashSet<StringName> gizmo_to_scale;
380 if (gizmo_to_scale.is_empty()) {
381 gizmo_to_scale.insert("EditorHandle");
382 gizmo_to_scale.insert("EditorHandleAdd");
383 gizmo_to_scale.insert("EditorHandleDisabled");
384 gizmo_to_scale.insert("EditorCurveHandle");
385 gizmo_to_scale.insert("EditorPathSharpHandle");
386 gizmo_to_scale.insert("EditorPathSmoothHandle");
387 }
388
389 if (gizmo_to_scale.has(gizmo_handle_name)) {
390 return EDSCALE * scale_gizmo_handles_for_touch;
391 }
392 }
393
394 return EDSCALE;
395}
396
397void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme, float p_icon_saturation, int p_thumb_size, bool p_only_thumbs = false) {
398 OS::get_singleton()->benchmark_begin_measure("editor_register_and_generate_icons_" + String((p_only_thumbs ? "with_only_thumbs" : "all")));
399 // Before we register the icons, we adjust their colors and saturation.
400 // Most icons follow the standard rules for color conversion to follow the editor
401 // theme's polarity (dark/light). We also adjust the saturation for most icons,
402 // following the editor setting.
403 // Some icons are excluded from this conversion, and instead use the configured
404 // accent color to replace their innate accent color to match the editor theme.
405 // And then some icons are completely excluded from the conversion.
406
407 // Standard color conversion map.
408 HashMap<Color, Color> color_conversion_map;
409 // Icons by default are set up for the dark theme, so if the theme is light,
410 // we apply the dark-to-light color conversion map.
411 if (!p_dark_theme) {
412 for (KeyValue<Color, Color> &E : EditorColorMap::get_color_conversion_map()) {
413 color_conversion_map[E.key] = E.value;
414 }
415 }
416 // These colors should be converted even if we are using a dark theme.
417 const Color error_color = p_theme->get_color(SNAME("error_color"), EditorStringName(Editor));
418 const Color success_color = p_theme->get_color(SNAME("success_color"), EditorStringName(Editor));
419 const Color warning_color = p_theme->get_color(SNAME("warning_color"), EditorStringName(Editor));
420 color_conversion_map[Color::html("#ff5f5f")] = error_color;
421 color_conversion_map[Color::html("#5fff97")] = success_color;
422 color_conversion_map[Color::html("#ffdd65")] = warning_color;
423
424 // The names of the icons to exclude from the standard color conversion.
425 HashSet<StringName> conversion_exceptions = EditorColorMap::get_color_conversion_exceptions();
426
427 // The names of the icons to exclude when adjusting for saturation.
428 HashSet<StringName> saturation_exceptions;
429 saturation_exceptions.insert("DefaultProjectIcon");
430 saturation_exceptions.insert("Godot");
431 saturation_exceptions.insert("Logo");
432
433 // Accent color conversion map.
434 // It is used on some icons (checkbox, radio, toggle, etc.), regardless of the dark
435 // or light mode.
436 HashMap<Color, Color> accent_color_map;
437 HashSet<StringName> accent_color_icons;
438
439 const Color accent_color = p_theme->get_color(SNAME("accent_color"), EditorStringName(Editor));
440 accent_color_map[Color::html("699ce8")] = accent_color;
441 if (accent_color.get_luminance() > 0.75) {
442 accent_color_map[Color::html("ffffff")] = Color(0.2, 0.2, 0.2);
443 }
444
445 accent_color_icons.insert("GuiChecked");
446 accent_color_icons.insert("GuiRadioChecked");
447 accent_color_icons.insert("GuiIndeterminate");
448 accent_color_icons.insert("GuiToggleOn");
449 accent_color_icons.insert("GuiToggleOnMirrored");
450 accent_color_icons.insert("PlayOverlay");
451
452 // Generate icons.
453 if (!p_only_thumbs) {
454 for (int i = 0; i < editor_icons_count; i++) {
455 Ref<ImageTexture> icon;
456
457 const String &editor_icon_name = editor_icons_names[i];
458 if (accent_color_icons.has(editor_icon_name)) {
459 icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name), 1.0, accent_color_map);
460 } else {
461 float saturation = p_icon_saturation;
462 if (saturation_exceptions.has(editor_icon_name)) {
463 saturation = 1.0;
464 }
465
466 if (conversion_exceptions.has(editor_icon_name)) {
467 icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name), saturation);
468 } else {
469 icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name), saturation, color_conversion_map);
470 }
471 }
472
473 p_theme->set_icon(editor_icon_name, EditorStringName(EditorIcons), icon);
474 }
475 }
476
477 // Generate thumbnail icons with the given thumbnail size.
478 // See editor\icons\editor_icons_builders.py for the code that determines which icons are thumbnails.
479 if (p_thumb_size >= 64) {
480 const float scale = (float)p_thumb_size / 64.0 * EDSCALE;
481 for (int i = 0; i < editor_bg_thumbs_count; i++) {
482 const int index = editor_bg_thumbs_indices[i];
483 Ref<ImageTexture> icon;
484
485 if (accent_color_icons.has(editor_icons_names[index])) {
486 icon = editor_generate_icon(index, scale, 1.0, accent_color_map);
487 } else {
488 float saturation = p_icon_saturation;
489 if (saturation_exceptions.has(editor_icons_names[index])) {
490 saturation = 1.0;
491 }
492
493 if (conversion_exceptions.has(editor_icons_names[index])) {
494 icon = editor_generate_icon(index, scale, saturation);
495 } else {
496 icon = editor_generate_icon(index, scale, saturation, color_conversion_map);
497 }
498 }
499
500 p_theme->set_icon(editor_icons_names[index], EditorStringName(EditorIcons), icon);
501 }
502 } else {
503 const float scale = (float)p_thumb_size / 32.0 * EDSCALE;
504 for (int i = 0; i < editor_md_thumbs_count; i++) {
505 const int index = editor_md_thumbs_indices[i];
506 Ref<ImageTexture> icon;
507
508 if (accent_color_icons.has(editor_icons_names[index])) {
509 icon = editor_generate_icon(index, scale, 1.0, accent_color_map);
510 } else {
511 float saturation = p_icon_saturation;
512 if (saturation_exceptions.has(editor_icons_names[index])) {
513 saturation = 1.0;
514 }
515
516 if (conversion_exceptions.has(editor_icons_names[index])) {
517 icon = editor_generate_icon(index, scale, saturation);
518 } else {
519 icon = editor_generate_icon(index, scale, saturation, color_conversion_map);
520 }
521 }
522
523 p_theme->set_icon(editor_icons_names[index], EditorStringName(EditorIcons), icon);
524 }
525 }
526 OS::get_singleton()->benchmark_end_measure("editor_register_and_generate_icons_" + String((p_only_thumbs ? "with_only_thumbs" : "all")));
527}
528
529Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
530 OS::get_singleton()->benchmark_begin_measure("create_editor_theme");
531 Ref<EditorTheme> theme = memnew(EditorTheme);
532
533 // Controls may rely on the scale for their internal drawing logic.
534 theme->set_default_base_scale(EDSCALE);
535
536 // Theme settings
537 Color accent_color = EDITOR_GET("interface/theme/accent_color");
538 Color base_color = EDITOR_GET("interface/theme/base_color");
539 float contrast = EDITOR_GET("interface/theme/contrast");
540 bool increase_scrollbar_touch_area = EDITOR_GET("interface/touchscreen/increase_scrollbar_touch_area");
541 const float gizmo_handle_scale = EDITOR_GET("interface/touchscreen/scale_gizmo_handles");
542 bool draw_extra_borders = EDITOR_GET("interface/theme/draw_extra_borders");
543 float icon_saturation = EDITOR_GET("interface/theme/icon_saturation");
544 float relationship_line_opacity = EDITOR_GET("interface/theme/relationship_line_opacity");
545
546 String preset = EDITOR_GET("interface/theme/preset");
547
548 int border_size = EDITOR_GET("interface/theme/border_size");
549 int corner_radius = EDITOR_GET("interface/theme/corner_radius");
550
551 Color preset_accent_color;
552 Color preset_base_color;
553 float preset_contrast = 0;
554 bool preset_draw_extra_borders = false;
555
556 const float default_contrast = 0.3;
557
558 // Please use alphabetical order if you're adding a new theme here
559 // (after "Custom")
560
561 if (preset == "Custom") {
562 accent_color = EDITOR_GET("interface/theme/accent_color");
563 base_color = EDITOR_GET("interface/theme/base_color");
564 contrast = EDITOR_GET("interface/theme/contrast");
565 } else if (preset == "Breeze Dark") {
566 preset_accent_color = Color(0.26, 0.76, 1.00);
567 preset_base_color = Color(0.24, 0.26, 0.28);
568 preset_contrast = default_contrast;
569 } else if (preset == "Godot 2") {
570 preset_accent_color = Color(0.53, 0.67, 0.89);
571 preset_base_color = Color(0.24, 0.23, 0.27);
572 preset_contrast = default_contrast;
573 } else if (preset == "Gray") {
574 preset_accent_color = Color(0.44, 0.73, 0.98);
575 preset_base_color = Color(0.24, 0.24, 0.24);
576 preset_contrast = default_contrast;
577 } else if (preset == "Light") {
578 preset_accent_color = Color(0.18, 0.50, 1.00);
579 preset_base_color = Color(0.9, 0.9, 0.9);
580 // A negative contrast rate looks better for light themes, since it better follows the natural order of UI "elevation".
581 preset_contrast = -0.06;
582 } else if (preset == "Solarized (Dark)") {
583 preset_accent_color = Color(0.15, 0.55, 0.82);
584 preset_base_color = Color(0.04, 0.23, 0.27);
585 preset_contrast = default_contrast;
586 } else if (preset == "Solarized (Light)") {
587 preset_accent_color = Color(0.15, 0.55, 0.82);
588 preset_base_color = Color(0.89, 0.86, 0.79);
589 // A negative contrast rate looks better for light themes, since it better follows the natural order of UI "elevation".
590 preset_contrast = -0.06;
591 } else if (preset == "Black (OLED)") {
592 preset_accent_color = Color(0.45, 0.75, 1.0);
593 preset_base_color = Color(0, 0, 0);
594 // The contrast rate value is irrelevant on a fully black theme.
595 preset_contrast = 0.0;
596 preset_draw_extra_borders = true;
597 } else { // Default
598 preset_accent_color = Color(0.44, 0.73, 0.98);
599 preset_base_color = Color(0.21, 0.24, 0.29);
600 preset_contrast = default_contrast;
601 }
602
603 if (preset != "Custom") {
604 accent_color = preset_accent_color;
605 base_color = preset_base_color;
606 contrast = preset_contrast;
607 draw_extra_borders = preset_draw_extra_borders;
608 EditorSettings::get_singleton()->set_initial_value("interface/theme/accent_color", accent_color);
609 EditorSettings::get_singleton()->set_initial_value("interface/theme/base_color", base_color);
610 EditorSettings::get_singleton()->set_initial_value("interface/theme/contrast", contrast);
611 EditorSettings::get_singleton()->set_initial_value("interface/theme/draw_extra_borders", draw_extra_borders);
612 }
613
614 EditorSettings::get_singleton()->set_manually("interface/theme/preset", preset);
615 EditorSettings::get_singleton()->set_manually("interface/theme/accent_color", accent_color);
616 EditorSettings::get_singleton()->set_manually("interface/theme/base_color", base_color);
617 EditorSettings::get_singleton()->set_manually("interface/theme/contrast", contrast);
618 EditorSettings::get_singleton()->set_manually("interface/theme/draw_extra_borders", draw_extra_borders);
619
620 // Colors
621 bool dark_theme = EditorSettings::get_singleton()->is_dark_theme();
622
623#ifdef MODULE_SVG_ENABLED
624 if (dark_theme) {
625 ImageLoaderSVG::set_forced_color_map(HashMap<Color, Color>());
626 } else {
627 ImageLoaderSVG::set_forced_color_map(EditorColorMap::get_color_conversion_map());
628 }
629#endif
630
631 // Ensure base colors are in the 0..1 luminance range to avoid 8-bit integer overflow or text rendering issues.
632 // Some places in the editor use 8-bit integer colors.
633 const Color dark_color_1 = base_color.lerp(Color(0, 0, 0, 1), contrast).clamp();
634 const Color dark_color_2 = base_color.lerp(Color(0, 0, 0, 1), contrast * 1.5).clamp();
635 const Color dark_color_3 = base_color.lerp(Color(0, 0, 0, 1), contrast * 2).clamp();
636
637 // Only used when the Draw Extra Borders editor setting is enabled.
638 const Color extra_border_color_1 = Color(0.5, 0.5, 0.5);
639 const Color extra_border_color_2 = dark_theme ? Color(0.3, 0.3, 0.3) : Color(0.7, 0.7, 0.7);
640
641 const Color background_color = dark_color_2;
642
643 // White (dark theme) or black (light theme), will be used to generate the rest of the colors
644 const Color mono_color = dark_theme ? Color(1, 1, 1) : Color(0, 0, 0);
645
646 const Color contrast_color_1 = base_color.lerp(mono_color, MAX(contrast, default_contrast));
647 const Color contrast_color_2 = base_color.lerp(mono_color, MAX(contrast * 1.5, default_contrast * 1.5));
648
649 const Color font_color = mono_color.lerp(base_color, 0.25);
650 const Color font_hover_color = mono_color.lerp(base_color, 0.125);
651 const Color font_focus_color = mono_color.lerp(base_color, 0.125);
652 const Color font_hover_pressed_color = font_hover_color.lerp(accent_color, 0.74);
653 const Color font_disabled_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.35);
654 const Color font_readonly_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.65);
655 const Color font_placeholder_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.6);
656 const Color font_outline_color = Color(0, 0, 0, 0);
657 const Color selection_color = accent_color * Color(1, 1, 1, 0.4);
658 const Color disabled_color = mono_color.inverted().lerp(base_color, 0.7);
659 const Color disabled_bg_color = mono_color.inverted().lerp(base_color, 0.9);
660
661 const Color icon_normal_color = Color(1, 1, 1);
662 Color icon_hover_color = icon_normal_color * (dark_theme ? 1.15 : 1.45);
663 icon_hover_color.a = 1.0;
664 Color icon_focus_color = icon_hover_color;
665 Color icon_disabled_color = Color(icon_normal_color, 0.4);
666 // Make the pressed icon color overbright because icons are not completely white on a dark theme.
667 // On a light theme, icons are dark, so we need to modulate them with an even brighter color.
668 Color icon_pressed_color = accent_color * (dark_theme ? 1.15 : 3.5);
669 icon_pressed_color.a = 1.0;
670
671 const Color separator_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.1);
672 const Color highlight_color = Color(accent_color.r, accent_color.g, accent_color.b, 0.275);
673 const Color disabled_highlight_color = highlight_color.lerp(dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.5);
674
675 // Can't save single float in theme, so using Color.
676 theme->set_color("icon_saturation", EditorStringName(Editor), Color(icon_saturation, icon_saturation, icon_saturation));
677 theme->set_color("accent_color", EditorStringName(Editor), accent_color);
678 theme->set_color("highlight_color", EditorStringName(Editor), highlight_color);
679 theme->set_color("disabled_highlight_color", EditorStringName(Editor), disabled_highlight_color);
680 theme->set_color("base_color", EditorStringName(Editor), base_color);
681 theme->set_color("dark_color_1", EditorStringName(Editor), dark_color_1);
682 theme->set_color("dark_color_2", EditorStringName(Editor), dark_color_2);
683 theme->set_color("dark_color_3", EditorStringName(Editor), dark_color_3);
684 theme->set_color("contrast_color_1", EditorStringName(Editor), contrast_color_1);
685 theme->set_color("contrast_color_2", EditorStringName(Editor), contrast_color_2);
686 theme->set_color("box_selection_fill_color", EditorStringName(Editor), accent_color * Color(1, 1, 1, 0.3));
687 theme->set_color("box_selection_stroke_color", EditorStringName(Editor), accent_color * Color(1, 1, 1, 0.8));
688
689 theme->set_color("axis_x_color", EditorStringName(Editor), Color(0.96, 0.20, 0.32));
690 theme->set_color("axis_y_color", EditorStringName(Editor), Color(0.53, 0.84, 0.01));
691 theme->set_color("axis_z_color", EditorStringName(Editor), Color(0.16, 0.55, 0.96));
692 theme->set_color("axis_w_color", EditorStringName(Editor), Color(0.55, 0.55, 0.55));
693
694 const float prop_color_saturation = accent_color.get_s() * 0.75;
695 const float prop_color_value = accent_color.get_v();
696
697 theme->set_color("property_color_x", EditorStringName(Editor), Color().from_hsv(0.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value));
698 theme->set_color("property_color_y", EditorStringName(Editor), Color().from_hsv(1.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value));
699 theme->set_color("property_color_z", EditorStringName(Editor), Color().from_hsv(2.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value));
700 theme->set_color("property_color_w", EditorStringName(Editor), Color().from_hsv(1.5 / 3.0 + 0.05, prop_color_saturation, prop_color_value));
701
702 theme->set_color("font_color", EditorStringName(Editor), font_color);
703 theme->set_color("highlighted_font_color", EditorStringName(Editor), font_hover_color);
704 theme->set_color("disabled_font_color", EditorStringName(Editor), font_disabled_color);
705 theme->set_color("readonly_font_color", EditorStringName(Editor), font_readonly_color);
706
707 theme->set_color("mono_color", EditorStringName(Editor), mono_color);
708
709 Color success_color = Color(0.45, 0.95, 0.5);
710 Color warning_color = Color(1, 0.87, 0.4);
711 Color error_color = Color(1, 0.47, 0.42);
712 Color property_color = font_color.lerp(Color(0.5, 0.5, 0.5), 0.5);
713 Color readonly_color = property_color.lerp(dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.25);
714 Color readonly_warning_color = error_color.lerp(dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.25);
715
716 if (!dark_theme) {
717 // Darken some colors to be readable on a light background.
718 success_color = success_color.lerp(mono_color, 0.35);
719 warning_color = warning_color.lerp(mono_color, 0.35);
720 error_color = error_color.lerp(mono_color, 0.25);
721 }
722
723 theme->set_color("success_color", EditorStringName(Editor), success_color);
724 theme->set_color("warning_color", EditorStringName(Editor), warning_color);
725 theme->set_color("error_color", EditorStringName(Editor), error_color);
726 theme->set_color("property_color", EditorStringName(Editor), property_color);
727 theme->set_color("readonly_color", EditorStringName(Editor), readonly_color);
728
729 if (!dark_theme) {
730 theme->set_color("highend_color", EditorStringName(Editor), Color::hex(0xad1128ff));
731 } else {
732 theme->set_color("highend_color", EditorStringName(Editor), Color(1.0, 0.0, 0.0));
733 }
734
735 const int thumb_size = EDITOR_GET("filesystem/file_dialog/thumbnail_size");
736 theme->set_constant("scale", EditorStringName(Editor), EDSCALE);
737 theme->set_constant("thumb_size", EditorStringName(Editor), thumb_size);
738 theme->set_constant("class_icon_size", EditorStringName(Editor), 16 * EDSCALE);
739 theme->set_constant("dark_theme", EditorStringName(Editor), dark_theme);
740 theme->set_constant("color_picker_button_height", EditorStringName(Editor), 28 * EDSCALE);
741 theme->set_constant("gizmo_handle_scale", EditorStringName(Editor), gizmo_handle_scale);
742 theme->set_constant("window_border_margin", EditorStringName(Editor), 8);
743 theme->set_constant("top_bar_separation", EditorStringName(Editor), 8 * EDSCALE);
744
745 // Register editor icons.
746 // If the settings are comparable to the old theme, then just copy them over.
747 // Otherwise, regenerate them. Also check if we need to regenerate "thumb" icons.
748 bool keep_old_icons = false;
749 bool regenerate_thumb_icons = true;
750 if (p_theme != nullptr) {
751 // We check editor scale, theme dark/light mode, icon saturation, and accent color.
752
753 // That doesn't really work as expected, since theme constants are integers, and scales are floats.
754 // So this check will never work when changing between 100-199% values.
755 const float prev_scale = (float)p_theme->get_constant(SNAME("scale"), EditorStringName(Editor));
756 const bool prev_dark_theme = (bool)p_theme->get_constant(SNAME("dark_theme"), EditorStringName(Editor));
757 const Color prev_accent_color = p_theme->get_color(SNAME("accent_color"), EditorStringName(Editor));
758 const float prev_icon_saturation = p_theme->get_color(SNAME("icon_saturation"), EditorStringName(Editor)).r;
759 const float prev_gizmo_handle_scale = (float)p_theme->get_constant(SNAME("gizmo_handle_scale"), EditorStringName(Editor));
760
761 keep_old_icons = (Math::is_equal_approx(prev_scale, EDSCALE) &&
762 Math::is_equal_approx(prev_gizmo_handle_scale, gizmo_handle_scale) &&
763 prev_dark_theme == dark_theme &&
764 prev_accent_color == accent_color &&
765 prev_icon_saturation == icon_saturation);
766
767 const double prev_thumb_size = (double)p_theme->get_constant(SNAME("thumb_size"), EditorStringName(Editor));
768
769 regenerate_thumb_icons = !Math::is_equal_approx(prev_thumb_size, thumb_size);
770 }
771
772#ifndef MODULE_SVG_ENABLED
773 WARN_PRINT("SVG support disabled, editor icons won't be rendered.");
774#endif
775
776 if (keep_old_icons) {
777 for (int i = 0; i < editor_icons_count; i++) {
778 theme->set_icon(editor_icons_names[i], EditorStringName(EditorIcons), p_theme->get_icon(editor_icons_names[i], EditorStringName(EditorIcons)));
779 }
780 } else {
781 editor_register_and_generate_icons(theme, dark_theme, icon_saturation, thumb_size, false);
782 }
783 if (regenerate_thumb_icons) {
784 editor_register_and_generate_icons(theme, dark_theme, icon_saturation, thumb_size, true);
785 }
786
787 // Register editor fonts.
788 editor_register_fonts(theme);
789
790 // Ensure borders are visible when using an editor scale below 100%.
791 const int border_width = CLAMP(border_size, 0, 2) * MAX(1, EDSCALE);
792 const int corner_width = CLAMP(corner_radius, 0, 6);
793 const int default_margin_size = 4;
794 const int margin_size_extra = default_margin_size + CLAMP(border_size, 0, 2);
795
796 // Styleboxes
797 // This is the most commonly used stylebox, variations should be made as duplicate of this
798 Ref<StyleBoxFlat> style_default = make_flat_stylebox(base_color, default_margin_size, default_margin_size, default_margin_size, default_margin_size, corner_width);
799 style_default->set_border_width_all(border_width);
800 style_default->set_border_color(base_color);
801
802 // Button and widgets
803 const float extra_spacing = EDITOR_GET("interface/theme/additional_spacing");
804
805 const Vector2 widget_default_margin = Vector2(extra_spacing + 6, extra_spacing + default_margin_size + 1) * EDSCALE;
806
807 Ref<StyleBoxFlat> style_widget = style_default->duplicate();
808 style_widget->set_content_margin_individual(widget_default_margin.x, widget_default_margin.y, widget_default_margin.x, widget_default_margin.y);
809 style_widget->set_bg_color(dark_color_1);
810 if (draw_extra_borders) {
811 style_widget->set_border_width_all(Math::round(EDSCALE));
812 style_widget->set_border_color(extra_border_color_1);
813 } else {
814 style_widget->set_border_color(dark_color_2);
815 }
816
817 Ref<StyleBoxFlat> style_widget_disabled = style_widget->duplicate();
818 if (draw_extra_borders) {
819 style_widget_disabled->set_border_color(extra_border_color_2);
820 } else {
821 style_widget_disabled->set_border_color(disabled_color);
822 }
823 style_widget_disabled->set_bg_color(disabled_bg_color);
824
825 Ref<StyleBoxFlat> style_widget_focus = style_widget->duplicate();
826 style_widget_focus->set_draw_center(false);
827 style_widget_focus->set_border_width_all(Math::round(2 * MAX(1, EDSCALE)));
828 style_widget_focus->set_border_color(accent_color);
829
830 Ref<StyleBoxFlat> style_widget_pressed = style_widget->duplicate();
831 style_widget_pressed->set_bg_color(dark_color_1.darkened(0.125));
832
833 Ref<StyleBoxFlat> style_widget_hover = style_widget->duplicate();
834 style_widget_hover->set_bg_color(mono_color * Color(1, 1, 1, 0.11));
835 if (draw_extra_borders) {
836 style_widget_hover->set_border_color(extra_border_color_1);
837 } else {
838 style_widget_hover->set_border_color(mono_color * Color(1, 1, 1, 0.05));
839 }
840
841 // Style for windows, popups, etc..
842 Ref<StyleBoxFlat> style_popup = style_default->duplicate();
843 const int popup_margin_size = default_margin_size * EDSCALE * 3;
844 style_popup->set_content_margin_all(popup_margin_size);
845 style_popup->set_border_color(contrast_color_1);
846 const Color shadow_color = Color(0, 0, 0, dark_theme ? 0.3 : 0.1);
847 style_popup->set_shadow_color(shadow_color);
848 style_popup->set_shadow_size(4 * EDSCALE);
849 // Popups are separate windows by default in the editor. Windows currently don't support per-pixel transparency
850 // in 4.0, and even if it was, it may not always work in practice (e.g. running with compositing disabled).
851 style_popup->set_corner_radius_all(0);
852
853 Ref<StyleBoxLine> style_popup_separator(memnew(StyleBoxLine));
854 style_popup_separator->set_color(separator_color);
855 style_popup_separator->set_grow_begin(popup_margin_size - MAX(Math::round(EDSCALE), border_width));
856 style_popup_separator->set_grow_end(popup_margin_size - MAX(Math::round(EDSCALE), border_width));
857 style_popup_separator->set_thickness(MAX(Math::round(EDSCALE), border_width));
858
859 Ref<StyleBoxLine> style_popup_labeled_separator_left(memnew(StyleBoxLine));
860 style_popup_labeled_separator_left->set_grow_begin(popup_margin_size - MAX(Math::round(EDSCALE), border_width));
861 style_popup_labeled_separator_left->set_color(separator_color);
862 style_popup_labeled_separator_left->set_thickness(MAX(Math::round(EDSCALE), border_width));
863
864 Ref<StyleBoxLine> style_popup_labeled_separator_right(memnew(StyleBoxLine));
865 style_popup_labeled_separator_right->set_grow_end(popup_margin_size - MAX(Math::round(EDSCALE), border_width));
866 style_popup_labeled_separator_right->set_color(separator_color);
867 style_popup_labeled_separator_right->set_thickness(MAX(Math::round(EDSCALE), border_width));
868
869 Ref<StyleBoxEmpty> style_empty = make_empty_stylebox(default_margin_size, default_margin_size, default_margin_size, default_margin_size);
870
871 // TabBar
872
873 Ref<StyleBoxFlat> style_tab_base = style_widget->duplicate();
874
875 style_tab_base->set_border_width_all(0);
876 // Don't round the top corners to avoid creating a small blank space between the tabs and the main panel.
877 // This also makes the top highlight look better.
878 style_tab_base->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
879 style_tab_base->set_corner_radius(CORNER_BOTTOM_RIGHT, 0);
880
881 // When using a border width greater than 0, visually line up the left of the selected tab with the underlying panel.
882 style_tab_base->set_expand_margin(SIDE_LEFT, -border_width);
883
884 style_tab_base->set_content_margin(SIDE_LEFT, widget_default_margin.x + 5 * EDSCALE);
885 style_tab_base->set_content_margin(SIDE_RIGHT, widget_default_margin.x + 5 * EDSCALE);
886 style_tab_base->set_content_margin(SIDE_BOTTOM, widget_default_margin.y);
887 style_tab_base->set_content_margin(SIDE_TOP, widget_default_margin.y);
888
889 Ref<StyleBoxFlat> style_tab_selected = style_tab_base->duplicate();
890
891 style_tab_selected->set_bg_color(base_color);
892 // Add a highlight line at the top of the selected tab.
893 style_tab_selected->set_border_width(SIDE_TOP, Math::round(2 * EDSCALE));
894 // Make the highlight line prominent, but not too prominent as to not be distracting.
895 Color tab_highlight = dark_color_2.lerp(accent_color, 0.75);
896 style_tab_selected->set_border_color(tab_highlight);
897 style_tab_selected->set_corner_radius_all(0);
898
899 Ref<StyleBoxFlat> style_tab_hovered = style_tab_base->duplicate();
900
901 style_tab_hovered->set_bg_color(dark_color_1.lerp(base_color, 0.4));
902 // Hovered tab has a subtle highlight between normal and selected states.
903 style_tab_hovered->set_corner_radius_all(0);
904
905 Ref<StyleBoxFlat> style_tab_unselected = style_tab_base->duplicate();
906 style_tab_unselected->set_expand_margin(SIDE_BOTTOM, 0);
907 style_tab_unselected->set_bg_color(dark_color_1);
908 // Add some spacing between unselected tabs to make them easier to distinguish from each other
909 style_tab_unselected->set_border_color(Color(0, 0, 0, 0));
910
911 Ref<StyleBoxFlat> style_tab_disabled = style_tab_base->duplicate();
912 style_tab_disabled->set_expand_margin(SIDE_BOTTOM, 0);
913 style_tab_disabled->set_bg_color(disabled_bg_color);
914 style_tab_disabled->set_border_color(disabled_bg_color);
915
916 // Editor background
917 Color background_color_opaque = background_color;
918 background_color_opaque.a = 1.0;
919 theme->set_color("background", EditorStringName(Editor), background_color_opaque);
920 theme->set_stylebox("Background", EditorStringName(EditorStyles), make_flat_stylebox(background_color_opaque, default_margin_size, default_margin_size, default_margin_size, default_margin_size));
921
922 // Focus
923 theme->set_stylebox("Focus", EditorStringName(EditorStyles), style_widget_focus);
924 // Use a less opaque color to be less distracting for the 2D and 3D editor viewports.
925 Ref<StyleBoxFlat> style_widget_focus_viewport = style_widget_focus->duplicate();
926 style_widget_focus_viewport->set_border_color(accent_color * Color(1, 1, 1, 0.5));
927 theme->set_stylebox("FocusViewport", EditorStringName(EditorStyles), style_widget_focus_viewport);
928
929 // Menu
930 Ref<StyleBoxFlat> style_menu = style_widget->duplicate();
931 style_menu->set_draw_center(false);
932 style_menu->set_border_width_all(0);
933 theme->set_stylebox("panel", "PanelContainer", style_menu);
934 theme->set_stylebox("MenuPanel", EditorStringName(EditorStyles), style_menu);
935
936 // CanvasItem Editor
937 Ref<StyleBoxFlat> style_canvas_editor_info = make_flat_stylebox(Color(0.0, 0.0, 0.0, 0.2));
938 style_canvas_editor_info->set_expand_margin_all(4 * EDSCALE);
939 theme->set_stylebox("CanvasItemInfoOverlay", EditorStringName(EditorStyles), style_canvas_editor_info);
940
941 // 2D and 3D contextual toolbar.
942 // Use a custom stylebox to make contextual menu items stand out from the rest.
943 // This helps with editor usability as contextual menu items change when selecting nodes,
944 // even though it may not be immediately obvious at first.
945 Ref<StyleBoxFlat> toolbar_stylebox = memnew(StyleBoxFlat);
946 toolbar_stylebox->set_bg_color(accent_color * Color(1, 1, 1, 0.1));
947 toolbar_stylebox->set_anti_aliased(false);
948 // Add an underline to the StyleBox, but prevent its minimum vertical size from changing.
949 toolbar_stylebox->set_border_color(accent_color);
950 toolbar_stylebox->set_border_width(SIDE_BOTTOM, Math::round(2 * EDSCALE));
951 toolbar_stylebox->set_content_margin(SIDE_BOTTOM, 0);
952 toolbar_stylebox->set_expand_margin_all(2 * EDSCALE);
953 theme->set_stylebox("ContextualToolbar", EditorStringName(EditorStyles), toolbar_stylebox);
954
955 // Script Editor
956 theme->set_stylebox("ScriptEditorPanel", EditorStringName(EditorStyles), make_empty_stylebox(default_margin_size, 0, default_margin_size, default_margin_size));
957 theme->set_stylebox("ScriptEditorPanelFloating", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0));
958
959 theme->set_stylebox("ScriptEditor", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0));
960
961 // Launch Pad and Play buttons
962 Ref<StyleBoxFlat> style_launch_pad = make_flat_stylebox(dark_color_1, 2 * EDSCALE, 0, 2 * EDSCALE, 0, corner_width);
963 style_launch_pad->set_corner_radius_all(corner_radius * EDSCALE);
964 theme->set_stylebox("LaunchPadNormal", EditorStringName(EditorStyles), style_launch_pad);
965 Ref<StyleBoxFlat> style_launch_pad_movie = style_launch_pad->duplicate();
966 style_launch_pad_movie->set_bg_color(accent_color * Color(1, 1, 1, 0.1));
967 style_launch_pad_movie->set_border_color(accent_color);
968 style_launch_pad_movie->set_border_width_all(Math::round(2 * EDSCALE));
969 theme->set_stylebox("LaunchPadMovieMode", EditorStringName(EditorStyles), style_launch_pad_movie);
970
971 theme->set_stylebox("MovieWriterButtonNormal", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0));
972 Ref<StyleBoxFlat> style_write_movie_button = style_widget_pressed->duplicate();
973 style_write_movie_button->set_bg_color(accent_color);
974 style_write_movie_button->set_corner_radius_all(corner_radius * EDSCALE);
975 style_write_movie_button->set_content_margin(SIDE_TOP, 0);
976 style_write_movie_button->set_content_margin(SIDE_BOTTOM, 0);
977 style_write_movie_button->set_content_margin(SIDE_LEFT, 0);
978 style_write_movie_button->set_content_margin(SIDE_RIGHT, 0);
979 style_write_movie_button->set_expand_margin(SIDE_RIGHT, 2 * EDSCALE);
980 theme->set_stylebox("MovieWriterButtonPressed", EditorStringName(EditorStyles), style_write_movie_button);
981
982 // MenuButton
983 theme->set_stylebox("normal", "MenuButton", style_menu);
984 theme->set_stylebox("hover", "MenuButton", style_widget_hover);
985 theme->set_stylebox("pressed", "MenuButton", style_menu);
986 theme->set_stylebox("focus", "MenuButton", style_menu);
987 theme->set_stylebox("disabled", "MenuButton", style_menu);
988
989 theme->set_color("font_color", "MenuButton", font_color);
990 theme->set_color("font_hover_color", "MenuButton", font_hover_color);
991 theme->set_color("font_hover_pressed_color", "MenuButton", font_hover_pressed_color);
992 theme->set_color("font_focus_color", "MenuButton", font_focus_color);
993 theme->set_color("font_outline_color", "MenuButton", font_outline_color);
994
995 theme->set_constant("outline_size", "MenuButton", 0);
996
997 theme->set_stylebox("MenuHover", EditorStringName(EditorStyles), style_widget_hover);
998
999 // Buttons
1000 theme->set_stylebox("normal", "Button", style_widget);
1001 theme->set_stylebox("hover", "Button", style_widget_hover);
1002 theme->set_stylebox("pressed", "Button", style_widget_pressed);
1003 theme->set_stylebox("focus", "Button", style_widget_focus);
1004 theme->set_stylebox("disabled", "Button", style_widget_disabled);
1005
1006 theme->set_color("font_color", "Button", font_color);
1007 theme->set_color("font_hover_color", "Button", font_hover_color);
1008 theme->set_color("font_hover_pressed_color", "Button", font_hover_pressed_color);
1009 theme->set_color("font_focus_color", "Button", font_focus_color);
1010 theme->set_color("font_pressed_color", "Button", accent_color);
1011 theme->set_color("font_disabled_color", "Button", font_disabled_color);
1012 theme->set_color("font_outline_color", "Button", font_outline_color);
1013
1014 theme->set_color("icon_normal_color", "Button", icon_normal_color);
1015 theme->set_color("icon_hover_color", "Button", icon_hover_color);
1016 theme->set_color("icon_focus_color", "Button", icon_focus_color);
1017 theme->set_color("icon_pressed_color", "Button", icon_pressed_color);
1018 theme->set_color("icon_disabled_color", "Button", icon_disabled_color);
1019
1020 theme->set_constant("h_separation", "Button", 4 * EDSCALE);
1021 theme->set_constant("outline_size", "Button", 0);
1022
1023 const float ACTION_BUTTON_EXTRA_MARGIN = 32 * EDSCALE;
1024
1025 theme->set_type_variation("InspectorActionButton", "Button");
1026 Color color_inspector_action = dark_color_1.lerp(mono_color, 0.12);
1027 color_inspector_action.a = 0.5;
1028 Ref<StyleBoxFlat> style_inspector_action = style_widget->duplicate();
1029 style_inspector_action->set_bg_color(color_inspector_action);
1030 style_inspector_action->set_content_margin(SIDE_RIGHT, ACTION_BUTTON_EXTRA_MARGIN);
1031 theme->set_stylebox("normal", "InspectorActionButton", style_inspector_action);
1032 style_inspector_action = style_widget_hover->duplicate();
1033 style_inspector_action->set_content_margin(SIDE_RIGHT, ACTION_BUTTON_EXTRA_MARGIN);
1034 theme->set_stylebox("hover", "InspectorActionButton", style_inspector_action);
1035 style_inspector_action = style_widget_pressed->duplicate();
1036 style_inspector_action->set_content_margin(SIDE_RIGHT, ACTION_BUTTON_EXTRA_MARGIN);
1037 theme->set_stylebox("pressed", "InspectorActionButton", style_inspector_action);
1038 style_inspector_action = style_widget_disabled->duplicate();
1039 style_inspector_action->set_content_margin(SIDE_RIGHT, ACTION_BUTTON_EXTRA_MARGIN);
1040 theme->set_stylebox("disabled", "InspectorActionButton", style_inspector_action);
1041 theme->set_constant("h_separation", "InspectorActionButton", ACTION_BUTTON_EXTRA_MARGIN);
1042
1043 // Variation for Editor Log filter buttons
1044 theme->set_type_variation("EditorLogFilterButton", "Button");
1045 // When pressed, don't tint the icons with the accent color, just leave them normal.
1046 theme->set_color("icon_pressed_color", "EditorLogFilterButton", icon_normal_color);
1047 // When unpressed, dim the icons.
1048 theme->set_color("icon_normal_color", "EditorLogFilterButton", icon_disabled_color);
1049 // When pressed, add a small bottom border to the buttons to better show their active state,
1050 // similar to active tabs.
1051 Ref<StyleBoxFlat> editor_log_button_pressed = style_widget_pressed->duplicate();
1052 editor_log_button_pressed->set_border_width(SIDE_BOTTOM, 2 * EDSCALE);
1053 editor_log_button_pressed->set_border_color(accent_color);
1054 theme->set_stylebox("pressed", "EditorLogFilterButton", editor_log_button_pressed);
1055
1056 // Buttons in material previews
1057 const Color dim_light_color = icon_normal_color.darkened(0.24);
1058 const Color dim_light_highlighted_color = icon_normal_color.darkened(0.18);
1059 Ref<StyleBox> sb_empty_borderless = make_empty_stylebox();
1060
1061 theme->set_type_variation("PreviewLightButton", "Button");
1062 // When pressed, don't use the accent color tint. When unpressed, dim the icon.
1063 theme->set_color("icon_normal_color", "PreviewLightButton", dim_light_color);
1064 theme->set_color("icon_focus_color", "PreviewLightButton", dim_light_color);
1065 theme->set_color("icon_pressed_color", "PreviewLightButton", icon_normal_color);
1066 theme->set_color("icon_hover_pressed_color", "PreviewLightButton", icon_normal_color);
1067 // Unpressed icon is dim, so use a dim highlight.
1068 theme->set_color("icon_hover_color", "PreviewLightButton", dim_light_highlighted_color);
1069
1070 theme->set_stylebox("normal", "PreviewLightButton", sb_empty_borderless);
1071 theme->set_stylebox("hover", "PreviewLightButton", sb_empty_borderless);
1072 theme->set_stylebox("focus", "PreviewLightButton", sb_empty_borderless);
1073 theme->set_stylebox("pressed", "PreviewLightButton", sb_empty_borderless);
1074
1075 // ProjectTag
1076 {
1077 theme->set_type_variation("ProjectTag", "Button");
1078
1079 Ref<StyleBoxFlat> tag = style_widget->duplicate();
1080 tag->set_bg_color(dark_theme ? tag->get_bg_color().lightened(0.2) : tag->get_bg_color().darkened(0.2));
1081 tag->set_corner_radius(CORNER_TOP_LEFT, 0);
1082 tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
1083 tag->set_corner_radius(CORNER_TOP_RIGHT, 4);
1084 tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4);
1085 theme->set_stylebox("normal", "ProjectTag", tag);
1086
1087 tag = style_widget_hover->duplicate();
1088 tag->set_corner_radius(CORNER_TOP_LEFT, 0);
1089 tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
1090 tag->set_corner_radius(CORNER_TOP_RIGHT, 4);
1091 tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4);
1092 theme->set_stylebox("hover", "ProjectTag", tag);
1093
1094 tag = style_widget_pressed->duplicate();
1095 tag->set_corner_radius(CORNER_TOP_LEFT, 0);
1096 tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
1097 tag->set_corner_radius(CORNER_TOP_RIGHT, 4);
1098 tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4);
1099 theme->set_stylebox("pressed", "ProjectTag", tag);
1100 }
1101
1102 // MenuBar
1103 theme->set_stylebox("normal", "MenuBar", style_widget);
1104 theme->set_stylebox("hover", "MenuBar", style_widget_hover);
1105 theme->set_stylebox("pressed", "MenuBar", style_widget_pressed);
1106 theme->set_stylebox("focus", "MenuBar", style_widget_focus);
1107 theme->set_stylebox("disabled", "MenuBar", style_widget_disabled);
1108
1109 theme->set_color("font_color", "MenuBar", font_color);
1110 theme->set_color("font_hover_color", "MenuBar", font_hover_color);
1111 theme->set_color("font_hover_pressed_color", "MenuBar", font_hover_pressed_color);
1112 theme->set_color("font_focus_color", "MenuBar", font_focus_color);
1113 theme->set_color("font_pressed_color", "MenuBar", accent_color);
1114 theme->set_color("font_disabled_color", "MenuBar", font_disabled_color);
1115 theme->set_color("font_outline_color", "MenuBar", font_outline_color);
1116
1117 theme->set_color("icon_normal_color", "MenuBar", icon_normal_color);
1118 theme->set_color("icon_hover_color", "MenuBar", icon_hover_color);
1119 theme->set_color("icon_focus_color", "MenuBar", icon_focus_color);
1120 theme->set_color("icon_pressed_color", "MenuBar", icon_pressed_color);
1121 theme->set_color("icon_disabled_color", "MenuBar", icon_disabled_color);
1122
1123 theme->set_constant("h_separation", "MenuBar", 4 * EDSCALE);
1124 theme->set_constant("outline_size", "MenuBar", 0);
1125
1126 // OptionButton
1127 Ref<StyleBoxFlat> style_option_button_focus = style_widget_focus->duplicate();
1128 Ref<StyleBoxFlat> style_option_button_normal = style_widget->duplicate();
1129 Ref<StyleBoxFlat> style_option_button_hover = style_widget_hover->duplicate();
1130 Ref<StyleBoxFlat> style_option_button_pressed = style_widget_pressed->duplicate();
1131 Ref<StyleBoxFlat> style_option_button_disabled = style_widget_disabled->duplicate();
1132
1133 style_option_button_focus->set_content_margin(SIDE_RIGHT, 4 * EDSCALE);
1134 style_option_button_normal->set_content_margin(SIDE_RIGHT, 4 * EDSCALE);
1135 style_option_button_hover->set_content_margin(SIDE_RIGHT, 4 * EDSCALE);
1136 style_option_button_pressed->set_content_margin(SIDE_RIGHT, 4 * EDSCALE);
1137 style_option_button_disabled->set_content_margin(SIDE_RIGHT, 4 * EDSCALE);
1138
1139 theme->set_stylebox("focus", "OptionButton", style_option_button_focus);
1140 theme->set_stylebox("normal", "OptionButton", style_widget);
1141 theme->set_stylebox("hover", "OptionButton", style_widget_hover);
1142 theme->set_stylebox("pressed", "OptionButton", style_widget_pressed);
1143 theme->set_stylebox("disabled", "OptionButton", style_widget_disabled);
1144
1145 theme->set_stylebox("normal_mirrored", "OptionButton", style_option_button_normal);
1146 theme->set_stylebox("hover_mirrored", "OptionButton", style_option_button_hover);
1147 theme->set_stylebox("pressed_mirrored", "OptionButton", style_option_button_pressed);
1148 theme->set_stylebox("disabled_mirrored", "OptionButton", style_option_button_disabled);
1149
1150 theme->set_color("font_color", "OptionButton", font_color);
1151 theme->set_color("font_hover_color", "OptionButton", font_hover_color);
1152 theme->set_color("font_hover_pressed_color", "OptionButton", font_hover_pressed_color);
1153 theme->set_color("font_focus_color", "OptionButton", font_focus_color);
1154 theme->set_color("font_pressed_color", "OptionButton", accent_color);
1155 theme->set_color("font_disabled_color", "OptionButton", font_disabled_color);
1156 theme->set_color("font_outline_color", "OptionButton", font_outline_color);
1157
1158 theme->set_color("icon_normal_color", "OptionButton", icon_normal_color);
1159 theme->set_color("icon_hover_color", "OptionButton", icon_hover_color);
1160 theme->set_color("icon_focus_color", "OptionButton", icon_focus_color);
1161 theme->set_color("icon_pressed_color", "OptionButton", icon_pressed_color);
1162 theme->set_color("icon_disabled_color", "OptionButton", icon_disabled_color);
1163
1164 theme->set_icon("arrow", "OptionButton", theme->get_icon(SNAME("GuiOptionArrow"), EditorStringName(EditorIcons)));
1165 theme->set_constant("arrow_margin", "OptionButton", widget_default_margin.x - 2 * EDSCALE);
1166 theme->set_constant("modulate_arrow", "OptionButton", true);
1167 theme->set_constant("h_separation", "OptionButton", 4 * EDSCALE);
1168 theme->set_constant("outline_size", "OptionButton", 0);
1169
1170 // CheckButton
1171 theme->set_stylebox("normal", "CheckButton", style_menu);
1172 theme->set_stylebox("pressed", "CheckButton", style_menu);
1173 theme->set_stylebox("disabled", "CheckButton", style_menu);
1174 theme->set_stylebox("hover", "CheckButton", style_menu);
1175 theme->set_stylebox("hover_pressed", "CheckButton", style_menu);
1176
1177 theme->set_icon("checked", "CheckButton", theme->get_icon(SNAME("GuiToggleOn"), EditorStringName(EditorIcons)));
1178 theme->set_icon("checked_disabled", "CheckButton", theme->get_icon(SNAME("GuiToggleOnDisabled"), EditorStringName(EditorIcons)));
1179 theme->set_icon("unchecked", "CheckButton", theme->get_icon(SNAME("GuiToggleOff"), EditorStringName(EditorIcons)));
1180 theme->set_icon("unchecked_disabled", "CheckButton", theme->get_icon(SNAME("GuiToggleOffDisabled"), EditorStringName(EditorIcons)));
1181
1182 theme->set_icon("checked_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOnMirrored"), EditorStringName(EditorIcons)));
1183 theme->set_icon("checked_disabled_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOnDisabledMirrored"), EditorStringName(EditorIcons)));
1184 theme->set_icon("unchecked_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOffMirrored"), EditorStringName(EditorIcons)));
1185 theme->set_icon("unchecked_disabled_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOffDisabledMirrored"), EditorStringName(EditorIcons)));
1186
1187 theme->set_color("font_color", "CheckButton", font_color);
1188 theme->set_color("font_hover_color", "CheckButton", font_hover_color);
1189 theme->set_color("font_hover_pressed_color", "CheckButton", font_hover_pressed_color);
1190 theme->set_color("font_focus_color", "CheckButton", font_focus_color);
1191 theme->set_color("font_pressed_color", "CheckButton", accent_color);
1192 theme->set_color("font_disabled_color", "CheckButton", font_disabled_color);
1193 theme->set_color("font_outline_color", "CheckButton", font_outline_color);
1194
1195 theme->set_color("icon_normal_color", "CheckButton", icon_normal_color);
1196 theme->set_color("icon_hover_color", "CheckButton", icon_hover_color);
1197 theme->set_color("icon_focus_color", "CheckButton", icon_focus_color);
1198 theme->set_color("icon_pressed_color", "CheckButton", icon_pressed_color);
1199 theme->set_color("icon_disabled_color", "CheckButton", icon_disabled_color);
1200
1201 theme->set_constant("h_separation", "CheckButton", 8 * EDSCALE);
1202 theme->set_constant("check_v_offset", "CheckButton", 0);
1203 theme->set_constant("outline_size", "CheckButton", 0);
1204
1205 // Checkbox
1206 Ref<StyleBoxFlat> sb_checkbox = style_menu->duplicate();
1207 sb_checkbox->set_content_margin_all(default_margin_size * EDSCALE);
1208
1209 theme->set_stylebox("normal", "CheckBox", sb_checkbox);
1210 theme->set_stylebox("pressed", "CheckBox", sb_checkbox);
1211 theme->set_stylebox("disabled", "CheckBox", sb_checkbox);
1212 theme->set_stylebox("hover", "CheckBox", sb_checkbox);
1213 theme->set_stylebox("hover_pressed", "CheckBox", sb_checkbox);
1214 theme->set_icon("checked", "CheckBox", theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons)));
1215 theme->set_icon("unchecked", "CheckBox", theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons)));
1216 theme->set_icon("radio_checked", "CheckBox", theme->get_icon(SNAME("GuiRadioChecked"), EditorStringName(EditorIcons)));
1217 theme->set_icon("radio_unchecked", "CheckBox", theme->get_icon(SNAME("GuiRadioUnchecked"), EditorStringName(EditorIcons)));
1218 theme->set_icon("checked_disabled", "CheckBox", theme->get_icon(SNAME("GuiCheckedDisabled"), EditorStringName(EditorIcons)));
1219 theme->set_icon("unchecked_disabled", "CheckBox", theme->get_icon(SNAME("GuiUncheckedDisabled"), EditorStringName(EditorIcons)));
1220 theme->set_icon("radio_checked_disabled", "CheckBox", theme->get_icon(SNAME("GuiRadioCheckedDisabled"), EditorStringName(EditorIcons)));
1221 theme->set_icon("radio_unchecked_disabled", "CheckBox", theme->get_icon(SNAME("GuiRadioUncheckedDisabled"), EditorStringName(EditorIcons)));
1222
1223 theme->set_color("font_color", "CheckBox", font_color);
1224 theme->set_color("font_hover_color", "CheckBox", font_hover_color);
1225 theme->set_color("font_hover_pressed_color", "CheckBox", font_hover_pressed_color);
1226 theme->set_color("font_focus_color", "CheckBox", font_focus_color);
1227 theme->set_color("font_pressed_color", "CheckBox", accent_color);
1228 theme->set_color("font_disabled_color", "CheckBox", font_disabled_color);
1229 theme->set_color("font_outline_color", "CheckBox", font_outline_color);
1230
1231 theme->set_color("icon_normal_color", "CheckBox", icon_normal_color);
1232 theme->set_color("icon_hover_color", "CheckBox", icon_hover_color);
1233 theme->set_color("icon_focus_color", "CheckBox", icon_focus_color);
1234 theme->set_color("icon_pressed_color", "CheckBox", icon_pressed_color);
1235 theme->set_color("icon_disabled_color", "CheckBox", icon_disabled_color);
1236
1237 theme->set_constant("h_separation", "CheckBox", 8 * EDSCALE);
1238 theme->set_constant("check_v_offset", "CheckBox", 0);
1239 theme->set_constant("outline_size", "CheckBox", 0);
1240
1241 // PopupDialog
1242 theme->set_stylebox("panel", "PopupDialog", style_popup);
1243
1244 // PopupMenu
1245 Ref<StyleBoxFlat> style_popup_menu = style_popup->duplicate();
1246 // Use 1 pixel for the sides, since if 0 is used, the highlight of hovered items is drawn
1247 // on top of the popup border. This causes a 'gap' in the panel border when an item is highlighted,
1248 // and it looks weird. 1px solves this.
1249 style_popup_menu->set_content_margin_individual(EDSCALE, 2 * EDSCALE, EDSCALE, 2 * EDSCALE);
1250 // Always display a border for PopupMenus so they can be distinguished from their background.
1251 style_popup_menu->set_border_width_all(EDSCALE);
1252 if (draw_extra_borders) {
1253 style_popup_menu->set_border_color(extra_border_color_2);
1254 } else {
1255 style_popup_menu->set_border_color(dark_color_2);
1256 }
1257 theme->set_stylebox("panel", "PopupMenu", style_popup_menu);
1258
1259 Ref<StyleBoxFlat> style_menu_hover = style_widget_hover->duplicate();
1260 // Don't use rounded corners for hover highlights since the StyleBox touches the PopupMenu's edges.
1261 style_menu_hover->set_corner_radius_all(0);
1262 theme->set_stylebox("hover", "PopupMenu", style_menu_hover);
1263
1264 theme->set_stylebox("separator", "PopupMenu", style_popup_separator);
1265 theme->set_stylebox("labeled_separator_left", "PopupMenu", style_popup_labeled_separator_left);
1266 theme->set_stylebox("labeled_separator_right", "PopupMenu", style_popup_labeled_separator_right);
1267
1268 theme->set_color("font_color", "PopupMenu", font_color);
1269 theme->set_color("font_hover_color", "PopupMenu", font_hover_color);
1270 theme->set_color("font_accelerator_color", "PopupMenu", font_disabled_color);
1271 theme->set_color("font_disabled_color", "PopupMenu", font_disabled_color);
1272 theme->set_color("font_separator_color", "PopupMenu", font_disabled_color);
1273 theme->set_color("font_outline_color", "PopupMenu", font_outline_color);
1274 theme->set_icon("checked", "PopupMenu", theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons)));
1275 theme->set_icon("unchecked", "PopupMenu", theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons)));
1276 theme->set_icon("radio_checked", "PopupMenu", theme->get_icon(SNAME("GuiRadioChecked"), EditorStringName(EditorIcons)));
1277 theme->set_icon("radio_unchecked", "PopupMenu", theme->get_icon(SNAME("GuiRadioUnchecked"), EditorStringName(EditorIcons)));
1278 theme->set_icon("checked_disabled", "PopupMenu", theme->get_icon(SNAME("GuiCheckedDisabled"), EditorStringName(EditorIcons)));
1279 theme->set_icon("unchecked_disabled", "PopupMenu", theme->get_icon(SNAME("GuiUncheckedDisabled"), EditorStringName(EditorIcons)));
1280 theme->set_icon("radio_checked_disabled", "PopupMenu", theme->get_icon(SNAME("GuiRadioCheckedDisabled"), EditorStringName(EditorIcons)));
1281 theme->set_icon("radio_unchecked_disabled", "PopupMenu", theme->get_icon(SNAME("GuiRadioUncheckedDisabled"), EditorStringName(EditorIcons)));
1282 theme->set_icon("submenu", "PopupMenu", theme->get_icon(SNAME("ArrowRight"), EditorStringName(EditorIcons)));
1283 theme->set_icon("submenu_mirrored", "PopupMenu", theme->get_icon(SNAME("ArrowLeft"), EditorStringName(EditorIcons)));
1284 theme->set_icon("visibility_hidden", "PopupMenu", theme->get_icon(SNAME("GuiVisibilityHidden"), EditorStringName(EditorIcons)));
1285 theme->set_icon("visibility_visible", "PopupMenu", theme->get_icon(SNAME("GuiVisibilityVisible"), EditorStringName(EditorIcons)));
1286 theme->set_icon("visibility_xray", "PopupMenu", theme->get_icon(SNAME("GuiVisibilityXray"), EditorStringName(EditorIcons)));
1287
1288 // Force the v_separation to be even so that the spacing on top and bottom is even.
1289 // If the vsep is odd and cannot be split into 2 even groups (of pixels), then it will be lopsided.
1290 // We add 2 to the vsep to give it some extra spacing which looks a bit more modern (see Windows, for example).
1291 const int vsep_base = extra_spacing + default_margin_size + 6;
1292 const int force_even_vsep = vsep_base + (vsep_base % 2);
1293 theme->set_constant("v_separation", "PopupMenu", force_even_vsep * EDSCALE);
1294 theme->set_constant("outline_size", "PopupMenu", 0);
1295 theme->set_constant("item_start_padding", "PopupMenu", default_margin_size * 1.5 * EDSCALE);
1296 theme->set_constant("item_end_padding", "PopupMenu", default_margin_size * 1.5 * EDSCALE);
1297
1298 // Sub-inspectors
1299 for (int i = 0; i < 16; i++) {
1300 Color si_base_color = accent_color;
1301
1302 float hue_rotate = (i * 2 % 16) / 16.0;
1303 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());
1304 si_base_color = accent_color.lerp(si_base_color, float(EDITOR_GET("docks/property_editor/subresource_hue_tint")));
1305
1306 // Sub-inspector background.
1307 Ref<StyleBoxFlat> sub_inspector_bg = style_default->duplicate();
1308 sub_inspector_bg->set_bg_color(dark_color_1.lerp(si_base_color, 0.08));
1309 sub_inspector_bg->set_border_width_all(2 * EDSCALE);
1310 sub_inspector_bg->set_border_color(si_base_color * Color(0.7, 0.7, 0.7, 0.8));
1311 sub_inspector_bg->set_content_margin_all(4 * EDSCALE);
1312 sub_inspector_bg->set_corner_radius(CORNER_TOP_LEFT, 0);
1313 sub_inspector_bg->set_corner_radius(CORNER_TOP_RIGHT, 0);
1314
1315 theme->set_stylebox("sub_inspector_bg" + itos(i), EditorStringName(Editor), sub_inspector_bg);
1316
1317 // EditorProperty background while it has a sub-inspector open.
1318 Ref<StyleBoxFlat> bg_color = make_flat_stylebox(si_base_color * Color(0.7, 0.7, 0.7, 0.8), 0, 0, 0, 0, corner_radius);
1319 bg_color->set_anti_aliased(false);
1320 bg_color->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
1321 bg_color->set_corner_radius(CORNER_BOTTOM_RIGHT, 0);
1322
1323 theme->set_stylebox("sub_inspector_property_bg" + itos(i), EditorStringName(Editor), bg_color);
1324 }
1325
1326 theme->set_color("sub_inspector_property_color", EditorStringName(Editor), dark_theme ? Color(1, 1, 1, 1) : Color(0, 0, 0, 1));
1327
1328 // EditorSpinSlider.
1329 theme->set_color("label_color", "EditorSpinSlider", font_color);
1330 theme->set_color("read_only_label_color", "EditorSpinSlider", font_readonly_color);
1331
1332 Ref<StyleBoxFlat> editor_spin_label_bg = style_default->duplicate();
1333 editor_spin_label_bg->set_bg_color(dark_color_3);
1334 editor_spin_label_bg->set_border_width_all(0);
1335 theme->set_stylebox("label_bg", "EditorSpinSlider", editor_spin_label_bg);
1336
1337 // EditorProperty
1338 Ref<StyleBoxFlat> style_property_bg = style_default->duplicate();
1339 style_property_bg->set_bg_color(highlight_color);
1340 style_property_bg->set_border_width_all(0);
1341
1342 Ref<StyleBoxFlat> style_property_child_bg = style_default->duplicate();
1343 style_property_child_bg->set_bg_color(dark_color_2);
1344 style_property_child_bg->set_border_width_all(0);
1345
1346 theme->set_constant("font_offset", "EditorProperty", 8 * EDSCALE);
1347 theme->set_stylebox("bg_selected", "EditorProperty", style_property_bg);
1348 theme->set_stylebox("bg", "EditorProperty", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty)));
1349 theme->set_stylebox("child_bg", "EditorProperty", style_property_child_bg);
1350 theme->set_constant("v_separation", "EditorProperty", (extra_spacing + default_margin_size) * EDSCALE);
1351 theme->set_color("warning_color", "EditorProperty", warning_color);
1352 theme->set_color("property_color", "EditorProperty", property_color);
1353 theme->set_color("readonly_color", "EditorProperty", readonly_color);
1354 theme->set_color("readonly_warning_color", "EditorProperty", readonly_warning_color);
1355
1356 Ref<StyleBoxFlat> style_property_group_note = style_default->duplicate();
1357 Color property_group_note_color = accent_color;
1358 property_group_note_color.a = 0.1;
1359 style_property_group_note->set_bg_color(property_group_note_color);
1360 theme->set_stylebox("bg_group_note", "EditorProperty", style_property_group_note);
1361
1362 // EditorInspectorSection
1363 Color inspector_section_color = font_color.lerp(Color(0.5, 0.5, 0.5), 0.35);
1364 theme->set_color("font_color", "EditorInspectorSection", inspector_section_color);
1365
1366 Color inspector_indent_color = accent_color;
1367 inspector_indent_color.a = 0.2;
1368 Ref<StyleBoxFlat> inspector_indent_style = make_flat_stylebox(inspector_indent_color, 2.0 * EDSCALE, 0, 2.0 * EDSCALE, 0);
1369 theme->set_stylebox("indent_box", "EditorInspectorSection", inspector_indent_style);
1370 theme->set_constant("indent_size", "EditorInspectorSection", 6.0 * EDSCALE);
1371
1372 theme->set_constant("inspector_margin", EditorStringName(Editor), 12 * EDSCALE);
1373
1374 // Tree & ItemList background
1375 Ref<StyleBoxFlat> style_tree_bg = style_default->duplicate();
1376 // Make Trees easier to distinguish from other controls by using a darker background color.
1377 style_tree_bg->set_bg_color(dark_color_1.lerp(dark_color_2, 0.5));
1378 if (draw_extra_borders) {
1379 style_tree_bg->set_border_width_all(Math::round(EDSCALE));
1380 style_tree_bg->set_border_color(extra_border_color_2);
1381 } else {
1382 style_tree_bg->set_border_color(dark_color_3);
1383 }
1384
1385 theme->set_stylebox("panel", "Tree", style_tree_bg);
1386 theme->set_stylebox("panel", "EditorValidationPanel", style_tree_bg);
1387
1388 // Tree
1389 theme->set_icon("checked", "Tree", theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons)));
1390 theme->set_icon("indeterminate", "Tree", theme->get_icon(SNAME("GuiIndeterminate"), EditorStringName(EditorIcons)));
1391 theme->set_icon("unchecked", "Tree", theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons)));
1392 theme->set_icon("arrow", "Tree", theme->get_icon(SNAME("GuiTreeArrowDown"), EditorStringName(EditorIcons)));
1393 theme->set_icon("arrow_collapsed", "Tree", theme->get_icon(SNAME("GuiTreeArrowRight"), EditorStringName(EditorIcons)));
1394 theme->set_icon("arrow_collapsed_mirrored", "Tree", theme->get_icon(SNAME("GuiTreeArrowLeft"), EditorStringName(EditorIcons)));
1395 theme->set_icon("updown", "Tree", theme->get_icon(SNAME("GuiTreeUpdown"), EditorStringName(EditorIcons)));
1396 theme->set_icon("select_arrow", "Tree", theme->get_icon(SNAME("GuiDropdown"), EditorStringName(EditorIcons)));
1397 theme->set_stylebox("focus", "Tree", style_widget_focus);
1398 theme->set_stylebox("custom_button", "Tree", make_empty_stylebox());
1399 theme->set_stylebox("custom_button_pressed", "Tree", make_empty_stylebox());
1400 theme->set_stylebox("custom_button_hover", "Tree", style_widget);
1401 theme->set_color("custom_button_font_highlight", "Tree", font_hover_color);
1402 theme->set_color("font_color", "Tree", font_color);
1403 theme->set_color("font_selected_color", "Tree", mono_color);
1404 theme->set_color("font_outline_color", "Tree", font_outline_color);
1405 theme->set_color("title_button_color", "Tree", font_color);
1406 theme->set_color("drop_position_color", "Tree", accent_color);
1407 theme->set_constant("v_separation", "Tree", widget_default_margin.y - EDSCALE);
1408 theme->set_constant("h_separation", "Tree", 6 * EDSCALE);
1409 theme->set_constant("guide_width", "Tree", border_width);
1410 theme->set_constant("item_margin", "Tree", 3 * default_margin_size * EDSCALE);
1411 theme->set_constant("inner_item_margin_bottom", "Tree", (default_margin_size + extra_spacing) * EDSCALE);
1412 theme->set_constant("inner_item_margin_left", "Tree", (default_margin_size + extra_spacing) * EDSCALE);
1413 theme->set_constant("inner_item_margin_right", "Tree", (default_margin_size + extra_spacing) * EDSCALE);
1414 theme->set_constant("inner_item_margin_top", "Tree", (default_margin_size + extra_spacing) * EDSCALE);
1415 theme->set_constant("button_margin", "Tree", default_margin_size * EDSCALE);
1416 theme->set_constant("scroll_border", "Tree", 40 * EDSCALE);
1417 theme->set_constant("scroll_speed", "Tree", 12);
1418 theme->set_constant("outline_size", "Tree", 0);
1419 theme->set_constant("scrollbar_margin_left", "Tree", 0);
1420 theme->set_constant("scrollbar_margin_top", "Tree", 0);
1421 theme->set_constant("scrollbar_margin_right", "Tree", 0);
1422 theme->set_constant("scrollbar_margin_bottom", "Tree", 0);
1423 theme->set_constant("scrollbar_h_separation", "Tree", 1 * EDSCALE);
1424 theme->set_constant("scrollbar_v_separation", "Tree", 1 * EDSCALE);
1425
1426 const Color guide_color = mono_color * Color(1, 1, 1, 0.05);
1427 Color relationship_line_color = mono_color * Color(1, 1, 1, relationship_line_opacity);
1428
1429 theme->set_constant("draw_guides", "Tree", relationship_line_opacity < 0.01);
1430 theme->set_color("guide_color", "Tree", guide_color);
1431
1432 int relationship_line_width = 1;
1433 Color parent_line_color = mono_color * Color(1, 1, 1, CLAMP(relationship_line_opacity + 0.45, 0.0, 1.0));
1434 Color children_line_color = mono_color * Color(1, 1, 1, CLAMP(relationship_line_opacity + 0.25, 0.0, 1.0));
1435 theme->set_constant("draw_relationship_lines", "Tree", relationship_line_opacity >= 0.01);
1436 theme->set_constant("relationship_line_width", "Tree", relationship_line_width);
1437 theme->set_constant("parent_hl_line_width", "Tree", relationship_line_width * 2);
1438 theme->set_constant("children_hl_line_width", "Tree", relationship_line_width);
1439 theme->set_constant("parent_hl_line_margin", "Tree", relationship_line_width * 3);
1440 theme->set_color("relationship_line_color", "Tree", relationship_line_color);
1441 theme->set_color("parent_hl_line_color", "Tree", parent_line_color);
1442 theme->set_color("children_hl_line_color", "Tree", children_line_color);
1443
1444 Ref<StyleBoxFlat> style_tree_btn = style_default->duplicate();
1445 style_tree_btn->set_bg_color(highlight_color);
1446 style_tree_btn->set_border_width_all(0);
1447 theme->set_stylebox("button_pressed", "Tree", style_tree_btn);
1448
1449 Ref<StyleBoxFlat> style_tree_hover = style_default->duplicate();
1450 style_tree_hover->set_bg_color(highlight_color * Color(1, 1, 1, 0.4));
1451 style_tree_hover->set_border_width_all(0);
1452 theme->set_stylebox("hover", "Tree", style_tree_hover);
1453
1454 Ref<StyleBoxFlat> style_tree_focus = style_default->duplicate();
1455 style_tree_focus->set_bg_color(highlight_color);
1456 style_tree_focus->set_border_width_all(0);
1457 theme->set_stylebox("selected_focus", "Tree", style_tree_focus);
1458
1459 Ref<StyleBoxFlat> style_tree_selected = style_tree_focus->duplicate();
1460 theme->set_stylebox("selected", "Tree", style_tree_selected);
1461
1462 Ref<StyleBoxFlat> style_tree_cursor = style_default->duplicate();
1463 style_tree_cursor->set_draw_center(false);
1464 style_tree_cursor->set_border_width_all(MAX(1, border_width));
1465 style_tree_cursor->set_border_color(contrast_color_1);
1466
1467 Ref<StyleBoxFlat> style_tree_title = style_default->duplicate();
1468 style_tree_title->set_bg_color(dark_color_3);
1469 style_tree_title->set_border_width_all(0);
1470 theme->set_stylebox("cursor", "Tree", style_tree_cursor);
1471 theme->set_stylebox("cursor_unfocused", "Tree", style_tree_cursor);
1472 theme->set_stylebox("title_button_normal", "Tree", style_tree_title);
1473 theme->set_stylebox("title_button_hover", "Tree", style_tree_title);
1474 theme->set_stylebox("title_button_pressed", "Tree", style_tree_title);
1475
1476 Color prop_category_color = dark_color_1.lerp(mono_color, 0.12);
1477 Color prop_section_color = dark_color_1.lerp(mono_color, 0.09);
1478 Color prop_subsection_color = dark_color_1.lerp(mono_color, 0.06);
1479 theme->set_color("prop_category", EditorStringName(Editor), prop_category_color);
1480 theme->set_color("prop_section", EditorStringName(Editor), prop_section_color);
1481 theme->set_color("prop_subsection", EditorStringName(Editor), prop_subsection_color);
1482 theme->set_color("drop_position_color", "Tree", accent_color);
1483
1484 // EditorInspectorCategory
1485 Ref<StyleBoxFlat> category_bg = style_default->duplicate();
1486 category_bg->set_bg_color(prop_category_color);
1487 category_bg->set_border_color(prop_category_color);
1488 theme->set_stylebox("bg", "EditorInspectorCategory", category_bg);
1489
1490 // ItemList
1491 Ref<StyleBoxFlat> style_itemlist_bg = style_default->duplicate();
1492 style_itemlist_bg->set_bg_color(dark_color_1);
1493
1494 if (draw_extra_borders) {
1495 style_itemlist_bg->set_border_width_all(Math::round(EDSCALE));
1496 style_itemlist_bg->set_border_color(extra_border_color_2);
1497 } else {
1498 style_itemlist_bg->set_border_width_all(border_width);
1499 style_itemlist_bg->set_border_color(dark_color_3);
1500 }
1501
1502 Ref<StyleBoxFlat> style_itemlist_cursor = style_default->duplicate();
1503 style_itemlist_cursor->set_draw_center(false);
1504 style_itemlist_cursor->set_border_width_all(border_width);
1505 style_itemlist_cursor->set_border_color(highlight_color);
1506
1507 Ref<StyleBoxFlat> style_itemlist_hover = style_tree_selected->duplicate();
1508 style_itemlist_hover->set_bg_color(highlight_color * Color(1, 1, 1, 0.3));
1509 style_itemlist_hover->set_border_width_all(0);
1510
1511 theme->set_stylebox("panel", "ItemList", style_itemlist_bg);
1512 theme->set_stylebox("focus", "ItemList", style_widget_focus);
1513 theme->set_stylebox("cursor", "ItemList", style_itemlist_cursor);
1514 theme->set_stylebox("cursor_unfocused", "ItemList", style_itemlist_cursor);
1515 theme->set_stylebox("selected_focus", "ItemList", style_tree_focus);
1516 theme->set_stylebox("selected", "ItemList", style_tree_selected);
1517 theme->set_stylebox("hovered", "ItemList", style_itemlist_hover);
1518 theme->set_color("font_color", "ItemList", font_color);
1519 theme->set_color("font_hovered_color", "ItemList", mono_color);
1520 theme->set_color("font_selected_color", "ItemList", mono_color);
1521 theme->set_color("font_outline_color", "ItemList", font_outline_color);
1522 theme->set_color("guide_color", "ItemList", guide_color);
1523 theme->set_constant("v_separation", "ItemList", force_even_vsep * 0.5 * EDSCALE);
1524 theme->set_constant("h_separation", "ItemList", 6 * EDSCALE);
1525 theme->set_constant("icon_margin", "ItemList", 6 * EDSCALE);
1526 theme->set_constant("line_separation", "ItemList", 3 * EDSCALE);
1527 theme->set_constant("outline_size", "ItemList", 0);
1528
1529 // TabBar & TabContainer
1530 Ref<StyleBoxFlat> style_tabbar_background = make_flat_stylebox(dark_color_1, 0, 0, 0, 0, corner_radius * EDSCALE);
1531 style_tabbar_background->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
1532 style_tabbar_background->set_corner_radius(CORNER_BOTTOM_RIGHT, 0);
1533 theme->set_stylebox("tabbar_background", "TabContainer", style_tabbar_background);
1534
1535 theme->set_stylebox("tab_selected", "TabContainer", style_tab_selected);
1536 theme->set_stylebox("tab_hovered", "TabContainer", style_tab_hovered);
1537 theme->set_stylebox("tab_unselected", "TabContainer", style_tab_unselected);
1538 theme->set_stylebox("tab_disabled", "TabContainer", style_tab_disabled);
1539 theme->set_stylebox("tab_selected", "TabBar", style_tab_selected);
1540 theme->set_stylebox("tab_hovered", "TabBar", style_tab_hovered);
1541 theme->set_stylebox("tab_unselected", "TabBar", style_tab_unselected);
1542 theme->set_stylebox("tab_disabled", "TabBar", style_tab_disabled);
1543 theme->set_stylebox("button_pressed", "TabBar", style_menu);
1544 theme->set_stylebox("button_highlight", "TabBar", style_menu);
1545 theme->set_color("font_selected_color", "TabContainer", font_color);
1546 theme->set_color("font_hovered_color", "TabContainer", font_color);
1547 theme->set_color("font_unselected_color", "TabContainer", font_disabled_color);
1548 theme->set_color("font_outline_color", "TabContainer", font_outline_color);
1549 theme->set_color("font_selected_color", "TabBar", font_color);
1550 theme->set_color("font_hovered_color", "TabBar", font_color);
1551 theme->set_color("font_unselected_color", "TabBar", font_disabled_color);
1552 theme->set_color("font_outline_color", "TabBar", font_outline_color);
1553 theme->set_color("drop_mark_color", "TabContainer", tab_highlight);
1554 theme->set_color("drop_mark_color", "TabBar", tab_highlight);
1555 theme->set_icon("menu", "TabContainer", theme->get_icon(SNAME("GuiTabMenu"), EditorStringName(EditorIcons)));
1556 theme->set_icon("menu_highlight", "TabContainer", theme->get_icon(SNAME("GuiTabMenuHl"), EditorStringName(EditorIcons)));
1557 theme->set_icon("close", "TabBar", theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons)));
1558 theme->set_icon("increment", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowRight"), EditorStringName(EditorIcons)));
1559 theme->set_icon("decrement", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowLeft"), EditorStringName(EditorIcons)));
1560 theme->set_icon("increment", "TabBar", theme->get_icon(SNAME("GuiScrollArrowRight"), EditorStringName(EditorIcons)));
1561 theme->set_icon("decrement", "TabBar", theme->get_icon(SNAME("GuiScrollArrowLeft"), EditorStringName(EditorIcons)));
1562 theme->set_icon("increment_highlight", "TabBar", theme->get_icon(SNAME("GuiScrollArrowRightHl"), EditorStringName(EditorIcons)));
1563 theme->set_icon("decrement_highlight", "TabBar", theme->get_icon(SNAME("GuiScrollArrowLeftHl"), EditorStringName(EditorIcons)));
1564 theme->set_icon("increment_highlight", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowRightHl"), EditorStringName(EditorIcons)));
1565 theme->set_icon("decrement_highlight", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowLeftHl"), EditorStringName(EditorIcons)));
1566 theme->set_icon("drop_mark", "TabContainer", theme->get_icon(SNAME("GuiTabDropMark"), EditorStringName(EditorIcons)));
1567 theme->set_icon("drop_mark", "TabBar", theme->get_icon(SNAME("GuiTabDropMark"), EditorStringName(EditorIcons)));
1568 theme->set_constant("side_margin", "TabContainer", 0);
1569 theme->set_constant("outline_size", "TabContainer", 0);
1570 theme->set_constant("h_separation", "TabBar", 4 * EDSCALE);
1571 theme->set_constant("outline_size", "TabBar", 0);
1572
1573 // Content of each tab.
1574 Ref<StyleBoxFlat> style_content_panel = style_default->duplicate();
1575 style_content_panel->set_border_color(dark_color_3);
1576 style_content_panel->set_border_width_all(border_width);
1577 style_content_panel->set_border_width(Side::SIDE_TOP, 0);
1578 style_content_panel->set_corner_radius(CORNER_TOP_LEFT, 0);
1579 style_content_panel->set_corner_radius(CORNER_TOP_RIGHT, 0);
1580 // Compensate for the border.
1581 style_content_panel->set_content_margin_individual(margin_size_extra * EDSCALE, (2 + margin_size_extra) * EDSCALE, margin_size_extra * EDSCALE, margin_size_extra * EDSCALE);
1582 theme->set_stylebox("panel", "TabContainer", style_content_panel);
1583
1584 // Bottom panel.
1585 Ref<StyleBoxFlat> style_bottom_panel = style_content_panel->duplicate();
1586 style_bottom_panel->set_corner_radius_all(corner_radius * EDSCALE);
1587 theme->set_stylebox("BottomPanel", EditorStringName(EditorStyles), style_bottom_panel);
1588
1589 // TabContainerOdd can be used on tabs against the base color background (e.g. nested tabs).
1590 theme->set_type_variation("TabContainerOdd", "TabContainer");
1591
1592 Ref<StyleBoxFlat> style_tab_selected_odd = style_tab_selected->duplicate();
1593 style_tab_selected_odd->set_bg_color(disabled_bg_color);
1594 theme->set_stylebox("tab_selected", "TabContainerOdd", style_tab_selected_odd);
1595
1596 Ref<StyleBoxFlat> style_content_panel_odd = style_content_panel->duplicate();
1597 style_content_panel_odd->set_bg_color(disabled_bg_color);
1598 theme->set_stylebox("panel", "TabContainerOdd", style_content_panel_odd);
1599
1600 // This stylebox is used in 3d and 2d viewports (no borders).
1601 Ref<StyleBoxFlat> style_content_panel_vp = style_content_panel->duplicate();
1602 style_content_panel_vp->set_content_margin_individual(border_width * 2, default_margin_size * EDSCALE, border_width * 2, border_width * 2);
1603 theme->set_stylebox("Content", EditorStringName(EditorStyles), style_content_panel_vp);
1604
1605 // This stylebox is used by preview tabs in the Theme Editor.
1606 Ref<StyleBoxFlat> style_theme_preview_tab = style_tab_selected_odd->duplicate();
1607 style_theme_preview_tab->set_expand_margin(SIDE_BOTTOM, 5 * EDSCALE);
1608 theme->set_stylebox("ThemeEditorPreviewFG", EditorStringName(EditorStyles), style_theme_preview_tab);
1609 Ref<StyleBoxFlat> style_theme_preview_bg_tab = style_tab_unselected->duplicate();
1610 style_theme_preview_bg_tab->set_expand_margin(SIDE_BOTTOM, 2 * EDSCALE);
1611 theme->set_stylebox("ThemeEditorPreviewBG", EditorStringName(EditorStyles), style_theme_preview_bg_tab);
1612
1613 Ref<StyleBoxFlat> style_texture_region_bg = style_tree_bg->duplicate();
1614 style_texture_region_bg->set_content_margin_all(0);
1615 theme->set_stylebox("TextureRegionPreviewBG", EditorStringName(EditorStyles), style_texture_region_bg);
1616 theme->set_stylebox("TextureRegionPreviewFG", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0));
1617
1618 // Separators
1619 theme->set_stylebox("separator", "HSeparator", make_line_stylebox(separator_color, MAX(Math::round(EDSCALE), border_width)));
1620 theme->set_stylebox("separator", "VSeparator", make_line_stylebox(separator_color, MAX(Math::round(EDSCALE), border_width), 0, 0, true));
1621
1622 // Debugger
1623
1624 Ref<StyleBoxFlat> style_panel_debugger = style_content_panel->duplicate();
1625 style_panel_debugger->set_border_width(SIDE_BOTTOM, 0);
1626 theme->set_stylebox("DebuggerPanel", EditorStringName(EditorStyles), style_panel_debugger);
1627
1628 Ref<StyleBoxFlat> style_panel_invisible_top = style_content_panel->duplicate();
1629 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);
1630 style_panel_invisible_top->set_expand_margin(SIDE_TOP, -stylebox_offset);
1631 style_panel_invisible_top->set_content_margin(SIDE_TOP, 0);
1632 theme->set_stylebox("BottomPanelDebuggerOverride", EditorStringName(EditorStyles), style_panel_invisible_top);
1633
1634 // LineEdit
1635
1636 Ref<StyleBoxFlat> style_line_edit = style_widget->duplicate();
1637 // The original style_widget style has an extra 1 pixel offset that makes LineEdits not align with Buttons,
1638 // so this compensates for that.
1639 style_line_edit->set_content_margin(SIDE_TOP, style_line_edit->get_content_margin(SIDE_TOP) - 1 * EDSCALE);
1640
1641 // Don't round the bottom corners to make the line look sharper.
1642 style_line_edit->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
1643 style_line_edit->set_corner_radius(CORNER_BOTTOM_RIGHT, 0);
1644
1645 if (draw_extra_borders) {
1646 style_line_edit->set_border_width_all(Math::round(EDSCALE));
1647 style_line_edit->set_border_color(extra_border_color_1);
1648 } else {
1649 // Add a bottom line to make LineEdits more visible, especially in sectioned inspectors
1650 // such as the Project Settings.
1651 style_line_edit->set_border_width(SIDE_BOTTOM, Math::round(2 * EDSCALE));
1652 style_line_edit->set_border_color(dark_color_2);
1653 }
1654
1655 Ref<StyleBoxFlat> style_line_edit_disabled = style_line_edit->duplicate();
1656 style_line_edit_disabled->set_border_color(disabled_color);
1657 style_line_edit_disabled->set_bg_color(disabled_bg_color);
1658
1659 theme->set_stylebox("normal", "LineEdit", style_line_edit);
1660 theme->set_stylebox("focus", "LineEdit", style_widget_focus);
1661 theme->set_stylebox("read_only", "LineEdit", style_line_edit_disabled);
1662 theme->set_icon("clear", "LineEdit", theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons)));
1663 theme->set_color("font_color", "LineEdit", font_color);
1664 theme->set_color("font_selected_color", "LineEdit", mono_color);
1665 theme->set_color("font_uneditable_color", "LineEdit", font_readonly_color);
1666 theme->set_color("font_placeholder_color", "LineEdit", font_placeholder_color);
1667 theme->set_color("font_outline_color", "LineEdit", font_outline_color);
1668 theme->set_color("caret_color", "LineEdit", font_color);
1669 theme->set_color("selection_color", "LineEdit", selection_color);
1670 theme->set_color("clear_button_color", "LineEdit", font_color);
1671 theme->set_color("clear_button_color_pressed", "LineEdit", accent_color);
1672
1673 theme->set_constant("minimum_character_width", "LineEdit", 4);
1674 theme->set_constant("outline_size", "LineEdit", 0);
1675 theme->set_constant("caret_width", "LineEdit", 1);
1676
1677 // TextEdit
1678 theme->set_stylebox("normal", "TextEdit", style_line_edit);
1679 theme->set_stylebox("focus", "TextEdit", style_widget_focus);
1680 theme->set_stylebox("read_only", "TextEdit", style_line_edit_disabled);
1681 theme->set_icon("tab", "TextEdit", theme->get_icon(SNAME("GuiTab"), EditorStringName(EditorIcons)));
1682 theme->set_icon("space", "TextEdit", theme->get_icon(SNAME("GuiSpace"), EditorStringName(EditorIcons)));
1683 theme->set_color("font_color", "TextEdit", font_color);
1684 theme->set_color("font_readonly_color", "TextEdit", font_readonly_color);
1685 theme->set_color("font_placeholder_color", "TextEdit", font_placeholder_color);
1686 theme->set_color("font_outline_color", "TextEdit", font_outline_color);
1687 theme->set_color("caret_color", "TextEdit", font_color);
1688 theme->set_color("selection_color", "TextEdit", selection_color);
1689 theme->set_color("background_color", "TextEdit", Color(0, 0, 0, 0));
1690
1691 theme->set_constant("line_spacing", "TextEdit", 4 * EDSCALE);
1692 theme->set_constant("outline_size", "TextEdit", 0);
1693 theme->set_constant("caret_width", "TextEdit", 1);
1694
1695 theme->set_icon("h_grabber", "SplitContainer", theme->get_icon(SNAME("GuiHsplitter"), EditorStringName(EditorIcons)));
1696 theme->set_icon("v_grabber", "SplitContainer", theme->get_icon(SNAME("GuiVsplitter"), EditorStringName(EditorIcons)));
1697 theme->set_icon("grabber", "VSplitContainer", theme->get_icon(SNAME("GuiVsplitter"), EditorStringName(EditorIcons)));
1698 theme->set_icon("grabber", "HSplitContainer", theme->get_icon(SNAME("GuiHsplitter"), EditorStringName(EditorIcons)));
1699
1700 theme->set_constant("separation", "SplitContainer", default_margin_size * 2 * EDSCALE);
1701 theme->set_constant("separation", "HSplitContainer", default_margin_size * 2 * EDSCALE);
1702 theme->set_constant("separation", "VSplitContainer", default_margin_size * 2 * EDSCALE);
1703
1704 theme->set_constant("minimum_grab_thickness", "SplitContainer", 6 * EDSCALE);
1705 theme->set_constant("minimum_grab_thickness", "HSplitContainer", 6 * EDSCALE);
1706 theme->set_constant("minimum_grab_thickness", "VSplitContainer", 6 * EDSCALE);
1707
1708 // Containers
1709 theme->set_constant("separation", "BoxContainer", default_margin_size * EDSCALE);
1710 theme->set_constant("separation", "HBoxContainer", default_margin_size * EDSCALE);
1711 theme->set_constant("separation", "VBoxContainer", default_margin_size * EDSCALE);
1712 theme->set_constant("margin_left", "MarginContainer", 0);
1713 theme->set_constant("margin_top", "MarginContainer", 0);
1714 theme->set_constant("margin_right", "MarginContainer", 0);
1715 theme->set_constant("margin_bottom", "MarginContainer", 0);
1716 theme->set_constant("h_separation", "GridContainer", default_margin_size * EDSCALE);
1717 theme->set_constant("v_separation", "GridContainer", default_margin_size * EDSCALE);
1718 theme->set_constant("h_separation", "FlowContainer", default_margin_size * EDSCALE);
1719 theme->set_constant("v_separation", "FlowContainer", default_margin_size * EDSCALE);
1720 theme->set_constant("h_separation", "HFlowContainer", default_margin_size * EDSCALE);
1721 theme->set_constant("v_separation", "HFlowContainer", default_margin_size * EDSCALE);
1722 theme->set_constant("h_separation", "VFlowContainer", default_margin_size * EDSCALE);
1723 theme->set_constant("v_separation", "VFlowContainer", default_margin_size * EDSCALE);
1724
1725 // Custom theme type for MarginContainer with 4px margins.
1726 theme->set_type_variation("MarginContainer4px", "MarginContainer");
1727 theme->set_constant("margin_left", "MarginContainer4px", 4 * EDSCALE);
1728 theme->set_constant("margin_top", "MarginContainer4px", 4 * EDSCALE);
1729 theme->set_constant("margin_right", "MarginContainer4px", 4 * EDSCALE);
1730 theme->set_constant("margin_bottom", "MarginContainer4px", 4 * EDSCALE);
1731
1732 // Window
1733
1734 // Prevent corner artifacts between window title and body.
1735 Ref<StyleBoxFlat> style_window_title = style_default->duplicate();
1736 style_window_title->set_corner_radius(CORNER_TOP_LEFT, 0);
1737 style_window_title->set_corner_radius(CORNER_TOP_RIGHT, 0);
1738 // Prevent visible line between window title and body.
1739 style_window_title->set_expand_margin(SIDE_BOTTOM, 2 * EDSCALE);
1740
1741 Ref<StyleBoxFlat> style_window = style_popup->duplicate();
1742 style_window->set_border_color(base_color);
1743 style_window->set_border_width(SIDE_TOP, 24 * EDSCALE);
1744 style_window->set_expand_margin(SIDE_TOP, 24 * EDSCALE);
1745 theme->set_stylebox("embedded_border", "Window", style_window);
1746 theme->set_stylebox("embedded_unfocused_border", "Window", style_window);
1747
1748 theme->set_color("title_color", "Window", font_color);
1749 theme->set_icon("close", "Window", theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons)));
1750 theme->set_icon("close_pressed", "Window", theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons)));
1751 theme->set_constant("close_h_offset", "Window", 22 * EDSCALE);
1752 theme->set_constant("close_v_offset", "Window", 20 * EDSCALE);
1753 theme->set_constant("title_height", "Window", 24 * EDSCALE);
1754 theme->set_constant("resize_margin", "Window", 4 * EDSCALE);
1755 theme->set_font("title_font", "Window", theme->get_font(SNAME("title"), EditorStringName(EditorFonts)));
1756 theme->set_font_size("title_font_size", "Window", theme->get_font_size(SNAME("title_size"), EditorStringName(EditorFonts)));
1757
1758 // Complex window (currently only Editor Settings and Project Settings)
1759 Ref<StyleBoxFlat> style_complex_window = style_window->duplicate();
1760 style_complex_window->set_bg_color(dark_color_2);
1761 style_complex_window->set_border_color(dark_color_2);
1762 theme->set_stylebox("panel", "EditorSettingsDialog", style_complex_window);
1763 theme->set_stylebox("panel", "ProjectSettingsEditor", style_complex_window);
1764 theme->set_stylebox("panel", "EditorAbout", style_complex_window);
1765
1766 // AcceptDialog
1767 theme->set_stylebox("panel", "AcceptDialog", style_window_title);
1768 theme->set_constant("buttons_separation", "AcceptDialog", 8 * EDSCALE);
1769
1770 // HScrollBar
1771 Ref<Texture2D> empty_icon = memnew(ImageTexture);
1772
1773 if (increase_scrollbar_touch_area) {
1774 theme->set_stylebox("scroll", "HScrollBar", make_line_stylebox(separator_color, 50));
1775 } else {
1776 theme->set_stylebox("scroll", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1));
1777 }
1778 theme->set_stylebox("scroll_focus", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1));
1779 theme->set_stylebox("grabber", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabber"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1));
1780 theme->set_stylebox("grabber_highlight", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberHl"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1));
1781 theme->set_stylebox("grabber_pressed", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberPressed"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1));
1782
1783 theme->set_icon("increment", "HScrollBar", empty_icon);
1784 theme->set_icon("increment_highlight", "HScrollBar", empty_icon);
1785 theme->set_icon("increment_pressed", "HScrollBar", empty_icon);
1786 theme->set_icon("decrement", "HScrollBar", empty_icon);
1787 theme->set_icon("decrement_highlight", "HScrollBar", empty_icon);
1788 theme->set_icon("decrement_pressed", "HScrollBar", empty_icon);
1789
1790 // VScrollBar
1791 if (increase_scrollbar_touch_area) {
1792 theme->set_stylebox("scroll", "VScrollBar", make_line_stylebox(separator_color, 50, 1, 1, true));
1793 } else {
1794 theme->set_stylebox("scroll", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1));
1795 }
1796 theme->set_stylebox("scroll_focus", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1));
1797 theme->set_stylebox("grabber", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabber"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1));
1798 theme->set_stylebox("grabber_highlight", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberHl"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1));
1799 theme->set_stylebox("grabber_pressed", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberPressed"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1));
1800
1801 theme->set_icon("increment", "VScrollBar", empty_icon);
1802 theme->set_icon("increment_highlight", "VScrollBar", empty_icon);
1803 theme->set_icon("increment_pressed", "VScrollBar", empty_icon);
1804 theme->set_icon("decrement", "VScrollBar", empty_icon);
1805 theme->set_icon("decrement_highlight", "VScrollBar", empty_icon);
1806 theme->set_icon("decrement_pressed", "VScrollBar", empty_icon);
1807
1808 // HSlider
1809 theme->set_icon("grabber_highlight", "HSlider", theme->get_icon(SNAME("GuiSliderGrabberHl"), EditorStringName(EditorIcons)));
1810 theme->set_icon("grabber", "HSlider", theme->get_icon(SNAME("GuiSliderGrabber"), EditorStringName(EditorIcons)));
1811 theme->set_stylebox("slider", "HSlider", make_flat_stylebox(dark_color_3, 0, default_margin_size / 2, 0, default_margin_size / 2, corner_width));
1812 theme->set_stylebox("grabber_area", "HSlider", make_flat_stylebox(contrast_color_1, 0, default_margin_size / 2, 0, default_margin_size / 2, corner_width));
1813 theme->set_stylebox("grabber_area_highlight", "HSlider", make_flat_stylebox(contrast_color_1, 0, default_margin_size / 2, 0, default_margin_size / 2));
1814 theme->set_constant("center_grabber", "HSlider", 0);
1815 theme->set_constant("grabber_offset", "HSlider", 0);
1816
1817 // VSlider
1818 theme->set_icon("grabber", "VSlider", theme->get_icon(SNAME("GuiSliderGrabber"), EditorStringName(EditorIcons)));
1819 theme->set_icon("grabber_highlight", "VSlider", theme->get_icon(SNAME("GuiSliderGrabberHl"), EditorStringName(EditorIcons)));
1820 theme->set_stylebox("slider", "VSlider", make_flat_stylebox(dark_color_3, default_margin_size / 2, 0, default_margin_size / 2, 0, corner_width));
1821 theme->set_stylebox("grabber_area", "VSlider", make_flat_stylebox(contrast_color_1, default_margin_size / 2, 0, default_margin_size / 2, 0, corner_width));
1822 theme->set_stylebox("grabber_area_highlight", "VSlider", make_flat_stylebox(contrast_color_1, default_margin_size / 2, 0, default_margin_size / 2, 0));
1823 theme->set_constant("center_grabber", "VSlider", 0);
1824 theme->set_constant("grabber_offset", "VSlider", 0);
1825
1826 // RichTextLabel
1827 theme->set_color("default_color", "RichTextLabel", font_color);
1828 theme->set_color("font_shadow_color", "RichTextLabel", Color(0, 0, 0, 0));
1829 theme->set_color("font_outline_color", "RichTextLabel", font_outline_color);
1830 theme->set_color("selection_color", "RichTextLabel", selection_color);
1831 theme->set_constant("shadow_offset_x", "RichTextLabel", 1 * EDSCALE);
1832 theme->set_constant("shadow_offset_y", "RichTextLabel", 1 * EDSCALE);
1833 theme->set_constant("shadow_outline_size", "RichTextLabel", 1 * EDSCALE);
1834 theme->set_constant("outline_size", "RichTextLabel", 0);
1835 theme->set_stylebox("focus", "RichTextLabel", make_empty_stylebox());
1836 theme->set_stylebox("normal", "RichTextLabel", style_tree_bg);
1837
1838 // Editor help.
1839 Ref<StyleBoxFlat> style_editor_help = style_default->duplicate();
1840 style_editor_help->set_bg_color(dark_color_2);
1841 style_editor_help->set_border_color(dark_color_3);
1842 theme->set_stylebox("background", "EditorHelp", style_editor_help);
1843
1844 theme->set_color("title_color", "EditorHelp", accent_color);
1845 theme->set_color("headline_color", "EditorHelp", mono_color);
1846 theme->set_color("text_color", "EditorHelp", font_color);
1847 theme->set_color("comment_color", "EditorHelp", font_color * Color(1, 1, 1, 0.6));
1848 theme->set_color("symbol_color", "EditorHelp", font_color * Color(1, 1, 1, 0.6));
1849 theme->set_color("value_color", "EditorHelp", font_color * Color(1, 1, 1, 0.6));
1850 theme->set_color("qualifier_color", "EditorHelp", font_color * Color(1, 1, 1, 0.8));
1851 theme->set_color("type_color", "EditorHelp", accent_color.lerp(font_color, 0.5));
1852 theme->set_color("selection_color", "EditorHelp", selection_color);
1853 theme->set_color("link_color", "EditorHelp", accent_color.lerp(mono_color, 0.8));
1854 theme->set_color("code_color", "EditorHelp", accent_color.lerp(mono_color, 0.6));
1855 theme->set_color("kbd_color", "EditorHelp", accent_color.lerp(property_color, 0.6));
1856 theme->set_color("code_bg_color", "EditorHelp", dark_color_3);
1857 theme->set_color("kbd_bg_color", "EditorHelp", dark_color_1);
1858 theme->set_color("param_bg_color", "EditorHelp", dark_color_1);
1859 theme->set_constant("line_separation", "EditorHelp", Math::round(6 * EDSCALE));
1860 theme->set_constant("table_h_separation", "EditorHelp", 16 * EDSCALE);
1861 theme->set_constant("table_v_separation", "EditorHelp", 6 * EDSCALE);
1862 theme->set_constant("text_highlight_h_padding", "EditorHelp", 1 * EDSCALE);
1863 theme->set_constant("text_highlight_v_padding", "EditorHelp", 2 * EDSCALE);
1864
1865 // Panel
1866 theme->set_stylebox("panel", "Panel", make_flat_stylebox(dark_color_1, 6, 4, 6, 4, corner_width));
1867 theme->set_stylebox("PanelForeground", EditorStringName(EditorStyles), style_default);
1868
1869 // Label
1870 theme->set_stylebox("normal", "Label", style_empty);
1871 theme->set_color("font_color", "Label", font_color);
1872 theme->set_color("font_shadow_color", "Label", Color(0, 0, 0, 0));
1873 theme->set_color("font_outline_color", "Label", font_outline_color);
1874 theme->set_constant("shadow_offset_x", "Label", 1 * EDSCALE);
1875 theme->set_constant("shadow_offset_y", "Label", 1 * EDSCALE);
1876 theme->set_constant("shadow_outline_size", "Label", 1 * EDSCALE);
1877 theme->set_constant("line_spacing", "Label", 3 * EDSCALE);
1878 theme->set_constant("outline_size", "Label", 0);
1879
1880 // LinkButton
1881 theme->set_stylebox("focus", "LinkButton", style_empty);
1882 theme->set_color("font_color", "LinkButton", font_color);
1883 theme->set_color("font_hover_color", "LinkButton", font_hover_color);
1884 theme->set_color("font_hover_pressed_color", "LinkButton", font_hover_pressed_color);
1885 theme->set_color("font_focus_color", "LinkButton", font_focus_color);
1886 theme->set_color("font_pressed_color", "LinkButton", accent_color);
1887 theme->set_color("font_disabled_color", "LinkButton", font_disabled_color);
1888 theme->set_color("font_outline_color", "LinkButton", font_outline_color);
1889
1890 theme->set_constant("outline_size", "LinkButton", 0);
1891
1892 // TooltipPanel + TooltipLabel
1893 // TooltipPanel is also used for custom tooltips, while TooltipLabel
1894 // is only relevant for default tooltips.
1895 Ref<StyleBoxFlat> style_tooltip = style_popup->duplicate();
1896 style_tooltip->set_shadow_size(0);
1897 style_tooltip->set_content_margin_all(default_margin_size * EDSCALE * 0.5);
1898 style_tooltip->set_bg_color(dark_color_3 * Color(0.8, 0.8, 0.8, 0.9));
1899 style_tooltip->set_border_width_all(0);
1900 theme->set_color("font_color", "TooltipLabel", font_hover_color);
1901 theme->set_color("font_shadow_color", "TooltipLabel", Color(0, 0, 0, 0));
1902 theme->set_stylebox("panel", "TooltipPanel", style_tooltip);
1903
1904 // PopupPanel
1905 theme->set_stylebox("panel", "PopupPanel", style_popup);
1906
1907 Ref<StyleBoxFlat> control_editor_popup_style = style_popup->duplicate();
1908 control_editor_popup_style->set_shadow_size(0);
1909 control_editor_popup_style->set_content_margin(SIDE_LEFT, default_margin_size * EDSCALE);
1910 control_editor_popup_style->set_content_margin(SIDE_TOP, default_margin_size * EDSCALE);
1911 control_editor_popup_style->set_content_margin(SIDE_RIGHT, default_margin_size * EDSCALE);
1912 control_editor_popup_style->set_content_margin(SIDE_BOTTOM, default_margin_size * EDSCALE);
1913 control_editor_popup_style->set_border_width_all(0);
1914
1915 theme->set_stylebox("panel", "ControlEditorPopupPanel", control_editor_popup_style);
1916 theme->set_type_variation("ControlEditorPopupPanel", "PopupPanel");
1917
1918 // SpinBox
1919 theme->set_icon("updown", "SpinBox", theme->get_icon(SNAME("GuiSpinboxUpdown"), EditorStringName(EditorIcons)));
1920 theme->set_icon("updown_disabled", "SpinBox", theme->get_icon(SNAME("GuiSpinboxUpdownDisabled"), EditorStringName(EditorIcons)));
1921
1922 // ProgressBar
1923 theme->set_stylebox("background", "ProgressBar", make_stylebox(theme->get_icon(SNAME("GuiProgressBar"), EditorStringName(EditorIcons)), 4, 4, 4, 4, 0, 0, 0, 0));
1924 theme->set_stylebox("fill", "ProgressBar", make_stylebox(theme->get_icon(SNAME("GuiProgressFill"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 2, 1, 2, 1));
1925 theme->set_color("font_color", "ProgressBar", font_color);
1926 theme->set_color("font_outline_color", "ProgressBar", font_outline_color);
1927 theme->set_constant("outline_size", "ProgressBar", 0);
1928
1929 // GraphEdit
1930 theme->set_stylebox("panel", "GraphEdit", style_tree_bg);
1931 if (dark_theme) {
1932 theme->set_color("grid_major", "GraphEdit", Color(1.0, 1.0, 1.0, 0.1));
1933 theme->set_color("grid_minor", "GraphEdit", Color(1.0, 1.0, 1.0, 0.05));
1934 } else {
1935 theme->set_color("grid_major", "GraphEdit", Color(0.0, 0.0, 0.0, 0.15));
1936 theme->set_color("grid_minor", "GraphEdit", Color(0.0, 0.0, 0.0, 0.07));
1937 }
1938 theme->set_color("selection_fill", "GraphEdit", theme->get_color(SNAME("box_selection_fill_color"), EditorStringName(Editor)));
1939 theme->set_color("selection_stroke", "GraphEdit", theme->get_color(SNAME("box_selection_stroke_color"), EditorStringName(Editor)));
1940 theme->set_color("activity", "GraphEdit", accent_color);
1941
1942 theme->set_icon("zoom_out", "GraphEdit", theme->get_icon(SNAME("ZoomLess"), EditorStringName(EditorIcons)));
1943 theme->set_icon("zoom_in", "GraphEdit", theme->get_icon(SNAME("ZoomMore"), EditorStringName(EditorIcons)));
1944 theme->set_icon("zoom_reset", "GraphEdit", theme->get_icon(SNAME("ZoomReset"), EditorStringName(EditorIcons)));
1945 theme->set_icon("grid_toggle", "GraphEdit", theme->get_icon(SNAME("GridToggle"), EditorStringName(EditorIcons)));
1946 theme->set_icon("minimap_toggle", "GraphEdit", theme->get_icon(SNAME("GridMinimap"), EditorStringName(EditorIcons)));
1947 theme->set_icon("snapping_toggle", "GraphEdit", theme->get_icon(SNAME("SnapGrid"), EditorStringName(EditorIcons)));
1948 theme->set_icon("layout", "GraphEdit", theme->get_icon(SNAME("GridLayout"), EditorStringName(EditorIcons)));
1949
1950 // GraphEditMinimap
1951 Ref<StyleBoxFlat> style_minimap_bg = make_flat_stylebox(dark_color_1, 0, 0, 0, 0);
1952 style_minimap_bg->set_border_color(dark_color_3);
1953 style_minimap_bg->set_border_width_all(1);
1954 theme->set_stylebox("panel", "GraphEditMinimap", style_minimap_bg);
1955
1956 Ref<StyleBoxFlat> style_minimap_camera;
1957 Ref<StyleBoxFlat> style_minimap_node;
1958 if (dark_theme) {
1959 style_minimap_camera = make_flat_stylebox(Color(0.65, 0.65, 0.65, 0.2), 0, 0, 0, 0);
1960 style_minimap_camera->set_border_color(Color(0.65, 0.65, 0.65, 0.45));
1961 style_minimap_node = make_flat_stylebox(Color(1, 1, 1), 0, 0, 0, 0);
1962 } else {
1963 style_minimap_camera = make_flat_stylebox(Color(0.38, 0.38, 0.38, 0.2), 0, 0, 0, 0);
1964 style_minimap_camera->set_border_color(Color(0.38, 0.38, 0.38, 0.45));
1965 style_minimap_node = make_flat_stylebox(Color(0, 0, 0), 0, 0, 0, 0);
1966 }
1967 style_minimap_camera->set_border_width_all(1);
1968 style_minimap_node->set_anti_aliased(false);
1969 theme->set_stylebox("camera", "GraphEditMinimap", style_minimap_camera);
1970 theme->set_stylebox("node", "GraphEditMinimap", style_minimap_node);
1971
1972 Color minimap_resizer_color;
1973 if (dark_theme) {
1974 minimap_resizer_color = Color(1, 1, 1, 0.65);
1975 } else {
1976 minimap_resizer_color = Color(0, 0, 0, 0.65);
1977 }
1978 theme->set_icon("resizer", "GraphEditMinimap", theme->get_icon(SNAME("GuiResizerTopLeft"), EditorStringName(EditorIcons)));
1979 theme->set_color("resizer_color", "GraphEditMinimap", minimap_resizer_color);
1980
1981 // GraphNode
1982
1983 const int gn_margin_top = 2;
1984 const int gn_margin_side = 2;
1985 const int gn_margin_bottom = 2;
1986
1987 Color graphnode_bg = dark_color_3;
1988 if (!dark_theme) {
1989 graphnode_bg = prop_section_color;
1990 }
1991 const Color graph_node_selected_border_color = graphnode_bg.lerp(accent_color, 0.275);
1992
1993 const Color graphnode_frame_bg = graphnode_bg.lerp(style_tree_bg->get_bg_color(), 0.3);
1994
1995 Ref<StyleBoxFlat> graphn_sb_panel = make_flat_stylebox(graphnode_frame_bg, gn_margin_side, gn_margin_top, gn_margin_side, gn_margin_bottom, corner_width);
1996 graphn_sb_panel->set_border_width_all(border_width);
1997 graphn_sb_panel->set_border_color(graphnode_bg);
1998 graphn_sb_panel->set_corner_radius_individual(0, 0, corner_radius * EDSCALE, corner_radius * EDSCALE);
1999 graphn_sb_panel->set_expand_margin(SIDE_TOP, 17 * EDSCALE);
2000
2001 Ref<StyleBoxFlat> graphn_sb_panel_selected = make_flat_stylebox(graphnode_frame_bg, gn_margin_side, gn_margin_top, gn_margin_side, gn_margin_bottom, corner_width);
2002 graphn_sb_panel_selected->set_border_width_all(2 * EDSCALE + border_width);
2003 graphn_sb_panel_selected->set_border_color(graph_node_selected_border_color);
2004 graphn_sb_panel_selected->set_corner_radius_individual(0, 0, corner_radius * EDSCALE, corner_radius * EDSCALE);
2005 graphn_sb_panel_selected->set_expand_margin(SIDE_TOP, 17 * EDSCALE);
2006
2007 const int gn_titlebar_margin_side = 12;
2008 Ref<StyleBoxFlat> graphn_sb_titlebar = make_flat_stylebox(graphnode_bg, gn_titlebar_margin_side, gn_margin_top, gn_titlebar_margin_side, 0, corner_width);
2009 graphn_sb_titlebar->set_expand_margin(SIDE_TOP, 2 * EDSCALE);
2010 graphn_sb_titlebar->set_corner_radius_individual(corner_radius * EDSCALE, corner_radius * EDSCALE, 0, 0);
2011
2012 Ref<StyleBoxFlat> graphn_sb_titlebar_selected = make_flat_stylebox(graph_node_selected_border_color, gn_titlebar_margin_side, gn_margin_top, gn_titlebar_margin_side, 0, corner_width);
2013 graphn_sb_titlebar_selected->set_corner_radius_individual(corner_radius * EDSCALE, corner_radius * EDSCALE, 0, 0);
2014 graphn_sb_titlebar_selected->set_expand_margin(SIDE_TOP, 2 * EDSCALE);
2015 Ref<StyleBoxEmpty> graphn_sb_slot = make_empty_stylebox(12, 0, 12, 0);
2016
2017 // StateMachine.
2018 const int sm_margin_side = 10;
2019 Ref<StyleBoxFlat> smgraphsb = make_flat_stylebox(dark_color_3 * Color(1, 1, 1, 0.7), sm_margin_side, 24, sm_margin_side, gn_margin_bottom, corner_width);
2020 smgraphsb->set_border_width_all(border_width);
2021 smgraphsb->set_border_color(graphnode_bg);
2022 Ref<StyleBoxFlat> smgraphsbselected = make_flat_stylebox(graphnode_bg * Color(1, 1, 1, 0.9), sm_margin_side, 24, sm_margin_side, gn_margin_bottom, corner_width);
2023 smgraphsbselected->set_border_width_all(2 * EDSCALE + border_width);
2024 smgraphsbselected->set_border_color(Color(accent_color.r, accent_color.g, accent_color.b, 0.9));
2025 smgraphsbselected->set_shadow_size(8 * EDSCALE);
2026 smgraphsbselected->set_shadow_color(shadow_color);
2027
2028 theme->set_stylebox("panel", "GraphElement", graphn_sb_panel);
2029 theme->set_stylebox("panel_selected", "GraphElement", graphn_sb_panel_selected);
2030 theme->set_stylebox("titlebar", "GraphElement", graphn_sb_titlebar);
2031 theme->set_stylebox("titlebar_selected", "GraphElement", graphn_sb_titlebar_selected);
2032
2033 // GraphNode's title Label.
2034 theme->set_type_variation("GraphNodeTitleLabel", "Label");
2035
2036 theme->set_stylebox("normal", "GraphNodeTitleLabel", make_empty_stylebox(0, 0, 0, 0));
2037 theme->set_color("font_color", "GraphNodeTitleLabel", font_color);
2038 theme->set_constant("line_spacing", "GraphNodeTitleLabel", 3 * EDSCALE);
2039
2040 Color graphnode_decoration_color = dark_color_1.inverted();
2041
2042 theme->set_color("resizer_color", "GraphElement", graphnode_decoration_color);
2043 theme->set_icon("resizer", "GraphElement", theme->get_icon(SNAME("GuiResizer"), EditorStringName(EditorIcons)));
2044
2045 // GraphNode.
2046 theme->set_stylebox("panel", "GraphNode", graphn_sb_panel);
2047 theme->set_stylebox("panel_selected", "GraphNode", graphn_sb_panel_selected);
2048 theme->set_stylebox("titlebar", "GraphNode", graphn_sb_titlebar);
2049 theme->set_stylebox("titlebar_selected", "GraphNode", graphn_sb_titlebar_selected);
2050 theme->set_stylebox("slot", "GraphNode", graphn_sb_slot);
2051
2052 theme->set_color("resizer_color", "GraphNode", graphnode_decoration_color);
2053
2054 theme->set_constant("port_h_offset", "GraphNode", 0);
2055 theme->set_constant("separation", "GraphNode", 1 * EDSCALE);
2056
2057 Ref<ImageTexture> port_icon = theme->get_icon(SNAME("GuiGraphNodePort"), EditorStringName(EditorIcons));
2058 // The true size is 24x24 This is necessary for sharp port icons at high zoom levels in GraphEdit (up to ~200%).
2059 port_icon->set_size_override(Size2(12, 12));
2060 theme->set_icon("port", "GraphNode", port_icon);
2061
2062 theme->set_stylebox("state_machine_frame", "GraphNode", smgraphsb);
2063 theme->set_stylebox("state_machine_selected_frame", "GraphNode", smgraphsbselected);
2064
2065 // GridContainer
2066 theme->set_constant("v_separation", "GridContainer", Math::round(widget_default_margin.y - 2 * EDSCALE));
2067
2068 // FileDialog
2069 theme->set_icon("folder", "FileDialog", theme->get_icon(SNAME("Folder"), EditorStringName(EditorIcons)));
2070 theme->set_icon("parent_folder", "FileDialog", theme->get_icon(SNAME("ArrowUp"), EditorStringName(EditorIcons)));
2071 theme->set_icon("back_folder", "FileDialog", theme->get_icon(SNAME("Back"), EditorStringName(EditorIcons)));
2072 theme->set_icon("forward_folder", "FileDialog", theme->get_icon(SNAME("Forward"), EditorStringName(EditorIcons)));
2073 theme->set_icon("reload", "FileDialog", theme->get_icon(SNAME("Reload"), EditorStringName(EditorIcons)));
2074 theme->set_icon("toggle_hidden", "FileDialog", theme->get_icon(SNAME("GuiVisibilityVisible"), EditorStringName(EditorIcons)));
2075 // Use a different color for folder icons to make them easier to distinguish from files.
2076 // On a light theme, the icon will be dark, so we need to lighten it before blending it with the accent color.
2077 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));
2078 theme->set_color("files_disabled", "FileDialog", font_disabled_color);
2079
2080 // ColorPicker
2081 theme->set_constant("margin", "ColorPicker", default_margin_size);
2082 theme->set_constant("sv_width", "ColorPicker", 256 * EDSCALE);
2083 theme->set_constant("sv_height", "ColorPicker", 256 * EDSCALE);
2084 theme->set_constant("h_width", "ColorPicker", 30 * EDSCALE);
2085 theme->set_constant("label_width", "ColorPicker", 10 * EDSCALE);
2086 theme->set_constant("center_slider_grabbers", "ColorPicker", 1);
2087 theme->set_icon("screen_picker", "ColorPicker", theme->get_icon(SNAME("ColorPick"), EditorStringName(EditorIcons)));
2088 theme->set_icon("shape_circle", "ColorPicker", theme->get_icon(SNAME("PickerShapeCircle"), EditorStringName(EditorIcons)));
2089 theme->set_icon("shape_rect", "ColorPicker", theme->get_icon(SNAME("PickerShapeRectangle"), EditorStringName(EditorIcons)));
2090 theme->set_icon("shape_rect_wheel", "ColorPicker", theme->get_icon(SNAME("PickerShapeRectangleWheel"), EditorStringName(EditorIcons)));
2091 theme->set_icon("add_preset", "ColorPicker", theme->get_icon(SNAME("Add"), EditorStringName(EditorIcons)));
2092 theme->set_icon("sample_bg", "ColorPicker", theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons)));
2093 theme->set_icon("overbright_indicator", "ColorPicker", theme->get_icon(SNAME("OverbrightIndicator"), EditorStringName(EditorIcons)));
2094 theme->set_icon("bar_arrow", "ColorPicker", theme->get_icon(SNAME("ColorPickerBarArrow"), EditorStringName(EditorIcons)));
2095 theme->set_icon("picker_cursor", "ColorPicker", theme->get_icon(SNAME("PickerCursor"), EditorStringName(EditorIcons)));
2096
2097 // ColorPickerButton
2098 theme->set_icon("bg", "ColorPickerButton", theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons)));
2099
2100 // ColorPresetButton
2101 Ref<StyleBoxFlat> preset_sb = make_flat_stylebox(Color(1, 1, 1), 2, 2, 2, 2, 2);
2102 theme->set_stylebox("preset_fg", "ColorPresetButton", preset_sb);
2103 theme->set_icon("preset_bg", "ColorPresetButton", theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons)));
2104 theme->set_icon("overbright_indicator", "ColorPresetButton", theme->get_icon(SNAME("OverbrightIndicator"), EditorStringName(EditorIcons)));
2105
2106 // Information on 3D viewport
2107 Ref<StyleBoxFlat> style_info_3d_viewport = style_default->duplicate();
2108 style_info_3d_viewport->set_bg_color(style_info_3d_viewport->get_bg_color() * Color(1, 1, 1, 0.5));
2109 style_info_3d_viewport->set_border_width_all(0);
2110 theme->set_stylebox("Information3dViewport", EditorStringName(EditorStyles), style_info_3d_viewport);
2111
2112 // Asset Library.
2113 theme->set_stylebox("bg", "AssetLib", style_empty);
2114 theme->set_stylebox("panel", "AssetLib", style_content_panel);
2115 theme->set_color("status_color", "AssetLib", Color(0.5, 0.5, 0.5));
2116 theme->set_icon("dismiss", "AssetLib", theme->get_icon(SNAME("Close"), EditorStringName(EditorIcons)));
2117
2118 // Theme editor.
2119 theme->set_color("preview_picker_overlay_color", "ThemeEditor", Color(0.1, 0.1, 0.1, 0.25));
2120 Color theme_preview_picker_bg_color = accent_color;
2121 theme_preview_picker_bg_color.a = 0.2;
2122 Ref<StyleBoxFlat> theme_preview_picker_sb = make_flat_stylebox(theme_preview_picker_bg_color, 0, 0, 0, 0);
2123 theme_preview_picker_sb->set_border_color(accent_color);
2124 theme_preview_picker_sb->set_border_width_all(1.0 * EDSCALE);
2125 theme->set_stylebox("preview_picker_overlay", "ThemeEditor", theme_preview_picker_sb);
2126 Color theme_preview_picker_label_bg_color = accent_color;
2127 theme_preview_picker_label_bg_color.set_v(0.5);
2128 Ref<StyleBoxFlat> theme_preview_picker_label_sb = make_flat_stylebox(theme_preview_picker_label_bg_color, 4.0, 1.0, 4.0, 3.0);
2129 theme->set_stylebox("preview_picker_label", "ThemeEditor", theme_preview_picker_label_sb);
2130
2131 // Dictionary editor add item.
2132 // Expand to the left and right by 4px to compensate for the dictionary editor margins.
2133 Ref<StyleBoxFlat> style_dictionary_add_item = make_flat_stylebox(prop_subsection_color, 0, 4, 0, 4, corner_radius);
2134 style_dictionary_add_item->set_expand_margin(SIDE_LEFT, 4 * EDSCALE);
2135 style_dictionary_add_item->set_expand_margin(SIDE_RIGHT, 4 * EDSCALE);
2136 theme->set_stylebox("DictionaryAddItem", EditorStringName(EditorStyles), style_dictionary_add_item);
2137
2138 Ref<StyleBoxEmpty> vshader_label_style = make_empty_stylebox(2, 1, 2, 1);
2139 theme->set_stylebox("label_style", "VShaderEditor", vshader_label_style);
2140
2141 // Project manager.
2142 theme->set_stylebox("search_panel", "ProjectManager", style_tree_bg);
2143 theme->set_constant("sidebar_button_icon_separation", "ProjectManager", int(6 * EDSCALE));
2144
2145 // adaptive script theme constants
2146 // for comments and elements with lower relevance
2147 const Color dim_color = Color(font_color.r, font_color.g, font_color.b, 0.5);
2148
2149 const float mono_value = mono_color.r;
2150 const Color alpha1 = Color(mono_value, mono_value, mono_value, 0.07);
2151 const Color alpha2 = Color(mono_value, mono_value, mono_value, 0.14);
2152 const Color alpha3 = Color(mono_value, mono_value, mono_value, 0.27);
2153
2154 const Color symbol_color = dark_theme ? Color(0.67, 0.79, 1) : Color(0, 0, 0.61);
2155 const Color keyword_color = dark_theme ? Color(1.0, 0.44, 0.52) : Color(0.9, 0.135, 0.51);
2156 const Color control_flow_keyword_color = dark_theme ? Color(1.0, 0.55, 0.8) : Color(0.743, 0.12, 0.8);
2157 const Color base_type_color = dark_theme ? Color(0.26, 1.0, 0.76) : Color(0, 0.6, 0.2);
2158 const Color engine_type_color = dark_theme ? Color(0.56, 1, 0.86) : Color(0.11, 0.55, 0.4);
2159 const Color user_type_color = dark_theme ? Color(0.78, 1, 0.93) : Color(0.18, 0.45, 0.4);
2160 const Color comment_color = dark_theme ? dim_color : Color(0.08, 0.08, 0.08, 0.5);
2161 const Color string_color = dark_theme ? Color(1, 0.93, 0.63) : Color(0.6, 0.42, 0);
2162
2163 // Use the brightest background color on a light theme (which generally uses a negative contrast rate).
2164 const Color te_background_color = dark_theme ? background_color : dark_color_3;
2165 const Color completion_background_color = dark_theme ? base_color : background_color;
2166 const Color completion_selected_color = alpha1;
2167 const Color completion_existing_color = alpha2;
2168 // Same opacity as the scroll grabber editor icon.
2169 const Color completion_scroll_color = Color(mono_value, mono_value, mono_value, 0.29);
2170 const Color completion_scroll_hovered_color = Color(mono_value, mono_value, mono_value, 0.4);
2171 const Color completion_font_color = font_color;
2172 const Color text_color = font_color;
2173 const Color line_number_color = dim_color;
2174 const Color safe_line_number_color = dark_theme ? (dim_color * Color(1, 1.2, 1, 1.5)) : Color(0, 0.4, 0, 0.75);
2175 const Color caret_color = mono_color;
2176 const Color caret_background_color = mono_color.inverted();
2177 const Color text_selected_color = Color(0, 0, 0, 0);
2178 const Color brace_mismatch_color = dark_theme ? error_color : Color(1, 0.08, 0, 1);
2179 const Color current_line_color = alpha1;
2180 const Color line_length_guideline_color = dark_theme ? base_color : background_color;
2181 const Color word_highlighted_color = alpha1;
2182 const Color number_color = dark_theme ? Color(0.63, 1, 0.88) : Color(0, 0.55, 0.28, 1);
2183 const Color function_color = dark_theme ? Color(0.34, 0.7, 1.0) : Color(0, 0.225, 0.9, 1);
2184 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);
2185 const Color mark_color = Color(error_color.r, error_color.g, error_color.b, 0.3);
2186 const Color bookmark_color = Color(0.08, 0.49, 0.98);
2187 const Color breakpoint_color = dark_theme ? error_color : Color(1, 0.27, 0.2, 1);
2188 const Color executing_line_color = Color(0.98, 0.89, 0.27);
2189 const Color code_folding_color = alpha3;
2190 const Color folded_code_region_color = Color(0.68, 0.46, 0.77, 0.2);
2191 const Color search_result_color = alpha1;
2192 const Color search_result_border_color = dark_theme ? Color(0.41, 0.61, 0.91, 0.38) : Color(0, 0.4, 1, 0.38);
2193
2194 EditorSettings *setting = EditorSettings::get_singleton();
2195 String text_editor_color_theme = setting->get("text_editor/theme/color_theme");
2196 if (text_editor_color_theme == "Default") {
2197 setting->set_initial_value("text_editor/theme/highlighting/symbol_color", symbol_color, true);
2198 setting->set_initial_value("text_editor/theme/highlighting/keyword_color", keyword_color, true);
2199 setting->set_initial_value("text_editor/theme/highlighting/control_flow_keyword_color", control_flow_keyword_color, true);
2200 setting->set_initial_value("text_editor/theme/highlighting/base_type_color", base_type_color, true);
2201 setting->set_initial_value("text_editor/theme/highlighting/engine_type_color", engine_type_color, true);
2202 setting->set_initial_value("text_editor/theme/highlighting/user_type_color", user_type_color, true);
2203 setting->set_initial_value("text_editor/theme/highlighting/comment_color", comment_color, true);
2204 setting->set_initial_value("text_editor/theme/highlighting/string_color", string_color, true);
2205 setting->set_initial_value("text_editor/theme/highlighting/background_color", te_background_color, true);
2206 setting->set_initial_value("text_editor/theme/highlighting/completion_background_color", completion_background_color, true);
2207 setting->set_initial_value("text_editor/theme/highlighting/completion_selected_color", completion_selected_color, true);
2208 setting->set_initial_value("text_editor/theme/highlighting/completion_existing_color", completion_existing_color, true);
2209 setting->set_initial_value("text_editor/theme/highlighting/completion_scroll_color", completion_scroll_color, true);
2210 setting->set_initial_value("text_editor/theme/highlighting/completion_scroll_hovered_color", completion_scroll_hovered_color, true);
2211 setting->set_initial_value("text_editor/theme/highlighting/completion_font_color", completion_font_color, true);
2212 setting->set_initial_value("text_editor/theme/highlighting/text_color", text_color, true);
2213 setting->set_initial_value("text_editor/theme/highlighting/line_number_color", line_number_color, true);
2214 setting->set_initial_value("text_editor/theme/highlighting/safe_line_number_color", safe_line_number_color, true);
2215 setting->set_initial_value("text_editor/theme/highlighting/caret_color", caret_color, true);
2216 setting->set_initial_value("text_editor/theme/highlighting/caret_background_color", caret_background_color, true);
2217 setting->set_initial_value("text_editor/theme/highlighting/text_selected_color", text_selected_color, true);
2218 setting->set_initial_value("text_editor/theme/highlighting/selection_color", selection_color, true);
2219 setting->set_initial_value("text_editor/theme/highlighting/brace_mismatch_color", brace_mismatch_color, true);
2220 setting->set_initial_value("text_editor/theme/highlighting/current_line_color", current_line_color, true);
2221 setting->set_initial_value("text_editor/theme/highlighting/line_length_guideline_color", line_length_guideline_color, true);
2222 setting->set_initial_value("text_editor/theme/highlighting/word_highlighted_color", word_highlighted_color, true);
2223 setting->set_initial_value("text_editor/theme/highlighting/number_color", number_color, true);
2224 setting->set_initial_value("text_editor/theme/highlighting/function_color", function_color, true);
2225 setting->set_initial_value("text_editor/theme/highlighting/member_variable_color", member_variable_color, true);
2226 setting->set_initial_value("text_editor/theme/highlighting/mark_color", mark_color, true);
2227 setting->set_initial_value("text_editor/theme/highlighting/bookmark_color", bookmark_color, true);
2228 setting->set_initial_value("text_editor/theme/highlighting/breakpoint_color", breakpoint_color, true);
2229 setting->set_initial_value("text_editor/theme/highlighting/executing_line_color", executing_line_color, true);
2230 setting->set_initial_value("text_editor/theme/highlighting/code_folding_color", code_folding_color, true);
2231 setting->set_initial_value("text_editor/theme/highlighting/folded_code_region_color", folded_code_region_color, true);
2232 setting->set_initial_value("text_editor/theme/highlighting/search_result_color", search_result_color, true);
2233 setting->set_initial_value("text_editor/theme/highlighting/search_result_border_color", search_result_border_color, true);
2234 } else if (text_editor_color_theme == "Godot 2") {
2235 setting->load_text_editor_theme();
2236 }
2237
2238 // Now theme is loaded, apply it to CodeEdit.
2239 theme->set_font("font", "CodeEdit", theme->get_font(SNAME("source"), EditorStringName(EditorFonts)));
2240 theme->set_font_size("font_size", "CodeEdit", theme->get_font_size(SNAME("source_size"), EditorStringName(EditorFonts)));
2241
2242 Ref<StyleBoxFlat> 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);
2243 theme->set_stylebox("normal", "CodeEdit", code_edit_stylebox);
2244 theme->set_stylebox("read_only", "CodeEdit", code_edit_stylebox);
2245 theme->set_stylebox("focus", "CodeEdit", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty)));
2246
2247 theme->set_icon("tab", "CodeEdit", theme->get_icon(SNAME("GuiTab"), EditorStringName(EditorIcons)));
2248 theme->set_icon("space", "CodeEdit", theme->get_icon(SNAME("GuiSpace"), EditorStringName(EditorIcons)));
2249 theme->set_icon("folded", "CodeEdit", theme->get_icon(SNAME("CodeFoldedRightArrow"), EditorStringName(EditorIcons)));
2250 theme->set_icon("can_fold", "CodeEdit", theme->get_icon(SNAME("CodeFoldDownArrow"), EditorStringName(EditorIcons)));
2251 theme->set_icon("folded_code_region", "CodeEdit", theme->get_icon(SNAME("CodeRegionFoldedRightArrow"), EditorStringName(EditorIcons)));
2252 theme->set_icon("can_fold_code_region", "CodeEdit", theme->get_icon(SNAME("CodeRegionFoldDownArrow"), EditorStringName(EditorIcons)));
2253 theme->set_icon("executing_line", "CodeEdit", theme->get_icon(SNAME("TextEditorPlay"), EditorStringName(EditorIcons)));
2254 theme->set_icon("breakpoint", "CodeEdit", theme->get_icon(SNAME("Breakpoint"), EditorStringName(EditorIcons)));
2255
2256 theme->set_constant("line_spacing", "CodeEdit", EDITOR_GET("text_editor/appearance/whitespace/line_spacing"));
2257
2258 theme->set_color("background_color", "CodeEdit", Color(0, 0, 0, 0));
2259 theme->set_color("completion_background_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_background_color"));
2260 theme->set_color("completion_selected_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_selected_color"));
2261 theme->set_color("completion_existing_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_existing_color"));
2262 theme->set_color("completion_scroll_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_scroll_color"));
2263 theme->set_color("completion_scroll_hovered_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_scroll_hovered_color"));
2264 theme->set_color("completion_font_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_font_color"));
2265 theme->set_color("font_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/text_color"));
2266 theme->set_color("line_number_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/line_number_color"));
2267 theme->set_color("caret_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/caret_color"));
2268 theme->set_color("font_selected_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/text_selected_color"));
2269 theme->set_color("selection_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/selection_color"));
2270 theme->set_color("brace_mismatch_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/brace_mismatch_color"));
2271 theme->set_color("current_line_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/current_line_color"));
2272 theme->set_color("line_length_guideline_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/line_length_guideline_color"));
2273 theme->set_color("word_highlighted_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/word_highlighted_color"));
2274 theme->set_color("bookmark_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/bookmark_color"));
2275 theme->set_color("breakpoint_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/breakpoint_color"));
2276 theme->set_color("executing_line_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/executing_line_color"));
2277 theme->set_color("code_folding_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/code_folding_color"));
2278 theme->set_color("folded_code_region_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/folded_code_region_color"));
2279 theme->set_color("search_result_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/search_result_color"));
2280 theme->set_color("search_result_border_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/search_result_border_color"));
2281
2282 OS::get_singleton()->benchmark_end_measure("create_editor_theme");
2283
2284 return theme;
2285}
2286
2287Ref<Theme> create_custom_theme(const Ref<Theme> p_theme) {
2288 OS::get_singleton()->benchmark_begin_measure("create_custom_theme");
2289 Ref<Theme> theme = create_editor_theme(p_theme);
2290
2291 const String custom_theme_path = EDITOR_GET("interface/theme/custom_theme");
2292 if (!custom_theme_path.is_empty()) {
2293 Ref<Theme> custom_theme = ResourceLoader::load(custom_theme_path);
2294 if (custom_theme.is_valid()) {
2295 theme->merge_with(custom_theme);
2296 }
2297 }
2298
2299 OS::get_singleton()->benchmark_end_measure("create_custom_theme");
2300 return theme;
2301}
2302
2303/**
2304 * Returns the SVG code for the default project icon.
2305 */
2306String get_default_project_icon() {
2307 for (int i = 0; i < editor_icons_count; i++) {
2308 if (strcmp(editor_icons_names[i], "DefaultProjectIcon") == 0) {
2309 return String(editor_icons_sources[i]);
2310 }
2311 }
2312 return String();
2313}
2314