summaryrefslogtreecommitdiffstats
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/SCsub14
-rw-r--r--editor/action_map_editor.cpp2
-rw-r--r--editor/animation_bezier_editor.cpp4
-rw-r--r--editor/animation_track_editor.cpp4
-rw-r--r--editor/animation_track_editor_plugins.cpp2
-rw-r--r--editor/code_editor.cpp2
-rw-r--r--editor/connections_dialog.cpp23
-rw-r--r--editor/connections_dialog.h2
-rw-r--r--editor/create_dialog.cpp4
-rw-r--r--editor/debugger/editor_debugger_node.cpp10
-rw-r--r--editor/debugger/editor_debugger_node.h3
-rw-r--r--editor/debugger/editor_performance_profiler.cpp2
-rw-r--r--editor/debugger/editor_profiler.cpp2
-rw-r--r--editor/debugger/editor_visual_profiler.cpp2
-rw-r--r--editor/debugger/script_editor_debugger.cpp10
-rw-r--r--editor/debugger/script_editor_debugger.h3
-rw-r--r--editor/dependency_editor.cpp2
-rw-r--r--editor/directory_create_dialog.cpp2
-rw-r--r--editor/doc_tools.cpp27
-rw-r--r--editor/doc_tools.h3
-rw-r--r--editor/editor_about.cpp1
-rw-r--r--editor/editor_about.h2
-rw-r--r--editor/editor_asset_installer.cpp2
-rw-r--r--editor/editor_audio_buses.cpp2
-rw-r--r--editor/editor_autoload_settings.cpp2
-rw-r--r--editor/editor_build_profile.cpp4
-rw-r--r--editor/editor_builders.py29
-rw-r--r--editor/editor_command_palette.cpp2
-rw-r--r--editor/editor_data.cpp2
-rw-r--r--editor/editor_dock_manager.cpp716
-rw-r--r--editor/editor_dock_manager.h135
-rw-r--r--editor/editor_feature_profile.cpp4
-rw-r--r--editor/editor_help.cpp40
-rw-r--r--editor/editor_help_search.cpp240
-rw-r--r--editor/editor_help_search.h17
-rw-r--r--editor/editor_inspector.cpp6
-rw-r--r--editor/editor_interface.cpp2
-rw-r--r--editor/editor_layouts_dialog.cpp2
-rw-r--r--editor/editor_locale_dialog.cpp2
-rw-r--r--editor/editor_log.cpp7
-rw-r--r--editor/editor_log.h1
-rw-r--r--editor/editor_node.cpp829
-rw-r--r--editor/editor_node.h71
-rw-r--r--editor/editor_plugin.cpp5
-rw-r--r--editor/editor_plugin_settings.cpp2
-rw-r--r--editor/editor_properties.cpp10
-rw-r--r--editor/editor_properties_array_dict.cpp6
-rw-r--r--editor/editor_quick_open.cpp2
-rw-r--r--editor/editor_resource_picker.cpp2
-rw-r--r--editor/editor_resource_preview.cpp50
-rw-r--r--editor/editor_resource_preview.h3
-rw-r--r--editor/editor_run_native.cpp2
-rw-r--r--editor/editor_sectioned_inspector.cpp2
-rw-r--r--editor/editor_settings.cpp4
-rw-r--r--editor/editor_settings_dialog.cpp8
-rw-r--r--editor/editor_themes.cpp2402
-rw-r--r--editor/export/editor_export_platform.cpp2
-rw-r--r--editor/export/export_template_manager.cpp4
-rw-r--r--editor/export/project_export.cpp4
-rw-r--r--editor/fbx_importer_manager.cpp2
-rw-r--r--editor/filesystem_dock.cpp79
-rw-r--r--editor/filesystem_dock.h9
-rw-r--r--editor/find_in_files.cpp2
-rw-r--r--editor/group_settings_editor.cpp6
-rw-r--r--editor/groups_editor.cpp2
-rw-r--r--editor/gui/editor_file_dialog.cpp2
-rw-r--r--editor/gui/editor_object_selector.cpp2
-rw-r--r--editor/gui/editor_scene_tabs.cpp2
-rw-r--r--editor/gui/editor_spin_slider.cpp2
-rw-r--r--editor/gui/editor_toaster.cpp2
-rw-r--r--editor/gui/editor_validation_panel.cpp2
-rw-r--r--editor/gui/editor_zoom_widget.cpp2
-rw-r--r--editor/gui/scene_tree_editor.cpp10
-rw-r--r--editor/icons/GuiHsplitter.svg2
-rw-r--r--editor/icons/GuiVsplitter.svg2
-rw-r--r--editor/icons/SCsub3
-rw-r--r--editor/icons/TileMapLayer.svg1
-rw-r--r--editor/icons/editor_icons_builders.py3
-rw-r--r--editor/import/3d/scene_import_settings.cpp2
-rw-r--r--editor/import/audio_stream_import_settings.cpp2
-rw-r--r--editor/import/dynamic_font_import_settings.cpp2
-rw-r--r--editor/import/resource_importer_texture.cpp2
-rw-r--r--editor/import_dock.cpp2
-rw-r--r--editor/input_event_configuration_dialog.cpp2
-rw-r--r--editor/inspector_dock.cpp2
-rw-r--r--editor/localization_editor.cpp2
-rw-r--r--editor/node_dock.cpp4
-rw-r--r--editor/plugin_config_dialog.cpp2
-rw-r--r--editor/plugins/abstract_polygon_2d_editor.cpp2
-rw-r--r--editor/plugins/animation_blend_space_1d_editor.cpp2
-rw-r--r--editor/plugins/animation_blend_space_2d_editor.cpp2
-rw-r--r--editor/plugins/animation_blend_tree_editor_plugin.cpp2
-rw-r--r--editor/plugins/animation_library_editor.cpp2
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp2
-rw-r--r--editor/plugins/animation_state_machine_editor.cpp2
-rw-r--r--editor/plugins/animation_tree_editor_plugin.cpp2
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp3
-rw-r--r--editor/plugins/audio_stream_editor_plugin.cpp2
-rw-r--r--editor/plugins/bit_map_editor_plugin.cpp2
-rw-r--r--editor/plugins/bone_map_editor_plugin.cpp2
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp2
-rw-r--r--editor/plugins/control_editor_plugin.cpp2
-rw-r--r--editor/plugins/curve_editor_plugin.cpp2
-rw-r--r--editor/plugins/debugger_editor_plugin.cpp2
-rw-r--r--editor/plugins/editor_preview_plugins.cpp2
-rw-r--r--editor/plugins/editor_resource_tooltip_plugins.cpp2
-rw-r--r--editor/plugins/font_config_plugin.cpp2
-rw-r--r--editor/plugins/gradient_editor_plugin.cpp6
-rw-r--r--editor/plugins/gradient_texture_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/material_editor_plugin.cpp2
-rw-r--r--editor/plugins/mesh_editor_plugin.cpp2
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.cpp2
-rw-r--r--editor/plugins/node_3d_editor_plugin.h2
-rw-r--r--editor/plugins/path_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.cpp2
-rw-r--r--editor/plugins/root_motion_editor_plugin.cpp2
-rw-r--r--editor/plugins/script_editor_plugin.cpp28
-rw-r--r--editor/plugins/script_editor_plugin.h5
-rw-r--r--editor/plugins/script_text_editor.cpp4
-rw-r--r--editor/plugins/shader_editor_plugin.cpp2
-rw-r--r--editor/plugins/shader_file_editor_plugin.cpp2
-rw-r--r--editor/plugins/skeleton_3d_editor_plugin.cpp4
-rw-r--r--editor/plugins/sprite_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp2
-rw-r--r--editor/plugins/style_box_editor_plugin.cpp2
-rw-r--r--editor/plugins/text_shader_editor.cpp2
-rw-r--r--editor/plugins/texture_editor_plugin.cpp2
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp2
-rw-r--r--editor/plugins/theme_editor_plugin.cpp7
-rw-r--r--editor/plugins/theme_editor_preview.cpp2
-rw-r--r--editor/plugins/tiles/atlas_merging_dialog.cpp2
-rw-r--r--editor/plugins/tiles/tile_atlas_view.cpp5
-rw-r--r--editor/plugins/tiles/tile_data_editors.cpp2
-rw-r--r--editor/plugins/tiles/tile_map_editor.cpp2
-rw-r--r--editor/plugins/tiles/tile_proxies_manager_dialog.cpp2
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.cpp4
-rw-r--r--editor/plugins/tiles/tile_set_editor.cpp2
-rw-r--r--editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp2
-rw-r--r--editor/plugins/tiles/tiles_editor_plugin.cpp2
-rw-r--r--editor/plugins/version_control_editor_plugin.cpp7
-rw-r--r--editor/plugins/visual_shader_editor_plugin.cpp2
-rw-r--r--editor/progress_dialog.cpp2
-rw-r--r--editor/project_manager.cpp13
-rw-r--r--editor/project_settings_editor.cpp2
-rw-r--r--editor/property_selector.cpp2
-rw-r--r--editor/rename_dialog.cpp3
-rw-r--r--editor/scene_create_dialog.cpp2
-rw-r--r--editor/scene_tree_dock.cpp2
-rw-r--r--editor/script_create_dialog.cpp2
-rw-r--r--editor/shader_create_dialog.cpp2
-rw-r--r--editor/surface_upgrade_tool.cpp2
-rw-r--r--editor/themes/SCsub22
-rw-r--r--editor/themes/editor_color_map.cpp204
-rw-r--r--editor/themes/editor_color_map.h (renamed from editor/editor_themes.h)37
-rw-r--r--editor/themes/editor_fonts.cpp (renamed from editor/editor_fonts.cpp)6
-rw-r--r--editor/themes/editor_fonts.h (renamed from editor/editor_fonts.h)2
-rw-r--r--editor/themes/editor_icons.cpp252
-rw-r--r--editor/themes/editor_icons.h42
-rw-r--r--editor/themes/editor_scale.cpp (renamed from editor/editor_scale.cpp)0
-rw-r--r--editor/themes/editor_scale.h (renamed from editor/editor_scale.h)0
-rw-r--r--editor/themes/editor_theme.cpp131
-rw-r--r--editor/themes/editor_theme.h53
-rw-r--r--editor/themes/editor_theme_builders.py41
-rw-r--r--editor/themes/editor_theme_manager.cpp2232
-rw-r--r--editor/themes/editor_theme_manager.h150
-rw-r--r--editor/window_wrapper.cpp2
167 files changed, 4679 insertions, 3594 deletions
diff --git a/editor/SCsub b/editor/SCsub
index b1a47dae45..5b36bca81a 100644
--- a/editor/SCsub
+++ b/editor/SCsub
@@ -104,19 +104,6 @@ if env.editor_build:
env.Run(editor_builders.make_doc_translations_header, "Generating translations header."),
)
- # Fonts
- flist = glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.ttf")
- flist.extend(glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.otf"))
- flist.extend(glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.woff"))
- flist.extend(glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.woff2"))
- flist.sort()
- env.Depends("#editor/builtin_fonts.gen.h", flist)
- env.CommandNoCache(
- "#editor/builtin_fonts.gen.h",
- flist,
- env.Run(editor_builders.make_fonts_header, "Generating builtin fonts header."),
- )
-
env.add_source_files(env.editor_sources, "*.cpp")
env.add_source_files(env.editor_sources, "register_exporters.gen.cpp")
@@ -126,6 +113,7 @@ if env.editor_build:
SConscript("icons/SCsub")
SConscript("import/SCsub")
SConscript("plugins/SCsub")
+ SConscript("themes/SCsub")
lib = env.add_library("editor", env.editor_sources)
env.Prepend(LIBS=[lib])
diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp
index d7302d873f..5154d2e0e0 100644
--- a/editor/action_map_editor.cpp
+++ b/editor/action_map_editor.cpp
@@ -30,11 +30,11 @@
#include "editor/action_map_editor.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/event_listener_line_edit.h"
#include "editor/input_event_configuration_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/check_button.h"
#include "scene/gui/separator.h"
#include "scene/gui/tree.h"
diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp
index 4849a6824c..f29b851673 100644
--- a/editor/animation_bezier_editor.cpp
+++ b/editor/animation_bezier_editor.cpp
@@ -31,10 +31,10 @@
#include "animation_bezier_editor.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/view_panner.h"
#include "scene/resources/text_line.h"
@@ -334,7 +334,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
}
}
- Color dc = get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor));
+ Color dc = get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor));
Ref<Texture2D> remove = get_editor_theme_icon(SNAME("Remove"));
float remove_hpos = limit - hsep - remove->get_width();
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 41a6d77860..3c704b3473 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -35,7 +35,6 @@
#include "core/input/input.h"
#include "editor/animation_bezier_editor.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
@@ -43,6 +42,7 @@
#include "editor/gui/scene_tree_editor.h"
#include "editor/inspector_dock.h"
#include "editor/plugins/animation_player_editor_plugin.h"
+#include "editor/themes/editor_scale.h"
#include "scene/animation/animation_player.h"
#include "scene/animation/tween.h"
#include "scene/gui/check_box.h"
@@ -1921,7 +1921,7 @@ void AnimationTrackEdit::_notification(int p_what) {
Color linecolor = color;
linecolor.a = 0.2;
- Color dc = get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor));
+ Color dc = get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor));
// NAMES AND ICONS //
diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp
index 390b722b7b..7a53f4dded 100644
--- a/editor/animation_track_editor_plugins.cpp
+++ b/editor/animation_track_editor_plugins.cpp
@@ -32,9 +32,9 @@
#include "editor/audio_stream_preview.h"
#include "editor/editor_resource_preview.h"
-#include "editor/editor_scale.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
+#include "editor/themes/editor_scale.h"
#include "scene/2d/animated_sprite_2d.h"
#include "scene/2d/sprite_2d.h"
#include "scene/3d/sprite_3d.h"
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index d9101466fc..76d0d40110 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -34,10 +34,10 @@
#include "core/os/keyboard.h"
#include "core/string/string_builder.h"
#include "core/templates/pair.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/plugins/script_editor_plugin.h"
+#include "editor/themes/editor_scale.h"
#include "scene/resources/font.h"
void GotoLineDialog::popup_find_line(CodeEdit *p_edit) {
diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp
index 69908af47d..0285692ab7 100644
--- a/editor/connections_dialog.cpp
+++ b/editor/connections_dialog.cpp
@@ -35,13 +35,13 @@
#include "editor/editor_help.h"
#include "editor/editor_inspector.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/scene_tree_editor.h"
#include "editor/node_dock.h"
#include "editor/scene_tree_dock.h"
+#include "editor/themes/editor_scale.h"
#include "plugins/script_editor_plugin.h"
#include "scene/gui/button.h"
#include "scene/gui/check_box.h"
@@ -1202,7 +1202,22 @@ void ConnectionsDock::_slot_menu_about_to_popup() {
slot_menu->set_item_disabled(slot_menu->get_item_index(SLOT_MENU_DISCONNECT), connection_is_inherited);
}
-void ConnectionsDock::_rmb_pressed(const Ref<InputEvent> &p_event) {
+void ConnectionsDock::_tree_gui_input(const Ref<InputEvent> &p_event) {
+ // Handle Delete press.
+ if (ED_IS_SHORTCUT("connections_editor/disconnect", p_event)) {
+ TreeItem *item = tree->get_selected();
+ if (item && _get_item_type(*item) == TREE_ITEM_TYPE_CONNECTION) {
+ Connection connection = item->get_metadata(0);
+ _disconnect(connection);
+ update_tree();
+
+ // Stop the Delete input from propagating elsewhere.
+ accept_event();
+ return;
+ }
+ }
+
+ // Handle RMB press.
const Ref<InputEventMouseButton> &mb_event = p_event;
if (mb_event.is_null() || !mb_event->is_pressed() || mb_event->get_button_index() != MouseButton::RIGHT) {
return;
@@ -1536,13 +1551,13 @@ ConnectionsDock::ConnectionsDock() {
slot_menu->connect("about_to_popup", callable_mp(this, &ConnectionsDock::_slot_menu_about_to_popup));
slot_menu->add_item(TTR("Edit..."), SLOT_MENU_EDIT);
slot_menu->add_item(TTR("Go to Method"), SLOT_MENU_GO_TO_METHOD);
- slot_menu->add_item(TTR("Disconnect"), SLOT_MENU_DISCONNECT);
+ slot_menu->add_shortcut(ED_SHORTCUT("connections_editor/disconnect", TTR("Disconnect"), Key::KEY_DELETE), SLOT_MENU_DISCONNECT);
add_child(slot_menu);
connect_dialog->connect("connected", callable_mp(this, &ConnectionsDock::_make_or_edit_connection));
tree->connect("item_selected", callable_mp(this, &ConnectionsDock::_tree_item_selected));
tree->connect("item_activated", callable_mp(this, &ConnectionsDock::_tree_item_activated));
- tree->connect("gui_input", callable_mp(this, &ConnectionsDock::_rmb_pressed));
+ tree->connect("gui_input", callable_mp(this, &ConnectionsDock::_tree_gui_input));
add_theme_constant_override("separation", 3 * EDSCALE);
}
diff --git a/editor/connections_dialog.h b/editor/connections_dialog.h
index 2fd4778389..a99f0dd0fe 100644
--- a/editor/connections_dialog.h
+++ b/editor/connections_dialog.h
@@ -252,7 +252,7 @@ class ConnectionsDock : public VBoxContainer {
void _signal_menu_about_to_popup();
void _handle_slot_menu_option(int p_option);
void _slot_menu_about_to_popup();
- void _rmb_pressed(const Ref<InputEvent> &p_event);
+ void _tree_gui_input(const Ref<InputEvent> &p_event);
void _close();
protected:
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 49d997fc6a..da0182b176 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -35,9 +35,9 @@
#include "editor/editor_feature_profile.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
+#include "editor/themes/editor_scale.h"
void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode, const String &p_current_type, const String &p_current_name) {
_fill_type_list();
@@ -306,7 +306,7 @@ void CreateDialog::_configure_search_option_item(TreeItem *r_item, const String
r_item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_type));
if (!instantiable) {
- r_item->set_custom_color(0, search_options->get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor)));
+ r_item->set_custom_color(0, search_options->get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor)));
}
HashMap<String, DocData::ClassDoc>::Iterator class_doc = EditorHelp::get_doc_data()->class_list.find(p_type);
diff --git a/editor/debugger/editor_debugger_node.cpp b/editor/debugger/editor_debugger_node.cpp
index 372d558aab..6471bd449e 100644
--- a/editor/debugger/editor_debugger_node.cpp
+++ b/editor/debugger/editor_debugger_node.cpp
@@ -593,9 +593,15 @@ void EditorDebuggerNode::set_breakpoints(const String &p_path, Array p_lines) {
}
}
-void EditorDebuggerNode::reload_scripts() {
+void EditorDebuggerNode::reload_all_scripts() {
_for_all(tabs, [&](ScriptEditorDebugger *dbg) {
- dbg->reload_scripts();
+ dbg->reload_all_scripts();
+ });
+}
+
+void EditorDebuggerNode::reload_scripts(const Vector<String> &p_script_paths) {
+ _for_all(tabs, [&](ScriptEditorDebugger *dbg) {
+ dbg->reload_scripts(p_script_paths);
});
}
diff --git a/editor/debugger/editor_debugger_node.h b/editor/debugger/editor_debugger_node.h
index 4338f144b8..d30f29c7c6 100644
--- a/editor/debugger/editor_debugger_node.h
+++ b/editor/debugger/editor_debugger_node.h
@@ -187,7 +187,8 @@ public:
bool is_skip_breakpoints() const;
void set_breakpoint(const String &p_path, int p_line, bool p_enabled);
void set_breakpoints(const String &p_path, Array p_lines);
- void reload_scripts();
+ void reload_all_scripts();
+ void reload_scripts(const Vector<String> &p_script_paths);
// Remote inspector/edit.
void request_remote_tree();
diff --git a/editor/debugger/editor_performance_profiler.cpp b/editor/debugger/editor_performance_profiler.cpp
index e93369179c..af723cc731 100644
--- a/editor/debugger/editor_performance_profiler.cpp
+++ b/editor/debugger/editor_performance_profiler.cpp
@@ -31,9 +31,9 @@
#include "editor_performance_profiler.h"
#include "editor/editor_property_name_processor.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
+#include "editor/themes/editor_scale.h"
#include "main/performance.h"
EditorPerformanceProfiler::Monitor::Monitor() {}
diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp
index d54fd62e8c..2809b873b1 100644
--- a/editor/debugger/editor_profiler.cpp
+++ b/editor/debugger/editor_profiler.cpp
@@ -31,9 +31,9 @@
#include "editor_profiler.h"
#include "core/os/os.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
+#include "editor/themes/editor_scale.h"
#include "scene/resources/image_texture.h"
void EditorProfiler::_make_metric_ptrs(Metric &m) {
diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp
index 7df942e288..4ebed726c5 100644
--- a/editor/debugger/editor_visual_profiler.cpp
+++ b/editor/debugger/editor_visual_profiler.cpp
@@ -31,9 +31,9 @@
#include "editor_visual_profiler.h"
#include "core/os/os.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
+#include "editor/themes/editor_scale.h"
#include "scene/resources/image_texture.h"
void EditorVisualProfiler::add_frame_metric(const Metric &p_metric) {
diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp
index d926bd0f12..3c863bdc19 100644
--- a/editor/debugger/script_editor_debugger.cpp
+++ b/editor/debugger/script_editor_debugger.cpp
@@ -44,7 +44,6 @@
#include "editor/editor_log.h"
#include "editor/editor_node.h"
#include "editor/editor_property_name_processor.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/gui/editor_file_dialog.h"
@@ -52,6 +51,7 @@
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "editor/plugins/editor_debugger_plugin.h"
#include "editor/plugins/node_3d_editor_plugin.h"
+#include "editor/themes/editor_scale.h"
#include "main/performance.h"
#include "scene/3d/camera_3d.h"
#include "scene/debugger/scene_debugger.h"
@@ -1518,8 +1518,12 @@ void ScriptEditorDebugger::set_breakpoint(const String &p_path, int p_line, bool
}
}
-void ScriptEditorDebugger::reload_scripts() {
- _put_msg("reload_scripts", Array(), debugging_thread_id != Thread::UNASSIGNED_ID ? debugging_thread_id : Thread::MAIN_ID);
+void ScriptEditorDebugger::reload_all_scripts() {
+ _put_msg("reload_all_scripts", Array(), debugging_thread_id != Thread::UNASSIGNED_ID ? debugging_thread_id : Thread::MAIN_ID);
+}
+
+void ScriptEditorDebugger::reload_scripts(const Vector<String> &p_script_paths) {
+ _put_msg("reload_scripts", Variant(p_script_paths).operator Array(), debugging_thread_id != Thread::UNASSIGNED_ID ? debugging_thread_id : Thread::MAIN_ID);
}
bool ScriptEditorDebugger::is_skip_breakpoints() {
diff --git a/editor/debugger/script_editor_debugger.h b/editor/debugger/script_editor_debugger.h
index 79224061ff..589e82ef25 100644
--- a/editor/debugger/script_editor_debugger.h
+++ b/editor/debugger/script_editor_debugger.h
@@ -300,7 +300,8 @@ public:
void update_live_edit_root();
- void reload_scripts();
+ void reload_all_scripts();
+ void reload_scripts(const Vector<String> &p_script_paths);
bool is_skip_breakpoints();
diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
index a891491339..4be6afbcff 100644
--- a/editor/dependency_editor.cpp
+++ b/editor/dependency_editor.cpp
@@ -35,9 +35,9 @@
#include "core/io/resource_loader.h"
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/gui/editor_file_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/margin_container.h"
void DependencyEditor::_searched(const String &p_path) {
diff --git a/editor/directory_create_dialog.cpp b/editor/directory_create_dialog.cpp
index aacd718fde..6f9b91731b 100644
--- a/editor/directory_create_dialog.cpp
+++ b/editor/directory_create_dialog.cpp
@@ -32,8 +32,8 @@
#include "core/io/dir_access.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/gui/editor_validation_panel.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/box_container.h"
#include "scene/gui/label.h"
#include "scene/gui/line_edit.h"
diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp
index 9c1fc2a8bf..44f6444a31 100644
--- a/editor/doc_tools.cpp
+++ b/editor/doc_tools.cpp
@@ -307,21 +307,21 @@ void DocTools::merge_from(const DocTools &p_data) {
}
}
-void DocTools::remove_from(const DocTools &p_data) {
- for (const KeyValue<String, DocData::ClassDoc> &E : p_data.class_list) {
- if (class_list.has(E.key)) {
- class_list.erase(E.key);
- }
- }
-}
-
void DocTools::add_doc(const DocData::ClassDoc &p_class_doc) {
ERR_FAIL_COND(p_class_doc.name.is_empty());
class_list[p_class_doc.name] = p_class_doc;
+ inheriting[p_class_doc.inherits].insert(p_class_doc.name);
}
void DocTools::remove_doc(const String &p_class_name) {
ERR_FAIL_COND(p_class_name.is_empty() || !class_list.has(p_class_name));
+ const String &inherits = class_list[p_class_name].inherits;
+ if (inheriting.has(inherits)) {
+ inheriting[inherits].erase(p_class_name);
+ if (inheriting[inherits].is_empty()) {
+ inheriting.erase(inherits);
+ }
+ }
class_list.erase(p_class_name);
}
@@ -391,6 +391,8 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) {
c.name = cname;
c.inherits = ClassDB::get_parent_class(name);
+ inheriting[c.inherits].insert(cname);
+
List<PropertyInfo> properties;
List<PropertyInfo> own_properties;
@@ -692,6 +694,7 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) {
// it's not a ClassDB-exposed class.
class_list["Variant"] = DocData::ClassDoc();
class_list["Variant"].name = "Variant";
+ inheriting[""].insert("Variant");
}
// Add Variant data types.
@@ -709,6 +712,8 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) {
DocData::ClassDoc &c = class_list[cname];
c.name = cname;
+ inheriting[""].insert(cname);
+
Callable::CallError cerror;
Variant v;
Variant::construct(Variant::Type(i), v, nullptr, 0, cerror);
@@ -870,6 +875,8 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) {
DocData::ClassDoc &c = class_list[cname];
c.name = cname;
+ inheriting[""].insert(cname);
+
// Global constants.
for (int i = 0; i < CoreConstants::get_global_constant_count(); i++) {
DocData::ConstantDoc cd;
@@ -953,6 +960,8 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) {
DocData::ClassDoc c;
c.name = cname;
+ inheriting[""].insert(cname);
+
// Get functions.
List<MethodInfo> minfo;
lang->get_public_functions(&minfo);
@@ -1195,6 +1204,8 @@ Error DocTools::_load(Ref<XMLParser> parser) {
c.inherits = parser->get_named_attribute_value("inherits");
}
+ inheriting[c.inherits].insert(name);
+
if (parser->has_attribute("is_deprecated")) {
c.is_deprecated = parser->get_named_attribute_value("is_deprecated").to_lower() == "true";
}
diff --git a/editor/doc_tools.h b/editor/doc_tools.h
index 5fffb6be38..7f29cc238a 100644
--- a/editor/doc_tools.h
+++ b/editor/doc_tools.h
@@ -32,16 +32,17 @@
#define DOC_TOOLS_H
#include "core/doc_data.h"
+#include "core/templates/rb_set.h"
class DocTools {
public:
String version;
HashMap<String, DocData::ClassDoc> class_list;
+ HashMap<String, RBSet<String, NaturalNoCaseComparator>> inheriting;
static Error erase_classes(const String &p_dir);
void merge_from(const DocTools &p_data);
- void remove_from(const DocTools &p_data);
void add_doc(const DocData::ClassDoc &p_class_doc);
void remove_doc(const String &p_class_name);
bool has_doc(const String &p_class_name);
diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp
index 1f9911f31e..6c859ce236 100644
--- a/editor/editor_about.cpp
+++ b/editor/editor_about.cpp
@@ -35,6 +35,7 @@
#include "core/license.gen.h"
#include "core/version.h"
#include "editor/editor_string_names.h"
+#include "editor/themes/editor_scale.h"
// The metadata key used to store and retrieve the version text to copy to the clipboard.
const String EditorAbout::META_TEXT_TO_COPY = "text_to_copy";
diff --git a/editor/editor_about.h b/editor/editor_about.h
index 22b5f3ded0..639dc6cc3f 100644
--- a/editor/editor_about.h
+++ b/editor/editor_about.h
@@ -42,8 +42,6 @@
#include "scene/gui/texture_rect.h"
#include "scene/gui/tree.h"
-#include "editor/editor_scale.h"
-
/**
* NOTE: Do not assume the EditorNode singleton to be available in this class' methods.
* EditorAbout is also used from the project manager where EditorNode isn't initialized.
diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp
index b609de9f67..ab0816805f 100644
--- a/editor/editor_asset_installer.cpp
+++ b/editor/editor_asset_installer.cpp
@@ -35,11 +35,11 @@
#include "core/io/zip_io.h"
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_string_names.h"
#include "editor/gui/editor_file_dialog.h"
#include "editor/gui/editor_toaster.h"
#include "editor/progress_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/check_box.h"
#include "scene/gui/label.h"
#include "scene/gui/link_button.h"
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index c1183c8d66..50845b4458 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -35,12 +35,12 @@
#include "core/io/resource_saver.h"
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/filesystem_dock.h"
#include "editor/gui/editor_file_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/separator.h"
#include "scene/resources/font.h"
#include "servers/audio_server.h"
diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp
index 45de4a54ae..4d5393299c 100644
--- a/editor/editor_autoload_settings.cpp
+++ b/editor/editor_autoload_settings.cpp
@@ -33,12 +33,12 @@
#include "core/config/project_settings.h"
#include "core/core_constants.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/filesystem_dock.h"
#include "editor/gui/editor_file_dialog.h"
#include "editor/project_settings_editor.h"
+#include "editor/themes/editor_scale.h"
#include "scene/main/window.h"
#include "scene/resources/packed_scene.h"
diff --git a/editor/editor_build_profile.cpp b/editor/editor_build_profile.cpp
index 8ab8bc4a52..3d10b7949e 100644
--- a/editor/editor_build_profile.cpp
+++ b/editor/editor_build_profile.cpp
@@ -36,10 +36,10 @@
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
#include "editor/editor_property_name_processor.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/gui/editor_file_dialog.h"
+#include "editor/themes/editor_scale.h"
const char *EditorBuildProfile::build_option_identifiers[BUILD_OPTION_MAX] = {
// This maps to SCons build options.
@@ -601,7 +601,7 @@ void EditorBuildProfileManager::_fill_classes_from(TreeItem *p_parent, const Str
bool disabled = edited->is_class_disabled(p_class);
if (disabled) {
- class_item->set_custom_color(0, class_list->get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor)));
+ class_item->set_custom_color(0, class_list->get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor)));
}
class_item->set_text(0, text);
diff --git a/editor/editor_builders.py b/editor/editor_builders.py
index 90ecccbf30..25004da877 100644
--- a/editor/editor_builders.py
+++ b/editor/editor_builders.py
@@ -3,6 +3,7 @@
All such functions are invoked in a subprocess on Windows to prevent build flakiness.
"""
+
import os
import os.path
import shutil
@@ -49,34 +50,6 @@ def make_doc_header(target, source, env):
g.close()
-def make_fonts_header(target, source, env):
- dst = target[0]
-
- g = open(dst, "w", encoding="utf-8")
-
- g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
- g.write("#ifndef _EDITOR_FONTS_H\n")
- g.write("#define _EDITOR_FONTS_H\n")
-
- # Saving uncompressed, since FreeType will reference from memory pointer.
- for i in range(len(source)):
- with open(source[i], "rb") as f:
- buf = f.read()
-
- name = os.path.splitext(os.path.basename(source[i]))[0]
-
- g.write("static const int _font_" + name + "_size = " + str(len(buf)) + ";\n")
- g.write("static const unsigned char _font_" + name + "[] = {\n")
- for j in range(len(buf)):
- g.write("\t" + str(buf[j]) + ",\n")
-
- g.write("};\n")
-
- g.write("#endif")
-
- g.close()
-
-
def make_translations_header(target, source, env, category):
dst = target[0]
diff --git a/editor/editor_command_palette.cpp b/editor/editor_command_palette.cpp
index ce5d8619e1..567b686b85 100644
--- a/editor/editor_command_palette.cpp
+++ b/editor/editor_command_palette.cpp
@@ -31,10 +31,10 @@
#include "editor/editor_command_palette.h"
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/gui/editor_toaster.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/control.h"
#include "scene/gui/tree.h"
diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp
index 5f77959127..794d1b3e10 100644
--- a/editor/editor_data.cpp
+++ b/editor/editor_data.cpp
@@ -37,10 +37,10 @@
#include "core/io/resource_loader.h"
#include "editor/editor_node.h"
#include "editor/editor_plugin.h"
-#include "editor/editor_scale.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/multi_node_edit.h"
#include "editor/plugins/script_editor_plugin.h"
+#include "editor/themes/editor_scale.h"
#include "scene/resources/packed_scene.h"
void EditorSelectionHistory::cleanup_history() {
diff --git a/editor/editor_dock_manager.cpp b/editor/editor_dock_manager.cpp
new file mode 100644
index 0000000000..dfe9504706
--- /dev/null
+++ b/editor/editor_dock_manager.cpp
@@ -0,0 +1,716 @@
+/**************************************************************************/
+/* editor_dock_manager.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "editor_dock_manager.h"
+
+#include "scene/gui/box_container.h"
+#include "scene/gui/button.h"
+#include "scene/gui/label.h"
+#include "scene/gui/popup.h"
+#include "scene/gui/split_container.h"
+#include "scene/gui/tab_container.h"
+#include "scene/main/window.h"
+
+#include "editor/editor_node.h"
+#include "editor/editor_settings.h"
+#include "editor/editor_string_names.h"
+#include "editor/filesystem_dock.h"
+#include "editor/themes/editor_scale.h"
+#include "editor/window_wrapper.h"
+
+EditorDockManager *EditorDockManager::singleton = nullptr;
+
+void DockSplitContainer::_update_visibility() {
+ if (is_updating) {
+ return;
+ }
+ is_updating = true;
+ bool any_visible = false;
+ for (int i = 0; i < 2; i++) {
+ Control *split = get_containable_child(i);
+ if (split && split->is_visible()) {
+ any_visible = true;
+ break;
+ }
+ }
+ set_visible(any_visible);
+ is_updating = false;
+}
+
+void DockSplitContainer::add_child_notify(Node *p_child) {
+ SplitContainer::add_child_notify(p_child);
+
+ Control *child_control = nullptr;
+ for (int i = 0; i < 2; i++) {
+ Control *split = get_containable_child(i);
+ if (p_child == split) {
+ child_control = split;
+ break;
+ }
+ }
+ if (!child_control) {
+ return;
+ }
+
+ child_control->connect("visibility_changed", callable_mp(this, &DockSplitContainer::_update_visibility));
+ _update_visibility();
+}
+
+void DockSplitContainer::remove_child_notify(Node *p_child) {
+ SplitContainer::remove_child_notify(p_child);
+
+ Control *child_control = nullptr;
+ for (int i = 0; i < 2; i++) {
+ Control *split = get_containable_child(i);
+ if (p_child == split) {
+ child_control = split;
+ break;
+ }
+ }
+ if (!child_control) {
+ return;
+ }
+
+ child_control->disconnect("visibility_changed", callable_mp(this, &DockSplitContainer::_update_visibility));
+ _update_visibility();
+}
+
+void EditorDockManager::_dock_select_popup_theme_changed() {
+ if (dock_float) {
+ dock_float->set_icon(dock_select_popup->get_editor_theme_icon(SNAME("MakeFloating")));
+ }
+ if (dock_select_popup->is_layout_rtl()) {
+ dock_tab_move_left->set_icon(dock_select_popup->get_editor_theme_icon(SNAME("Forward")));
+ dock_tab_move_right->set_icon(dock_select_popup->get_editor_theme_icon(SNAME("Back")));
+ } else {
+ dock_tab_move_left->set_icon(dock_select_popup->get_editor_theme_icon(SNAME("Back")));
+ dock_tab_move_right->set_icon(dock_select_popup->get_editor_theme_icon(SNAME("Forward")));
+ }
+}
+
+void EditorDockManager::_dock_popup_exit() {
+ dock_select_rect_over_idx = -1;
+ dock_select->queue_redraw();
+}
+
+void EditorDockManager::_dock_pre_popup(int p_dock_slot) {
+ dock_popup_selected_idx = p_dock_slot;
+}
+
+void EditorDockManager::_dock_move_left() {
+ if (dock_popup_selected_idx < 0 || dock_popup_selected_idx >= DOCK_SLOT_MAX) {
+ return;
+ }
+ Control *current_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab());
+ Control *prev_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab() - 1);
+ if (!current_ctl || !prev_ctl) {
+ return;
+ }
+ dock_slot[dock_popup_selected_idx]->move_child(current_ctl, prev_ctl->get_index(false));
+ dock_select->queue_redraw();
+ _edit_current();
+ emit_signal(SNAME("layout_changed"));
+}
+
+void EditorDockManager::_dock_move_right() {
+ if (dock_popup_selected_idx < 0 || dock_popup_selected_idx >= DOCK_SLOT_MAX) {
+ return;
+ }
+ Control *current_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab());
+ Control *next_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab() + 1);
+ if (!current_ctl || !next_ctl) {
+ return;
+ }
+ dock_slot[dock_popup_selected_idx]->move_child(next_ctl, current_ctl->get_index(false));
+ dock_select->queue_redraw();
+ _edit_current();
+ emit_signal(SNAME("layout_changed"));
+}
+
+void EditorDockManager::_dock_select_input(const Ref<InputEvent> &p_input) {
+ Ref<InputEventMouse> me = p_input;
+
+ if (me.is_valid()) {
+ Vector2 point = me->get_position();
+
+ int nrect = -1;
+ for (int i = 0; i < DOCK_SLOT_MAX; i++) {
+ if (dock_select_rect[i].has_point(point)) {
+ nrect = i;
+ break;
+ }
+ }
+
+ if (nrect != dock_select_rect_over_idx) {
+ dock_select->queue_redraw();
+ dock_select_rect_over_idx = nrect;
+ }
+
+ if (nrect == -1) {
+ return;
+ }
+
+ Ref<InputEventMouseButton> mb = me;
+
+ if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed() && dock_popup_selected_idx != nrect) {
+ dock_slot[nrect]->move_tab_from_tab_container(dock_slot[dock_popup_selected_idx], dock_slot[dock_popup_selected_idx]->get_current_tab(), dock_slot[nrect]->get_tab_count());
+
+ if (dock_slot[dock_popup_selected_idx]->get_tab_count() == 0) {
+ dock_slot[dock_popup_selected_idx]->hide();
+ } else {
+ dock_slot[dock_popup_selected_idx]->set_current_tab(0);
+ }
+
+ dock_popup_selected_idx = nrect;
+ dock_slot[nrect]->show();
+ dock_select->queue_redraw();
+
+ update_dock_slots_visibility(true);
+
+ _edit_current();
+ emit_signal(SNAME("layout_changed"));
+ }
+ }
+}
+
+void EditorDockManager::_dock_select_draw() {
+ Size2 s = dock_select->get_size();
+ s.y /= 2.0;
+ s.x /= 6.0;
+
+ Color used = Color(0.6, 0.6, 0.6, 0.8);
+ Color used_selected = Color(0.8, 0.8, 0.8, 0.8);
+ Color tab_selected = dock_select->get_theme_color(SNAME("mono_color"), EditorStringName(Editor));
+ Color unused = used;
+ unused.a = 0.4;
+ Color unusable = unused;
+ unusable.a = 0.1;
+
+ Rect2 unr(s.x * 2, 0, s.x * 2, s.y * 2);
+ unr.position += Vector2(2, 5);
+ unr.size -= Vector2(4, 7);
+
+ dock_select->draw_rect(unr, unusable);
+
+ dock_tab_move_left->set_disabled(true);
+ dock_tab_move_right->set_disabled(true);
+
+ if (dock_popup_selected_idx != -1 && dock_slot[dock_popup_selected_idx]->get_tab_count()) {
+ dock_tab_move_left->set_disabled(dock_slot[dock_popup_selected_idx]->get_current_tab() == 0);
+ dock_tab_move_right->set_disabled(dock_slot[dock_popup_selected_idx]->get_current_tab() >= dock_slot[dock_popup_selected_idx]->get_tab_count() - 1);
+ }
+
+ for (int i = 0; i < DOCK_SLOT_MAX; i++) {
+ Vector2 ofs;
+
+ switch (i) {
+ case DOCK_SLOT_LEFT_UL: {
+ } break;
+ case DOCK_SLOT_LEFT_BL: {
+ ofs.y += s.y;
+ } break;
+ case DOCK_SLOT_LEFT_UR: {
+ ofs.x += s.x;
+ } break;
+ case DOCK_SLOT_LEFT_BR: {
+ ofs += s;
+ } break;
+ case DOCK_SLOT_RIGHT_UL: {
+ ofs.x += s.x * 4;
+ } break;
+ case DOCK_SLOT_RIGHT_BL: {
+ ofs.x += s.x * 4;
+ ofs.y += s.y;
+
+ } break;
+ case DOCK_SLOT_RIGHT_UR: {
+ ofs.x += s.x * 4;
+ ofs.x += s.x;
+
+ } break;
+ case DOCK_SLOT_RIGHT_BR: {
+ ofs.x += s.x * 4;
+ ofs += s;
+
+ } break;
+ }
+
+ Rect2 r(ofs, s);
+ dock_select_rect[i] = r;
+ r.position += Vector2(2, 5);
+ r.size -= Vector2(4, 7);
+
+ if (i == dock_select_rect_over_idx) {
+ dock_select->draw_rect(r, used_selected);
+ } else if (dock_slot[i]->get_tab_count() == 0) {
+ dock_select->draw_rect(r, unused);
+ } else {
+ dock_select->draw_rect(r, used);
+ }
+
+ for (int j = 0; j < MIN(3, dock_slot[i]->get_tab_count()); j++) {
+ int xofs = (r.size.width / 3) * j;
+ Color c = used;
+ if (i == dock_popup_selected_idx && (dock_slot[i]->get_current_tab() > 3 || dock_slot[i]->get_current_tab() == j)) {
+ c = tab_selected;
+ }
+ dock_select->draw_rect(Rect2(2 + ofs.x + xofs, ofs.y, r.size.width / 3 - 1, 3), c);
+ }
+ }
+}
+
+void EditorDockManager::_dock_split_dragged(int p_offset) {
+ EditorNode::get_singleton()->save_editor_layout_delayed();
+}
+
+void EditorDockManager::_dock_tab_changed(int p_tab) {
+ // Update visibility but don't set current tab.
+ update_dock_slots_visibility(true);
+}
+
+void EditorDockManager::_edit_current() {
+ EditorNode::get_singleton()->edit_current();
+}
+
+void EditorDockManager::_dock_floating_close_request(WindowWrapper *p_wrapper) {
+ int dock_slot_num = p_wrapper->get_meta("dock_slot");
+ int dock_slot_index = p_wrapper->get_meta("dock_index");
+
+ // Give back the dock to the original owner.
+ Control *dock = p_wrapper->release_wrapped_control();
+
+ int target_index = MIN(dock_slot_index, dock_slot[dock_slot_num]->get_tab_count());
+ dock_slot[dock_slot_num]->add_child(dock);
+ dock_slot[dock_slot_num]->move_child(dock, target_index);
+ dock_slot[dock_slot_num]->set_current_tab(target_index);
+
+ floating_docks.erase(p_wrapper);
+ p_wrapper->queue_free();
+
+ update_dock_slots_visibility(true);
+
+ _edit_current();
+}
+
+void EditorDockManager::_dock_make_selected_float() {
+ Control *dock = dock_slot[dock_popup_selected_idx]->get_current_tab_control();
+ _dock_make_float(dock, dock_popup_selected_idx);
+
+ dock_select_popup->hide();
+ _edit_current();
+}
+
+void EditorDockManager::_dock_make_float(Control *p_dock, int p_slot_index, bool p_show_window) {
+ ERR_FAIL_NULL(p_dock);
+
+ Size2 borders = Size2(4, 4) * EDSCALE;
+ // Remember size and position before removing it from the main window.
+ Size2 dock_size = p_dock->get_size() + borders * 2;
+ Point2 dock_screen_pos = p_dock->get_screen_position();
+
+ int dock_index = p_dock->get_index() - 1;
+ dock_slot[p_slot_index]->remove_child(p_dock);
+
+ WindowWrapper *wrapper = memnew(WindowWrapper);
+ wrapper->set_window_title(vformat(TTR("%s - Godot Engine"), p_dock->get_name()));
+ wrapper->set_margins_enabled(true);
+
+ EditorNode::get_singleton()->get_gui_base()->add_child(wrapper);
+
+ wrapper->set_wrapped_control(p_dock);
+ wrapper->set_meta("dock_slot", p_slot_index);
+ wrapper->set_meta("dock_index", dock_index);
+ wrapper->set_meta("dock_name", p_dock->get_name().operator String());
+ p_dock->show();
+
+ wrapper->connect("window_close_requested", callable_mp(this, &EditorDockManager::_dock_floating_close_request).bind(wrapper));
+
+ dock_select_popup->hide();
+
+ if (p_show_window) {
+ wrapper->restore_window(Rect2i(dock_screen_pos, dock_size), EditorNode::get_singleton()->get_gui_base()->get_window()->get_current_screen());
+ }
+
+ update_dock_slots_visibility(true);
+
+ floating_docks.push_back(wrapper);
+
+ _edit_current();
+}
+
+void EditorDockManager::_restore_floating_dock(const Dictionary &p_dock_dump, Control *p_dock, int p_slot_index) {
+ WindowWrapper *wrapper = Object::cast_to<WindowWrapper>(p_dock);
+ if (!wrapper) {
+ _dock_make_float(p_dock, p_slot_index, false);
+ wrapper = floating_docks[floating_docks.size() - 1];
+ }
+
+ wrapper->restore_window_from_saved_position(
+ p_dock_dump.get("window_rect", Rect2i()),
+ p_dock_dump.get("window_screen", -1),
+ p_dock_dump.get("window_screen_rect", Rect2i()));
+}
+
+void EditorDockManager::save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section) const {
+ for (int i = 0; i < DOCK_SLOT_MAX; i++) {
+ String names;
+ for (int j = 0; j < dock_slot[i]->get_tab_count(); j++) {
+ String name = dock_slot[i]->get_tab_control(j)->get_name();
+ if (!names.is_empty()) {
+ names += ",";
+ }
+ names += name;
+ }
+
+ String config_key = "dock_" + itos(i + 1);
+
+ if (p_layout->has_section_key(p_section, config_key)) {
+ p_layout->erase_section_key(p_section, config_key);
+ }
+
+ if (!names.is_empty()) {
+ p_layout->set_value(p_section, config_key, names);
+ }
+
+ int selected_tab_idx = dock_slot[i]->get_current_tab();
+ if (selected_tab_idx >= 0) {
+ p_layout->set_value(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx", selected_tab_idx);
+ }
+ }
+
+ Dictionary floating_docks_dump;
+
+ for (WindowWrapper *wrapper : floating_docks) {
+ Control *dock = wrapper->get_wrapped_control();
+
+ Dictionary dock_dump;
+ dock_dump["window_rect"] = wrapper->get_window_rect();
+
+ int screen = wrapper->get_window_screen();
+ dock_dump["window_screen"] = wrapper->get_window_screen();
+ dock_dump["window_screen_rect"] = DisplayServer::get_singleton()->screen_get_usable_rect(screen);
+
+ String name = dock->get_name();
+ floating_docks_dump[name] = dock_dump;
+
+ int dock_slot_id = wrapper->get_meta("dock_slot");
+ String config_key = "dock_" + itos(dock_slot_id + 1);
+
+ String names = p_layout->get_value(p_section, config_key, "");
+ if (names.is_empty()) {
+ names = name;
+ } else {
+ names += "," + name;
+ }
+ p_layout->set_value(p_section, config_key, names);
+ }
+
+ p_layout->set_value(p_section, "dock_floating", floating_docks_dump);
+
+ for (int i = 0; i < vsplits.size(); i++) {
+ if (vsplits[i]->is_visible_in_tree()) {
+ p_layout->set_value(p_section, "dock_split_" + itos(i + 1), vsplits[i]->get_split_offset());
+ }
+ }
+
+ for (int i = 0; i < hsplits.size(); i++) {
+ p_layout->set_value(p_section, "dock_hsplit_" + itos(i + 1), hsplits[i]->get_split_offset());
+ }
+
+ FileSystemDock::get_singleton()->save_layout_to_config(p_layout, p_section);
+}
+
+void EditorDockManager::load_docks_from_config(Ref<ConfigFile> p_layout, const String &p_section) {
+ Dictionary floating_docks_dump = p_layout->get_value(p_section, "dock_floating", Dictionary());
+
+ bool restore_window_on_load = EDITOR_GET("interface/multi_window/restore_windows_on_load");
+
+ for (int i = 0; i < DOCK_SLOT_MAX; i++) {
+ if (!p_layout->has_section_key(p_section, "dock_" + itos(i + 1))) {
+ continue;
+ }
+
+ Vector<String> names = String(p_layout->get_value(p_section, "dock_" + itos(i + 1))).split(",");
+
+ for (int j = names.size() - 1; j >= 0; j--) {
+ String name = names[j];
+
+ // FIXME: Find it, in a horribly inefficient way.
+ int atidx = -1;
+ Control *node = nullptr;
+ for (int k = 0; k < DOCK_SLOT_MAX; k++) {
+ if (!dock_slot[k]->has_node(name)) {
+ continue;
+ }
+ node = Object::cast_to<Control>(dock_slot[k]->get_node(name));
+ if (!node) {
+ continue;
+ }
+ atidx = k;
+ break;
+ }
+
+ if (atidx == -1) {
+ // Try floating docks.
+ for (WindowWrapper *wrapper : floating_docks) {
+ if (wrapper->get_meta("dock_name") == name) {
+ if (restore_window_on_load && floating_docks_dump.has(name)) {
+ _restore_floating_dock(floating_docks_dump[name], wrapper, i);
+ } else {
+ atidx = wrapper->get_meta("dock_slot");
+ node = wrapper->get_wrapped_control();
+ wrapper->set_window_enabled(false);
+ }
+ break;
+ }
+ }
+ }
+ if (!node) {
+ // Well, it's not anywhere.
+ continue;
+ }
+
+ if (atidx == i) {
+ dock_slot[i]->move_child(node, 0);
+ } else if (atidx != -1) {
+ dock_slot[i]->set_block_signals(true);
+ dock_slot[atidx]->set_block_signals(true);
+ dock_slot[i]->move_tab_from_tab_container(dock_slot[atidx], dock_slot[atidx]->get_tab_idx_from_control(node), 0);
+ dock_slot[i]->set_block_signals(false);
+ dock_slot[atidx]->set_block_signals(false);
+ }
+
+ WindowWrapper *wrapper = Object::cast_to<WindowWrapper>(node);
+ if (restore_window_on_load && floating_docks_dump.has(name)) {
+ if (!dock_slot[i]->is_tab_hidden(dock_slot[i]->get_tab_idx_from_control(node))) {
+ _restore_floating_dock(floating_docks_dump[name], node, i);
+ }
+ } else if (wrapper) {
+ wrapper->set_window_enabled(false);
+ }
+ }
+
+ if (!p_layout->has_section_key(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx")) {
+ continue;
+ }
+
+ int selected_tab_idx = p_layout->get_value(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx");
+ if (selected_tab_idx >= 0 && selected_tab_idx < dock_slot[i]->get_tab_count()) {
+ callable_mp(dock_slot[i], &TabContainer::set_current_tab).call_deferred(selected_tab_idx);
+ }
+ }
+
+ for (int i = 0; i < vsplits.size(); i++) {
+ if (!p_layout->has_section_key(p_section, "dock_split_" + itos(i + 1))) {
+ continue;
+ }
+
+ int ofs = p_layout->get_value(p_section, "dock_split_" + itos(i + 1));
+ vsplits[i]->set_split_offset(ofs);
+ }
+
+ for (int i = 0; i < hsplits.size(); i++) {
+ if (!p_layout->has_section_key(p_section, "dock_hsplit_" + itos(i + 1))) {
+ continue;
+ }
+ int ofs = p_layout->get_value(p_section, "dock_hsplit_" + itos(i + 1));
+ hsplits[i]->set_split_offset(ofs);
+ }
+
+ update_dock_slots_visibility(false);
+
+ FileSystemDock::get_singleton()->load_layout_from_config(p_layout, p_section);
+}
+
+void EditorDockManager::update_dock_slots_visibility(bool p_keep_selected_tabs) {
+ if (!docks_visible) {
+ for (int i = 0; i < DOCK_SLOT_MAX; i++) {
+ dock_slot[i]->hide();
+ }
+ } else {
+ for (int i = 0; i < DOCK_SLOT_MAX; i++) {
+ int first_tab_visible = -1;
+ for (int j = 0; j < dock_slot[i]->get_tab_count(); j++) {
+ if (!dock_slot[i]->is_tab_hidden(j)) {
+ first_tab_visible = j;
+ break;
+ }
+ }
+ if (first_tab_visible >= 0) {
+ dock_slot[i]->show();
+ if (p_keep_selected_tabs) {
+ int current_tab = dock_slot[i]->get_current_tab();
+ if (dock_slot[i]->is_tab_hidden(current_tab)) {
+ dock_slot[i]->set_block_signals(true);
+ dock_slot[i]->select_next_available();
+ dock_slot[i]->set_block_signals(false);
+ }
+ } else {
+ dock_slot[i]->set_block_signals(true);
+ dock_slot[i]->set_current_tab(first_tab_visible);
+ dock_slot[i]->set_block_signals(false);
+ }
+ } else {
+ dock_slot[i]->hide();
+ }
+ }
+ }
+}
+
+void EditorDockManager::close_all_floating_docks() {
+ for (WindowWrapper *wrapper : floating_docks) {
+ wrapper->set_window_enabled(false);
+ }
+}
+
+void EditorDockManager::add_control_to_dock(DockSlot p_slot, Control *p_control, const String &p_name) {
+ ERR_FAIL_INDEX(p_slot, DOCK_SLOT_MAX);
+ dock_slot[p_slot]->add_child(p_control);
+ if (!p_name.is_empty()) {
+ dock_slot[p_slot]->set_tab_title(dock_slot[p_slot]->get_tab_idx_from_control(p_control), p_name);
+ }
+}
+
+void EditorDockManager::remove_control_from_dock(Control *p_control) {
+ // If the dock is floating, close it first.
+ for (WindowWrapper *wrapper : floating_docks) {
+ if (p_control == wrapper->get_wrapped_control()) {
+ wrapper->set_window_enabled(false);
+ break;
+ }
+ }
+
+ Control *dock = nullptr;
+ for (int i = 0; i < DOCK_SLOT_MAX; i++) {
+ if (p_control->get_parent() == dock_slot[i]) {
+ dock = dock_slot[i];
+ break;
+ }
+ }
+
+ ERR_FAIL_NULL_MSG(dock, "Control is not in a dock.");
+
+ dock->remove_child(p_control);
+ update_dock_slots_visibility();
+}
+
+void EditorDockManager::set_docks_visible(bool p_show) {
+ docks_visible = p_show;
+ update_dock_slots_visibility(true);
+}
+
+bool EditorDockManager::are_docks_visible() const {
+ return docks_visible;
+}
+
+void EditorDockManager::add_vsplit(DockSplitContainer *p_split) {
+ vsplits.push_back(p_split);
+ p_split->connect("dragged", callable_mp(this, &EditorDockManager::_dock_split_dragged));
+}
+
+void EditorDockManager::add_hsplit(DockSplitContainer *p_split) {
+ hsplits.push_back(p_split);
+ p_split->connect("dragged", callable_mp(this, &EditorDockManager::_dock_split_dragged));
+}
+
+void EditorDockManager::register_dock_slot(DockSlot p_dock_slot, TabContainer *p_tab_container) {
+ ERR_FAIL_NULL(p_tab_container);
+ ERR_FAIL_INDEX(p_dock_slot, DOCK_SLOT_MAX);
+
+ dock_slot[p_dock_slot] = p_tab_container;
+
+ p_tab_container->set_custom_minimum_size(Size2(170, 0) * EDSCALE);
+ p_tab_container->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ p_tab_container->set_popup(dock_select_popup);
+ p_tab_container->connect("pre_popup_pressed", callable_mp(this, &EditorDockManager::_dock_pre_popup).bind(p_dock_slot));
+ p_tab_container->set_drag_to_rearrange_enabled(true);
+ p_tab_container->set_tabs_rearrange_group(1);
+ p_tab_container->connect("tab_changed", callable_mp(this, &EditorDockManager::_dock_tab_changed));
+ p_tab_container->set_use_hidden_tabs_for_min_size(true);
+}
+
+int EditorDockManager::get_vsplit_count() const {
+ return vsplits.size();
+}
+
+void EditorDockManager::_bind_methods() {
+ ADD_SIGNAL(MethodInfo("layout_changed"));
+}
+
+EditorDockManager::EditorDockManager() {
+ singleton = this;
+
+ dock_select_popup = memnew(PopupPanel);
+ EditorNode::get_singleton()->get_gui_base()->add_child(dock_select_popup);
+ VBoxContainer *dock_vb = memnew(VBoxContainer);
+ dock_select_popup->add_child(dock_vb);
+ dock_select_popup->connect("theme_changed", callable_mp(this, &EditorDockManager::_dock_select_popup_theme_changed));
+
+ HBoxContainer *dock_hb = memnew(HBoxContainer);
+ dock_tab_move_left = memnew(Button);
+ dock_tab_move_left->set_flat(true);
+ dock_tab_move_left->set_focus_mode(Control::FOCUS_NONE);
+ dock_tab_move_left->connect("pressed", callable_mp(this, &EditorDockManager::_dock_move_left));
+ dock_hb->add_child(dock_tab_move_left);
+
+ Label *dock_label = memnew(Label);
+ dock_label->set_text(TTR("Dock Position"));
+ dock_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ dock_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
+ dock_hb->add_child(dock_label);
+
+ dock_tab_move_right = memnew(Button);
+ dock_tab_move_right->set_flat(true);
+ dock_tab_move_right->set_focus_mode(Control::FOCUS_NONE);
+ dock_tab_move_right->connect("pressed", callable_mp(this, &EditorDockManager::_dock_move_right));
+
+ dock_hb->add_child(dock_tab_move_right);
+ dock_vb->add_child(dock_hb);
+
+ dock_select = memnew(Control);
+ dock_select->set_custom_minimum_size(Size2(128, 64) * EDSCALE);
+ dock_select->connect("gui_input", callable_mp(this, &EditorDockManager::_dock_select_input));
+ dock_select->connect("draw", callable_mp(this, &EditorDockManager::_dock_select_draw));
+ dock_select->connect("mouse_exited", callable_mp(this, &EditorDockManager::_dock_popup_exit));
+ dock_select->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ dock_vb->add_child(dock_select);
+
+ if (!SceneTree::get_singleton()->get_root()->is_embedding_subwindows() && !EDITOR_GET("interface/editor/single_window_mode") && EDITOR_GET("interface/multi_window/enable")) {
+ dock_float = memnew(Button);
+ dock_float->set_text(TTR("Make Floating"));
+ dock_float->set_focus_mode(Control::FOCUS_NONE);
+ dock_float->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
+ dock_float->connect("pressed", callable_mp(this, &EditorDockManager::_dock_make_selected_float));
+
+ dock_vb->add_child(dock_float);
+ }
+
+ dock_select_popup->reset_size();
+}
diff --git a/editor/editor_dock_manager.h b/editor/editor_dock_manager.h
new file mode 100644
index 0000000000..e685fe1380
--- /dev/null
+++ b/editor/editor_dock_manager.h
@@ -0,0 +1,135 @@
+/**************************************************************************/
+/* editor_dock_manager.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef EDITOR_DOCK_MANAGER_H
+#define EDITOR_DOCK_MANAGER_H
+
+#include "scene/gui/split_container.h"
+
+class Button;
+class ConfigFile;
+class Control;
+class PopupPanel;
+class TabContainer;
+class WindowWrapper;
+
+class DockSplitContainer : public SplitContainer {
+ GDCLASS(DockSplitContainer, SplitContainer);
+
+private:
+ bool is_updating = false;
+
+protected:
+ void _update_visibility();
+
+ virtual void add_child_notify(Node *p_child) override;
+ virtual void remove_child_notify(Node *p_child) override;
+};
+
+class EditorDockManager : public Object {
+ GDCLASS(EditorDockManager, Object);
+
+public:
+ enum DockSlot {
+ DOCK_SLOT_LEFT_UL,
+ DOCK_SLOT_LEFT_BL,
+ DOCK_SLOT_LEFT_UR,
+ DOCK_SLOT_LEFT_BR,
+ DOCK_SLOT_RIGHT_UL,
+ DOCK_SLOT_RIGHT_BL,
+ DOCK_SLOT_RIGHT_UR,
+ DOCK_SLOT_RIGHT_BR,
+ DOCK_SLOT_MAX
+ };
+
+private:
+ static EditorDockManager *singleton;
+
+ // To access splits easily by index.
+ Vector<DockSplitContainer *> vsplits;
+ Vector<DockSplitContainer *> hsplits;
+
+ Vector<WindowWrapper *> floating_docks;
+ TabContainer *dock_slot[DOCK_SLOT_MAX];
+ bool docks_visible = true;
+
+ PopupPanel *dock_select_popup = nullptr;
+ Button *dock_float = nullptr;
+ Button *dock_tab_move_left = nullptr;
+ Button *dock_tab_move_right = nullptr;
+ Control *dock_select = nullptr;
+ Rect2 dock_select_rect[DOCK_SLOT_MAX];
+ int dock_select_rect_over_idx = -1;
+ int dock_popup_selected_idx = -1;
+
+ void _dock_select_popup_theme_changed();
+ void _dock_popup_exit();
+ void _dock_pre_popup(int p_dock_slot);
+ void _dock_move_left();
+ void _dock_move_right();
+ void _dock_select_input(const Ref<InputEvent> &p_input);
+ void _dock_select_draw();
+ void _dock_split_dragged(int p_offset);
+
+ void _dock_tab_changed(int p_tab);
+ void _edit_current();
+
+ void _dock_floating_close_request(WindowWrapper *p_wrapper);
+ void _dock_make_selected_float();
+ void _dock_make_float(Control *p_control, int p_slot_index, bool p_show_window = true);
+ void _restore_floating_dock(const Dictionary &p_dock_dump, Control *p_wrapper, int p_slot_index);
+
+protected:
+ static void _bind_methods();
+
+public:
+ static EditorDockManager *get_singleton() { return singleton; }
+
+ void add_vsplit(DockSplitContainer *p_split);
+ void add_hsplit(DockSplitContainer *p_split);
+ void register_dock_slot(DockSlot p_dock_slot, TabContainer *p_tab_container);
+ int get_vsplit_count() const;
+
+ void save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section) const;
+ void load_docks_from_config(Ref<ConfigFile> p_layout, const String &p_section);
+ void update_dock_slots_visibility(bool p_keep_selected_tabs = false);
+
+ void close_all_floating_docks();
+
+ void set_docks_visible(bool p_show);
+ bool are_docks_visible() const;
+
+ void add_control_to_dock(DockSlot p_slot, Control *p_control, const String &p_name = "");
+ void remove_control_from_dock(Control *p_control);
+
+ EditorDockManager();
+};
+
+#endif // EDITOR_DOCK_MANAGER_H
diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp
index 5a44ae1aba..aa44ea380b 100644
--- a/editor/editor_feature_profile.cpp
+++ b/editor/editor_feature_profile.cpp
@@ -35,10 +35,10 @@
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
#include "editor/editor_property_name_processor.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/gui/editor_file_dialog.h"
+#include "editor/themes/editor_scale.h"
const char *EditorFeatureProfile::feature_names[FEATURE_MAX] = {
TTRC("3D Editor"),
@@ -503,7 +503,7 @@ void EditorFeatureProfileManager::_fill_classes_from(TreeItem *p_parent, const S
bool disabled_editor = edited->is_class_editor_disabled(p_class);
bool disabled_properties = edited->has_class_properties_disabled(p_class);
if (disabled) {
- class_item->set_custom_color(0, class_list->get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor)));
+ class_item->set_custom_color(0, class_list->get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor)));
} else if (disabled_editor && disabled_properties) {
text += " " + TTR("(Editor Disabled, Properties Disabled)");
} else if (disabled_properties) {
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 6e448d8866..f0f7f87711 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -35,14 +35,14 @@
#include "core/object/script_language.h"
#include "core/os/keyboard.h"
#include "core/version.h"
-#include "doc_data_compressed.gen.h"
+#include "editor/doc_data_compressed.gen.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
#include "editor/editor_property_name_processor.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/plugins/script_editor_plugin.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/line_edit.h"
#define CONTRIBUTE_URL vformat("%s/contributing/documentation/updating_the_class_reference.html", VERSION_DOCS_URL)
@@ -812,35 +812,25 @@ void EditorHelp::_update_doc() {
class_desc->add_newline();
}
- // Descendents
- if (cd.is_script_doc || ClassDB::class_exists(cd.name)) {
- bool found = false;
- bool prev = false;
-
+ // Descendants
+ if ((cd.is_script_doc || ClassDB::class_exists(cd.name)) && doc->inheriting.has(cd.name)) {
_push_normal_font();
- for (const KeyValue<String, DocData::ClassDoc> &E : doc->class_list) {
- if (E.value.inherits == cd.name) {
- if (!found) {
- class_desc->push_color(theme_cache.title_color);
- class_desc->add_text(TTR("Inherited by:") + " ");
- found = true;
- }
+ class_desc->push_color(theme_cache.title_color);
+ class_desc->add_text(TTR("Inherited by:") + " ");
- if (prev) {
- class_desc->add_text(" , ");
- }
- _add_type_icon(E.value.name, theme_cache.doc_font_size, "ArrowRight");
- class_desc->add_text(non_breaking_space); // Otherwise icon borrows hyperlink from _add_type().
- _add_type(E.value.name);
- prev = true;
+ for (RBSet<String, NaturalNoCaseComparator>::Element *itr = doc->inheriting[cd.name].front(); itr; itr = itr->next()) {
+ if (itr->prev()) {
+ class_desc->add_text(" , ");
}
+
+ _add_type_icon(itr->get(), theme_cache.doc_font_size, "ArrowRight");
+ class_desc->add_text(non_breaking_space); // Otherwise icon borrows hyperlink from _add_type().
+ _add_type(itr->get());
}
_pop_normal_font();
- if (found) {
- class_desc->pop();
- class_desc->add_newline();
- }
+ class_desc->pop();
+ class_desc->add_newline();
}
// Note if deprecated.
diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp
index 64bd209d4d..229eb79e11 100644
--- a/editor/editor_help_search.cpp
+++ b/editor/editor_help_search.cpp
@@ -33,9 +33,9 @@
#include "core/os/keyboard.h"
#include "editor/editor_feature_profile.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
+#include "editor/themes/editor_scale.h"
void EditorHelpSearch::_update_results() {
String term = search_box->get_text();
@@ -48,7 +48,7 @@ void EditorHelpSearch::_update_results() {
search_flags |= SEARCH_SHOW_HIERARCHY;
}
- search = Ref<Runner>(memnew(Runner(results_tree, results_tree, term, search_flags)));
+ search = Ref<Runner>(memnew(Runner(results_tree, results_tree, &tree_cache, term, search_flags)));
set_process(true);
}
@@ -96,6 +96,7 @@ void EditorHelpSearch::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_VISIBILITY_CHANGED: {
if (!is_visible()) {
+ tree_cache.clear();
callable_mp(results_tree, &Tree::clear).call_deferred(); // Wait for the Tree's mouse event propagation.
get_ok_button()->set_disabled(true);
EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "search_help", Rect2(get_position(), get_size()));
@@ -258,6 +259,13 @@ EditorHelpSearch::EditorHelpSearch() {
vbox->add_child(results_tree, true);
}
+void EditorHelpSearch::TreeCache::clear() {
+ for (const KeyValue<String, TreeItem *> &E : item_cache) {
+ memdelete(E.value);
+ }
+ item_cache.clear();
+}
+
bool EditorHelpSearch::Runner::_is_class_disabled_by_feature_profile(const StringName &p_class) {
Ref<EditorFeatureProfile> profile = EditorFeatureProfileManager::get_singleton()->get_current_profile();
if (profile.is_null()) {
@@ -317,7 +325,13 @@ bool EditorHelpSearch::Runner::_slice() {
}
bool EditorHelpSearch::Runner::_phase_match_classes_init() {
- iterator_doc = EditorHelp::get_doc_data()->class_list.begin();
+ iterator_doc = nullptr;
+ iterator_stack.clear();
+ if (search_flags & SEARCH_SHOW_HIERARCHY) {
+ iterator_stack.push_back(EditorHelp::get_doc_data()->inheriting[""].front());
+ } else {
+ iterator_doc = EditorHelp::get_doc_data()->class_list.begin();
+ }
matches.clear();
matched_item = nullptr;
match_highest_score = 0;
@@ -331,88 +345,141 @@ bool EditorHelpSearch::Runner::_phase_match_classes_init() {
}
bool EditorHelpSearch::Runner::_phase_match_classes() {
- if (!iterator_doc) {
+ if (!iterator_doc && iterator_stack.is_empty()) {
return true;
}
- DocData::ClassDoc &class_doc = iterator_doc->value;
- if (class_doc.name.is_empty()) {
- ++iterator_doc;
- return false;
+ DocData::ClassDoc *class_doc = nullptr;
+ if (iterator_doc) {
+ class_doc = &iterator_doc->value;
+ } else if (!iterator_stack.is_empty() && iterator_stack[iterator_stack.size() - 1]) {
+ class_doc = EditorHelp::get_doc_data()->class_list.getptr(iterator_stack[iterator_stack.size() - 1]->get());
+ }
+
+ if (class_doc && class_doc->name.is_empty()) {
+ class_doc = nullptr;
}
- if (!_is_class_disabled_by_feature_profile(class_doc.name)) {
+ if (class_doc && !_is_class_disabled_by_feature_profile(class_doc->name)) {
ClassMatch match;
- match.doc = &class_doc;
+ match.doc = class_doc;
// Match class name.
if (search_flags & SEARCH_CLASSES) {
// If the search term is empty, add any classes which are not script docs or which don't start with
// a double-quotation. This will ensure that only C++ classes and explicitly named classes will
// be added.
- match.name = (term.is_empty() && (!class_doc.is_script_doc || class_doc.name[0] != '\"')) || _match_string(term, class_doc.name);
+ match.name = (term.is_empty() && (!class_doc->is_script_doc || class_doc->name[0] != '\"')) || _match_string(term, class_doc->name);
}
// Match members only if the term is long enough, to avoid slow performance from building a large tree.
// Make an exception for annotations, since there are not that many of them.
if (term.length() > 1 || term == "@") {
if (search_flags & SEARCH_CONSTRUCTORS) {
- _match_method_name_and_push_back(class_doc.constructors, &match.constructors);
+ _match_method_name_and_push_back(class_doc->constructors, &match.constructors);
}
if (search_flags & SEARCH_METHODS) {
- _match_method_name_and_push_back(class_doc.methods, &match.methods);
+ _match_method_name_and_push_back(class_doc->methods, &match.methods);
}
if (search_flags & SEARCH_OPERATORS) {
- _match_method_name_and_push_back(class_doc.operators, &match.operators);
+ _match_method_name_and_push_back(class_doc->operators, &match.operators);
}
if (search_flags & SEARCH_SIGNALS) {
- for (int i = 0; i < class_doc.signals.size(); i++) {
- if (_all_terms_in_name(class_doc.signals[i].name)) {
- match.signals.push_back(const_cast<DocData::MethodDoc *>(&class_doc.signals[i]));
+ for (int i = 0; i < class_doc->signals.size(); i++) {
+ if (_all_terms_in_name(class_doc->signals[i].name)) {
+ match.signals.push_back(const_cast<DocData::MethodDoc *>(&class_doc->signals[i]));
}
}
}
if (search_flags & SEARCH_CONSTANTS) {
- for (int i = 0; i < class_doc.constants.size(); i++) {
- if (_all_terms_in_name(class_doc.constants[i].name)) {
- match.constants.push_back(const_cast<DocData::ConstantDoc *>(&class_doc.constants[i]));
+ for (int i = 0; i < class_doc->constants.size(); i++) {
+ if (_all_terms_in_name(class_doc->constants[i].name)) {
+ match.constants.push_back(const_cast<DocData::ConstantDoc *>(&class_doc->constants[i]));
}
}
}
if (search_flags & SEARCH_PROPERTIES) {
- for (int i = 0; i < class_doc.properties.size(); i++) {
- if (_all_terms_in_name(class_doc.properties[i].name)) {
- match.properties.push_back(const_cast<DocData::PropertyDoc *>(&class_doc.properties[i]));
+ for (int i = 0; i < class_doc->properties.size(); i++) {
+ if (_all_terms_in_name(class_doc->properties[i].name)) {
+ match.properties.push_back(const_cast<DocData::PropertyDoc *>(&class_doc->properties[i]));
}
}
}
if (search_flags & SEARCH_THEME_ITEMS) {
- for (int i = 0; i < class_doc.theme_properties.size(); i++) {
- if (_all_terms_in_name(class_doc.theme_properties[i].name)) {
- match.theme_properties.push_back(const_cast<DocData::ThemeItemDoc *>(&class_doc.theme_properties[i]));
+ for (int i = 0; i < class_doc->theme_properties.size(); i++) {
+ if (_all_terms_in_name(class_doc->theme_properties[i].name)) {
+ match.theme_properties.push_back(const_cast<DocData::ThemeItemDoc *>(&class_doc->theme_properties[i]));
}
}
}
if (search_flags & SEARCH_ANNOTATIONS) {
- for (int i = 0; i < class_doc.annotations.size(); i++) {
- if (_match_string(term, class_doc.annotations[i].name)) {
- match.annotations.push_back(const_cast<DocData::MethodDoc *>(&class_doc.annotations[i]));
+ for (int i = 0; i < class_doc->annotations.size(); i++) {
+ if (_match_string(term, class_doc->annotations[i].name)) {
+ match.annotations.push_back(const_cast<DocData::MethodDoc *>(&class_doc->annotations[i]));
}
}
}
}
- matches[class_doc.name] = match;
+ matches[class_doc->name] = match;
}
- ++iterator_doc;
- return !iterator_doc;
+ if (iterator_doc) {
+ ++iterator_doc;
+ return !iterator_doc;
+ }
+
+ if (!iterator_stack.is_empty()) {
+ if (iterator_stack[iterator_stack.size() - 1]) {
+ iterator_stack[iterator_stack.size() - 1] = iterator_stack[iterator_stack.size() - 1]->next();
+ }
+ if (!iterator_stack[iterator_stack.size() - 1]) {
+ iterator_stack.resize(iterator_stack.size() - 1);
+ }
+ }
+
+ if (class_doc && EditorHelp::get_doc_data()->inheriting.has(class_doc->name)) {
+ iterator_stack.push_back(EditorHelp::get_doc_data()->inheriting[class_doc->name].front());
+ }
+
+ return iterator_stack.is_empty();
+}
+
+void EditorHelpSearch::Runner::_populate_cache() {
+ root_item = results_tree->get_root();
+
+ if (root_item) {
+ LocalVector<TreeItem *> stack;
+
+ // Add children of root item to stack.
+ for (TreeItem *child = root_item->get_first_child(); child; child = child->get_next()) {
+ stack.push_back(child);
+ }
+
+ // Traverse stack and cache items.
+ while (!stack.is_empty()) {
+ TreeItem *cur_item = stack[stack.size() - 1];
+ stack.resize(stack.size() - 1);
+
+ // Add to the cache.
+ tree_cache->item_cache.insert(cur_item->get_metadata(0).operator String(), cur_item);
+
+ // Add any children to the stack.
+ for (TreeItem *child = cur_item->get_first_child(); child; child = child->get_next()) {
+ stack.push_back(child);
+ }
+
+ // Remove from parent.
+ cur_item->get_parent()->remove_child(cur_item);
+ }
+ } else {
+ root_item = results_tree->create_item();
+ }
}
bool EditorHelpSearch::Runner::_phase_class_items_init() {
iterator_match = matches.begin();
- results_tree->clear();
- root_item = results_tree->create_item();
+ _populate_cache();
class_items.clear();
return true;
@@ -590,27 +657,54 @@ TreeItem *EditorHelpSearch::Runner::_create_class_hierarchy(const ClassMatch &p_
return class_item;
}
+bool EditorHelpSearch::Runner::_find_or_create_item(TreeItem *p_parent, const String &p_item_meta, TreeItem *&r_item) {
+ // Attempt to find in cache.
+ if (tree_cache->item_cache.has(p_item_meta)) {
+ r_item = tree_cache->item_cache[p_item_meta];
+
+ // Remove from cache.
+ tree_cache->item_cache.erase(p_item_meta);
+
+ // Add to tree.
+ p_parent->add_child(r_item);
+
+ return false;
+ } else {
+ // Otherwise create item.
+ r_item = results_tree->create_item(p_parent);
+
+ return true;
+ }
+}
+
TreeItem *EditorHelpSearch::Runner::_create_class_item(TreeItem *p_parent, const DocData::ClassDoc *p_doc, bool p_gray) {
String tooltip = DTR(p_doc->brief_description.strip_edges());
- TreeItem *item = results_tree->create_item(p_parent);
- item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_doc->name));
- item->set_text(0, p_doc->name);
- item->set_text(1, TTR("Class"));
- item->set_tooltip_text(0, tooltip);
- item->set_tooltip_text(1, tooltip);
- item->set_metadata(0, "class_name:" + p_doc->name);
+ const String item_meta = "class_name:" + p_doc->name;
+
+ TreeItem *item = nullptr;
+ if (_find_or_create_item(p_parent, item_meta, item)) {
+ item->set_icon(0, EditorNode::get_singleton()->get_class_icon(p_doc->name));
+ item->set_text(0, p_doc->name);
+ item->set_text(1, TTR("Class"));
+ item->set_tooltip_text(0, tooltip);
+ item->set_tooltip_text(1, tooltip);
+ item->set_metadata(0, item_meta);
+ if (p_doc->is_deprecated) {
+ Ref<Texture2D> error_icon = ui_service->get_editor_theme_icon(SNAME("StatusError"));
+ item->add_button(0, error_icon, 0, false, TTR("This class is marked as deprecated."));
+ } else if (p_doc->is_experimental) {
+ Ref<Texture2D> warning_icon = ui_service->get_editor_theme_icon(SNAME("NodeWarning"));
+ item->add_button(0, warning_icon, 0, false, TTR("This class is marked as experimental."));
+ }
+ }
+
if (p_gray) {
item->set_custom_color(0, disabled_color);
item->set_custom_color(1, disabled_color);
- }
-
- if (p_doc->is_deprecated) {
- Ref<Texture2D> error_icon = ui_service->get_editor_theme_icon("StatusError");
- item->add_button(0, error_icon, 0, false, TTR("This class is marked as deprecated."));
- } else if (p_doc->is_experimental) {
- Ref<Texture2D> warning_icon = ui_service->get_editor_theme_icon("NodeWarning");
- item->add_button(0, warning_icon, 0, false, TTR("This class is marked as experimental."));
+ } else {
+ item->clear_custom_color(0);
+ item->clear_custom_color(1);
}
_match_item(item, p_doc->name);
@@ -651,30 +745,29 @@ TreeItem *EditorHelpSearch::Runner::_create_theme_property_item(TreeItem *p_pare
}
TreeItem *EditorHelpSearch::Runner::_create_member_item(TreeItem *p_parent, const String &p_class_name, const String &p_icon, const String &p_name, const String &p_text, const String &p_type, const String &p_metatype, const String &p_tooltip, bool is_deprecated, bool is_experimental) {
- Ref<Texture2D> icon;
- String text;
- if (search_flags & SEARCH_SHOW_HIERARCHY) {
- icon = ui_service->get_editor_theme_icon(p_icon);
- text = p_text;
- } else {
- icon = ui_service->get_editor_theme_icon(p_icon);
- text = p_class_name + "." + p_text;
+ const String item_meta = "class_" + p_metatype + ":" + p_class_name + ":" + p_name;
+
+ TreeItem *item = nullptr;
+ if (_find_or_create_item(p_parent, item_meta, item)) {
+ item->set_icon(0, ui_service->get_editor_theme_icon(p_icon));
+ item->set_text(1, TTRGET(p_type));
+ item->set_tooltip_text(0, p_tooltip);
+ item->set_tooltip_text(1, p_tooltip);
+ item->set_metadata(0, item_meta);
+
+ if (is_deprecated) {
+ Ref<Texture2D> error_icon = ui_service->get_editor_theme_icon(SNAME("StatusError"));
+ item->add_button(0, error_icon, 0, false, TTR("This member is marked as deprecated."));
+ } else if (is_experimental) {
+ Ref<Texture2D> warning_icon = ui_service->get_editor_theme_icon(SNAME("NodeWarning"));
+ item->add_button(0, warning_icon, 0, false, TTR("This member is marked as experimental."));
+ }
}
- TreeItem *item = results_tree->create_item(p_parent);
- item->set_icon(0, icon);
- item->set_text(0, text);
- item->set_text(1, TTRGET(p_type));
- item->set_tooltip_text(0, p_tooltip);
- item->set_tooltip_text(1, p_tooltip);
- item->set_metadata(0, "class_" + p_metatype + ":" + p_class_name + ":" + p_name);
-
- if (is_deprecated) {
- Ref<Texture2D> error_icon = ui_service->get_editor_theme_icon("StatusError");
- item->add_button(0, error_icon, 0, false, TTR("This member is marked as deprecated."));
- } else if (is_experimental) {
- Ref<Texture2D> warning_icon = ui_service->get_editor_theme_icon("NodeWarning");
- item->add_button(0, warning_icon, 0, false, TTR("This member is marked as experimental."));
+ if (search_flags & SEARCH_SHOW_HIERARCHY) {
+ item->set_text(0, p_text);
+ } else {
+ item->set_text(0, p_class_name + "." + p_text);
}
_match_item(item, p_name);
@@ -693,10 +786,11 @@ bool EditorHelpSearch::Runner::work(uint64_t slot) {
return true;
}
-EditorHelpSearch::Runner::Runner(Control *p_icon_service, Tree *p_results_tree, const String &p_term, int p_search_flags) :
+EditorHelpSearch::Runner::Runner(Control *p_icon_service, Tree *p_results_tree, TreeCache *p_tree_cache, const String &p_term, int p_search_flags) :
ui_service(p_icon_service),
results_tree(p_results_tree),
+ tree_cache(p_tree_cache),
term((p_search_flags & SEARCH_CASE_SENSITIVE) == 0 ? p_term.strip_edges().to_lower() : p_term.strip_edges()),
search_flags(p_search_flags),
- disabled_color(ui_service->get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor))) {
+ disabled_color(ui_service->get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor))) {
}
diff --git a/editor/editor_help_search.h b/editor/editor_help_search.h
index 30a783a628..e4980d6ff7 100644
--- a/editor/editor_help_search.h
+++ b/editor/editor_help_search.h
@@ -67,6 +67,16 @@ class EditorHelpSearch : public ConfirmationDialog {
class Runner;
Ref<Runner> search;
+ struct TreeCache {
+ HashMap<String, TreeItem *> item_cache;
+
+ void clear();
+
+ ~TreeCache() {
+ clear();
+ }
+ } tree_cache;
+
void _update_results();
void _search_box_gui_input(const Ref<InputEvent> &p_event);
@@ -117,6 +127,7 @@ class EditorHelpSearch::Runner : public RefCounted {
Control *ui_service = nullptr;
Tree *results_tree = nullptr;
+ TreeCache *tree_cache = nullptr;
String term;
Vector<String> terms;
int search_flags;
@@ -124,6 +135,7 @@ class EditorHelpSearch::Runner : public RefCounted {
Color disabled_color;
HashMap<String, DocData::ClassDoc>::Iterator iterator_doc;
+ LocalVector<RBSet<String, NaturalNoCaseComparator>::Element *> iterator_stack;
HashMap<String, ClassMatch> matches;
HashMap<String, ClassMatch>::Iterator iterator_match;
TreeItem *root_item = nullptr;
@@ -133,6 +145,9 @@ class EditorHelpSearch::Runner : public RefCounted {
bool _is_class_disabled_by_feature_profile(const StringName &p_class);
+ void _populate_cache();
+ bool _find_or_create_item(TreeItem *p_parent, const String &p_item_meta, TreeItem *&r_item);
+
bool _slice();
bool _phase_match_classes_init();
bool _phase_match_classes();
@@ -161,7 +176,7 @@ class EditorHelpSearch::Runner : public RefCounted {
public:
bool work(uint64_t slot = 100000);
- Runner(Control *p_icon_service, Tree *p_results_tree, const String &p_term, int p_search_flags);
+ Runner(Control *p_icon_service, Tree *p_results_tree, TreeCache *p_tree_cache, const String &p_term, int p_search_flags);
};
#endif // EDITOR_HELP_SEARCH_H
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 6809739dc1..a3530fc9ab 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -35,14 +35,14 @@
#include "editor/editor_feature_profile.h"
#include "editor/editor_node.h"
#include "editor/editor_property_name_processor.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_validation_panel.h"
#include "editor/inspector_dock.h"
+#include "editor/multi_node_edit.h"
#include "editor/plugins/script_editor_plugin.h"
-#include "multi_node_edit.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/spin_box.h"
#include "scene/gui/texture_rect.h"
#include "scene/property_utils.h"
@@ -1357,7 +1357,7 @@ void EditorInspectorSection::_notification(int p_what) {
Ref<Font> light_font = get_theme_font(SNAME("main"), EditorStringName(EditorFonts));
int light_font_size = get_theme_font_size(SNAME("main_size"), EditorStringName(EditorFonts));
- Color light_font_color = get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor));
+ Color light_font_color = get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor));
// Can we fit the long version of the revertable count text?
num_revertable_str = vformat(TTRN("(%d change)", "(%d changes)", revertable_properties.size()), revertable_properties.size());
diff --git a/editor/editor_interface.cpp b/editor/editor_interface.cpp
index b007f6d530..bad28ff43d 100644
--- a/editor/editor_interface.cpp
+++ b/editor/editor_interface.cpp
@@ -35,13 +35,13 @@
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
#include "editor/editor_resource_preview.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/filesystem_dock.h"
#include "editor/gui/editor_run_bar.h"
#include "editor/inspector_dock.h"
#include "editor/plugins/node_3d_editor_plugin.h"
+#include "editor/themes/editor_scale.h"
#include "main/main.h"
#include "scene/gui/box_container.h"
#include "scene/gui/control.h"
diff --git a/editor/editor_layouts_dialog.cpp b/editor/editor_layouts_dialog.cpp
index c6f518d4c1..e1b370f44a 100644
--- a/editor/editor_layouts_dialog.cpp
+++ b/editor/editor_layouts_dialog.cpp
@@ -33,8 +33,8 @@
#include "core/io/config_file.h"
#include "core/object/class_db.h"
#include "core/os/keyboard.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/item_list.h"
#include "scene/gui/line_edit.h"
diff --git a/editor/editor_locale_dialog.cpp b/editor/editor_locale_dialog.cpp
index 13b4a8c128..f1d82557fd 100644
--- a/editor/editor_locale_dialog.cpp
+++ b/editor/editor_locale_dialog.cpp
@@ -31,8 +31,8 @@
#include "editor_locale_dialog.h"
#include "core/config/project_settings.h"
-#include "editor/editor_scale.h"
#include "editor/editor_undo_redo_manager.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/check_button.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/option_button.h"
diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp
index c58a0a7572..c0c26bbfeb 100644
--- a/editor/editor_log.cpp
+++ b/editor/editor_log.cpp
@@ -35,9 +35,9 @@
#include "core/version.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/center_container.h"
#include "scene/gui/separator.h"
#include "scene/resources/font.h"
@@ -192,6 +192,10 @@ void EditorLog::_load_state() {
is_loading_state = false;
}
+void EditorLog::_meta_clicked(const String &p_meta) {
+ OS::get_singleton()->shell_open(p_meta);
+}
+
void EditorLog::_clear_request() {
log->clear();
messages.clear();
@@ -407,6 +411,7 @@ EditorLog::EditorLog() {
log->set_v_size_flags(SIZE_EXPAND_FILL);
log->set_h_size_flags(SIZE_EXPAND_FILL);
log->set_deselect_on_focus_loss_enabled(false);
+ log->connect("meta_clicked", callable_mp(this, &EditorLog::_meta_clicked));
vb_left->add_child(log);
// Search box
diff --git a/editor/editor_log.h b/editor/editor_log.h
index 07f3a25c3e..03a0a071c6 100644
--- a/editor/editor_log.h
+++ b/editor/editor_log.h
@@ -157,6 +157,7 @@ private:
Thread::ID current;
//void _dragged(const Point2& p_ofs);
+ void _meta_clicked(const String &p_meta);
void _clear_request();
void _copy_request();
static void _undo_redo_cbk(void *p_self, const String &p_name);
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index fd1d598f90..521477d470 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -79,6 +79,7 @@
#include "editor/editor_build_profile.h"
#include "editor/editor_command_palette.h"
#include "editor/editor_data.h"
+#include "editor/editor_dock_manager.h"
#include "editor/editor_feature_profile.h"
#include "editor/editor_folding.h"
#include "editor/editor_help.h"
@@ -95,10 +96,8 @@
#include "editor/editor_resource_preview.h"
#include "editor/editor_run.h"
#include "editor/editor_run_native.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_settings_dialog.h"
-#include "editor/editor_themes.h"
#include "editor/editor_translation_parser.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/export/editor_export.h"
@@ -157,6 +156,8 @@
#include "editor/register_exporters.h"
#include "editor/scene_tree_dock.h"
#include "editor/surface_upgrade_tool.h"
+#include "editor/themes/editor_scale.h"
+#include "editor/themes/editor_theme_manager.h"
#include "editor/window_wrapper.h"
#include <stdio.h>
@@ -468,7 +469,7 @@ void EditorNode::_select_default_main_screen_plugin() {
void EditorNode::_update_theme(bool p_skip_creation) {
if (!p_skip_creation) {
- theme = create_custom_theme(theme);
+ theme = EditorThemeManager::generate_theme(theme);
DisplayServer::set_early_window_clear_color_override(true, theme->get_color(SNAME("background"), EditorStringName(Editor)));
}
@@ -507,14 +508,6 @@ void EditorNode::_update_theme(bool p_skip_creation) {
distraction_free->set_icon(theme->get_icon(SNAME("DistractionFree"), EditorStringName(EditorIcons)));
bottom_panel_raise->set_icon(theme->get_icon(SNAME("ExpandBottomDock"), EditorStringName(EditorIcons)));
- if (gui_base->is_layout_rtl()) {
- dock_tab_move_left->set_icon(theme->get_icon(SNAME("Forward"), EditorStringName(EditorIcons)));
- dock_tab_move_right->set_icon(theme->get_icon(SNAME("Back"), EditorStringName(EditorIcons)));
- } else {
- dock_tab_move_left->set_icon(theme->get_icon(SNAME("Back"), EditorStringName(EditorIcons)));
- dock_tab_move_right->set_icon(theme->get_icon(SNAME("Forward"), EditorStringName(EditorIcons)));
- }
-
help_menu->set_item_icon(help_menu->get_item_index(HELP_SEARCH), theme->get_icon(SNAME("HelpSearch"), EditorStringName(EditorIcons)));
help_menu->set_item_icon(help_menu->get_item_index(HELP_DOCS), theme->get_icon(SNAME("ExternalLink"), EditorStringName(EditorIcons)));
help_menu->set_item_icon(help_menu->get_item_index(HELP_QA), theme->get_icon(SNAME("ExternalLink"), EditorStringName(EditorIcons)));
@@ -771,19 +764,7 @@ void EditorNode::_notification(int p_what) {
EditorFileDialog::set_default_show_hidden_files(EDITOR_GET("filesystem/file_dialog/show_hidden_files"));
EditorFileDialog::set_default_display_mode((EditorFileDialog::DisplayMode)EDITOR_GET("filesystem/file_dialog/display_mode").operator int());
- bool theme_changed =
- EditorSettings::get_singleton()->check_changed_settings_in_group("interface/theme") ||
- EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/font") ||
- EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/main_font") ||
- EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/code_font") ||
- EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/theme") ||
- EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/help/help") ||
- EditorSettings::get_singleton()->check_changed_settings_in_group("filesystem/file_dialog/thumbnail_size") ||
- EditorSettings::get_singleton()->check_changed_settings_in_group("run/output/font_size") ||
- EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/increase_scrollbar_touch_area") ||
- EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/scale_gizmo_handles");
-
- if (theme_changed) {
+ if (EditorThemeManager::is_generated_theme_outdated()) {
_update_theme();
}
@@ -2095,7 +2076,7 @@ void EditorNode::_dialog_action(String p_file) {
return;
}
- _save_docks_to_config(config, p_file);
+ editor_dock_manager->save_docks_to_config(config, p_file);
config->save(EditorSettings::get_singleton()->get_editor_layouts_config());
@@ -4738,240 +4719,6 @@ void EditorNode::_copy_warning(const String &p_str) {
DisplayServer::get_singleton()->clipboard_set(warning->get_text());
}
-void EditorNode::_dock_floating_close_request(WindowWrapper *p_wrapper) {
- int dock_slot_num = p_wrapper->get_meta("dock_slot");
- int dock_slot_index = p_wrapper->get_meta("dock_index");
-
- // Give back the dock to the original owner.
- Control *dock = p_wrapper->release_wrapped_control();
-
- int target_index = MIN(dock_slot_index, dock_slot[dock_slot_num]->get_tab_count());
- dock_slot[dock_slot_num]->add_child(dock);
- dock_slot[dock_slot_num]->move_child(dock, target_index);
- dock_slot[dock_slot_num]->set_current_tab(target_index);
-
- floating_docks.erase(p_wrapper);
- p_wrapper->queue_free();
-
- _update_dock_slots_visibility(true);
-
- _edit_current();
-}
-
-void EditorNode::_dock_make_selected_float() {
- Control *dock = dock_slot[dock_popup_selected_idx]->get_current_tab_control();
- _dock_make_float(dock, dock_popup_selected_idx);
-
- dock_select_popup->hide();
- _edit_current();
-}
-
-void EditorNode::_dock_make_float(Control *p_dock, int p_slot_index, bool p_show_window) {
- ERR_FAIL_NULL(p_dock);
-
- Size2 borders = Size2(4, 4) * EDSCALE;
- // Remember size and position before removing it from the main window.
- Size2 dock_size = p_dock->get_size() + borders * 2;
- Point2 dock_screen_pos = p_dock->get_screen_position();
-
- int dock_index = p_dock->get_index() - 1;
- dock_slot[p_slot_index]->remove_child(p_dock);
-
- WindowWrapper *wrapper = memnew(WindowWrapper);
- wrapper->set_window_title(vformat(TTR("%s - Godot Engine"), p_dock->get_name()));
- wrapper->set_margins_enabled(true);
-
- gui_base->add_child(wrapper);
-
- wrapper->set_wrapped_control(p_dock);
- wrapper->set_meta("dock_slot", p_slot_index);
- wrapper->set_meta("dock_index", dock_index);
- wrapper->set_meta("dock_name", p_dock->get_name().operator String());
- p_dock->show();
-
- wrapper->connect("window_close_requested", callable_mp(this, &EditorNode::_dock_floating_close_request).bind(wrapper));
-
- dock_select_popup->hide();
-
- if (p_show_window) {
- wrapper->restore_window(Rect2i(dock_screen_pos, dock_size), get_window()->get_current_screen());
- }
-
- _update_dock_slots_visibility(true);
-
- floating_docks.push_back(wrapper);
-
- _edit_current();
-}
-
-void EditorNode::_dock_select_input(const Ref<InputEvent> &p_input) {
- Ref<InputEventMouse> me = p_input;
-
- if (me.is_valid()) {
- Vector2 point = me->get_position();
-
- int nrect = -1;
- for (int i = 0; i < DOCK_SLOT_MAX; i++) {
- if (dock_select_rect[i].has_point(point)) {
- nrect = i;
- break;
- }
- }
-
- if (nrect != dock_select_rect_over_idx) {
- dock_select->queue_redraw();
- dock_select_rect_over_idx = nrect;
- }
-
- if (nrect == -1) {
- return;
- }
-
- Ref<InputEventMouseButton> mb = me;
-
- if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed() && dock_popup_selected_idx != nrect) {
- dock_slot[nrect]->move_tab_from_tab_container(dock_slot[dock_popup_selected_idx], dock_slot[dock_popup_selected_idx]->get_current_tab(), dock_slot[nrect]->get_tab_count());
-
- if (dock_slot[dock_popup_selected_idx]->get_tab_count() == 0) {
- dock_slot[dock_popup_selected_idx]->hide();
- } else {
- dock_slot[dock_popup_selected_idx]->set_current_tab(0);
- }
-
- dock_popup_selected_idx = nrect;
- dock_slot[nrect]->show();
- dock_select->queue_redraw();
-
- _update_dock_slots_visibility(true);
-
- _edit_current();
- _save_editor_layout();
- }
- }
-}
-
-void EditorNode::_dock_popup_exit() {
- dock_select_rect_over_idx = -1;
- dock_select->queue_redraw();
-}
-
-void EditorNode::_dock_pre_popup(int p_which) {
- dock_popup_selected_idx = p_which;
-}
-
-void EditorNode::_dock_move_left() {
- if (dock_popup_selected_idx < 0 || dock_popup_selected_idx >= DOCK_SLOT_MAX) {
- return;
- }
- Control *current_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab());
- Control *prev_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab() - 1);
- if (!current_ctl || !prev_ctl) {
- return;
- }
- dock_slot[dock_popup_selected_idx]->move_child(current_ctl, prev_ctl->get_index(false));
- dock_select->queue_redraw();
- _edit_current();
- _save_editor_layout();
-}
-
-void EditorNode::_dock_move_right() {
- Control *current_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab());
- Control *next_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab() + 1);
- if (!current_ctl || !next_ctl) {
- return;
- }
- dock_slot[dock_popup_selected_idx]->move_child(next_ctl, current_ctl->get_index(false));
- dock_select->queue_redraw();
- _edit_current();
- _save_editor_layout();
-}
-
-void EditorNode::_dock_select_draw() {
- Size2 s = dock_select->get_size();
- s.y /= 2.0;
- s.x /= 6.0;
-
- Color used = Color(0.6, 0.6, 0.6, 0.8);
- Color used_selected = Color(0.8, 0.8, 0.8, 0.8);
- Color tab_selected = theme->get_color(SNAME("mono_color"), EditorStringName(Editor));
- Color unused = used;
- unused.a = 0.4;
- Color unusable = unused;
- unusable.a = 0.1;
-
- Rect2 unr(s.x * 2, 0, s.x * 2, s.y * 2);
- unr.position += Vector2(2, 5);
- unr.size -= Vector2(4, 7);
-
- dock_select->draw_rect(unr, unusable);
-
- dock_tab_move_left->set_disabled(true);
- dock_tab_move_right->set_disabled(true);
-
- if (dock_popup_selected_idx != -1 && dock_slot[dock_popup_selected_idx]->get_tab_count()) {
- dock_tab_move_left->set_disabled(dock_slot[dock_popup_selected_idx]->get_current_tab() == 0);
- dock_tab_move_right->set_disabled(dock_slot[dock_popup_selected_idx]->get_current_tab() >= dock_slot[dock_popup_selected_idx]->get_tab_count() - 1);
- }
-
- for (int i = 0; i < DOCK_SLOT_MAX; i++) {
- Vector2 ofs;
-
- switch (i) {
- case DOCK_SLOT_LEFT_UL: {
- } break;
- case DOCK_SLOT_LEFT_BL: {
- ofs.y += s.y;
- } break;
- case DOCK_SLOT_LEFT_UR: {
- ofs.x += s.x;
- } break;
- case DOCK_SLOT_LEFT_BR: {
- ofs += s;
- } break;
- case DOCK_SLOT_RIGHT_UL: {
- ofs.x += s.x * 4;
- } break;
- case DOCK_SLOT_RIGHT_BL: {
- ofs.x += s.x * 4;
- ofs.y += s.y;
-
- } break;
- case DOCK_SLOT_RIGHT_UR: {
- ofs.x += s.x * 4;
- ofs.x += s.x;
-
- } break;
- case DOCK_SLOT_RIGHT_BR: {
- ofs.x += s.x * 4;
- ofs += s;
-
- } break;
- }
-
- Rect2 r(ofs, s);
- dock_select_rect[i] = r;
- r.position += Vector2(2, 5);
- r.size -= Vector2(4, 7);
-
- if (i == dock_select_rect_over_idx) {
- dock_select->draw_rect(r, used_selected);
- } else if (dock_slot[i]->get_tab_count() == 0) {
- dock_select->draw_rect(r, unused);
- } else {
- dock_select->draw_rect(r, used);
- }
-
- for (int j = 0; j < MIN(3, dock_slot[i]->get_tab_count()); j++) {
- int xofs = (r.size.width / 3) * j;
- Color c = used;
- if (i == dock_popup_selected_idx && (dock_slot[i]->get_current_tab() > 3 || dock_slot[i]->get_current_tab() == j)) {
- c = tab_selected;
- }
- dock_select->draw_rect(Rect2(2 + ofs.x + xofs, ofs.y, r.size.width / 3 - 1, 3), c);
- }
- }
-}
-
void EditorNode::_save_editor_layout() {
if (waiting_for_first_scan) {
return; // Scanning, do not touch docks.
@@ -4981,7 +4728,7 @@ void EditorNode::_save_editor_layout() {
// Load and amend existing config if it exists.
config->load(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg"));
- _save_docks_to_config(config, "docks");
+ editor_dock_manager->save_docks_to_config(config, "docks");
_save_open_scenes_to_config(config);
_save_central_editor_layout_to_config(config);
editor_data.get_plugin_window_layout(config);
@@ -4989,85 +4736,6 @@ void EditorNode::_save_editor_layout() {
config->save(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg"));
}
-void EditorNode::_save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section) {
- for (int i = 0; i < DOCK_SLOT_MAX; i++) {
- String names;
- for (int j = 0; j < dock_slot[i]->get_tab_count(); j++) {
- String name = dock_slot[i]->get_tab_control(j)->get_name();
- if (!names.is_empty()) {
- names += ",";
- }
- names += name;
- }
-
- String config_key = "dock_" + itos(i + 1);
-
- if (p_layout->has_section_key(p_section, config_key)) {
- p_layout->erase_section_key(p_section, config_key);
- }
-
- if (!names.is_empty()) {
- p_layout->set_value(p_section, config_key, names);
- }
-
- int selected_tab_idx = dock_slot[i]->get_current_tab();
- if (selected_tab_idx >= 0) {
- p_layout->set_value(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx", selected_tab_idx);
- }
- }
-
- Dictionary floating_docks_dump;
-
- for (WindowWrapper *wrapper : floating_docks) {
- Control *dock = wrapper->get_wrapped_control();
-
- Dictionary dock_dump;
- dock_dump["window_rect"] = wrapper->get_window_rect();
-
- int screen = wrapper->get_window_screen();
- dock_dump["window_screen"] = wrapper->get_window_screen();
- dock_dump["window_screen_rect"] = DisplayServer::get_singleton()->screen_get_usable_rect(screen);
-
- String name = dock->get_name();
- floating_docks_dump[name] = dock_dump;
-
- int dock_slot_id = wrapper->get_meta("dock_slot");
- String config_key = "dock_" + itos(dock_slot_id + 1);
-
- String names = p_layout->get_value(p_section, config_key, "");
- if (names.is_empty()) {
- names = name;
- } else {
- names += "," + name;
- }
- p_layout->set_value(p_section, config_key, names);
- }
-
- p_layout->set_value(p_section, "dock_floating", floating_docks_dump);
-
- for (int i = 0; i < vsplits.size(); i++) {
- if (vsplits[i]->is_visible_in_tree()) {
- p_layout->set_value(p_section, "dock_split_" + itos(i + 1), vsplits[i]->get_split_offset());
- }
- }
-
- for (int i = 0; i < hsplits.size(); i++) {
- p_layout->set_value(p_section, "dock_hsplit_" + itos(i + 1), hsplits[i]->get_split_offset());
- }
-
- // Save FileSystemDock state.
-
- p_layout->set_value(p_section, "dock_filesystem_h_split_offset", FileSystemDock::get_singleton()->get_h_split_offset());
- p_layout->set_value(p_section, "dock_filesystem_v_split_offset", FileSystemDock::get_singleton()->get_v_split_offset());
- p_layout->set_value(p_section, "dock_filesystem_display_mode", FileSystemDock::get_singleton()->get_display_mode());
- p_layout->set_value(p_section, "dock_filesystem_file_sort", FileSystemDock::get_singleton()->get_file_sort());
- p_layout->set_value(p_section, "dock_filesystem_file_list_display_mode", FileSystemDock::get_singleton()->get_file_list_display_mode());
- PackedStringArray selected_files = FileSystemDock::get_singleton()->get_selected_paths();
- p_layout->set_value(p_section, "dock_filesystem_selected_paths", selected_files);
- Vector<String> uncollapsed_paths = FileSystemDock::get_singleton()->get_uncollapsed_paths();
- p_layout->set_value(p_section, "dock_filesystem_uncollapsed_paths", uncollapsed_paths);
-}
-
void EditorNode::_save_open_scenes_to_config(Ref<ConfigFile> p_layout) {
PackedStringArray scenes;
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
@@ -5087,10 +4755,6 @@ void EditorNode::save_editor_layout_delayed() {
editor_layout_save_delay_timer->start();
}
-void EditorNode::_dock_split_dragged(int ofs) {
- editor_layout_save_delay_timer->start();
-}
-
void EditorNode::_load_editor_layout() {
Ref<ConfigFile> config;
config.instantiate();
@@ -5113,227 +4777,13 @@ void EditorNode::_load_editor_layout() {
return;
}
- _load_docks_from_config(config, "docks");
+ editor_dock_manager->load_docks_from_config(config, "docks");
_load_open_scenes_from_config(config);
_load_central_editor_layout_from_config(config);
editor_data.set_plugin_window_layout(config);
}
-void EditorNode::_update_dock_slots_visibility(bool p_keep_selected_tabs) {
- if (!docks_visible) {
- for (int i = 0; i < DOCK_SLOT_MAX; i++) {
- dock_slot[i]->hide();
- }
-
- for (int i = 0; i < vsplits.size(); i++) {
- vsplits[i]->hide();
- }
-
- right_hsplit->hide();
- } else {
- for (int i = 0; i < DOCK_SLOT_MAX; i++) {
- int first_tab_visible = -1;
- for (int j = 0; j < dock_slot[i]->get_tab_count(); j++) {
- if (!dock_slot[i]->is_tab_hidden(j)) {
- first_tab_visible = j;
- break;
- }
- }
- if (first_tab_visible >= 0) {
- dock_slot[i]->show();
- if (p_keep_selected_tabs) {
- int current_tab = dock_slot[i]->get_current_tab();
- if (dock_slot[i]->is_tab_hidden(current_tab)) {
- dock_slot[i]->set_block_signals(true);
- dock_slot[i]->select_next_available();
- dock_slot[i]->set_block_signals(false);
- }
- } else {
- dock_slot[i]->set_block_signals(true);
- dock_slot[i]->set_current_tab(first_tab_visible);
- dock_slot[i]->set_block_signals(false);
- }
- } else {
- dock_slot[i]->hide();
- }
- }
-
- for (int i = 0; i < vsplits.size(); i++) {
- bool in_use = dock_slot[i * 2 + 0]->is_visible() || dock_slot[i * 2 + 1]->is_visible();
- vsplits[i]->set_visible(in_use);
- }
-
- right_hsplit->set_visible(right_l_vsplit->is_visible() || right_r_vsplit->is_visible());
- }
-}
-
-void EditorNode::_dock_tab_changed(int p_tab) {
- // Update visibility but don't set current tab.
- _update_dock_slots_visibility(true);
-}
-
-void EditorNode::_restore_floating_dock(const Dictionary &p_dock_dump, Control *p_dock, int p_slot_index) {
- WindowWrapper *wrapper = Object::cast_to<WindowWrapper>(p_dock);
- if (!wrapper) {
- _dock_make_float(p_dock, p_slot_index, false);
- wrapper = floating_docks[floating_docks.size() - 1];
- }
-
- wrapper->restore_window_from_saved_position(
- p_dock_dump.get("window_rect", Rect2i()),
- p_dock_dump.get("window_screen", -1),
- p_dock_dump.get("window_screen_rect", Rect2i()));
-}
-
-void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String &p_section) {
- Dictionary floating_docks_dump = p_layout->get_value(p_section, "dock_floating", Dictionary());
-
- bool restore_window_on_load = EDITOR_GET("interface/multi_window/restore_windows_on_load");
-
- for (int i = 0; i < DOCK_SLOT_MAX; i++) {
- if (!p_layout->has_section_key(p_section, "dock_" + itos(i + 1))) {
- continue;
- }
-
- Vector<String> names = String(p_layout->get_value(p_section, "dock_" + itos(i + 1))).split(",");
-
- for (int j = names.size() - 1; j >= 0; j--) {
- const String &name = names[j];
-
- // FIXME: Find it, in a horribly inefficient way.
- int atidx = -1;
- Control *node = nullptr;
- for (int k = 0; k < DOCK_SLOT_MAX; k++) {
- if (!dock_slot[k]->has_node(name)) {
- continue;
- }
- node = Object::cast_to<Control>(dock_slot[k]->get_node(name));
- if (!node) {
- continue;
- }
- atidx = k;
- break;
- }
-
- if (atidx == -1) {
- // Try floating docks.
- for (WindowWrapper *wrapper : floating_docks) {
- if (wrapper->get_meta("dock_name") == name) {
- if (restore_window_on_load && floating_docks_dump.has(name)) {
- _restore_floating_dock(floating_docks_dump[name], wrapper, i);
- } else {
- atidx = wrapper->get_meta("dock_slot");
- node = wrapper->get_wrapped_control();
- wrapper->set_window_enabled(false);
- }
- break;
- }
- }
- }
- if (!node) {
- // Well, it's not anywhere.
- continue;
- }
-
- if (atidx == i) {
- dock_slot[i]->move_child(node, 0);
- } else if (atidx != -1) {
- dock_slot[i]->move_tab_from_tab_container(dock_slot[atidx], dock_slot[atidx]->get_tab_idx_from_control(node), 0);
- }
-
- WindowWrapper *wrapper = Object::cast_to<WindowWrapper>(node);
- if (restore_window_on_load && floating_docks_dump.has(name)) {
- if (!dock_slot[i]->is_tab_hidden(dock_slot[i]->get_tab_idx_from_control(node))) {
- _restore_floating_dock(floating_docks_dump[name], node, i);
- }
- } else if (wrapper) {
- wrapper->set_window_enabled(false);
- }
- }
-
- if (!p_layout->has_section_key(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx")) {
- continue;
- }
-
- int selected_tab_idx = p_layout->get_value(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx");
- if (selected_tab_idx >= 0 && selected_tab_idx < dock_slot[i]->get_tab_count()) {
- callable_mp(dock_slot[i], &TabContainer::set_current_tab).call_deferred(selected_tab_idx);
- }
- }
-
- for (int i = 0; i < vsplits.size(); i++) {
- if (!p_layout->has_section_key(p_section, "dock_split_" + itos(i + 1))) {
- continue;
- }
-
- int ofs = p_layout->get_value(p_section, "dock_split_" + itos(i + 1));
- vsplits[i]->set_split_offset(ofs);
- }
-
- for (int i = 0; i < hsplits.size(); i++) {
- if (!p_layout->has_section_key(p_section, "dock_hsplit_" + itos(i + 1))) {
- continue;
- }
- int ofs = p_layout->get_value(p_section, "dock_hsplit_" + itos(i + 1));
- hsplits[i]->set_split_offset(ofs);
- }
-
- _update_dock_slots_visibility(false);
-
- // FileSystemDock.
-
- if (p_layout->has_section_key(p_section, "dock_filesystem_h_split_offset")) {
- int fs_h_split_ofs = p_layout->get_value(p_section, "dock_filesystem_h_split_offset");
- FileSystemDock::get_singleton()->set_h_split_offset(fs_h_split_ofs);
- }
-
- if (p_layout->has_section_key(p_section, "dock_filesystem_v_split_offset")) {
- int fs_v_split_ofs = p_layout->get_value(p_section, "dock_filesystem_v_split_offset");
- FileSystemDock::get_singleton()->set_v_split_offset(fs_v_split_ofs);
- }
-
- if (p_layout->has_section_key(p_section, "dock_filesystem_display_mode")) {
- FileSystemDock::DisplayMode dock_filesystem_display_mode = FileSystemDock::DisplayMode(int(p_layout->get_value(p_section, "dock_filesystem_display_mode")));
- FileSystemDock::get_singleton()->set_display_mode(dock_filesystem_display_mode);
- }
-
- if (p_layout->has_section_key(p_section, "dock_filesystem_file_sort")) {
- FileSystemDock::FileSortOption dock_filesystem_file_sort = FileSystemDock::FileSortOption(int(p_layout->get_value(p_section, "dock_filesystem_file_sort")));
- FileSystemDock::get_singleton()->set_file_sort(dock_filesystem_file_sort);
- }
-
- if (p_layout->has_section_key(p_section, "dock_filesystem_file_list_display_mode")) {
- FileSystemDock::FileListDisplayMode dock_filesystem_file_list_display_mode = FileSystemDock::FileListDisplayMode(int(p_layout->get_value(p_section, "dock_filesystem_file_list_display_mode")));
- FileSystemDock::get_singleton()->set_file_list_display_mode(dock_filesystem_file_list_display_mode);
- }
-
- if (p_layout->has_section_key(p_section, "dock_filesystem_selected_paths")) {
- PackedStringArray dock_filesystem_selected_paths = p_layout->get_value(p_section, "dock_filesystem_selected_paths");
- for (int i = 0; i < dock_filesystem_selected_paths.size(); i++) {
- FileSystemDock::get_singleton()->select_file(dock_filesystem_selected_paths[i]);
- }
- }
-
- // Restore collapsed state of FileSystemDock.
- PackedStringArray uncollapsed_tis;
- if (p_layout->has_section_key(p_section, "dock_filesystem_uncollapsed_paths")) {
- uncollapsed_tis = p_layout->get_value(p_section, "dock_filesystem_uncollapsed_paths");
- } else {
- uncollapsed_tis = { "res://" };
- }
-
- if (!uncollapsed_tis.is_empty()) {
- for (int i = 0; i < uncollapsed_tis.size(); i++) {
- TreeItem *uncollapsed_ti = FileSystemDock::get_singleton()->get_tree_control()->get_item_with_metadata(uncollapsed_tis[i], 0);
- if (uncollapsed_ti) {
- uncollapsed_ti->set_collapsed(false);
- }
- }
- FileSystemDock::get_singleton()->get_tree_control()->queue_redraw();
- }
-}
-
void EditorNode::_save_central_editor_layout_to_config(Ref<ConfigFile> p_config_file) {
// Bottom panel.
@@ -5582,7 +5032,7 @@ void EditorNode::_layout_menu_option(int p_id) {
layout_dialog->popup_centered();
} break;
case SETTINGS_LAYOUT_DEFAULT: {
- _load_docks_from_config(default_layout, "docks");
+ editor_dock_manager->load_docks_from_config(default_layout, "docks");
_save_editor_layout();
} break;
default: {
@@ -5593,7 +5043,7 @@ void EditorNode::_layout_menu_option(int p_id) {
return; // No config.
}
- _load_docks_from_config(config, editor_layouts->get_item_text(p_id));
+ editor_dock_manager->load_docks_from_config(config, editor_layouts->get_item_text(p_id));
_save_editor_layout();
}
}
@@ -5803,15 +5253,6 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) {
}
}
-void EditorNode::set_docks_visible(bool p_show) {
- docks_visible = p_show;
- _update_dock_slots_visibility(true);
-}
-
-bool EditorNode::get_docks_visible() const {
- return docks_visible;
-}
-
void EditorNode::_toggle_distraction_free_mode() {
if (EDITOR_GET("interface/editor/separate_distraction_mode")) {
int screen = -1;
@@ -5838,11 +5279,11 @@ void EditorNode::set_distraction_free_mode(bool p_enter) {
distraction_free->set_pressed(p_enter);
if (p_enter) {
- if (docks_visible) {
- set_docks_visible(false);
+ if (editor_dock_manager->are_docks_visible()) {
+ editor_dock_manager->set_docks_visible(false);
}
} else {
- set_docks_visible(true);
+ editor_dock_manager->set_docks_visible(true);
}
}
@@ -5850,35 +5291,6 @@ bool EditorNode::is_distraction_free_mode_enabled() const {
return distraction_free->is_pressed();
}
-void EditorNode::add_control_to_dock(DockSlot p_slot, Control *p_control) {
- ERR_FAIL_INDEX(p_slot, DOCK_SLOT_MAX);
- dock_slot[p_slot]->add_child(p_control);
- _update_dock_slots_visibility();
-}
-
-void EditorNode::remove_control_from_dock(Control *p_control) {
- // If the dock is floating, close it first.
- for (WindowWrapper *wrapper : floating_docks) {
- if (p_control == wrapper->get_wrapped_control()) {
- wrapper->set_window_enabled(false);
- break;
- }
- }
-
- Control *dock = nullptr;
- for (int i = 0; i < DOCK_SLOT_MAX; i++) {
- if (p_control->get_parent() == dock_slot[i]) {
- dock = dock_slot[i];
- break;
- }
- }
-
- ERR_FAIL_NULL_MSG(dock, "Control was not in dock.");
-
- dock->remove_child(p_control);
- _update_dock_slots_visibility();
-}
-
Variant EditorNode::drag_resource(const Ref<Resource> &p_res, Control *p_from) {
Control *drag_control = memnew(Control);
TextureRect *drag_preview = memnew(TextureRect);
@@ -6566,6 +5978,7 @@ void EditorNode::_bottom_panel_raise_toggled(bool p_pressed) {
void EditorNode::_update_renderer_color() {
String rendering_method = renderer->get_selected_metadata();
+ // TODO: Use theme colors instead of hardcoded values.
if (rendering_method == "forward_plus") {
renderer->add_theme_color_override("font_color", Color::hex(0x5d8c3fff));
}
@@ -6632,9 +6045,7 @@ void EditorNode::_resource_loaded(Ref<Resource> p_resource, const String &p_path
void EditorNode::_feature_profile_changed() {
Ref<EditorFeatureProfile> profile = feature_profile_manager->get_current_profile();
// FIXME: Close all floating docks to avoid crash.
- for (WindowWrapper *wrapper : floating_docks) {
- wrapper->set_window_enabled(false);
- }
+ editor_dock_manager->close_all_floating_docks();
TabContainer *import_tabs = cast_to<TabContainer>(ImportDock::get_singleton()->get_parent());
TabContainer *node_tabs = cast_to<TabContainer>(NodeDock::get_singleton()->get_parent());
TabContainer *fs_tabs = cast_to<TabContainer>(FileSystemDock::get_singleton()->get_parent());
@@ -6669,7 +6080,7 @@ void EditorNode::_feature_profile_changed() {
}
}
- _update_dock_slots_visibility();
+ editor_dock_manager->update_dock_slots_visibility();
}
void EditorNode::_bind_methods() {
@@ -7016,9 +6427,8 @@ EditorNode::EditorNode() {
add_child(editor_export);
// Exporters might need the theme.
- EditorColorMap::create();
- EditorTheme::initialize();
- theme = create_custom_theme();
+ EditorThemeManager::initialize();
+ theme = EditorThemeManager::generate_theme();
DisplayServer::set_early_window_clear_color_override(true, theme->get_color(SNAME("background"), EditorStringName(Editor)));
register_exporters();
@@ -7079,127 +6489,96 @@ EditorNode::EditorNode() {
title_bar = memnew(EditorTitleBar);
main_vbox->add_child(title_bar);
- left_l_hsplit = memnew(HSplitContainer);
+ left_l_hsplit = memnew(DockSplitContainer);
+ left_l_hsplit->set_name("DockHSplitLeftL");
main_vbox->add_child(left_l_hsplit);
left_l_hsplit->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- left_l_vsplit = memnew(VSplitContainer);
+ left_l_vsplit = memnew(DockSplitContainer);
+ left_l_vsplit->set_name("DockVSplitLeftL");
+ left_l_vsplit->set_vertical(true);
left_l_hsplit->add_child(left_l_vsplit);
- dock_slot[DOCK_SLOT_LEFT_UL] = memnew(TabContainer);
- left_l_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_UL]);
- dock_slot[DOCK_SLOT_LEFT_BL] = memnew(TabContainer);
- left_l_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_BL]);
- left_r_hsplit = memnew(HSplitContainer);
+ TabContainer *dock_slot[EditorDockManager::DOCK_SLOT_MAX];
+ dock_slot[EditorDockManager::DOCK_SLOT_LEFT_UL] = memnew(TabContainer);
+ dock_slot[EditorDockManager::DOCK_SLOT_LEFT_UL]->set_name("DockSlotLeftUL");
+ left_l_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_LEFT_UL]);
+ dock_slot[EditorDockManager::DOCK_SLOT_LEFT_BL] = memnew(TabContainer);
+ dock_slot[EditorDockManager::DOCK_SLOT_LEFT_BL]->set_name("DockSlotLeftBL");
+ left_l_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_LEFT_BL]);
+
+ left_r_hsplit = memnew(DockSplitContainer);
+ left_r_hsplit->set_name("DockHSplitLeftR");
left_l_hsplit->add_child(left_r_hsplit);
- left_r_vsplit = memnew(VSplitContainer);
+ left_r_vsplit = memnew(DockSplitContainer);
+ left_r_vsplit->set_name("DockVSplitLeftR");
+ left_r_vsplit->set_vertical(true);
left_r_hsplit->add_child(left_r_vsplit);
- dock_slot[DOCK_SLOT_LEFT_UR] = memnew(TabContainer);
- left_r_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_UR]);
- dock_slot[DOCK_SLOT_LEFT_BR] = memnew(TabContainer);
- left_r_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_BR]);
-
- main_hsplit = memnew(HSplitContainer);
+ dock_slot[EditorDockManager::DOCK_SLOT_LEFT_UR] = memnew(TabContainer);
+ dock_slot[EditorDockManager::DOCK_SLOT_LEFT_UR]->set_name("DockSlotLeftUR");
+ left_r_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_LEFT_UR]);
+ dock_slot[EditorDockManager::DOCK_SLOT_LEFT_BR] = memnew(TabContainer);
+ dock_slot[EditorDockManager::DOCK_SLOT_LEFT_BR]->set_name("DockSlotLeftBR");
+ left_r_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_LEFT_BR]);
+
+ main_hsplit = memnew(DockSplitContainer);
+ main_hsplit->set_name("DockHSplitMain");
left_r_hsplit->add_child(main_hsplit);
VBoxContainer *center_vb = memnew(VBoxContainer);
main_hsplit->add_child(center_vb);
+
center_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- center_split = memnew(VSplitContainer);
+ center_split = memnew(DockSplitContainer);
+ center_split->set_name("DockVSplitCenter");
+ center_split->set_vertical(true);
center_split->set_v_size_flags(Control::SIZE_EXPAND_FILL);
center_split->set_collapsed(false);
center_vb->add_child(center_split);
- right_hsplit = memnew(HSplitContainer);
+ right_hsplit = memnew(DockSplitContainer);
+ right_hsplit->set_name("DockHSplitRight");
main_hsplit->add_child(right_hsplit);
- right_l_vsplit = memnew(VSplitContainer);
+ right_l_vsplit = memnew(DockSplitContainer);
+ right_l_vsplit->set_name("DockVSplitRightL");
+ right_l_vsplit->set_vertical(true);
right_hsplit->add_child(right_l_vsplit);
- dock_slot[DOCK_SLOT_RIGHT_UL] = memnew(TabContainer);
- right_l_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_UL]);
- dock_slot[DOCK_SLOT_RIGHT_BL] = memnew(TabContainer);
- right_l_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_BL]);
-
- right_r_vsplit = memnew(VSplitContainer);
+ dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_UL] = memnew(TabContainer);
+ dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_UL]->set_name("DockSlotRightUL");
+ right_l_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_UL]);
+ dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_BL] = memnew(TabContainer);
+ dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_BL]->set_name("DockSlotRightBL");
+ right_l_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_BL]);
+
+ right_r_vsplit = memnew(DockSplitContainer);
+ right_r_vsplit->set_name("DockVSplitRightR");
+ right_r_vsplit->set_vertical(true);
right_hsplit->add_child(right_r_vsplit);
- dock_slot[DOCK_SLOT_RIGHT_UR] = memnew(TabContainer);
- right_r_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_UR]);
- dock_slot[DOCK_SLOT_RIGHT_BR] = memnew(TabContainer);
- right_r_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_BR]);
-
- // Store them for easier access.
- vsplits.push_back(left_l_vsplit);
- vsplits.push_back(left_r_vsplit);
- vsplits.push_back(right_l_vsplit);
- vsplits.push_back(right_r_vsplit);
-
- hsplits.push_back(left_l_hsplit);
- hsplits.push_back(left_r_hsplit);
- hsplits.push_back(main_hsplit);
- hsplits.push_back(right_hsplit);
-
- for (int i = 0; i < vsplits.size(); i++) {
- vsplits[i]->connect("dragged", callable_mp(this, &EditorNode::_dock_split_dragged));
- hsplits[i]->connect("dragged", callable_mp(this, &EditorNode::_dock_split_dragged));
- }
-
- dock_select_popup = memnew(PopupPanel);
- gui_base->add_child(dock_select_popup);
- VBoxContainer *dock_vb = memnew(VBoxContainer);
- dock_select_popup->add_child(dock_vb);
-
- HBoxContainer *dock_hb = memnew(HBoxContainer);
- dock_tab_move_left = memnew(Button);
- dock_tab_move_left->set_flat(true);
- dock_tab_move_left->set_focus_mode(Control::FOCUS_NONE);
- dock_tab_move_left->connect("pressed", callable_mp(this, &EditorNode::_dock_move_left));
- dock_hb->add_child(dock_tab_move_left);
-
- Label *dock_label = memnew(Label);
- dock_label->set_text(TTR("Dock Position"));
- dock_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
- dock_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
- dock_hb->add_child(dock_label);
-
- dock_tab_move_right = memnew(Button);
- dock_tab_move_right->set_flat(true);
- dock_tab_move_right->set_focus_mode(Control::FOCUS_NONE);
- dock_tab_move_right->connect("pressed", callable_mp(this, &EditorNode::_dock_move_right));
-
- dock_hb->add_child(dock_tab_move_right);
- dock_vb->add_child(dock_hb);
-
- dock_select = memnew(Control);
- dock_select->set_custom_minimum_size(Size2(128, 64) * EDSCALE);
- dock_select->connect("gui_input", callable_mp(this, &EditorNode::_dock_select_input));
- dock_select->connect("draw", callable_mp(this, &EditorNode::_dock_select_draw));
- dock_select->connect("mouse_exited", callable_mp(this, &EditorNode::_dock_popup_exit));
- dock_select->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- dock_vb->add_child(dock_select);
-
- if (!SceneTree::get_singleton()->get_root()->is_embedding_subwindows() && !EDITOR_GET("interface/editor/single_window_mode") && EDITOR_GET("interface/multi_window/enable")) {
- dock_float = memnew(Button);
- dock_float->set_icon(theme->get_icon("MakeFloating", EditorStringName(EditorIcons)));
- dock_float->set_text(TTR("Make Floating"));
- dock_float->set_focus_mode(Control::FOCUS_NONE);
- dock_float->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
- dock_float->connect("pressed", callable_mp(this, &EditorNode::_dock_make_selected_float));
-
- dock_vb->add_child(dock_float);
- }
-
- dock_select_popup->reset_size();
-
- for (int i = 0; i < DOCK_SLOT_MAX; i++) {
- dock_slot[i]->set_custom_minimum_size(Size2(170, 0) * EDSCALE);
- dock_slot[i]->set_v_size_flags(Control::SIZE_EXPAND_FILL);
- dock_slot[i]->set_popup(dock_select_popup);
- dock_slot[i]->connect("pre_popup_pressed", callable_mp(this, &EditorNode::_dock_pre_popup).bind(i));
- dock_slot[i]->set_drag_to_rearrange_enabled(true);
- dock_slot[i]->set_tabs_rearrange_group(1);
- dock_slot[i]->connect("tab_changed", callable_mp(this, &EditorNode::_dock_tab_changed));
- dock_slot[i]->set_use_hidden_tabs_for_min_size(true);
+ dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_UR] = memnew(TabContainer);
+ dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_UR]->set_name("DockSlotRightUR");
+ right_r_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_UR]);
+ dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_BR] = memnew(TabContainer);
+ dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_BR]->set_name("DockSlotRightBR");
+ right_r_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_BR]);
+
+ editor_dock_manager = memnew(EditorDockManager);
+ editor_dock_manager->connect("layout_changed", callable_mp(this, &EditorNode::_save_editor_layout));
+
+ // Save the splits for easier access.
+ editor_dock_manager->add_vsplit(left_l_vsplit);
+ editor_dock_manager->add_vsplit(left_r_vsplit);
+ editor_dock_manager->add_vsplit(right_l_vsplit);
+ editor_dock_manager->add_vsplit(right_r_vsplit);
+
+ editor_dock_manager->add_hsplit(left_l_hsplit);
+ editor_dock_manager->add_hsplit(left_r_hsplit);
+ editor_dock_manager->add_hsplit(main_hsplit);
+ editor_dock_manager->add_hsplit(right_hsplit);
+
+ for (int i = 0; i < EditorDockManager::DOCK_SLOT_MAX; i++) {
+ editor_dock_manager->register_dock_slot((EditorDockManager::DockSlot)i, dock_slot[i]);
}
editor_layout_save_delay_timer = memnew(Timer);
@@ -7642,37 +7021,22 @@ EditorNode::EditorNode() {
history_dock = memnew(HistoryDock);
// Scene: Top left.
- dock_slot[DOCK_SLOT_LEFT_UR]->add_child(SceneTreeDock::get_singleton());
- dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(dock_slot[DOCK_SLOT_LEFT_UR]->get_tab_idx_from_control(SceneTreeDock::get_singleton()), TTR("Scene"));
+ editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_LEFT_UR, SceneTreeDock::get_singleton(), TTR("Scene"));
// Import: Top left, behind Scene.
- dock_slot[DOCK_SLOT_LEFT_UR]->add_child(ImportDock::get_singleton());
- dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(dock_slot[DOCK_SLOT_LEFT_UR]->get_tab_idx_from_control(ImportDock::get_singleton()), TTR("Import"));
+ editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_LEFT_UR, ImportDock::get_singleton(), TTR("Import"));
// FileSystem: Bottom left.
- dock_slot[DOCK_SLOT_LEFT_BR]->add_child(FileSystemDock::get_singleton());
- dock_slot[DOCK_SLOT_LEFT_BR]->set_tab_title(dock_slot[DOCK_SLOT_LEFT_BR]->get_tab_idx_from_control(FileSystemDock::get_singleton()), TTR("FileSystem"));
+ editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_LEFT_BR, FileSystemDock::get_singleton(), TTR("FileSystem"));
// Inspector: Full height right.
- dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(InspectorDock::get_singleton());
- dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(dock_slot[DOCK_SLOT_RIGHT_UL]->get_tab_idx_from_control(InspectorDock::get_singleton()), TTR("Inspector"));
+ editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_RIGHT_UL, InspectorDock::get_singleton(), TTR("Inspector"));
// Node: Full height right, behind Inspector.
- dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(NodeDock::get_singleton());
- dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(dock_slot[DOCK_SLOT_RIGHT_UL]->get_tab_idx_from_control(NodeDock::get_singleton()), TTR("Node"));
+ editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_RIGHT_UL, NodeDock::get_singleton(), TTR("Node"));
// History: Full height right, behind Node.
- dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(history_dock);
- dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(dock_slot[DOCK_SLOT_RIGHT_UL]->get_tab_idx_from_control(history_dock), TTR("History"));
-
- // Hide unused dock slots and vsplits.
- dock_slot[DOCK_SLOT_LEFT_UL]->hide();
- dock_slot[DOCK_SLOT_LEFT_BL]->hide();
- dock_slot[DOCK_SLOT_RIGHT_BL]->hide();
- dock_slot[DOCK_SLOT_RIGHT_UR]->hide();
- dock_slot[DOCK_SLOT_RIGHT_BR]->hide();
- left_l_vsplit->hide();
- right_r_vsplit->hide();
+ editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_RIGHT_UL, history_dock, TTR("History"));
// Add some offsets to left_r and main hsplits to make LEFT_R and RIGHT_L docks wider than minsize.
left_r_hsplit->set_split_offset(270 * EDSCALE);
@@ -7687,7 +7051,8 @@ EditorNode::EditorNode() {
default_layout->set_value(docks_section, "dock_4", "FileSystem");
default_layout->set_value(docks_section, "dock_5", "Inspector,Node,History");
- for (int i = 0; i < vsplits.size(); i++) {
+ // There are 4 vsplits and 4 hsplits.
+ for (int i = 0; i < editor_dock_manager->get_vsplit_count(); i++) {
default_layout->set_value(docks_section, "dock_split_" + itos(i + 1), 0);
}
default_layout->set_value(docks_section, "dock_hsplit_1", 0);
@@ -8120,10 +7485,10 @@ EditorNode::~EditorNode() {
memdelete(editor_plugins_force_input_forwarding);
memdelete(progress_hb);
memdelete(surface_upgrade_tool);
+ memdelete(editor_dock_manager);
EditorSettings::destroy();
- EditorColorMap::finish();
- EditorTheme::finalize();
+ EditorThemeManager::finalize();
GDExtensionEditorPlugins::editor_node_add_plugin = nullptr;
GDExtensionEditorPlugins::editor_node_remove_plugin = nullptr;
diff --git a/editor/editor_node.h b/editor/editor_node.h
index c72a8f9324..f1dea0c11e 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -73,10 +73,12 @@ class AudioStreamPreviewGenerator;
class BackgroundProgress;
class DependencyEditor;
class DependencyErrorDialog;
+class DockSplitContainer;
class DynamicFontImportSettingsDialog;
class EditorAbout;
class EditorBuildProfileManager;
class EditorCommandPalette;
+class EditorDockManager;
class EditorExport;
class EditorExtensionManager;
class EditorFeatureProfileManager;
@@ -121,18 +123,6 @@ class EditorNode : public Node {
GDCLASS(EditorNode, Node);
public:
- enum DockSlot {
- DOCK_SLOT_LEFT_UL,
- DOCK_SLOT_LEFT_BL,
- DOCK_SLOT_LEFT_UR,
- DOCK_SLOT_LEFT_BR,
- DOCK_SLOT_RIGHT_UL,
- DOCK_SLOT_RIGHT_BL,
- DOCK_SLOT_RIGHT_UR,
- DOCK_SLOT_RIGHT_BR,
- DOCK_SLOT_MAX
- };
-
enum EditorTable {
EDITOR_2D = 0,
EDITOR_3D,
@@ -310,18 +300,15 @@ private:
String renderer_request;
// Split containers.
- HSplitContainer *left_l_hsplit = nullptr;
- VSplitContainer *left_l_vsplit = nullptr;
- HSplitContainer *left_r_hsplit = nullptr;
- VSplitContainer *left_r_vsplit = nullptr;
- HSplitContainer *main_hsplit = nullptr;
- HSplitContainer *right_hsplit = nullptr;
- VSplitContainer *right_l_vsplit = nullptr;
- VSplitContainer *right_r_vsplit = nullptr;
- VSplitContainer *center_split = nullptr;
- // To access those easily by index.
- Vector<VSplitContainer *> vsplits;
- Vector<HSplitContainer *> hsplits;
+ DockSplitContainer *left_l_hsplit = nullptr;
+ DockSplitContainer *left_l_vsplit = nullptr;
+ DockSplitContainer *left_r_hsplit = nullptr;
+ DockSplitContainer *left_r_vsplit = nullptr;
+ DockSplitContainer *main_hsplit = nullptr;
+ DockSplitContainer *right_hsplit = nullptr;
+ DockSplitContainer *right_l_vsplit = nullptr;
+ DockSplitContainer *right_r_vsplit = nullptr;
+ DockSplitContainer *center_split = nullptr;
// Main tabs.
EditorSceneTabs *scene_tabs = nullptr;
@@ -426,20 +413,8 @@ private:
Button *new_inherited_button = nullptr;
String open_import_request;
- Vector<WindowWrapper *> floating_docks;
-
- Button *dock_float = nullptr;
- Button *dock_tab_move_left = nullptr;
- Button *dock_tab_move_right = nullptr;
- Control *dock_select = nullptr;
- PopupPanel *dock_select_popup = nullptr;
- Rect2 dock_select_rect[DOCK_SLOT_MAX];
- TabContainer *dock_slot[DOCK_SLOT_MAX];
+ EditorDockManager *editor_dock_manager = nullptr;
Timer *editor_layout_save_delay_timer = nullptr;
- bool docks_visible = true;
- int dock_popup_selected_idx = -1;
- int dock_select_rect_over_idx = -1;
-
Button *distraction_free = nullptr;
Vector<BottomPanelItem> bottom_panel_items;
@@ -634,17 +609,6 @@ private:
bool _find_scene_in_use(Node *p_node, const String &p_path) const;
- void _dock_select_input(const Ref<InputEvent> &p_input);
- void _dock_move_left();
- void _dock_move_right();
- void _dock_select_draw();
- void _dock_pre_popup(int p_which);
- void _dock_split_dragged(int ofs);
- void _dock_popup_exit();
- void _dock_floating_close_request(WindowWrapper *p_wrapper);
- void _dock_make_selected_float();
- void _dock_make_float(Control *p_control, int p_slot_index, bool p_show_window = true);
-
void _proceed_closing_scene_tabs();
bool _is_closing_editor() const;
@@ -655,11 +619,6 @@ private:
void _save_editor_layout();
void _load_editor_layout();
- void _save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section);
- void _restore_floating_dock(const Dictionary &p_dock_dump, Control *p_wrapper, int p_slot_index);
- void _load_docks_from_config(Ref<ConfigFile> p_layout, const String &p_section);
- void _update_dock_slots_visibility(bool p_keep_selected_tabs = false);
- void _dock_tab_changed(int p_tab);
void _save_central_editor_layout_to_config(Ref<ConfigFile> p_config_file);
void _load_central_editor_layout_from_config(Ref<ConfigFile> p_config_file);
@@ -772,15 +731,9 @@ public:
void new_inherited_scene() { _menu_option_confirm(FILE_NEW_INHERITED_SCENE, false); }
- void set_docks_visible(bool p_show);
- bool get_docks_visible() const;
-
void set_distraction_free_mode(bool p_enter);
bool is_distraction_free_mode_enabled() const;
- void add_control_to_dock(DockSlot p_slot, Control *p_control);
- void remove_control_from_dock(Control *p_control);
-
void set_addon_plugin_enabled(const String &p_addon, bool p_enabled, bool p_config_changed = false);
bool is_addon_plugin_enabled(const String &p_addon) const;
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index 49c62a3a6c..f0044edff2 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -31,6 +31,7 @@
#include "editor_plugin.h"
#include "editor/debugger/editor_debugger_node.h"
+#include "editor/editor_dock_manager.h"
#include "editor/editor_file_system.h"
#include "editor/editor_inspector.h"
#include "editor/editor_interface.h"
@@ -84,12 +85,12 @@ Button *EditorPlugin::add_control_to_bottom_panel(Control *p_control, const Stri
void EditorPlugin::add_control_to_dock(DockSlot p_slot, Control *p_control) {
ERR_FAIL_NULL(p_control);
- EditorNode::get_singleton()->add_control_to_dock(EditorNode::DockSlot(p_slot), p_control);
+ EditorDockManager::get_singleton()->add_control_to_dock(EditorDockManager::DockSlot(p_slot), p_control);
}
void EditorPlugin::remove_control_from_docks(Control *p_control) {
ERR_FAIL_NULL(p_control);
- EditorNode::get_singleton()->remove_control_from_dock(p_control);
+ EditorDockManager::get_singleton()->remove_control_from_dock(p_control);
}
void EditorPlugin::remove_control_from_bottom_panel(Control *p_control) {
diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp
index 6c38d9de58..d22e60d7b4 100644
--- a/editor/editor_plugin_settings.cpp
+++ b/editor/editor_plugin_settings.cpp
@@ -36,7 +36,7 @@
#include "core/io/file_access.h"
#include "core/os/main_loop.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/margin_container.h"
#include "scene/gui/tree.h"
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 404f1151f1..f237649c5d 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -37,7 +37,6 @@
#include "editor/editor_properties_array_dict.h"
#include "editor/editor_properties_vector.h"
#include "editor/editor_resource_picker.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/gui/editor_file_dialog.h"
@@ -48,6 +47,7 @@
#include "editor/project_settings_editor.h"
#include "editor/property_selector.h"
#include "editor/scene_tree_dock.h"
+#include "editor/themes/editor_scale.h"
#include "scene/2d/gpu_particles_2d.h"
#include "scene/3d/fog_volume.h"
#include "scene/3d/gpu_particles_3d.h"
@@ -992,12 +992,12 @@ void EditorPropertyLayersGrid::_notification(int p_what) {
const int bsize = (grid_size.height * 80 / 100) / 2;
const int h = bsize * 2 + 1;
- Color color = get_theme_color(read_only ? SNAME("disabled_highlight_color") : SNAME("highlight_color"), EditorStringName(Editor));
+ Color color = get_theme_color(read_only ? SNAME("highlight_disabled_color") : SNAME("highlight_color"), EditorStringName(Editor));
- Color text_color = get_theme_color(read_only ? SNAME("disabled_font_color") : SNAME("font_color"), EditorStringName(Editor));
+ Color text_color = get_theme_color(read_only ? SNAME("font_disabled_color") : SNAME("font_color"), EditorStringName(Editor));
text_color.a *= 0.5;
- Color text_color_on = get_theme_color(read_only ? SNAME("disabled_font_color") : SNAME("font_hover_color"), EditorStringName(Editor));
+ Color text_color_on = get_theme_color(read_only ? SNAME("font_disabled_color") : SNAME("font_hover_color"), EditorStringName(Editor));
text_color_on.a *= 0.7;
const int vofs = (grid_size.height - h) / 2;
@@ -2073,7 +2073,7 @@ void EditorPropertyQuaternion::_notification(int p_what) {
euler[i]->add_theme_color_override("label_color", colors[i]);
}
edit_button->set_icon(get_editor_theme_icon(SNAME("Edit")));
- euler_label->add_theme_color_override(SNAME("font_color"), get_theme_color(SNAME("property_color"), EditorStringName(Editor)));
+ euler_label->add_theme_color_override(SNAME("font_color"), get_theme_color(SNAME("property_color"), SNAME("EditorProperty")));
warning->set_icon(get_editor_theme_icon(SNAME("NodeWarning")));
warning->add_theme_color_override(SNAME("font_color"), get_theme_color(SNAME("warning_color"), EditorStringName(Editor)));
} break;
diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp
index 7f9d80961b..f5b8d04444 100644
--- a/editor/editor_properties_array_dict.cpp
+++ b/editor/editor_properties_array_dict.cpp
@@ -34,11 +34,11 @@
#include "core/io/marshalls.h"
#include "editor/editor_properties.h"
#include "editor/editor_properties_vector.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/gui/editor_spin_slider.h"
#include "editor/inspector_dock.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/button.h"
#include "scene/resources/packed_scene.h"
@@ -407,8 +407,8 @@ void EditorPropertyArray::update_property() {
new_prop->connect(SNAME("object_id_selected"), callable_mp(this, &EditorPropertyArray::_object_id_selected));
new_prop->set_h_size_flags(SIZE_EXPAND_FILL);
new_prop->set_read_only(is_read_only());
- callable_mp((Node *)slot.prop, &Node::add_sibling).call_deferred(new_prop, false);
- callable_mp((Node *)slot.prop, &Node::queue_free).call_deferred();
+ slot.prop->add_sibling(new_prop, false);
+ slot.prop->queue_free();
slot.prop = new_prop;
slot.set_index(idx);
}
diff --git a/editor/editor_quick_open.cpp b/editor/editor_quick_open.cpp
index 965d0269d6..f39872ba2c 100644
--- a/editor/editor_quick_open.cpp
+++ b/editor/editor_quick_open.cpp
@@ -32,7 +32,7 @@
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
+#include "editor/themes/editor_scale.h"
Rect2i EditorQuickOpen::prev_rect = Rect2i();
bool EditorQuickOpen::was_showed = false;
diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp
index 977e65d78c..27ce27591f 100644
--- a/editor/editor_resource_picker.cpp
+++ b/editor/editor_resource_picker.cpp
@@ -34,7 +34,6 @@
#include "editor/editor_node.h"
#include "editor/editor_quick_open.h"
#include "editor/editor_resource_preview.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/filesystem_dock.h"
@@ -42,6 +41,7 @@
#include "editor/plugins/editor_resource_conversion_plugin.h"
#include "editor/plugins/script_editor_plugin.h"
#include "editor/scene_tree_dock.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/button.h"
#include "scene/gui/texture_rect.h"
#include "scene/resources/gradient_texture.h"
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index f21f0ac216..1702277ebc 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -37,10 +37,11 @@
#include "core/variant/variant_utility.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
+#include "editor/themes/editor_scale.h"
#include "scene/resources/image_texture.h"
+#include "servers/rendering/rendering_server_default.h"
bool EditorResourcePreviewGenerator::handles(const String &p_type) const {
bool success = false;
@@ -338,6 +339,20 @@ void EditorResourcePreview::_thread() {
exited.set();
}
+void EditorResourcePreview::_idle_callback() {
+ if (!singleton) {
+ // Just in case the shutdown of the editor involves the deletion of the singleton
+ // happening while additional idle callbacks can happen.
+ return;
+ }
+
+ // Process preview tasks, trying to leave a little bit of responsiveness worst case.
+ uint64_t start = OS::get_singleton()->get_ticks_msec();
+ while (!singleton->queue.is_empty() && OS::get_singleton()->get_ticks_msec() - start < 100) {
+ singleton->_iterate();
+ }
+}
+
void EditorResourcePreview::_update_thumbnail_sizes() {
if (small_thumbnail_size == -1) {
// Kind of a workaround to retrieve the default icon size.
@@ -441,27 +456,36 @@ void EditorResourcePreview::check_for_invalidation(const String &p_path) {
}
void EditorResourcePreview::start() {
- if (DisplayServer::get_singleton()->get_name() != "headless") {
+ if (DisplayServer::get_singleton()->get_name() == "headless") {
+ return;
+ }
+
+ if (RSG::texture_storage->can_create_resources_async()) {
ERR_FAIL_COND_MSG(thread.is_started(), "Thread already started.");
thread.start(_thread_func, this);
+ } else {
+ SceneTree *st = Object::cast_to<SceneTree>(OS::get_singleton()->get_main_loop());
+ ERR_FAIL_NULL_MSG(st, "Editor's MainLoop is not a SceneTree. This is a bug.");
}
}
void EditorResourcePreview::stop() {
- if (thread.is_started()) {
- exiting.set();
- preview_sem.post();
+ if (RSG::texture_storage->can_create_resources_async()) {
+ if (thread.is_started()) {
+ exiting.set();
+ preview_sem.post();
- for (int i = 0; i < preview_generators.size(); i++) {
- preview_generators.write[i]->abort();
- }
+ for (int i = 0; i < preview_generators.size(); i++) {
+ preview_generators.write[i]->abort();
+ }
- while (!exited.is_set()) {
- OS::get_singleton()->delay_usec(10000);
- RenderingServer::get_singleton()->sync(); //sync pending stuff, as thread may be blocked on rendering server
- }
+ while (!exited.is_set()) {
+ OS::get_singleton()->delay_usec(10000);
+ RenderingServer::get_singleton()->sync(); //sync pending stuff, as thread may be blocked on rendering server
+ }
- thread.wait_to_finish();
+ thread.wait_to_finish();
+ }
}
}
diff --git a/editor/editor_resource_preview.h b/editor/editor_resource_preview.h
index 324245ba23..bc99372bc2 100644
--- a/editor/editor_resource_preview.h
+++ b/editor/editor_resource_preview.h
@@ -103,7 +103,8 @@ class EditorResourcePreview : public Node {
int small_thumbnail_size = -1;
static void _thread_func(void *ud);
- void _thread();
+ void _thread(); // For rendering drivers supporting async texture creation.
+ static void _idle_callback(); // For other rendering drivers (i.e., OpenGL).
void _iterate();
void _write_preview_cache(Ref<FileAccess> p_file, int p_thumbnail_size, bool p_has_small_texture, uint64_t p_modified_time, String p_hash, const Dictionary &p_metadata);
diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp
index 6744e79931..fd6b083c12 100644
--- a/editor/editor_run_native.cpp
+++ b/editor/editor_run_native.cpp
@@ -31,10 +31,10 @@
#include "editor_run_native.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/export/editor_export.h"
#include "editor/export/editor_export_platform.h"
+#include "editor/themes/editor_scale.h"
#include "scene/resources/image_texture.h"
void EditorRunNative::_notification(int p_what) {
diff --git a/editor/editor_sectioned_inspector.cpp b/editor/editor_sectioned_inspector.cpp
index 7bf88ba94f..8d1f97f6b1 100644
--- a/editor/editor_sectioned_inspector.cpp
+++ b/editor/editor_sectioned_inspector.cpp
@@ -31,9 +31,9 @@
#include "editor_sectioned_inspector.h"
#include "editor/editor_property_name_processor.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
+#include "editor/themes/editor_scale.h"
static bool _property_path_matches(const String &p_property_path, const String &p_filter, EditorPropertyNameProcessor::Style p_style) {
if (p_property_path.findn(p_filter) != -1) {
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index e6ba39cae7..b565431185 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -460,6 +460,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
// Theme
EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_ENUM, "interface/theme/preset", "Default", "Default,Breeze Dark,Godot 2,Gray,Light,Solarized (Dark),Solarized (Light),Black (OLED),Custom")
+ EDITOR_SETTING(Variant::STRING, PROPERTY_HINT_ENUM, "interface/theme/spacing_preset", "Default", "Compact,Default,Spacious,Custom")
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/theme/icon_and_font_color", 0, "Auto,Dark,Light")
EDITOR_SETTING(Variant::COLOR, PROPERTY_HINT_NONE, "interface/theme/base_color", Color(0.2, 0.23, 0.31), "")
EDITOR_SETTING(Variant::COLOR, PROPERTY_HINT_NONE, "interface/theme/accent_color", Color(0.41, 0.61, 0.91), "")
@@ -469,7 +470,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/theme/relationship_line_opacity", 0.1, "0.00,1,0.01")
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/theme/border_size", 0, "0,2,1")
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/theme/corner_radius", 3, "0,6,1")
- EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/theme/additional_spacing", 0.0, "0,5,0.1")
+ EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/theme/base_spacing", 4, "0,8,1")
+ EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/theme/additional_spacing", 0, "0,8,1")
EDITOR_SETTING_USAGE(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "interface/theme/custom_theme", "", "*.res,*.tres,*.theme", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)
// Touchscreen
diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp
index 33a176499d..becc376cd4 100644
--- a/editor/editor_settings_dialog.cpp
+++ b/editor/editor_settings_dialog.cpp
@@ -38,12 +38,12 @@
#include "editor/editor_log.h"
#include "editor/editor_node.h"
#include "editor/editor_property_name_processor.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/event_listener_line_edit.h"
#include "editor/input_event_configuration_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/margin_container.h"
void EditorSettingsDialog::ok_pressed() {
@@ -62,8 +62,12 @@ void EditorSettingsDialog::_settings_changed() {
void EditorSettingsDialog::_settings_property_edited(const String &p_name) {
String full_name = inspector->get_full_item_path(p_name);
+ // Set theme presets to Custom when controlled settings change.
+
if (full_name == "interface/theme/accent_color" || full_name == "interface/theme/base_color" || full_name == "interface/theme/contrast" || full_name == "interface/theme/draw_extra_borders") {
- EditorSettings::get_singleton()->set_manually("interface/theme/preset", "Custom"); // set preset to Custom
+ EditorSettings::get_singleton()->set_manually("interface/theme/preset", "Custom");
+ } else if (full_name == "interface/theme/base_spacing" || full_name == "interface/theme/additional_spacing") {
+ EditorSettings::get_singleton()->set_manually("interface/theme/spacing_preset", "Custom");
} else if (full_name.begins_with("text_editor/theme/highlighting")) {
EditorSettings::get_singleton()->set_manually("text_editor/theme/color_theme", "Custom");
}
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
deleted file mode 100644
index da5eecfb73..0000000000
--- a/editor/editor_themes.cpp
+++ /dev/null
@@ -1,2402 +0,0 @@
-/**************************************************************************/
-/* editor_themes.cpp */
-/**************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/**************************************************************************/
-/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
-/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/**************************************************************************/
-
-#include "editor_themes.h"
-
-#include "core/error/error_macros.h"
-#include "core/io/resource_loader.h"
-#include "editor/editor_fonts.h"
-#include "editor/editor_icons.gen.h"
-#include "editor/editor_scale.h"
-#include "editor/editor_settings.h"
-#include "editor/editor_string_names.h"
-#include "scene/resources/image_texture.h"
-#include "scene/resources/style_box_flat.h"
-#include "scene/resources/style_box_line.h"
-#include "scene/resources/style_box_texture.h"
-#include "scene/theme/theme_db.h"
-
-#include "modules/modules_enabled.gen.h" // For svg.
-#ifdef MODULE_SVG_ENABLED
-#include "modules/svg/image_loader_svg.h"
-#endif
-
-HashMap<Color, Color> EditorColorMap::color_conversion_map;
-HashSet<StringName> EditorColorMap::color_conversion_exceptions;
-
-void EditorColorMap::add_conversion_color_pair(const String p_from_color, const String p_to_color) {
- color_conversion_map[Color::html(p_from_color)] = Color::html(p_to_color);
-}
-
-void EditorColorMap::add_conversion_exception(const StringName &p_icon_name) {
- color_conversion_exceptions.insert(p_icon_name);
-}
-
-void EditorColorMap::create() {
- // Some of the colors below are listed for completeness sake.
- // This can be a basis for proper palette validation later.
-
- // Convert: FROM TO
- add_conversion_color_pair("#478cbf", "#478cbf"); // Godot Blue
- add_conversion_color_pair("#414042", "#414042"); // Godot Gray
-
- add_conversion_color_pair("#ffffff", "#414141"); // Pure white
- add_conversion_color_pair("#fefefe", "#fefefe"); // Forced light color
- add_conversion_color_pair("#000000", "#bfbfbf"); // Pure black
- add_conversion_color_pair("#010101", "#010101"); // Forced dark color
-
- // Keep pure RGB colors as is, but list them for explicitness.
- add_conversion_color_pair("#ff0000", "#ff0000"); // Pure red
- add_conversion_color_pair("#00ff00", "#00ff00"); // Pure green
- add_conversion_color_pair("#0000ff", "#0000ff"); // Pure blue
-
- // GUI Colors
- add_conversion_color_pair("#e0e0e0", "#5a5a5a"); // Common icon color
- add_conversion_color_pair("#808080", "#808080"); // GUI disabled color
- add_conversion_color_pair("#b3b3b3", "#363636"); // GUI disabled light color
- add_conversion_color_pair("#699ce8", "#699ce8"); // GUI highlight color
- add_conversion_color_pair("#f9f9f9", "#606060"); // Scrollbar grabber highlight color
-
- add_conversion_color_pair("#c38ef1", "#a85de9"); // Animation
- add_conversion_color_pair("#8da5f3", "#3d64dd"); // 2D
- add_conversion_color_pair("#7582a8", "#6d83c8"); // 2D Abstract
- add_conversion_color_pair("#fc7f7f", "#cd3838"); // 3D
- add_conversion_color_pair("#b56d6d", "#be6a6a"); // 3D Abstract
- add_conversion_color_pair("#8eef97", "#2fa139"); // GUI Control
- add_conversion_color_pair("#76ad7b", "#64a66a"); // GUI Control Abstract
-
- add_conversion_color_pair("#5fb2ff", "#0079f0"); // Selection (blue)
- add_conversion_color_pair("#003e7a", "#2b74bb"); // Selection (darker blue)
- add_conversion_color_pair("#f7f5cf", "#615f3a"); // Gizmo (yellow)
-
- // Rainbow
- add_conversion_color_pair("#ff4545", "#ff2929"); // Red
- add_conversion_color_pair("#ffe345", "#ffe337"); // Yellow
- add_conversion_color_pair("#80ff45", "#74ff34"); // Green
- add_conversion_color_pair("#45ffa2", "#2cff98"); // Aqua
- add_conversion_color_pair("#45d7ff", "#22ccff"); // Blue
- add_conversion_color_pair("#8045ff", "#702aff"); // Purple
- add_conversion_color_pair("#ff4596", "#ff2781"); // Pink
-
- // Audio gradients
- add_conversion_color_pair("#e1da5b", "#d6cf4b"); // Yellow
-
- add_conversion_color_pair("#62aeff", "#1678e0"); // Frozen gradient top
- add_conversion_color_pair("#75d1e6", "#41acc5"); // Frozen gradient middle
- add_conversion_color_pair("#84ffee", "#49ccba"); // Frozen gradient bottom
-
- add_conversion_color_pair("#f70000", "#c91616"); // Color track red
- add_conversion_color_pair("#eec315", "#d58c0b"); // Color track orange
- add_conversion_color_pair("#dbee15", "#b7d10a"); // Color track yellow
- add_conversion_color_pair("#288027", "#218309"); // Color track green
-
- // Other objects
- add_conversion_color_pair("#ffca5f", "#fea900"); // Mesh resource (orange)
- add_conversion_color_pair("#2998ff", "#68b6ff"); // Shape resource (blue)
- add_conversion_color_pair("#a2d2ff", "#4998e3"); // Shape resource (light blue)
- add_conversion_color_pair("#69c4d4", "#29a3cc"); // Input event highlight (light blue)
-
- // Animation editor tracks
- // The property track icon color is set by the common icon color.
- add_conversion_color_pair("#ea7940", "#bd5e2c"); // 3D Position track
- add_conversion_color_pair("#ff2b88", "#bd165f"); // 3D Rotation track
- add_conversion_color_pair("#eac840", "#bd9d1f"); // 3D Scale track
- add_conversion_color_pair("#3cf34e", "#16a827"); // Call Method track
- add_conversion_color_pair("#2877f6", "#236be6"); // Bezier Curve track
- add_conversion_color_pair("#eae440", "#9f9722"); // Audio Playback track
- add_conversion_color_pair("#a448f0", "#9853ce"); // Animation Playback track
- add_conversion_color_pair("#5ad5c4", "#0a9c88"); // Blend Shape track
-
- // Control layouts
- add_conversion_color_pair("#d6d6d6", "#474747"); // Highlighted part
- add_conversion_color_pair("#474747", "#d6d6d6"); // Background part
- add_conversion_color_pair("#919191", "#6e6e6e"); // Border part
-
- // TileSet editor icons
- add_conversion_color_pair("#fce00e", "#aa8d24"); // New Single Tile
- add_conversion_color_pair("#0e71fc", "#0350bd"); // New Autotile
- add_conversion_color_pair("#c6ced4", "#828f9b"); // New Atlas
-
- // Variant types
- add_conversion_color_pair("#41ecad", "#25e3a0"); // Variant
- add_conversion_color_pair("#6f91f0", "#6d8eeb"); // bool
- add_conversion_color_pair("#5abbef", "#4fb2e9"); // int/uint
- add_conversion_color_pair("#35d4f4", "#27ccf0"); // float
- add_conversion_color_pair("#4593ec", "#4690e7"); // String
- add_conversion_color_pair("#ee5677", "#ee7991"); // AABB
- add_conversion_color_pair("#e0e0e0", "#5a5a5a"); // Array
- add_conversion_color_pair("#e1ec41", "#b2bb19"); // Basis
- add_conversion_color_pair("#54ed9e", "#57e99f"); // Dictionary
- add_conversion_color_pair("#417aec", "#6993ec"); // NodePath
- add_conversion_color_pair("#55f3e3", "#12d5c3"); // Object
- add_conversion_color_pair("#f74949", "#f77070"); // Plane
- add_conversion_color_pair("#44bd44", "#46b946"); // Projection
- add_conversion_color_pair("#ec418e", "#ec69a3"); // Quaternion
- add_conversion_color_pair("#f1738f", "#ee758e"); // Rect2
- add_conversion_color_pair("#41ec80", "#2ce573"); // RID
- add_conversion_color_pair("#b9ec41", "#96ce1a"); // Transform2D
- add_conversion_color_pair("#f68f45", "#f49047"); // Transform3D
- add_conversion_color_pair("#ac73f1", "#ad76ee"); // Vector2
- add_conversion_color_pair("#de66f0", "#dc6aed"); // Vector3
- add_conversion_color_pair("#f066bd", "#ed6abd"); // Vector4
-
- // Visual shaders
- add_conversion_color_pair("#77ce57", "#67c046"); // Vector funcs
- add_conversion_color_pair("#ea686c", "#d95256"); // Vector transforms
- add_conversion_color_pair("#eac968", "#d9b64f"); // Textures and cubemaps
- add_conversion_color_pair("#cf68ea", "#c050dd"); // Functions and expressions
-
- // These icons should not be converted.
- add_conversion_exception("EditorPivot");
- add_conversion_exception("EditorHandle");
- add_conversion_exception("Editor3DHandle");
- add_conversion_exception("EditorBoneHandle");
- add_conversion_exception("Godot");
- add_conversion_exception("Sky");
- add_conversion_exception("EditorControlAnchor");
- add_conversion_exception("DefaultProjectIcon");
- add_conversion_exception("ZoomMore");
- add_conversion_exception("ZoomLess");
- add_conversion_exception("ZoomReset");
- add_conversion_exception("LockViewport");
- add_conversion_exception("GroupViewport");
- add_conversion_exception("StatusError");
- add_conversion_exception("StatusSuccess");
- add_conversion_exception("StatusWarning");
- add_conversion_exception("OverbrightIndicator");
- add_conversion_exception("MaterialPreviewCube");
- add_conversion_exception("MaterialPreviewSphere");
- add_conversion_exception("MaterialPreviewLight1");
- add_conversion_exception("MaterialPreviewLight2");
-
- // GUI
- add_conversion_exception("GuiChecked");
- add_conversion_exception("GuiRadioChecked");
- add_conversion_exception("GuiIndeterminate");
- add_conversion_exception("GuiCloseCustomizable");
- add_conversion_exception("GuiGraphNodePort");
- add_conversion_exception("GuiResizer");
- add_conversion_exception("GuiMiniCheckerboard");
-
- /// Code Editor.
- add_conversion_exception("GuiTab");
- add_conversion_exception("GuiSpace");
- add_conversion_exception("CodeFoldedRightArrow");
- add_conversion_exception("CodeFoldDownArrow");
- add_conversion_exception("CodeRegionFoldedRightArrow");
- add_conversion_exception("CodeRegionFoldDownArrow");
- add_conversion_exception("TextEditorPlay");
- add_conversion_exception("Breakpoint");
-}
-
-void EditorColorMap::finish() {
- color_conversion_map.clear();
- color_conversion_exceptions.clear();
-}
-
-Vector<StringName> EditorTheme::editor_theme_types;
-
-// TODO: Refactor these and corresponding Theme methods to use the bool get_xxx(r_value) pattern internally.
-
-// Keep in sync with Theme::get_color.
-Color EditorTheme::get_color(const StringName &p_name, const StringName &p_theme_type) const {
- if (color_map.has(p_theme_type) && color_map[p_theme_type].has(p_name)) {
- return color_map[p_theme_type][p_name];
- } else {
- if (editor_theme_types.has(p_theme_type)) {
- WARN_PRINT(vformat("Trying to access a non-existing editor theme color '%s' in '%s'.", p_name, p_theme_type));
- }
- return Color();
- }
-}
-
-// Keep in sync with Theme::get_constant.
-int EditorTheme::get_constant(const StringName &p_name, const StringName &p_theme_type) const {
- if (constant_map.has(p_theme_type) && constant_map[p_theme_type].has(p_name)) {
- return constant_map[p_theme_type][p_name];
- } else {
- if (editor_theme_types.has(p_theme_type)) {
- WARN_PRINT(vformat("Trying to access a non-existing editor theme constant '%s' in '%s'.", p_name, p_theme_type));
- }
- return 0;
- }
-}
-
-// Keep in sync with Theme::get_font.
-Ref<Font> EditorTheme::get_font(const StringName &p_name, const StringName &p_theme_type) const {
- if (font_map.has(p_theme_type) && font_map[p_theme_type].has(p_name) && font_map[p_theme_type][p_name].is_valid()) {
- return font_map[p_theme_type][p_name];
- } else if (has_default_font()) {
- if (editor_theme_types.has(p_theme_type)) {
- WARN_PRINT(vformat("Trying to access a non-existing editor theme font '%s' in '%s'.", p_name, p_theme_type));
- }
- return default_font;
- } else {
- if (editor_theme_types.has(p_theme_type)) {
- WARN_PRINT(vformat("Trying to access a non-existing editor theme font '%s' in '%s'.", p_name, p_theme_type));
- }
- return ThemeDB::get_singleton()->get_fallback_font();
- }
-}
-
-// Keep in sync with Theme::get_font_size.
-int EditorTheme::get_font_size(const StringName &p_name, const StringName &p_theme_type) const {
- 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)) {
- return font_size_map[p_theme_type][p_name];
- } else if (has_default_font_size()) {
- if (editor_theme_types.has(p_theme_type)) {
- WARN_PRINT(vformat("Trying to access a non-existing editor theme font size '%s' in '%s'.", p_name, p_theme_type));
- }
- return default_font_size;
- } else {
- if (editor_theme_types.has(p_theme_type)) {
- WARN_PRINT(vformat("Trying to access a non-existing editor theme font size '%s' in '%s'.", p_name, p_theme_type));
- }
- return ThemeDB::get_singleton()->get_fallback_font_size();
- }
-}
-
-// Keep in sync with Theme::get_icon.
-Ref<Texture2D> EditorTheme::get_icon(const StringName &p_name, const StringName &p_theme_type) const {
- if (icon_map.has(p_theme_type) && icon_map[p_theme_type].has(p_name) && icon_map[p_theme_type][p_name].is_valid()) {
- return icon_map[p_theme_type][p_name];
- } else {
- if (editor_theme_types.has(p_theme_type)) {
- WARN_PRINT(vformat("Trying to access a non-existing editor theme icon '%s' in '%s'.", p_name, p_theme_type));
- }
- return ThemeDB::get_singleton()->get_fallback_icon();
- }
-}
-
-// Keep in sync with Theme::get_stylebox.
-Ref<StyleBox> EditorTheme::get_stylebox(const StringName &p_name, const StringName &p_theme_type) const {
- if (style_map.has(p_theme_type) && style_map[p_theme_type].has(p_name) && style_map[p_theme_type][p_name].is_valid()) {
- return style_map[p_theme_type][p_name];
- } else {
- if (editor_theme_types.has(p_theme_type)) {
- WARN_PRINT(vformat("Trying to access a non-existing editor theme stylebox '%s' in '%s'.", p_name, p_theme_type));
- }
- return ThemeDB::get_singleton()->get_fallback_stylebox();
- }
-}
-
-void EditorTheme::initialize() {
- editor_theme_types.append(EditorStringName(Editor));
- editor_theme_types.append(EditorStringName(EditorFonts));
- editor_theme_types.append(EditorStringName(EditorIcons));
- editor_theme_types.append(EditorStringName(EditorStyles));
-}
-
-void EditorTheme::finalize() {
- editor_theme_types.clear();
-}
-
-// Editor theme generatior.
-
-static 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) {
- Ref<StyleBoxTexture> style(memnew(StyleBoxTexture));
- style->set_texture(p_texture);
- style->set_texture_margin_individual(p_left * EDSCALE, p_top * EDSCALE, p_right * EDSCALE, p_bottom * EDSCALE);
- 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);
- style->set_draw_center(p_draw_center);
- return style;
-}
-
-static 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) {
- Ref<StyleBoxEmpty> style(memnew(StyleBoxEmpty));
- style->set_content_margin_individual(p_margin_left * EDSCALE, p_margin_top * EDSCALE, p_margin_right * EDSCALE, p_margin_bottom * EDSCALE);
- return style;
-}
-
-static 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) {
- Ref<StyleBoxFlat> style(memnew(StyleBoxFlat));
- style->set_bg_color(p_color);
- // Adjust level of detail based on the corners' effective sizes.
- style->set_corner_detail(Math::ceil(0.8 * p_corner_width * EDSCALE));
- style->set_corner_radius_all(p_corner_width * EDSCALE);
- style->set_content_margin_individual(p_margin_left * EDSCALE, p_margin_top * EDSCALE, p_margin_right * EDSCALE, p_margin_bottom * EDSCALE);
- // Work around issue about antialiased edges being blurrier (GH-35279).
- style->set_anti_aliased(false);
- return style;
-}
-
-static 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) {
- Ref<StyleBoxLine> style(memnew(StyleBoxLine));
- style->set_color(p_color);
- style->set_grow_begin(p_grow_begin);
- style->set_grow_end(p_grow_end);
- style->set_thickness(p_thickness);
- style->set_vertical(p_vertical);
- return style;
-}
-
-// See also `generate_icon()` in `scene/theme/default_theme.cpp`.
-static Ref<ImageTexture> editor_generate_icon(int p_index, float p_scale, float p_saturation, const HashMap<Color, Color> &p_convert_colors = HashMap<Color, Color>()) {
- Ref<Image> img = memnew(Image);
-
-#ifdef MODULE_SVG_ENABLED
- // Upsample icon generation only if the editor scale isn't an integer multiplier.
- // Generating upsampled icons is slower, and the benefit is hardly visible
- // with integer editor scales.
- const bool upsample = !Math::is_equal_approx(Math::round(p_scale), p_scale);
- Error err = ImageLoaderSVG::create_image_from_string(img, editor_icons_sources[p_index], p_scale, upsample, p_convert_colors);
- ERR_FAIL_COND_V_MSG(err != OK, Ref<ImageTexture>(), "Failed generating icon, unsupported or invalid SVG data in editor theme.");
- if (p_saturation != 1.0) {
- img->adjust_bcs(1.0, 1.0, p_saturation);
- }
-#else
- // If the SVG module is disabled, we can't really display the UI well, but at least we won't crash.
- // 16 pixels is used as it's the most common base size for Godot icons.
- img = Image::create_empty(16 * p_scale, 16 * p_scale, false, Image::FORMAT_RGBA8);
-#endif
-
- return ImageTexture::create_from_image(img);
-}
-
-float get_gizmo_handle_scale(const String &gizmo_handle_name = "") {
- const float scale_gizmo_handles_for_touch = EDITOR_GET("interface/touchscreen/scale_gizmo_handles");
- if (scale_gizmo_handles_for_touch > 1.0f) {
- // The names of the icons that require additional scaling.
- static HashSet<StringName> gizmo_to_scale;
- if (gizmo_to_scale.is_empty()) {
- gizmo_to_scale.insert("EditorHandle");
- gizmo_to_scale.insert("EditorHandleAdd");
- gizmo_to_scale.insert("EditorHandleDisabled");
- gizmo_to_scale.insert("EditorCurveHandle");
- gizmo_to_scale.insert("EditorPathSharpHandle");
- gizmo_to_scale.insert("EditorPathSmoothHandle");
- }
-
- if (gizmo_to_scale.has(gizmo_handle_name)) {
- return EDSCALE * scale_gizmo_handles_for_touch;
- }
- }
-
- return EDSCALE;
-}
-
-void 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) {
- const String benchmark_key = vformat("Generate Icons (%s)", (p_only_thumbs ? "Only Thumbs" : "All"));
- OS::get_singleton()->benchmark_begin_measure("EditorTheme", benchmark_key);
-
- // Before we register the icons, we adjust their colors and saturation.
- // Most icons follow the standard rules for color conversion to follow the editor
- // theme's polarity (dark/light). We also adjust the saturation for most icons,
- // following the editor setting.
- // Some icons are excluded from this conversion, and instead use the configured
- // accent color to replace their innate accent color to match the editor theme.
- // And then some icons are completely excluded from the conversion.
-
- // Standard color conversion map.
- HashMap<Color, Color> color_conversion_map;
- // Icons by default are set up for the dark theme, so if the theme is light,
- // we apply the dark-to-light color conversion map.
- if (!p_dark_theme) {
- for (KeyValue<Color, Color> &E : EditorColorMap::get_color_conversion_map()) {
- color_conversion_map[E.key] = E.value;
- }
- }
- // These colors should be converted even if we are using a dark theme.
- const Color error_color = p_theme->get_color(SNAME("error_color"), EditorStringName(Editor));
- const Color success_color = p_theme->get_color(SNAME("success_color"), EditorStringName(Editor));
- const Color warning_color = p_theme->get_color(SNAME("warning_color"), EditorStringName(Editor));
- color_conversion_map[Color::html("#ff5f5f")] = error_color;
- color_conversion_map[Color::html("#5fff97")] = success_color;
- color_conversion_map[Color::html("#ffdd65")] = warning_color;
-
- // The names of the icons to exclude from the standard color conversion.
- HashSet<StringName> conversion_exceptions = EditorColorMap::get_color_conversion_exceptions();
-
- // The names of the icons to exclude when adjusting for saturation.
- HashSet<StringName> saturation_exceptions;
- saturation_exceptions.insert("DefaultProjectIcon");
- saturation_exceptions.insert("Godot");
- saturation_exceptions.insert("Logo");
-
- // Accent color conversion map.
- // It is used on some icons (checkbox, radio, toggle, etc.), regardless of the dark
- // or light mode.
- HashMap<Color, Color> accent_color_map;
- HashSet<StringName> accent_color_icons;
-
- const Color accent_color = p_theme->get_color(SNAME("accent_color"), EditorStringName(Editor));
- accent_color_map[Color::html("699ce8")] = accent_color;
- if (accent_color.get_luminance() > 0.75) {
- accent_color_map[Color::html("ffffff")] = Color(0.2, 0.2, 0.2);
- }
-
- accent_color_icons.insert("GuiChecked");
- accent_color_icons.insert("GuiRadioChecked");
- accent_color_icons.insert("GuiIndeterminate");
- accent_color_icons.insert("GuiToggleOn");
- accent_color_icons.insert("GuiToggleOnMirrored");
- accent_color_icons.insert("PlayOverlay");
-
- // Generate icons.
- if (!p_only_thumbs) {
- for (int i = 0; i < editor_icons_count; i++) {
- Ref<ImageTexture> icon;
-
- const String &editor_icon_name = editor_icons_names[i];
- if (accent_color_icons.has(editor_icon_name)) {
- icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name), 1.0, accent_color_map);
- } else {
- float saturation = p_icon_saturation;
- if (saturation_exceptions.has(editor_icon_name)) {
- saturation = 1.0;
- }
-
- if (conversion_exceptions.has(editor_icon_name)) {
- icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name), saturation);
- } else {
- icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name), saturation, color_conversion_map);
- }
- }
-
- p_theme->set_icon(editor_icon_name, EditorStringName(EditorIcons), icon);
- }
- }
-
- // Generate thumbnail icons with the given thumbnail size.
- // See editor\icons\editor_icons_builders.py for the code that determines which icons are thumbnails.
- if (p_thumb_size >= 64) {
- const float scale = (float)p_thumb_size / 64.0 * EDSCALE;
- for (int i = 0; i < editor_bg_thumbs_count; i++) {
- const int index = editor_bg_thumbs_indices[i];
- Ref<ImageTexture> icon;
-
- if (accent_color_icons.has(editor_icons_names[index])) {
- icon = editor_generate_icon(index, scale, 1.0, accent_color_map);
- } else {
- float saturation = p_icon_saturation;
- if (saturation_exceptions.has(editor_icons_names[index])) {
- saturation = 1.0;
- }
-
- if (conversion_exceptions.has(editor_icons_names[index])) {
- icon = editor_generate_icon(index, scale, saturation);
- } else {
- icon = editor_generate_icon(index, scale, saturation, color_conversion_map);
- }
- }
-
- p_theme->set_icon(editor_icons_names[index], EditorStringName(EditorIcons), icon);
- }
- } else {
- const float scale = (float)p_thumb_size / 32.0 * EDSCALE;
- for (int i = 0; i < editor_md_thumbs_count; i++) {
- const int index = editor_md_thumbs_indices[i];
- Ref<ImageTexture> icon;
-
- if (accent_color_icons.has(editor_icons_names[index])) {
- icon = editor_generate_icon(index, scale, 1.0, accent_color_map);
- } else {
- float saturation = p_icon_saturation;
- if (saturation_exceptions.has(editor_icons_names[index])) {
- saturation = 1.0;
- }
-
- if (conversion_exceptions.has(editor_icons_names[index])) {
- icon = editor_generate_icon(index, scale, saturation);
- } else {
- icon = editor_generate_icon(index, scale, saturation, color_conversion_map);
- }
- }
-
- p_theme->set_icon(editor_icons_names[index], EditorStringName(EditorIcons), icon);
- }
- }
- OS::get_singleton()->benchmark_end_measure("EditorTheme", benchmark_key);
-}
-
-Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
- OS::get_singleton()->benchmark_begin_measure("EditorTheme", "Create Editor Theme");
- Ref<EditorTheme> theme = memnew(EditorTheme);
-
- // Controls may rely on the scale for their internal drawing logic.
- theme->set_default_base_scale(EDSCALE);
-
- // Theme settings
- Color accent_color = EDITOR_GET("interface/theme/accent_color");
- Color base_color = EDITOR_GET("interface/theme/base_color");
- float contrast = EDITOR_GET("interface/theme/contrast");
- bool increase_scrollbar_touch_area = EDITOR_GET("interface/touchscreen/increase_scrollbar_touch_area");
- const float gizmo_handle_scale = EDITOR_GET("interface/touchscreen/scale_gizmo_handles");
- bool draw_extra_borders = EDITOR_GET("interface/theme/draw_extra_borders");
- float icon_saturation = EDITOR_GET("interface/theme/icon_saturation");
- float relationship_line_opacity = EDITOR_GET("interface/theme/relationship_line_opacity");
-
- String preset = EDITOR_GET("interface/theme/preset");
-
- int border_size = EDITOR_GET("interface/theme/border_size");
- int corner_radius = EDITOR_GET("interface/theme/corner_radius");
-
- Color preset_accent_color;
- Color preset_base_color;
- float preset_contrast = 0;
- bool preset_draw_extra_borders = false;
-
- const float default_contrast = 0.3;
-
- // Please use alphabetical order if you're adding a new theme here
- // (after "Custom")
-
- if (preset == "Custom") {
- accent_color = EDITOR_GET("interface/theme/accent_color");
- base_color = EDITOR_GET("interface/theme/base_color");
- contrast = EDITOR_GET("interface/theme/contrast");
- } else if (preset == "Breeze Dark") {
- preset_accent_color = Color(0.26, 0.76, 1.00);
- preset_base_color = Color(0.24, 0.26, 0.28);
- preset_contrast = default_contrast;
- } else if (preset == "Godot 2") {
- preset_accent_color = Color(0.53, 0.67, 0.89);
- preset_base_color = Color(0.24, 0.23, 0.27);
- preset_contrast = default_contrast;
- } else if (preset == "Gray") {
- preset_accent_color = Color(0.44, 0.73, 0.98);
- preset_base_color = Color(0.24, 0.24, 0.24);
- preset_contrast = default_contrast;
- } else if (preset == "Light") {
- preset_accent_color = Color(0.18, 0.50, 1.00);
- preset_base_color = Color(0.9, 0.9, 0.9);
- // A negative contrast rate looks better for light themes, since it better follows the natural order of UI "elevation".
- preset_contrast = -0.06;
- } else if (preset == "Solarized (Dark)") {
- preset_accent_color = Color(0.15, 0.55, 0.82);
- preset_base_color = Color(0.04, 0.23, 0.27);
- preset_contrast = default_contrast;
- } else if (preset == "Solarized (Light)") {
- preset_accent_color = Color(0.15, 0.55, 0.82);
- preset_base_color = Color(0.89, 0.86, 0.79);
- // A negative contrast rate looks better for light themes, since it better follows the natural order of UI "elevation".
- preset_contrast = -0.06;
- } else if (preset == "Black (OLED)") {
- preset_accent_color = Color(0.45, 0.75, 1.0);
- preset_base_color = Color(0, 0, 0);
- // The contrast rate value is irrelevant on a fully black theme.
- preset_contrast = 0.0;
- preset_draw_extra_borders = true;
- } else { // Default
- preset_accent_color = Color(0.44, 0.73, 0.98);
- preset_base_color = Color(0.21, 0.24, 0.29);
- preset_contrast = default_contrast;
- }
-
- if (preset != "Custom") {
- accent_color = preset_accent_color;
- base_color = preset_base_color;
- contrast = preset_contrast;
- draw_extra_borders = preset_draw_extra_borders;
- EditorSettings::get_singleton()->set_initial_value("interface/theme/accent_color", accent_color);
- EditorSettings::get_singleton()->set_initial_value("interface/theme/base_color", base_color);
- EditorSettings::get_singleton()->set_initial_value("interface/theme/contrast", contrast);
- EditorSettings::get_singleton()->set_initial_value("interface/theme/draw_extra_borders", draw_extra_borders);
- }
-
- EditorSettings::get_singleton()->set_manually("interface/theme/preset", preset);
- EditorSettings::get_singleton()->set_manually("interface/theme/accent_color", accent_color);
- EditorSettings::get_singleton()->set_manually("interface/theme/base_color", base_color);
- EditorSettings::get_singleton()->set_manually("interface/theme/contrast", contrast);
- EditorSettings::get_singleton()->set_manually("interface/theme/draw_extra_borders", draw_extra_borders);
-
- // Colors
- bool dark_theme = EditorSettings::get_singleton()->is_dark_theme();
-
-#ifdef MODULE_SVG_ENABLED
- if (dark_theme) {
- ImageLoaderSVG::set_forced_color_map(HashMap<Color, Color>());
- } else {
- ImageLoaderSVG::set_forced_color_map(EditorColorMap::get_color_conversion_map());
- }
-#endif
-
- // Ensure base colors are in the 0..1 luminance range to avoid 8-bit integer overflow or text rendering issues.
- // Some places in the editor use 8-bit integer colors.
- const Color dark_color_1 = base_color.lerp(Color(0, 0, 0, 1), contrast).clamp();
- const Color dark_color_2 = base_color.lerp(Color(0, 0, 0, 1), contrast * 1.5).clamp();
- const Color dark_color_3 = base_color.lerp(Color(0, 0, 0, 1), contrast * 2).clamp();
-
- // Only used when the Draw Extra Borders editor setting is enabled.
- const Color extra_border_color_1 = Color(0.5, 0.5, 0.5);
- const Color extra_border_color_2 = dark_theme ? Color(0.3, 0.3, 0.3) : Color(0.7, 0.7, 0.7);
-
- const Color background_color = dark_color_2;
-
- // White (dark theme) or black (light theme), will be used to generate the rest of the colors
- const Color mono_color = dark_theme ? Color(1, 1, 1) : Color(0, 0, 0);
-
- const Color contrast_color_1 = base_color.lerp(mono_color, MAX(contrast, default_contrast));
- const Color contrast_color_2 = base_color.lerp(mono_color, MAX(contrast * 1.5, default_contrast * 1.5));
-
- const Color font_color = mono_color.lerp(base_color, 0.25);
- const Color font_hover_color = mono_color.lerp(base_color, 0.125);
- const Color font_focus_color = mono_color.lerp(base_color, 0.125);
- const Color font_hover_pressed_color = font_hover_color.lerp(accent_color, 0.74);
- const Color font_disabled_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.35);
- const Color font_readonly_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.65);
- const Color font_placeholder_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.6);
- const Color font_outline_color = Color(0, 0, 0, 0);
- const Color selection_color = accent_color * Color(1, 1, 1, 0.4);
- const Color disabled_color = mono_color.inverted().lerp(base_color, 0.7);
- const Color disabled_bg_color = mono_color.inverted().lerp(base_color, 0.9);
-
- const Color icon_normal_color = Color(1, 1, 1);
- Color icon_hover_color = icon_normal_color * (dark_theme ? 1.15 : 1.45);
- icon_hover_color.a = 1.0;
- Color icon_focus_color = icon_hover_color;
- Color icon_disabled_color = Color(icon_normal_color, 0.4);
- // Make the pressed icon color overbright because icons are not completely white on a dark theme.
- // On a light theme, icons are dark, so we need to modulate them with an even brighter color.
- Color icon_pressed_color = accent_color * (dark_theme ? 1.15 : 3.5);
- icon_pressed_color.a = 1.0;
-
- const Color separator_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.1);
- const Color highlight_color = Color(accent_color.r, accent_color.g, accent_color.b, 0.275);
- const Color disabled_highlight_color = highlight_color.lerp(dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.5);
-
- // Can't save single float in theme, so using Color.
- theme->set_color("icon_saturation", EditorStringName(Editor), Color(icon_saturation, icon_saturation, icon_saturation));
- theme->set_color("accent_color", EditorStringName(Editor), accent_color);
- theme->set_color("highlight_color", EditorStringName(Editor), highlight_color);
- theme->set_color("disabled_highlight_color", EditorStringName(Editor), disabled_highlight_color);
- theme->set_color("base_color", EditorStringName(Editor), base_color);
- theme->set_color("dark_color_1", EditorStringName(Editor), dark_color_1);
- theme->set_color("dark_color_2", EditorStringName(Editor), dark_color_2);
- theme->set_color("dark_color_3", EditorStringName(Editor), dark_color_3);
- theme->set_color("contrast_color_1", EditorStringName(Editor), contrast_color_1);
- theme->set_color("contrast_color_2", EditorStringName(Editor), contrast_color_2);
- theme->set_color("box_selection_fill_color", EditorStringName(Editor), accent_color * Color(1, 1, 1, 0.3));
- theme->set_color("box_selection_stroke_color", EditorStringName(Editor), accent_color * Color(1, 1, 1, 0.8));
-
- theme->set_color("axis_x_color", EditorStringName(Editor), Color(0.96, 0.20, 0.32));
- theme->set_color("axis_y_color", EditorStringName(Editor), Color(0.53, 0.84, 0.01));
- theme->set_color("axis_z_color", EditorStringName(Editor), Color(0.16, 0.55, 0.96));
- theme->set_color("axis_w_color", EditorStringName(Editor), Color(0.55, 0.55, 0.55));
-
- const float prop_color_saturation = accent_color.get_s() * 0.75;
- const float prop_color_value = accent_color.get_v();
-
- theme->set_color("property_color_x", EditorStringName(Editor), Color().from_hsv(0.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value));
- theme->set_color("property_color_y", EditorStringName(Editor), Color().from_hsv(1.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value));
- theme->set_color("property_color_z", EditorStringName(Editor), Color().from_hsv(2.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value));
- theme->set_color("property_color_w", EditorStringName(Editor), Color().from_hsv(1.5 / 3.0 + 0.05, prop_color_saturation, prop_color_value));
-
- theme->set_color("font_color", EditorStringName(Editor), font_color);
- theme->set_color("highlighted_font_color", EditorStringName(Editor), font_hover_color);
- theme->set_color("disabled_font_color", EditorStringName(Editor), font_disabled_color);
- theme->set_color("readonly_font_color", EditorStringName(Editor), font_readonly_color);
-
- theme->set_color("mono_color", EditorStringName(Editor), mono_color);
-
- Color success_color = Color(0.45, 0.95, 0.5);
- Color warning_color = Color(1, 0.87, 0.4);
- Color error_color = Color(1, 0.47, 0.42);
- Color property_color = font_color.lerp(Color(0.5, 0.5, 0.5), 0.5);
- Color readonly_color = property_color.lerp(dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.25);
- Color readonly_warning_color = error_color.lerp(dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.25);
-
- if (!dark_theme) {
- // Darken some colors to be readable on a light background.
- success_color = success_color.lerp(mono_color, 0.35);
- warning_color = warning_color.lerp(mono_color, 0.35);
- error_color = error_color.lerp(mono_color, 0.25);
- }
-
- theme->set_color("success_color", EditorStringName(Editor), success_color);
- theme->set_color("warning_color", EditorStringName(Editor), warning_color);
- theme->set_color("error_color", EditorStringName(Editor), error_color);
- theme->set_color("property_color", EditorStringName(Editor), property_color);
- theme->set_color("readonly_color", EditorStringName(Editor), readonly_color);
-
- if (!dark_theme) {
- theme->set_color("highend_color", EditorStringName(Editor), Color::hex(0xad1128ff));
- } else {
- theme->set_color("highend_color", EditorStringName(Editor), Color(1.0, 0.0, 0.0));
- }
-
- const int thumb_size = EDITOR_GET("filesystem/file_dialog/thumbnail_size");
- theme->set_constant("scale", EditorStringName(Editor), EDSCALE);
- theme->set_constant("thumb_size", EditorStringName(Editor), thumb_size);
- theme->set_constant("class_icon_size", EditorStringName(Editor), 16 * EDSCALE);
- theme->set_constant("dark_theme", EditorStringName(Editor), dark_theme);
- theme->set_constant("color_picker_button_height", EditorStringName(Editor), 28 * EDSCALE);
- theme->set_constant("gizmo_handle_scale", EditorStringName(Editor), gizmo_handle_scale);
- theme->set_constant("window_border_margin", EditorStringName(Editor), 8);
- theme->set_constant("top_bar_separation", EditorStringName(Editor), 8 * EDSCALE);
-
- // Register editor icons.
- // If the settings are comparable to the old theme, then just copy them over.
- // Otherwise, regenerate them. Also check if we need to regenerate "thumb" icons.
- bool keep_old_icons = false;
- bool regenerate_thumb_icons = true;
- if (p_theme != nullptr) {
- // We check editor scale, theme dark/light mode, icon saturation, and accent color.
-
- // That doesn't really work as expected, since theme constants are integers, and scales are floats.
- // So this check will never work when changing between 100-199% values.
- const float prev_scale = (float)p_theme->get_constant(SNAME("scale"), EditorStringName(Editor));
- const bool prev_dark_theme = (bool)p_theme->get_constant(SNAME("dark_theme"), EditorStringName(Editor));
- const Color prev_accent_color = p_theme->get_color(SNAME("accent_color"), EditorStringName(Editor));
- const float prev_icon_saturation = p_theme->get_color(SNAME("icon_saturation"), EditorStringName(Editor)).r;
- const float prev_gizmo_handle_scale = (float)p_theme->get_constant(SNAME("gizmo_handle_scale"), EditorStringName(Editor));
-
- keep_old_icons = (Math::is_equal_approx(prev_scale, EDSCALE) &&
- Math::is_equal_approx(prev_gizmo_handle_scale, gizmo_handle_scale) &&
- prev_dark_theme == dark_theme &&
- prev_accent_color == accent_color &&
- prev_icon_saturation == icon_saturation);
-
- const double prev_thumb_size = (double)p_theme->get_constant(SNAME("thumb_size"), EditorStringName(Editor));
-
- regenerate_thumb_icons = !Math::is_equal_approx(prev_thumb_size, thumb_size);
- }
-
-#ifndef MODULE_SVG_ENABLED
- WARN_PRINT("SVG support disabled, editor icons won't be rendered.");
-#endif
-
- if (keep_old_icons) {
- for (int i = 0; i < editor_icons_count; i++) {
- theme->set_icon(editor_icons_names[i], EditorStringName(EditorIcons), p_theme->get_icon(editor_icons_names[i], EditorStringName(EditorIcons)));
- }
- } else {
- editor_register_and_generate_icons(theme, dark_theme, icon_saturation, thumb_size, false);
- }
- if (regenerate_thumb_icons) {
- editor_register_and_generate_icons(theme, dark_theme, icon_saturation, thumb_size, true);
- }
-
- // Register editor fonts.
- editor_register_fonts(theme);
-
- // Ensure borders are visible when using an editor scale below 100%.
- const int border_width = CLAMP(border_size, 0, 2) * MAX(1, EDSCALE);
- const int corner_width = CLAMP(corner_radius, 0, 6);
- const int default_margin_size = 4;
- const int margin_size_extra = default_margin_size + CLAMP(border_size, 0, 2);
-
- // Styleboxes
- // This is the most commonly used stylebox, variations should be made as duplicate of this
- Ref<StyleBoxFlat> style_default = make_flat_stylebox(base_color, default_margin_size, default_margin_size, default_margin_size, default_margin_size, corner_width);
- style_default->set_border_width_all(border_width);
- style_default->set_border_color(base_color);
-
- // Button and widgets
- const float extra_spacing = EDITOR_GET("interface/theme/additional_spacing");
-
- const Vector2 widget_default_margin = Vector2(extra_spacing + 6, extra_spacing + default_margin_size + 1) * EDSCALE;
-
- Ref<StyleBoxFlat> style_widget = style_default->duplicate();
- style_widget->set_content_margin_individual(widget_default_margin.x, widget_default_margin.y, widget_default_margin.x, widget_default_margin.y);
- style_widget->set_bg_color(dark_color_1);
- if (draw_extra_borders) {
- style_widget->set_border_width_all(Math::round(EDSCALE));
- style_widget->set_border_color(extra_border_color_1);
- } else {
- style_widget->set_border_color(dark_color_2);
- }
-
- Ref<StyleBoxFlat> style_widget_disabled = style_widget->duplicate();
- if (draw_extra_borders) {
- style_widget_disabled->set_border_color(extra_border_color_2);
- } else {
- style_widget_disabled->set_border_color(disabled_color);
- }
- style_widget_disabled->set_bg_color(disabled_bg_color);
-
- Ref<StyleBoxFlat> style_widget_focus = style_widget->duplicate();
- style_widget_focus->set_draw_center(false);
- style_widget_focus->set_border_width_all(Math::round(2 * MAX(1, EDSCALE)));
- style_widget_focus->set_border_color(accent_color);
-
- Ref<StyleBoxFlat> style_widget_pressed = style_widget->duplicate();
- style_widget_pressed->set_bg_color(dark_color_1.darkened(0.125));
-
- Ref<StyleBoxFlat> style_widget_hover = style_widget->duplicate();
- style_widget_hover->set_bg_color(mono_color * Color(1, 1, 1, 0.11));
- if (draw_extra_borders) {
- style_widget_hover->set_border_color(extra_border_color_1);
- } else {
- style_widget_hover->set_border_color(mono_color * Color(1, 1, 1, 0.05));
- }
-
- // Style for windows, popups, etc..
- Ref<StyleBoxFlat> style_popup = style_default->duplicate();
- const int popup_margin_size = default_margin_size * EDSCALE * 3;
- style_popup->set_content_margin_all(popup_margin_size);
- style_popup->set_border_color(contrast_color_1);
- const Color shadow_color = Color(0, 0, 0, dark_theme ? 0.3 : 0.1);
- style_popup->set_shadow_color(shadow_color);
- style_popup->set_shadow_size(4 * EDSCALE);
- // Popups are separate windows by default in the editor. Windows currently don't support per-pixel transparency
- // in 4.0, and even if it was, it may not always work in practice (e.g. running with compositing disabled).
- style_popup->set_corner_radius_all(0);
-
- Ref<StyleBoxLine> style_popup_separator(memnew(StyleBoxLine));
- style_popup_separator->set_color(separator_color);
- style_popup_separator->set_grow_begin(popup_margin_size - MAX(Math::round(EDSCALE), border_width));
- style_popup_separator->set_grow_end(popup_margin_size - MAX(Math::round(EDSCALE), border_width));
- style_popup_separator->set_thickness(MAX(Math::round(EDSCALE), border_width));
-
- Ref<StyleBoxLine> style_popup_labeled_separator_left(memnew(StyleBoxLine));
- style_popup_labeled_separator_left->set_grow_begin(popup_margin_size - MAX(Math::round(EDSCALE), border_width));
- style_popup_labeled_separator_left->set_color(separator_color);
- style_popup_labeled_separator_left->set_thickness(MAX(Math::round(EDSCALE), border_width));
-
- Ref<StyleBoxLine> style_popup_labeled_separator_right(memnew(StyleBoxLine));
- style_popup_labeled_separator_right->set_grow_end(popup_margin_size - MAX(Math::round(EDSCALE), border_width));
- style_popup_labeled_separator_right->set_color(separator_color);
- style_popup_labeled_separator_right->set_thickness(MAX(Math::round(EDSCALE), border_width));
-
- Ref<StyleBoxEmpty> style_empty = make_empty_stylebox(default_margin_size, default_margin_size, default_margin_size, default_margin_size);
-
- // TabBar
-
- Ref<StyleBoxFlat> style_tab_base = style_widget->duplicate();
-
- style_tab_base->set_border_width_all(0);
- // Don't round the top corners to avoid creating a small blank space between the tabs and the main panel.
- // This also makes the top highlight look better.
- style_tab_base->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
- style_tab_base->set_corner_radius(CORNER_BOTTOM_RIGHT, 0);
-
- // When using a border width greater than 0, visually line up the left of the selected tab with the underlying panel.
- style_tab_base->set_expand_margin(SIDE_LEFT, -border_width);
-
- style_tab_base->set_content_margin(SIDE_LEFT, widget_default_margin.x + 5 * EDSCALE);
- style_tab_base->set_content_margin(SIDE_RIGHT, widget_default_margin.x + 5 * EDSCALE);
- style_tab_base->set_content_margin(SIDE_BOTTOM, widget_default_margin.y);
- style_tab_base->set_content_margin(SIDE_TOP, widget_default_margin.y);
-
- Ref<StyleBoxFlat> style_tab_selected = style_tab_base->duplicate();
-
- style_tab_selected->set_bg_color(base_color);
- // Add a highlight line at the top of the selected tab.
- style_tab_selected->set_border_width(SIDE_TOP, Math::round(2 * EDSCALE));
- // Make the highlight line prominent, but not too prominent as to not be distracting.
- Color tab_highlight = dark_color_2.lerp(accent_color, 0.75);
- style_tab_selected->set_border_color(tab_highlight);
- style_tab_selected->set_corner_radius_all(0);
-
- Ref<StyleBoxFlat> style_tab_hovered = style_tab_base->duplicate();
-
- style_tab_hovered->set_bg_color(dark_color_1.lerp(base_color, 0.4));
- // Hovered tab has a subtle highlight between normal and selected states.
- style_tab_hovered->set_corner_radius_all(0);
-
- Ref<StyleBoxFlat> style_tab_unselected = style_tab_base->duplicate();
- style_tab_unselected->set_expand_margin(SIDE_BOTTOM, 0);
- style_tab_unselected->set_bg_color(dark_color_1);
- // Add some spacing between unselected tabs to make them easier to distinguish from each other
- style_tab_unselected->set_border_color(Color(0, 0, 0, 0));
-
- Ref<StyleBoxFlat> style_tab_disabled = style_tab_base->duplicate();
- style_tab_disabled->set_expand_margin(SIDE_BOTTOM, 0);
- style_tab_disabled->set_bg_color(disabled_bg_color);
- style_tab_disabled->set_border_color(disabled_bg_color);
-
- Ref<StyleBoxFlat> style_tab_focus = style_widget_focus->duplicate();
-
- // Editor background
- Color background_color_opaque = background_color;
- background_color_opaque.a = 1.0;
- theme->set_color("background", EditorStringName(Editor), background_color_opaque);
- theme->set_stylebox("Background", EditorStringName(EditorStyles), make_flat_stylebox(background_color_opaque, default_margin_size, default_margin_size, default_margin_size, default_margin_size));
-
- // Focus
- theme->set_stylebox("Focus", EditorStringName(EditorStyles), style_widget_focus);
- // Use a less opaque color to be less distracting for the 2D and 3D editor viewports.
- Ref<StyleBoxFlat> style_widget_focus_viewport = style_widget_focus->duplicate();
- style_widget_focus_viewport->set_border_color(accent_color * Color(1, 1, 1, 0.5));
- theme->set_stylebox("FocusViewport", EditorStringName(EditorStyles), style_widget_focus_viewport);
-
- // Menu
- Ref<StyleBoxFlat> style_menu = style_widget->duplicate();
- style_menu->set_draw_center(false);
- style_menu->set_border_width_all(0);
- theme->set_stylebox("panel", "PanelContainer", style_menu);
- theme->set_stylebox("MenuPanel", EditorStringName(EditorStyles), style_menu);
-
- // CanvasItem Editor
- Ref<StyleBoxFlat> style_canvas_editor_info = make_flat_stylebox(Color(0.0, 0.0, 0.0, 0.2));
- style_canvas_editor_info->set_expand_margin_all(4 * EDSCALE);
- theme->set_stylebox("CanvasItemInfoOverlay", EditorStringName(EditorStyles), style_canvas_editor_info);
-
- // 2D and 3D contextual toolbar.
- // Use a custom stylebox to make contextual menu items stand out from the rest.
- // This helps with editor usability as contextual menu items change when selecting nodes,
- // even though it may not be immediately obvious at first.
- Ref<StyleBoxFlat> toolbar_stylebox = memnew(StyleBoxFlat);
- toolbar_stylebox->set_bg_color(accent_color * Color(1, 1, 1, 0.1));
- toolbar_stylebox->set_anti_aliased(false);
- // Add an underline to the StyleBox, but prevent its minimum vertical size from changing.
- toolbar_stylebox->set_border_color(accent_color);
- toolbar_stylebox->set_border_width(SIDE_BOTTOM, Math::round(2 * EDSCALE));
- toolbar_stylebox->set_content_margin(SIDE_BOTTOM, 0);
- toolbar_stylebox->set_expand_margin_individual(4 * EDSCALE, 2 * EDSCALE, 4 * EDSCALE, 4 * EDSCALE);
- theme->set_stylebox("ContextualToolbar", EditorStringName(EditorStyles), toolbar_stylebox);
-
- // Script Editor
- theme->set_stylebox("ScriptEditorPanel", EditorStringName(EditorStyles), make_empty_stylebox(default_margin_size, 0, default_margin_size, default_margin_size));
- theme->set_stylebox("ScriptEditorPanelFloating", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0));
-
- theme->set_stylebox("ScriptEditor", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0));
-
- // Launch Pad and Play buttons
- Ref<StyleBoxFlat> style_launch_pad = make_flat_stylebox(dark_color_1, 2 * EDSCALE, 0, 2 * EDSCALE, 0, corner_width);
- style_launch_pad->set_corner_radius_all(corner_radius * EDSCALE);
- theme->set_stylebox("LaunchPadNormal", EditorStringName(EditorStyles), style_launch_pad);
- Ref<StyleBoxFlat> style_launch_pad_movie = style_launch_pad->duplicate();
- style_launch_pad_movie->set_bg_color(accent_color * Color(1, 1, 1, 0.1));
- style_launch_pad_movie->set_border_color(accent_color);
- style_launch_pad_movie->set_border_width_all(Math::round(2 * EDSCALE));
- theme->set_stylebox("LaunchPadMovieMode", EditorStringName(EditorStyles), style_launch_pad_movie);
-
- theme->set_stylebox("MovieWriterButtonNormal", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0));
- Ref<StyleBoxFlat> style_write_movie_button = style_widget_pressed->duplicate();
- style_write_movie_button->set_bg_color(accent_color);
- style_write_movie_button->set_corner_radius_all(corner_radius * EDSCALE);
- style_write_movie_button->set_content_margin(SIDE_TOP, 0);
- style_write_movie_button->set_content_margin(SIDE_BOTTOM, 0);
- style_write_movie_button->set_content_margin(SIDE_LEFT, 0);
- style_write_movie_button->set_content_margin(SIDE_RIGHT, 0);
- style_write_movie_button->set_expand_margin(SIDE_RIGHT, 2 * EDSCALE);
- theme->set_stylebox("MovieWriterButtonPressed", EditorStringName(EditorStyles), style_write_movie_button);
-
- // MenuButton
- theme->set_stylebox("normal", "MenuButton", style_menu);
- theme->set_stylebox("hover", "MenuButton", style_widget_hover);
- theme->set_stylebox("pressed", "MenuButton", style_menu);
- theme->set_stylebox("focus", "MenuButton", style_menu);
- theme->set_stylebox("disabled", "MenuButton", style_menu);
-
- theme->set_color("font_color", "MenuButton", font_color);
- theme->set_color("font_hover_color", "MenuButton", font_hover_color);
- theme->set_color("font_hover_pressed_color", "MenuButton", font_hover_pressed_color);
- theme->set_color("font_focus_color", "MenuButton", font_focus_color);
- theme->set_color("font_outline_color", "MenuButton", font_outline_color);
-
- theme->set_constant("outline_size", "MenuButton", 0);
-
- theme->set_stylebox("MenuHover", EditorStringName(EditorStyles), style_widget_hover);
-
- // Buttons
- theme->set_stylebox("normal", "Button", style_widget);
- theme->set_stylebox("hover", "Button", style_widget_hover);
- theme->set_stylebox("pressed", "Button", style_widget_pressed);
- theme->set_stylebox("focus", "Button", style_widget_focus);
- theme->set_stylebox("disabled", "Button", style_widget_disabled);
-
- theme->set_color("font_color", "Button", font_color);
- theme->set_color("font_hover_color", "Button", font_hover_color);
- theme->set_color("font_hover_pressed_color", "Button", font_hover_pressed_color);
- theme->set_color("font_focus_color", "Button", font_focus_color);
- theme->set_color("font_pressed_color", "Button", accent_color);
- theme->set_color("font_disabled_color", "Button", font_disabled_color);
- theme->set_color("font_outline_color", "Button", font_outline_color);
-
- theme->set_color("icon_normal_color", "Button", icon_normal_color);
- theme->set_color("icon_hover_color", "Button", icon_hover_color);
- theme->set_color("icon_focus_color", "Button", icon_focus_color);
- theme->set_color("icon_pressed_color", "Button", icon_pressed_color);
- theme->set_color("icon_disabled_color", "Button", icon_disabled_color);
-
- theme->set_constant("h_separation", "Button", 4 * EDSCALE);
- theme->set_constant("outline_size", "Button", 0);
-
- // Flat button variations.
-
- Ref<StyleBoxEmpty> style_flat_button = make_empty_stylebox();
- for (int i = 0; i < 4; i++) {
- style_flat_button->set_content_margin((Side)i, style_widget->get_margin((Side)i) + style_widget->get_border_width((Side)i));
- }
-
- Ref<StyleBoxFlat> style_flat_button_pressed = style_widget_pressed->duplicate();
- Color flat_pressed_color = dark_color_1.lightened(0.24).lerp(accent_color, 0.2) * Color(0.8, 0.8, 0.8, 0.85);
- if (dark_theme) {
- flat_pressed_color = dark_color_1.lerp(accent_color, 0.12) * Color(0.6, 0.6, 0.6, 0.85);
- }
- style_flat_button_pressed->set_bg_color(flat_pressed_color);
-
- theme->set_stylebox("normal", "FlatButton", style_flat_button);
- theme->set_stylebox("hover", "FlatButton", style_flat_button);
- theme->set_stylebox("pressed", "FlatButton", style_flat_button_pressed);
- theme->set_stylebox("disabled", "FlatButton", style_flat_button);
-
- theme->set_stylebox("normal", "FlatMenuButton", style_flat_button);
- theme->set_stylebox("hover", "FlatMenuButton", style_flat_button);
- theme->set_stylebox("pressed", "FlatMenuButton", style_flat_button_pressed);
- theme->set_stylebox("disabled", "FlatMenuButton", style_flat_button);
-
- const float ACTION_BUTTON_EXTRA_MARGIN = 32 * EDSCALE;
-
- theme->set_type_variation("InspectorActionButton", "Button");
- Color color_inspector_action = dark_color_1.lerp(mono_color, 0.12);
- color_inspector_action.a = 0.5;
- Ref<StyleBoxFlat> style_inspector_action = style_widget->duplicate();
- style_inspector_action->set_bg_color(color_inspector_action);
- style_inspector_action->set_content_margin(SIDE_RIGHT, ACTION_BUTTON_EXTRA_MARGIN);
- theme->set_stylebox("normal", "InspectorActionButton", style_inspector_action);
- style_inspector_action = style_widget_hover->duplicate();
- style_inspector_action->set_content_margin(SIDE_RIGHT, ACTION_BUTTON_EXTRA_MARGIN);
- theme->set_stylebox("hover", "InspectorActionButton", style_inspector_action);
- style_inspector_action = style_widget_pressed->duplicate();
- style_inspector_action->set_content_margin(SIDE_RIGHT, ACTION_BUTTON_EXTRA_MARGIN);
- theme->set_stylebox("pressed", "InspectorActionButton", style_inspector_action);
- style_inspector_action = style_widget_disabled->duplicate();
- style_inspector_action->set_content_margin(SIDE_RIGHT, ACTION_BUTTON_EXTRA_MARGIN);
- theme->set_stylebox("disabled", "InspectorActionButton", style_inspector_action);
- theme->set_constant("h_separation", "InspectorActionButton", ACTION_BUTTON_EXTRA_MARGIN);
-
- // Variation for Editor Log filter buttons
- theme->set_type_variation("EditorLogFilterButton", "Button");
- // When pressed, don't tint the icons with the accent color, just leave them normal.
- theme->set_color("icon_pressed_color", "EditorLogFilterButton", icon_normal_color);
- // When unpressed, dim the icons.
- theme->set_color("icon_normal_color", "EditorLogFilterButton", icon_disabled_color);
- // When pressed, add a small bottom border to the buttons to better show their active state,
- // similar to active tabs.
-
- Ref<StyleBoxFlat> editor_log_button_pressed = style_flat_button_pressed->duplicate();
- editor_log_button_pressed->set_border_width(SIDE_BOTTOM, 2 * EDSCALE);
- editor_log_button_pressed->set_border_color(accent_color);
- theme->set_stylebox("pressed", "EditorLogFilterButton", editor_log_button_pressed);
-
- // Buttons in material previews
- const Color dim_light_color = icon_normal_color.darkened(0.24);
- const Color dim_light_highlighted_color = icon_normal_color.darkened(0.18);
- Ref<StyleBox> sb_empty_borderless = make_empty_stylebox();
-
- theme->set_type_variation("PreviewLightButton", "Button");
- // When pressed, don't use the accent color tint. When unpressed, dim the icon.
- theme->set_color("icon_normal_color", "PreviewLightButton", dim_light_color);
- theme->set_color("icon_focus_color", "PreviewLightButton", dim_light_color);
- theme->set_color("icon_pressed_color", "PreviewLightButton", icon_normal_color);
- theme->set_color("icon_hover_pressed_color", "PreviewLightButton", icon_normal_color);
- // Unpressed icon is dim, so use a dim highlight.
- theme->set_color("icon_hover_color", "PreviewLightButton", dim_light_highlighted_color);
-
- theme->set_stylebox("normal", "PreviewLightButton", sb_empty_borderless);
- theme->set_stylebox("hover", "PreviewLightButton", sb_empty_borderless);
- theme->set_stylebox("focus", "PreviewLightButton", sb_empty_borderless);
- theme->set_stylebox("pressed", "PreviewLightButton", sb_empty_borderless);
-
- // ProjectTag
- {
- theme->set_type_variation("ProjectTag", "Button");
-
- Ref<StyleBoxFlat> tag = style_widget->duplicate();
- tag->set_bg_color(dark_theme ? tag->get_bg_color().lightened(0.2) : tag->get_bg_color().darkened(0.2));
- tag->set_corner_radius(CORNER_TOP_LEFT, 0);
- tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
- tag->set_corner_radius(CORNER_TOP_RIGHT, 4);
- tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4);
- theme->set_stylebox("normal", "ProjectTag", tag);
-
- tag = style_widget_hover->duplicate();
- tag->set_corner_radius(CORNER_TOP_LEFT, 0);
- tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
- tag->set_corner_radius(CORNER_TOP_RIGHT, 4);
- tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4);
- theme->set_stylebox("hover", "ProjectTag", tag);
-
- tag = style_widget_pressed->duplicate();
- tag->set_corner_radius(CORNER_TOP_LEFT, 0);
- tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
- tag->set_corner_radius(CORNER_TOP_RIGHT, 4);
- tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4);
- theme->set_stylebox("pressed", "ProjectTag", tag);
- }
-
- // MenuBar
- theme->set_stylebox("normal", "MenuBar", style_widget);
- theme->set_stylebox("hover", "MenuBar", style_widget_hover);
- theme->set_stylebox("pressed", "MenuBar", style_widget_pressed);
- theme->set_stylebox("disabled", "MenuBar", style_widget_disabled);
-
- theme->set_color("font_color", "MenuBar", font_color);
- theme->set_color("font_hover_color", "MenuBar", font_hover_color);
- theme->set_color("font_hover_pressed_color", "MenuBar", font_hover_pressed_color);
- theme->set_color("font_focus_color", "MenuBar", font_focus_color);
- theme->set_color("font_pressed_color", "MenuBar", accent_color);
- theme->set_color("font_disabled_color", "MenuBar", font_disabled_color);
- theme->set_color("font_outline_color", "MenuBar", font_outline_color);
-
- theme->set_color("icon_normal_color", "MenuBar", icon_normal_color);
- theme->set_color("icon_hover_color", "MenuBar", icon_hover_color);
- theme->set_color("icon_focus_color", "MenuBar", icon_focus_color);
- theme->set_color("icon_pressed_color", "MenuBar", icon_pressed_color);
- theme->set_color("icon_disabled_color", "MenuBar", icon_disabled_color);
-
- theme->set_constant("h_separation", "MenuBar", 4 * EDSCALE);
- theme->set_constant("outline_size", "MenuBar", 0);
-
- // OptionButton
- Ref<StyleBoxFlat> style_option_button_focus = style_widget_focus->duplicate();
- Ref<StyleBoxFlat> style_option_button_normal = style_widget->duplicate();
- Ref<StyleBoxFlat> style_option_button_hover = style_widget_hover->duplicate();
- Ref<StyleBoxFlat> style_option_button_pressed = style_widget_pressed->duplicate();
- Ref<StyleBoxFlat> style_option_button_disabled = style_widget_disabled->duplicate();
-
- style_option_button_focus->set_content_margin(SIDE_RIGHT, 4 * EDSCALE);
- style_option_button_normal->set_content_margin(SIDE_RIGHT, 4 * EDSCALE);
- style_option_button_hover->set_content_margin(SIDE_RIGHT, 4 * EDSCALE);
- style_option_button_pressed->set_content_margin(SIDE_RIGHT, 4 * EDSCALE);
- style_option_button_disabled->set_content_margin(SIDE_RIGHT, 4 * EDSCALE);
-
- theme->set_stylebox("focus", "OptionButton", style_option_button_focus);
- theme->set_stylebox("normal", "OptionButton", style_widget);
- theme->set_stylebox("hover", "OptionButton", style_widget_hover);
- theme->set_stylebox("pressed", "OptionButton", style_widget_pressed);
- theme->set_stylebox("disabled", "OptionButton", style_widget_disabled);
-
- theme->set_stylebox("normal_mirrored", "OptionButton", style_option_button_normal);
- theme->set_stylebox("hover_mirrored", "OptionButton", style_option_button_hover);
- theme->set_stylebox("pressed_mirrored", "OptionButton", style_option_button_pressed);
- theme->set_stylebox("disabled_mirrored", "OptionButton", style_option_button_disabled);
-
- theme->set_color("font_color", "OptionButton", font_color);
- theme->set_color("font_hover_color", "OptionButton", font_hover_color);
- theme->set_color("font_hover_pressed_color", "OptionButton", font_hover_pressed_color);
- theme->set_color("font_focus_color", "OptionButton", font_focus_color);
- theme->set_color("font_pressed_color", "OptionButton", accent_color);
- theme->set_color("font_disabled_color", "OptionButton", font_disabled_color);
- theme->set_color("font_outline_color", "OptionButton", font_outline_color);
-
- theme->set_color("icon_normal_color", "OptionButton", icon_normal_color);
- theme->set_color("icon_hover_color", "OptionButton", icon_hover_color);
- theme->set_color("icon_focus_color", "OptionButton", icon_focus_color);
- theme->set_color("icon_pressed_color", "OptionButton", icon_pressed_color);
- theme->set_color("icon_disabled_color", "OptionButton", icon_disabled_color);
-
- theme->set_icon("arrow", "OptionButton", theme->get_icon(SNAME("GuiOptionArrow"), EditorStringName(EditorIcons)));
- theme->set_constant("arrow_margin", "OptionButton", widget_default_margin.x - 2 * EDSCALE);
- theme->set_constant("modulate_arrow", "OptionButton", true);
- theme->set_constant("h_separation", "OptionButton", 4 * EDSCALE);
- theme->set_constant("outline_size", "OptionButton", 0);
-
- // CheckButton
- theme->set_stylebox("normal", "CheckButton", style_menu);
- theme->set_stylebox("pressed", "CheckButton", style_menu);
- theme->set_stylebox("disabled", "CheckButton", style_menu);
- theme->set_stylebox("hover", "CheckButton", style_menu);
- theme->set_stylebox("hover_pressed", "CheckButton", style_menu);
-
- theme->set_icon("checked", "CheckButton", theme->get_icon(SNAME("GuiToggleOn"), EditorStringName(EditorIcons)));
- theme->set_icon("checked_disabled", "CheckButton", theme->get_icon(SNAME("GuiToggleOnDisabled"), EditorStringName(EditorIcons)));
- theme->set_icon("unchecked", "CheckButton", theme->get_icon(SNAME("GuiToggleOff"), EditorStringName(EditorIcons)));
- theme->set_icon("unchecked_disabled", "CheckButton", theme->get_icon(SNAME("GuiToggleOffDisabled"), EditorStringName(EditorIcons)));
-
- theme->set_icon("checked_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOnMirrored"), EditorStringName(EditorIcons)));
- theme->set_icon("checked_disabled_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOnDisabledMirrored"), EditorStringName(EditorIcons)));
- theme->set_icon("unchecked_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOffMirrored"), EditorStringName(EditorIcons)));
- theme->set_icon("unchecked_disabled_mirrored", "CheckButton", theme->get_icon(SNAME("GuiToggleOffDisabledMirrored"), EditorStringName(EditorIcons)));
-
- theme->set_color("font_color", "CheckButton", font_color);
- theme->set_color("font_hover_color", "CheckButton", font_hover_color);
- theme->set_color("font_hover_pressed_color", "CheckButton", font_hover_pressed_color);
- theme->set_color("font_focus_color", "CheckButton", font_focus_color);
- theme->set_color("font_pressed_color", "CheckButton", accent_color);
- theme->set_color("font_disabled_color", "CheckButton", font_disabled_color);
- theme->set_color("font_outline_color", "CheckButton", font_outline_color);
-
- theme->set_color("icon_normal_color", "CheckButton", icon_normal_color);
- theme->set_color("icon_hover_color", "CheckButton", icon_hover_color);
- theme->set_color("icon_focus_color", "CheckButton", icon_focus_color);
- theme->set_color("icon_pressed_color", "CheckButton", icon_pressed_color);
- theme->set_color("icon_disabled_color", "CheckButton", icon_disabled_color);
-
- theme->set_constant("h_separation", "CheckButton", 8 * EDSCALE);
- theme->set_constant("check_v_offset", "CheckButton", 0);
- theme->set_constant("outline_size", "CheckButton", 0);
-
- // Checkbox
- Ref<StyleBoxFlat> sb_checkbox = style_menu->duplicate();
- sb_checkbox->set_content_margin_all(default_margin_size * EDSCALE);
-
- theme->set_stylebox("normal", "CheckBox", sb_checkbox);
- theme->set_stylebox("pressed", "CheckBox", sb_checkbox);
- theme->set_stylebox("disabled", "CheckBox", sb_checkbox);
- theme->set_stylebox("hover", "CheckBox", sb_checkbox);
- theme->set_stylebox("hover_pressed", "CheckBox", sb_checkbox);
- theme->set_icon("checked", "CheckBox", theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons)));
- theme->set_icon("unchecked", "CheckBox", theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons)));
- theme->set_icon("radio_checked", "CheckBox", theme->get_icon(SNAME("GuiRadioChecked"), EditorStringName(EditorIcons)));
- theme->set_icon("radio_unchecked", "CheckBox", theme->get_icon(SNAME("GuiRadioUnchecked"), EditorStringName(EditorIcons)));
- theme->set_icon("checked_disabled", "CheckBox", theme->get_icon(SNAME("GuiCheckedDisabled"), EditorStringName(EditorIcons)));
- theme->set_icon("unchecked_disabled", "CheckBox", theme->get_icon(SNAME("GuiUncheckedDisabled"), EditorStringName(EditorIcons)));
- theme->set_icon("radio_checked_disabled", "CheckBox", theme->get_icon(SNAME("GuiRadioCheckedDisabled"), EditorStringName(EditorIcons)));
- theme->set_icon("radio_unchecked_disabled", "CheckBox", theme->get_icon(SNAME("GuiRadioUncheckedDisabled"), EditorStringName(EditorIcons)));
-
- theme->set_color("font_color", "CheckBox", font_color);
- theme->set_color("font_hover_color", "CheckBox", font_hover_color);
- theme->set_color("font_hover_pressed_color", "CheckBox", font_hover_pressed_color);
- theme->set_color("font_focus_color", "CheckBox", font_focus_color);
- theme->set_color("font_pressed_color", "CheckBox", accent_color);
- theme->set_color("font_disabled_color", "CheckBox", font_disabled_color);
- theme->set_color("font_outline_color", "CheckBox", font_outline_color);
-
- theme->set_color("icon_normal_color", "CheckBox", icon_normal_color);
- theme->set_color("icon_hover_color", "CheckBox", icon_hover_color);
- theme->set_color("icon_focus_color", "CheckBox", icon_focus_color);
- theme->set_color("icon_pressed_color", "CheckBox", icon_pressed_color);
- theme->set_color("icon_disabled_color", "CheckBox", icon_disabled_color);
-
- theme->set_constant("h_separation", "CheckBox", 8 * EDSCALE);
- theme->set_constant("check_v_offset", "CheckBox", 0);
- theme->set_constant("outline_size", "CheckBox", 0);
-
- // PopupDialog
- theme->set_stylebox("panel", "PopupDialog", style_popup);
-
- // PopupMenu
- Ref<StyleBoxFlat> style_popup_menu = style_popup->duplicate();
- // Use 1 pixel for the sides, since if 0 is used, the highlight of hovered items is drawn
- // on top of the popup border. This causes a 'gap' in the panel border when an item is highlighted,
- // and it looks weird. 1px solves this.
- style_popup_menu->set_content_margin_individual(EDSCALE, 2 * EDSCALE, EDSCALE, 2 * EDSCALE);
- // Always display a border for PopupMenus so they can be distinguished from their background.
- style_popup_menu->set_border_width_all(EDSCALE);
- if (draw_extra_borders) {
- style_popup_menu->set_border_color(extra_border_color_2);
- } else {
- style_popup_menu->set_border_color(dark_color_2);
- }
- theme->set_stylebox("panel", "PopupMenu", style_popup_menu);
-
- Ref<StyleBoxFlat> style_menu_hover = style_widget_hover->duplicate();
- // Don't use rounded corners for hover highlights since the StyleBox touches the PopupMenu's edges.
- style_menu_hover->set_corner_radius_all(0);
- theme->set_stylebox("hover", "PopupMenu", style_menu_hover);
-
- theme->set_stylebox("separator", "PopupMenu", style_popup_separator);
- theme->set_stylebox("labeled_separator_left", "PopupMenu", style_popup_labeled_separator_left);
- theme->set_stylebox("labeled_separator_right", "PopupMenu", style_popup_labeled_separator_right);
-
- theme->set_color("font_color", "PopupMenu", font_color);
- theme->set_color("font_hover_color", "PopupMenu", font_hover_color);
- theme->set_color("font_accelerator_color", "PopupMenu", font_disabled_color);
- theme->set_color("font_disabled_color", "PopupMenu", font_disabled_color);
- theme->set_color("font_separator_color", "PopupMenu", font_disabled_color);
- theme->set_color("font_outline_color", "PopupMenu", font_outline_color);
- theme->set_icon("checked", "PopupMenu", theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons)));
- theme->set_icon("unchecked", "PopupMenu", theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons)));
- theme->set_icon("radio_checked", "PopupMenu", theme->get_icon(SNAME("GuiRadioChecked"), EditorStringName(EditorIcons)));
- theme->set_icon("radio_unchecked", "PopupMenu", theme->get_icon(SNAME("GuiRadioUnchecked"), EditorStringName(EditorIcons)));
- theme->set_icon("checked_disabled", "PopupMenu", theme->get_icon(SNAME("GuiCheckedDisabled"), EditorStringName(EditorIcons)));
- theme->set_icon("unchecked_disabled", "PopupMenu", theme->get_icon(SNAME("GuiUncheckedDisabled"), EditorStringName(EditorIcons)));
- theme->set_icon("radio_checked_disabled", "PopupMenu", theme->get_icon(SNAME("GuiRadioCheckedDisabled"), EditorStringName(EditorIcons)));
- theme->set_icon("radio_unchecked_disabled", "PopupMenu", theme->get_icon(SNAME("GuiRadioUncheckedDisabled"), EditorStringName(EditorIcons)));
- theme->set_icon("submenu", "PopupMenu", theme->get_icon(SNAME("ArrowRight"), EditorStringName(EditorIcons)));
- theme->set_icon("submenu_mirrored", "PopupMenu", theme->get_icon(SNAME("ArrowLeft"), EditorStringName(EditorIcons)));
- theme->set_icon("visibility_hidden", "PopupMenu", theme->get_icon(SNAME("GuiVisibilityHidden"), EditorStringName(EditorIcons)));
- theme->set_icon("visibility_visible", "PopupMenu", theme->get_icon(SNAME("GuiVisibilityVisible"), EditorStringName(EditorIcons)));
- theme->set_icon("visibility_xray", "PopupMenu", theme->get_icon(SNAME("GuiVisibilityXray"), EditorStringName(EditorIcons)));
-
- // Force the v_separation to be even so that the spacing on top and bottom is even.
- // If the vsep is odd and cannot be split into 2 even groups (of pixels), then it will be lopsided.
- // We add 2 to the vsep to give it some extra spacing which looks a bit more modern (see Windows, for example).
- const int vsep_base = extra_spacing + default_margin_size + 6;
- const int force_even_vsep = vsep_base + (vsep_base % 2);
- theme->set_constant("v_separation", "PopupMenu", force_even_vsep * EDSCALE);
- theme->set_constant("outline_size", "PopupMenu", 0);
- theme->set_constant("item_start_padding", "PopupMenu", default_margin_size * 1.5 * EDSCALE);
- theme->set_constant("item_end_padding", "PopupMenu", default_margin_size * 1.5 * EDSCALE);
-
- // Sub-inspectors
- for (int i = 0; i < 16; i++) {
- Color si_base_color = accent_color;
-
- float hue_rotate = (i * 2 % 16) / 16.0;
- si_base_color.set_hsv(Math::fmod(float(si_base_color.get_h() + hue_rotate), float(1.0)), si_base_color.get_s(), si_base_color.get_v());
- si_base_color = accent_color.lerp(si_base_color, float(EDITOR_GET("docks/property_editor/subresource_hue_tint")));
-
- // Sub-inspector background.
- Ref<StyleBoxFlat> sub_inspector_bg = style_default->duplicate();
- sub_inspector_bg->set_bg_color(dark_color_1.lerp(si_base_color, 0.08));
- sub_inspector_bg->set_border_width_all(2 * EDSCALE);
- sub_inspector_bg->set_border_color(si_base_color * Color(0.7, 0.7, 0.7, 0.8));
- sub_inspector_bg->set_content_margin_all(4 * EDSCALE);
- sub_inspector_bg->set_corner_radius(CORNER_TOP_LEFT, 0);
- sub_inspector_bg->set_corner_radius(CORNER_TOP_RIGHT, 0);
-
- theme->set_stylebox("sub_inspector_bg" + itos(i), EditorStringName(Editor), sub_inspector_bg);
-
- // EditorProperty background while it has a sub-inspector open.
- Ref<StyleBoxFlat> bg_color = make_flat_stylebox(si_base_color * Color(0.7, 0.7, 0.7, 0.8), 0, 0, 0, 0, corner_radius);
- bg_color->set_anti_aliased(false);
- bg_color->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
- bg_color->set_corner_radius(CORNER_BOTTOM_RIGHT, 0);
-
- theme->set_stylebox("sub_inspector_property_bg" + itos(i), EditorStringName(Editor), bg_color);
- }
-
- theme->set_color("sub_inspector_property_color", EditorStringName(Editor), dark_theme ? Color(1, 1, 1, 1) : Color(0, 0, 0, 1));
-
- // EditorSpinSlider.
- theme->set_color("label_color", "EditorSpinSlider", font_color);
- theme->set_color("read_only_label_color", "EditorSpinSlider", font_readonly_color);
-
- Ref<StyleBoxFlat> editor_spin_label_bg = style_default->duplicate();
- editor_spin_label_bg->set_bg_color(dark_color_3);
- editor_spin_label_bg->set_border_width_all(0);
- theme->set_stylebox("label_bg", "EditorSpinSlider", editor_spin_label_bg);
-
- // EditorProperty
- Ref<StyleBoxFlat> style_property_bg = style_default->duplicate();
- style_property_bg->set_bg_color(highlight_color);
- style_property_bg->set_border_width_all(0);
-
- Ref<StyleBoxFlat> style_property_child_bg = style_default->duplicate();
- style_property_child_bg->set_bg_color(dark_color_2);
- style_property_child_bg->set_border_width_all(0);
-
- theme->set_constant("font_offset", "EditorProperty", 8 * EDSCALE);
- theme->set_stylebox("bg_selected", "EditorProperty", style_property_bg);
- theme->set_stylebox("bg", "EditorProperty", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty)));
- theme->set_stylebox("child_bg", "EditorProperty", style_property_child_bg);
- theme->set_constant("v_separation", "EditorProperty", (extra_spacing + default_margin_size) * EDSCALE);
- theme->set_color("warning_color", "EditorProperty", warning_color);
- theme->set_color("property_color", "EditorProperty", property_color);
- theme->set_color("readonly_color", "EditorProperty", readonly_color);
- theme->set_color("readonly_warning_color", "EditorProperty", readonly_warning_color);
-
- Ref<StyleBoxFlat> style_property_group_note = style_default->duplicate();
- Color property_group_note_color = accent_color;
- property_group_note_color.a = 0.1;
- style_property_group_note->set_bg_color(property_group_note_color);
- theme->set_stylebox("bg_group_note", "EditorProperty", style_property_group_note);
-
- // EditorInspectorSection
- Color inspector_section_color = font_color.lerp(Color(0.5, 0.5, 0.5), 0.35);
- theme->set_color("font_color", "EditorInspectorSection", inspector_section_color);
-
- Color inspector_indent_color = accent_color;
- inspector_indent_color.a = 0.2;
- Ref<StyleBoxFlat> inspector_indent_style = make_flat_stylebox(inspector_indent_color, 2.0 * EDSCALE, 0, 2.0 * EDSCALE, 0);
- theme->set_stylebox("indent_box", "EditorInspectorSection", inspector_indent_style);
- theme->set_constant("indent_size", "EditorInspectorSection", 6.0 * EDSCALE);
-
- theme->set_constant("inspector_margin", EditorStringName(Editor), 12 * EDSCALE);
-
- // Tree & ItemList background
- Ref<StyleBoxFlat> style_tree_bg = style_default->duplicate();
- // Make Trees easier to distinguish from other controls by using a darker background color.
- style_tree_bg->set_bg_color(dark_color_1.lerp(dark_color_2, 0.5));
- if (draw_extra_borders) {
- style_tree_bg->set_border_width_all(Math::round(EDSCALE));
- style_tree_bg->set_border_color(extra_border_color_2);
- } else {
- style_tree_bg->set_border_color(dark_color_3);
- }
-
- theme->set_stylebox("panel", "Tree", style_tree_bg);
- theme->set_stylebox("panel", "EditorValidationPanel", style_tree_bg);
-
- // Tree
- theme->set_icon("checked", "Tree", theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons)));
- theme->set_icon("checked_disabled", "Tree", theme->get_icon(SNAME("GuiCheckedDisabled"), EditorStringName(EditorIcons)));
- theme->set_icon("indeterminate", "Tree", theme->get_icon(SNAME("GuiIndeterminate"), EditorStringName(EditorIcons)));
- theme->set_icon("indeterminate_disabled", "Tree", theme->get_icon(SNAME("GuiIndeterminateDisabled"), EditorStringName(EditorIcons)));
- theme->set_icon("unchecked", "Tree", theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons)));
- theme->set_icon("unchecked_disabled", "Tree", theme->get_icon(SNAME("GuiUncheckedDisabled"), EditorStringName(EditorIcons)));
- theme->set_icon("arrow", "Tree", theme->get_icon(SNAME("GuiTreeArrowDown"), EditorStringName(EditorIcons)));
- theme->set_icon("arrow_collapsed", "Tree", theme->get_icon(SNAME("GuiTreeArrowRight"), EditorStringName(EditorIcons)));
- theme->set_icon("arrow_collapsed_mirrored", "Tree", theme->get_icon(SNAME("GuiTreeArrowLeft"), EditorStringName(EditorIcons)));
- theme->set_icon("updown", "Tree", theme->get_icon(SNAME("GuiTreeUpdown"), EditorStringName(EditorIcons)));
- theme->set_icon("select_arrow", "Tree", theme->get_icon(SNAME("GuiDropdown"), EditorStringName(EditorIcons)));
- theme->set_stylebox("focus", "Tree", style_widget_focus);
- theme->set_stylebox("custom_button", "Tree", make_empty_stylebox());
- theme->set_stylebox("custom_button_pressed", "Tree", make_empty_stylebox());
- theme->set_stylebox("custom_button_hover", "Tree", style_widget);
- theme->set_color("custom_button_font_highlight", "Tree", font_hover_color);
- theme->set_color("font_color", "Tree", font_color);
- theme->set_color("font_selected_color", "Tree", mono_color);
- theme->set_color("font_disabled_color", "Tree", font_disabled_color);
- theme->set_color("font_outline_color", "Tree", font_outline_color);
- theme->set_color("title_button_color", "Tree", font_color);
- theme->set_color("drop_position_color", "Tree", accent_color);
- theme->set_constant("v_separation", "Tree", widget_default_margin.y - EDSCALE);
- theme->set_constant("h_separation", "Tree", 6 * EDSCALE);
- theme->set_constant("guide_width", "Tree", border_width);
- theme->set_constant("item_margin", "Tree", 3 * default_margin_size * EDSCALE);
- theme->set_constant("inner_item_margin_bottom", "Tree", (default_margin_size + extra_spacing) * EDSCALE);
- theme->set_constant("inner_item_margin_left", "Tree", (default_margin_size + extra_spacing) * EDSCALE);
- theme->set_constant("inner_item_margin_right", "Tree", (default_margin_size + extra_spacing) * EDSCALE);
- theme->set_constant("inner_item_margin_top", "Tree", (default_margin_size + extra_spacing) * EDSCALE);
- theme->set_constant("button_margin", "Tree", default_margin_size * EDSCALE);
- theme->set_constant("scroll_border", "Tree", 40 * EDSCALE);
- theme->set_constant("scroll_speed", "Tree", 12);
- theme->set_constant("outline_size", "Tree", 0);
- theme->set_constant("scrollbar_margin_left", "Tree", 0);
- theme->set_constant("scrollbar_margin_top", "Tree", 0);
- theme->set_constant("scrollbar_margin_right", "Tree", 0);
- theme->set_constant("scrollbar_margin_bottom", "Tree", 0);
- theme->set_constant("scrollbar_h_separation", "Tree", 1 * EDSCALE);
- theme->set_constant("scrollbar_v_separation", "Tree", 1 * EDSCALE);
-
- const Color guide_color = mono_color * Color(1, 1, 1, 0.05);
- Color relationship_line_color = mono_color * Color(1, 1, 1, relationship_line_opacity);
-
- theme->set_constant("draw_guides", "Tree", relationship_line_opacity < 0.01);
- theme->set_color("guide_color", "Tree", guide_color);
-
- int relationship_line_width = 1;
- Color parent_line_color = mono_color * Color(1, 1, 1, CLAMP(relationship_line_opacity + 0.45, 0.0, 1.0));
- Color children_line_color = mono_color * Color(1, 1, 1, CLAMP(relationship_line_opacity + 0.25, 0.0, 1.0));
- theme->set_constant("draw_relationship_lines", "Tree", relationship_line_opacity >= 0.01);
- theme->set_constant("relationship_line_width", "Tree", relationship_line_width);
- theme->set_constant("parent_hl_line_width", "Tree", relationship_line_width * 2);
- theme->set_constant("children_hl_line_width", "Tree", relationship_line_width);
- theme->set_constant("parent_hl_line_margin", "Tree", relationship_line_width * 3);
- theme->set_color("relationship_line_color", "Tree", relationship_line_color);
- theme->set_color("parent_hl_line_color", "Tree", parent_line_color);
- theme->set_color("children_hl_line_color", "Tree", children_line_color);
-
- Ref<StyleBoxFlat> style_tree_btn = style_default->duplicate();
- style_tree_btn->set_bg_color(highlight_color);
- style_tree_btn->set_border_width_all(0);
- theme->set_stylebox("button_pressed", "Tree", style_tree_btn);
-
- Ref<StyleBoxFlat> style_tree_hover = style_default->duplicate();
- style_tree_hover->set_bg_color(highlight_color * Color(1, 1, 1, 0.4));
- style_tree_hover->set_border_width_all(0);
- theme->set_stylebox("hover", "Tree", style_tree_hover);
-
- Ref<StyleBoxFlat> style_tree_focus = style_default->duplicate();
- style_tree_focus->set_bg_color(highlight_color);
- style_tree_focus->set_border_width_all(0);
- theme->set_stylebox("selected_focus", "Tree", style_tree_focus);
-
- Ref<StyleBoxFlat> style_tree_selected = style_tree_focus->duplicate();
- theme->set_stylebox("selected", "Tree", style_tree_selected);
-
- Ref<StyleBoxFlat> style_tree_cursor = style_default->duplicate();
- style_tree_cursor->set_draw_center(false);
- style_tree_cursor->set_border_width_all(MAX(1, border_width));
- style_tree_cursor->set_border_color(contrast_color_1);
-
- Ref<StyleBoxFlat> style_tree_title = style_default->duplicate();
- style_tree_title->set_bg_color(dark_color_3);
- style_tree_title->set_border_width_all(0);
- theme->set_stylebox("cursor", "Tree", style_tree_cursor);
- theme->set_stylebox("cursor_unfocused", "Tree", style_tree_cursor);
- theme->set_stylebox("title_button_normal", "Tree", style_tree_title);
- theme->set_stylebox("title_button_hover", "Tree", style_tree_title);
- theme->set_stylebox("title_button_pressed", "Tree", style_tree_title);
-
- Color prop_category_color = dark_color_1.lerp(mono_color, 0.12);
- Color prop_section_color = dark_color_1.lerp(mono_color, 0.09);
- Color prop_subsection_color = dark_color_1.lerp(mono_color, 0.06);
- theme->set_color("prop_category", EditorStringName(Editor), prop_category_color);
- theme->set_color("prop_section", EditorStringName(Editor), prop_section_color);
- theme->set_color("prop_subsection", EditorStringName(Editor), prop_subsection_color);
- theme->set_color("drop_position_color", "Tree", accent_color);
-
- // EditorInspectorCategory
- Ref<StyleBoxFlat> category_bg = style_default->duplicate();
- category_bg->set_bg_color(prop_category_color);
- category_bg->set_border_color(prop_category_color);
- theme->set_stylebox("bg", "EditorInspectorCategory", category_bg);
-
- // ItemList
- Ref<StyleBoxFlat> style_itemlist_bg = style_default->duplicate();
- style_itemlist_bg->set_bg_color(dark_color_1);
-
- if (draw_extra_borders) {
- style_itemlist_bg->set_border_width_all(Math::round(EDSCALE));
- style_itemlist_bg->set_border_color(extra_border_color_2);
- } else {
- style_itemlist_bg->set_border_width_all(border_width);
- style_itemlist_bg->set_border_color(dark_color_3);
- }
-
- Ref<StyleBoxFlat> style_itemlist_cursor = style_default->duplicate();
- style_itemlist_cursor->set_draw_center(false);
- style_itemlist_cursor->set_border_width_all(border_width);
- style_itemlist_cursor->set_border_color(highlight_color);
-
- Ref<StyleBoxFlat> style_itemlist_hover = style_tree_selected->duplicate();
- style_itemlist_hover->set_bg_color(highlight_color * Color(1, 1, 1, 0.3));
- style_itemlist_hover->set_border_width_all(0);
-
- theme->set_stylebox("panel", "ItemList", style_itemlist_bg);
- theme->set_stylebox("focus", "ItemList", style_widget_focus);
- theme->set_stylebox("cursor", "ItemList", style_itemlist_cursor);
- theme->set_stylebox("cursor_unfocused", "ItemList", style_itemlist_cursor);
- theme->set_stylebox("selected_focus", "ItemList", style_tree_focus);
- theme->set_stylebox("selected", "ItemList", style_tree_selected);
- theme->set_stylebox("hovered", "ItemList", style_itemlist_hover);
- theme->set_color("font_color", "ItemList", font_color);
- theme->set_color("font_hovered_color", "ItemList", mono_color);
- theme->set_color("font_selected_color", "ItemList", mono_color);
- theme->set_color("font_outline_color", "ItemList", font_outline_color);
- theme->set_color("guide_color", "ItemList", guide_color);
- theme->set_constant("v_separation", "ItemList", force_even_vsep * 0.5 * EDSCALE);
- theme->set_constant("h_separation", "ItemList", 6 * EDSCALE);
- theme->set_constant("icon_margin", "ItemList", 6 * EDSCALE);
- theme->set_constant("line_separation", "ItemList", 3 * EDSCALE);
- theme->set_constant("outline_size", "ItemList", 0);
-
- // TabBar & TabContainer
- Ref<StyleBoxFlat> style_tabbar_background = make_flat_stylebox(dark_color_1, 0, 0, 0, 0, corner_radius * EDSCALE);
- style_tabbar_background->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
- style_tabbar_background->set_corner_radius(CORNER_BOTTOM_RIGHT, 0);
- theme->set_stylebox("tabbar_background", "TabContainer", style_tabbar_background);
-
- theme->set_stylebox("tab_selected", "TabContainer", style_tab_selected);
- theme->set_stylebox("tab_hovered", "TabContainer", style_tab_hovered);
- theme->set_stylebox("tab_unselected", "TabContainer", style_tab_unselected);
- theme->set_stylebox("tab_disabled", "TabContainer", style_tab_disabled);
- theme->set_stylebox("tab_focus", "TabContainer", style_tab_focus);
- theme->set_stylebox("tab_selected", "TabBar", style_tab_selected);
- theme->set_stylebox("tab_hovered", "TabBar", style_tab_hovered);
- theme->set_stylebox("tab_unselected", "TabBar", style_tab_unselected);
- theme->set_stylebox("tab_disabled", "TabBar", style_tab_disabled);
- theme->set_stylebox("tab_focus", "TabBar", style_tab_focus);
- theme->set_stylebox("button_pressed", "TabBar", style_menu);
- theme->set_stylebox("button_highlight", "TabBar", style_menu);
- theme->set_color("font_selected_color", "TabContainer", font_color);
- theme->set_color("font_hovered_color", "TabContainer", font_color);
- theme->set_color("font_unselected_color", "TabContainer", font_disabled_color);
- theme->set_color("font_outline_color", "TabContainer", font_outline_color);
- theme->set_color("font_selected_color", "TabBar", font_color);
- theme->set_color("font_hovered_color", "TabBar", font_color);
- theme->set_color("font_unselected_color", "TabBar", font_disabled_color);
- theme->set_color("font_outline_color", "TabBar", font_outline_color);
- theme->set_color("drop_mark_color", "TabContainer", tab_highlight);
- theme->set_color("drop_mark_color", "TabBar", tab_highlight);
- theme->set_icon("menu", "TabContainer", theme->get_icon(SNAME("GuiTabMenu"), EditorStringName(EditorIcons)));
- theme->set_icon("menu_highlight", "TabContainer", theme->get_icon(SNAME("GuiTabMenuHl"), EditorStringName(EditorIcons)));
- theme->set_icon("close", "TabBar", theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons)));
- theme->set_icon("increment", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowRight"), EditorStringName(EditorIcons)));
- theme->set_icon("decrement", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowLeft"), EditorStringName(EditorIcons)));
- theme->set_icon("increment", "TabBar", theme->get_icon(SNAME("GuiScrollArrowRight"), EditorStringName(EditorIcons)));
- theme->set_icon("decrement", "TabBar", theme->get_icon(SNAME("GuiScrollArrowLeft"), EditorStringName(EditorIcons)));
- theme->set_icon("increment_highlight", "TabBar", theme->get_icon(SNAME("GuiScrollArrowRightHl"), EditorStringName(EditorIcons)));
- theme->set_icon("decrement_highlight", "TabBar", theme->get_icon(SNAME("GuiScrollArrowLeftHl"), EditorStringName(EditorIcons)));
- theme->set_icon("increment_highlight", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowRightHl"), EditorStringName(EditorIcons)));
- theme->set_icon("decrement_highlight", "TabContainer", theme->get_icon(SNAME("GuiScrollArrowLeftHl"), EditorStringName(EditorIcons)));
- theme->set_icon("drop_mark", "TabContainer", theme->get_icon(SNAME("GuiTabDropMark"), EditorStringName(EditorIcons)));
- theme->set_icon("drop_mark", "TabBar", theme->get_icon(SNAME("GuiTabDropMark"), EditorStringName(EditorIcons)));
- theme->set_constant("side_margin", "TabContainer", 0);
- theme->set_constant("outline_size", "TabContainer", 0);
- theme->set_constant("h_separation", "TabBar", 4 * EDSCALE);
- theme->set_constant("outline_size", "TabBar", 0);
-
- // Content of each tab.
- Ref<StyleBoxFlat> style_content_panel = style_default->duplicate();
- style_content_panel->set_border_color(dark_color_3);
- style_content_panel->set_border_width_all(border_width);
- style_content_panel->set_border_width(Side::SIDE_TOP, 0);
- style_content_panel->set_corner_radius(CORNER_TOP_LEFT, 0);
- style_content_panel->set_corner_radius(CORNER_TOP_RIGHT, 0);
- // Compensate for the border.
- style_content_panel->set_content_margin_individual(margin_size_extra * EDSCALE, (2 + margin_size_extra) * EDSCALE, margin_size_extra * EDSCALE, margin_size_extra * EDSCALE);
- theme->set_stylebox("panel", "TabContainer", style_content_panel);
-
- // Bottom panel.
- Ref<StyleBoxFlat> style_bottom_panel = style_content_panel->duplicate();
- style_bottom_panel->set_corner_radius_all(corner_radius * EDSCALE);
- theme->set_stylebox("BottomPanel", EditorStringName(EditorStyles), style_bottom_panel);
-
- // TabContainerOdd can be used on tabs against the base color background (e.g. nested tabs).
- theme->set_type_variation("TabContainerOdd", "TabContainer");
-
- Ref<StyleBoxFlat> style_tab_selected_odd = style_tab_selected->duplicate();
- style_tab_selected_odd->set_bg_color(disabled_bg_color);
- theme->set_stylebox("tab_selected", "TabContainerOdd", style_tab_selected_odd);
-
- Ref<StyleBoxFlat> style_content_panel_odd = style_content_panel->duplicate();
- style_content_panel_odd->set_bg_color(disabled_bg_color);
- theme->set_stylebox("panel", "TabContainerOdd", style_content_panel_odd);
-
- // This stylebox is used in 3d and 2d viewports (no borders).
- Ref<StyleBoxFlat> style_content_panel_vp = style_content_panel->duplicate();
- style_content_panel_vp->set_content_margin_individual(border_width * 2, default_margin_size * EDSCALE, border_width * 2, border_width * 2);
- theme->set_stylebox("Content", EditorStringName(EditorStyles), style_content_panel_vp);
-
- // This stylebox is used by preview tabs in the Theme Editor.
- Ref<StyleBoxFlat> style_theme_preview_tab = style_tab_selected_odd->duplicate();
- style_theme_preview_tab->set_expand_margin(SIDE_BOTTOM, 5 * EDSCALE);
- theme->set_stylebox("ThemeEditorPreviewFG", EditorStringName(EditorStyles), style_theme_preview_tab);
- Ref<StyleBoxFlat> style_theme_preview_bg_tab = style_tab_unselected->duplicate();
- style_theme_preview_bg_tab->set_expand_margin(SIDE_BOTTOM, 2 * EDSCALE);
- theme->set_stylebox("ThemeEditorPreviewBG", EditorStringName(EditorStyles), style_theme_preview_bg_tab);
-
- Ref<StyleBoxFlat> style_texture_region_bg = style_tree_bg->duplicate();
- style_texture_region_bg->set_content_margin_all(0);
- theme->set_stylebox("TextureRegionPreviewBG", EditorStringName(EditorStyles), style_texture_region_bg);
- theme->set_stylebox("TextureRegionPreviewFG", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0));
-
- // Separators
- theme->set_stylebox("separator", "HSeparator", make_line_stylebox(separator_color, MAX(Math::round(EDSCALE), border_width)));
- theme->set_stylebox("separator", "VSeparator", make_line_stylebox(separator_color, MAX(Math::round(EDSCALE), border_width), 0, 0, true));
-
- // Debugger
-
- Ref<StyleBoxFlat> style_panel_debugger = style_content_panel->duplicate();
- style_panel_debugger->set_border_width(SIDE_BOTTOM, 0);
- theme->set_stylebox("DebuggerPanel", EditorStringName(EditorStyles), style_panel_debugger);
-
- Ref<StyleBoxFlat> style_panel_invisible_top = style_content_panel->duplicate();
- int stylebox_offset = theme->get_font(SNAME("tab_selected"), SNAME("TabContainer"))->get_height(theme->get_font_size(SNAME("tab_selected"), SNAME("TabContainer"))) + theme->get_stylebox(SNAME("tab_selected"), SNAME("TabContainer"))->get_minimum_size().height + theme->get_stylebox(SNAME("panel"), SNAME("TabContainer"))->get_content_margin(SIDE_TOP);
- style_panel_invisible_top->set_expand_margin(SIDE_TOP, -stylebox_offset);
- style_panel_invisible_top->set_content_margin(SIDE_TOP, 0);
- theme->set_stylebox("BottomPanelDebuggerOverride", EditorStringName(EditorStyles), style_panel_invisible_top);
-
- // LineEdit
-
- Ref<StyleBoxFlat> style_line_edit = style_widget->duplicate();
- // The original style_widget style has an extra 1 pixel offset that makes LineEdits not align with Buttons,
- // so this compensates for that.
- style_line_edit->set_content_margin(SIDE_TOP, style_line_edit->get_content_margin(SIDE_TOP) - 1 * EDSCALE);
-
- // Don't round the bottom corners to make the line look sharper.
- style_line_edit->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
- style_line_edit->set_corner_radius(CORNER_BOTTOM_RIGHT, 0);
-
- if (draw_extra_borders) {
- style_line_edit->set_border_width_all(Math::round(EDSCALE));
- style_line_edit->set_border_color(extra_border_color_1);
- } else {
- // Add a bottom line to make LineEdits more visible, especially in sectioned inspectors
- // such as the Project Settings.
- style_line_edit->set_border_width(SIDE_BOTTOM, Math::round(2 * EDSCALE));
- style_line_edit->set_border_color(dark_color_2);
- }
-
- Ref<StyleBoxFlat> style_line_edit_disabled = style_line_edit->duplicate();
- style_line_edit_disabled->set_border_color(disabled_color);
- style_line_edit_disabled->set_bg_color(disabled_bg_color);
-
- theme->set_stylebox("normal", "LineEdit", style_line_edit);
- theme->set_stylebox("focus", "LineEdit", style_widget_focus);
- theme->set_stylebox("read_only", "LineEdit", style_line_edit_disabled);
- theme->set_icon("clear", "LineEdit", theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons)));
- theme->set_color("font_color", "LineEdit", font_color);
- theme->set_color("font_selected_color", "LineEdit", mono_color);
- theme->set_color("font_uneditable_color", "LineEdit", font_readonly_color);
- theme->set_color("font_placeholder_color", "LineEdit", font_placeholder_color);
- theme->set_color("font_outline_color", "LineEdit", font_outline_color);
- theme->set_color("caret_color", "LineEdit", font_color);
- theme->set_color("selection_color", "LineEdit", selection_color);
- theme->set_color("clear_button_color", "LineEdit", font_color);
- theme->set_color("clear_button_color_pressed", "LineEdit", accent_color);
-
- theme->set_constant("minimum_character_width", "LineEdit", 4);
- theme->set_constant("outline_size", "LineEdit", 0);
- theme->set_constant("caret_width", "LineEdit", 1);
-
- // TextEdit
- theme->set_stylebox("normal", "TextEdit", style_line_edit);
- theme->set_stylebox("focus", "TextEdit", style_widget_focus);
- theme->set_stylebox("read_only", "TextEdit", style_line_edit_disabled);
- theme->set_icon("tab", "TextEdit", theme->get_icon(SNAME("GuiTab"), EditorStringName(EditorIcons)));
- theme->set_icon("space", "TextEdit", theme->get_icon(SNAME("GuiSpace"), EditorStringName(EditorIcons)));
- theme->set_color("font_color", "TextEdit", font_color);
- theme->set_color("font_readonly_color", "TextEdit", font_readonly_color);
- theme->set_color("font_placeholder_color", "TextEdit", font_placeholder_color);
- theme->set_color("font_outline_color", "TextEdit", font_outline_color);
- theme->set_color("caret_color", "TextEdit", font_color);
- theme->set_color("selection_color", "TextEdit", selection_color);
- theme->set_color("background_color", "TextEdit", Color(0, 0, 0, 0));
-
- theme->set_constant("line_spacing", "TextEdit", 4 * EDSCALE);
- theme->set_constant("outline_size", "TextEdit", 0);
- theme->set_constant("caret_width", "TextEdit", 1);
-
- theme->set_icon("h_grabber", "SplitContainer", theme->get_icon(SNAME("GuiHsplitter"), EditorStringName(EditorIcons)));
- theme->set_icon("v_grabber", "SplitContainer", theme->get_icon(SNAME("GuiVsplitter"), EditorStringName(EditorIcons)));
- theme->set_icon("grabber", "VSplitContainer", theme->get_icon(SNAME("GuiVsplitter"), EditorStringName(EditorIcons)));
- theme->set_icon("grabber", "HSplitContainer", theme->get_icon(SNAME("GuiHsplitter"), EditorStringName(EditorIcons)));
-
- theme->set_constant("separation", "SplitContainer", default_margin_size * 2 * EDSCALE);
- theme->set_constant("separation", "HSplitContainer", default_margin_size * 2 * EDSCALE);
- theme->set_constant("separation", "VSplitContainer", default_margin_size * 2 * EDSCALE);
-
- theme->set_constant("minimum_grab_thickness", "SplitContainer", 6 * EDSCALE);
- theme->set_constant("minimum_grab_thickness", "HSplitContainer", 6 * EDSCALE);
- theme->set_constant("minimum_grab_thickness", "VSplitContainer", 6 * EDSCALE);
-
- // Containers
- theme->set_constant("separation", "BoxContainer", default_margin_size * EDSCALE);
- theme->set_constant("separation", "HBoxContainer", default_margin_size * EDSCALE);
- theme->set_constant("separation", "VBoxContainer", default_margin_size * EDSCALE);
- theme->set_constant("margin_left", "MarginContainer", 0);
- theme->set_constant("margin_top", "MarginContainer", 0);
- theme->set_constant("margin_right", "MarginContainer", 0);
- theme->set_constant("margin_bottom", "MarginContainer", 0);
- theme->set_constant("h_separation", "GridContainer", default_margin_size * EDSCALE);
- theme->set_constant("v_separation", "GridContainer", default_margin_size * EDSCALE);
- theme->set_constant("h_separation", "FlowContainer", default_margin_size * EDSCALE);
- theme->set_constant("v_separation", "FlowContainer", default_margin_size * EDSCALE);
- theme->set_constant("h_separation", "HFlowContainer", default_margin_size * EDSCALE);
- theme->set_constant("v_separation", "HFlowContainer", default_margin_size * EDSCALE);
- theme->set_constant("h_separation", "VFlowContainer", default_margin_size * EDSCALE);
- theme->set_constant("v_separation", "VFlowContainer", default_margin_size * EDSCALE);
-
- // Custom theme type for MarginContainer with 4px margins.
- theme->set_type_variation("MarginContainer4px", "MarginContainer");
- theme->set_constant("margin_left", "MarginContainer4px", 4 * EDSCALE);
- theme->set_constant("margin_top", "MarginContainer4px", 4 * EDSCALE);
- theme->set_constant("margin_right", "MarginContainer4px", 4 * EDSCALE);
- theme->set_constant("margin_bottom", "MarginContainer4px", 4 * EDSCALE);
-
- // Window
-
- // Prevent corner artifacts between window title and body.
- Ref<StyleBoxFlat> style_window_title = style_default->duplicate();
- style_window_title->set_corner_radius(CORNER_TOP_LEFT, 0);
- style_window_title->set_corner_radius(CORNER_TOP_RIGHT, 0);
- // Prevent visible line between window title and body.
- style_window_title->set_expand_margin(SIDE_BOTTOM, 2 * EDSCALE);
-
- Ref<StyleBoxFlat> style_window = style_popup->duplicate();
- style_window->set_border_color(base_color);
- style_window->set_border_width(SIDE_TOP, 24 * EDSCALE);
- style_window->set_expand_margin(SIDE_TOP, 24 * EDSCALE);
- theme->set_stylebox("embedded_border", "Window", style_window);
- theme->set_stylebox("embedded_unfocused_border", "Window", style_window);
-
- theme->set_color("title_color", "Window", font_color);
- theme->set_icon("close", "Window", theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons)));
- theme->set_icon("close_pressed", "Window", theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons)));
- theme->set_constant("close_h_offset", "Window", 22 * EDSCALE);
- theme->set_constant("close_v_offset", "Window", 20 * EDSCALE);
- theme->set_constant("title_height", "Window", 24 * EDSCALE);
- theme->set_constant("resize_margin", "Window", 4 * EDSCALE);
- theme->set_font("title_font", "Window", theme->get_font(SNAME("title"), EditorStringName(EditorFonts)));
- theme->set_font_size("title_font_size", "Window", theme->get_font_size(SNAME("title_size"), EditorStringName(EditorFonts)));
-
- // Complex window (currently only Editor Settings and Project Settings)
- Ref<StyleBoxFlat> style_complex_window = style_window->duplicate();
- style_complex_window->set_bg_color(dark_color_2);
- style_complex_window->set_border_color(dark_color_2);
- theme->set_stylebox("panel", "EditorSettingsDialog", style_complex_window);
- theme->set_stylebox("panel", "ProjectSettingsEditor", style_complex_window);
- theme->set_stylebox("panel", "EditorAbout", style_complex_window);
-
- // AcceptDialog
- theme->set_stylebox("panel", "AcceptDialog", style_window_title);
- theme->set_constant("buttons_separation", "AcceptDialog", 8 * EDSCALE);
-
- // HScrollBar
- Ref<Texture2D> empty_icon = memnew(ImageTexture);
-
- if (increase_scrollbar_touch_area) {
- theme->set_stylebox("scroll", "HScrollBar", make_line_stylebox(separator_color, 50));
- } else {
- theme->set_stylebox("scroll", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, -5, 1, -5, 1));
- }
- theme->set_stylebox("scroll_focus", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1));
- theme->set_stylebox("grabber", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabber"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1));
- theme->set_stylebox("grabber_highlight", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberHl"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1));
- theme->set_stylebox("grabber_pressed", "HScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberPressed"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1));
-
- theme->set_icon("increment", "HScrollBar", empty_icon);
- theme->set_icon("increment_highlight", "HScrollBar", empty_icon);
- theme->set_icon("increment_pressed", "HScrollBar", empty_icon);
- theme->set_icon("decrement", "HScrollBar", empty_icon);
- theme->set_icon("decrement_highlight", "HScrollBar", empty_icon);
- theme->set_icon("decrement_pressed", "HScrollBar", empty_icon);
-
- // VScrollBar
- if (increase_scrollbar_touch_area) {
- theme->set_stylebox("scroll", "VScrollBar", make_line_stylebox(separator_color, 50, 1, 1, true));
- } else {
- theme->set_stylebox("scroll", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, -5, 1, -5));
- }
- theme->set_stylebox("scroll_focus", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1));
- theme->set_stylebox("grabber", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabber"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1));
- theme->set_stylebox("grabber_highlight", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberHl"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1));
- theme->set_stylebox("grabber_pressed", "VScrollBar", make_stylebox(theme->get_icon(SNAME("GuiScrollGrabberPressed"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1));
-
- theme->set_icon("increment", "VScrollBar", empty_icon);
- theme->set_icon("increment_highlight", "VScrollBar", empty_icon);
- theme->set_icon("increment_pressed", "VScrollBar", empty_icon);
- theme->set_icon("decrement", "VScrollBar", empty_icon);
- theme->set_icon("decrement_highlight", "VScrollBar", empty_icon);
- theme->set_icon("decrement_pressed", "VScrollBar", empty_icon);
-
- // HSlider
- theme->set_icon("grabber_highlight", "HSlider", theme->get_icon(SNAME("GuiSliderGrabberHl"), EditorStringName(EditorIcons)));
- theme->set_icon("grabber", "HSlider", theme->get_icon(SNAME("GuiSliderGrabber"), EditorStringName(EditorIcons)));
- theme->set_stylebox("slider", "HSlider", make_flat_stylebox(dark_color_3, 0, default_margin_size / 2, 0, default_margin_size / 2, corner_width));
- theme->set_stylebox("grabber_area", "HSlider", make_flat_stylebox(contrast_color_1, 0, default_margin_size / 2, 0, default_margin_size / 2, corner_width));
- theme->set_stylebox("grabber_area_highlight", "HSlider", make_flat_stylebox(contrast_color_1, 0, default_margin_size / 2, 0, default_margin_size / 2));
- theme->set_constant("center_grabber", "HSlider", 0);
- theme->set_constant("grabber_offset", "HSlider", 0);
-
- // VSlider
- theme->set_icon("grabber", "VSlider", theme->get_icon(SNAME("GuiSliderGrabber"), EditorStringName(EditorIcons)));
- theme->set_icon("grabber_highlight", "VSlider", theme->get_icon(SNAME("GuiSliderGrabberHl"), EditorStringName(EditorIcons)));
- theme->set_stylebox("slider", "VSlider", make_flat_stylebox(dark_color_3, default_margin_size / 2, 0, default_margin_size / 2, 0, corner_width));
- theme->set_stylebox("grabber_area", "VSlider", make_flat_stylebox(contrast_color_1, default_margin_size / 2, 0, default_margin_size / 2, 0, corner_width));
- theme->set_stylebox("grabber_area_highlight", "VSlider", make_flat_stylebox(contrast_color_1, default_margin_size / 2, 0, default_margin_size / 2, 0));
- theme->set_constant("center_grabber", "VSlider", 0);
- theme->set_constant("grabber_offset", "VSlider", 0);
-
- // RichTextLabel
- theme->set_color("default_color", "RichTextLabel", font_color);
- theme->set_color("font_shadow_color", "RichTextLabel", Color(0, 0, 0, 0));
- theme->set_color("font_outline_color", "RichTextLabel", font_outline_color);
- theme->set_color("selection_color", "RichTextLabel", selection_color);
- theme->set_constant("shadow_offset_x", "RichTextLabel", 1 * EDSCALE);
- theme->set_constant("shadow_offset_y", "RichTextLabel", 1 * EDSCALE);
- theme->set_constant("shadow_outline_size", "RichTextLabel", 1 * EDSCALE);
- theme->set_constant("outline_size", "RichTextLabel", 0);
- theme->set_stylebox("focus", "RichTextLabel", make_empty_stylebox());
- theme->set_stylebox("normal", "RichTextLabel", style_tree_bg);
-
- // Editor help.
- Ref<StyleBoxFlat> style_editor_help = style_default->duplicate();
- style_editor_help->set_bg_color(dark_color_2);
- style_editor_help->set_border_color(dark_color_3);
- theme->set_stylebox("background", "EditorHelp", style_editor_help);
-
- theme->set_color("title_color", "EditorHelp", accent_color);
- theme->set_color("headline_color", "EditorHelp", mono_color);
- theme->set_color("text_color", "EditorHelp", font_color);
- theme->set_color("comment_color", "EditorHelp", font_color * Color(1, 1, 1, 0.6));
- theme->set_color("symbol_color", "EditorHelp", font_color * Color(1, 1, 1, 0.6));
- theme->set_color("value_color", "EditorHelp", font_color * Color(1, 1, 1, 0.6));
- theme->set_color("qualifier_color", "EditorHelp", font_color * Color(1, 1, 1, 0.8));
- theme->set_color("type_color", "EditorHelp", accent_color.lerp(font_color, 0.5));
- theme->set_color("selection_color", "EditorHelp", selection_color);
- theme->set_color("link_color", "EditorHelp", accent_color.lerp(mono_color, 0.8));
- theme->set_color("code_color", "EditorHelp", accent_color.lerp(mono_color, 0.6));
- theme->set_color("kbd_color", "EditorHelp", accent_color.lerp(property_color, 0.6));
- theme->set_color("code_bg_color", "EditorHelp", dark_color_3);
- theme->set_color("kbd_bg_color", "EditorHelp", dark_color_1);
- theme->set_color("param_bg_color", "EditorHelp", dark_color_1);
- theme->set_constant("line_separation", "EditorHelp", Math::round(6 * EDSCALE));
- theme->set_constant("table_h_separation", "EditorHelp", 16 * EDSCALE);
- theme->set_constant("table_v_separation", "EditorHelp", 6 * EDSCALE);
- theme->set_constant("text_highlight_h_padding", "EditorHelp", 1 * EDSCALE);
- theme->set_constant("text_highlight_v_padding", "EditorHelp", 2 * EDSCALE);
-
- // Panel
- theme->set_stylebox("panel", "Panel", make_flat_stylebox(dark_color_1, 6, 4, 6, 4, corner_width));
- theme->set_stylebox("PanelForeground", EditorStringName(EditorStyles), style_default);
-
- // Label
- theme->set_stylebox("normal", "Label", style_empty);
- theme->set_color("font_color", "Label", font_color);
- theme->set_color("font_shadow_color", "Label", Color(0, 0, 0, 0));
- theme->set_color("font_outline_color", "Label", font_outline_color);
- theme->set_constant("shadow_offset_x", "Label", 1 * EDSCALE);
- theme->set_constant("shadow_offset_y", "Label", 1 * EDSCALE);
- theme->set_constant("shadow_outline_size", "Label", 1 * EDSCALE);
- theme->set_constant("line_spacing", "Label", 3 * EDSCALE);
- theme->set_constant("outline_size", "Label", 0);
-
- // LinkButton
- theme->set_stylebox("focus", "LinkButton", style_empty);
- theme->set_color("font_color", "LinkButton", font_color);
- theme->set_color("font_hover_color", "LinkButton", font_hover_color);
- theme->set_color("font_hover_pressed_color", "LinkButton", font_hover_pressed_color);
- theme->set_color("font_focus_color", "LinkButton", font_focus_color);
- theme->set_color("font_pressed_color", "LinkButton", accent_color);
- theme->set_color("font_disabled_color", "LinkButton", font_disabled_color);
- theme->set_color("font_outline_color", "LinkButton", font_outline_color);
-
- theme->set_constant("outline_size", "LinkButton", 0);
-
- theme->set_type_variation("HeaderSmallLink", "LinkButton");
- theme->set_font("font", "HeaderSmallLink", theme->get_font(SNAME("font"), SNAME("HeaderSmall")));
- theme->set_font_size("font_size", "HeaderSmallLink", theme->get_font_size(SNAME("font_size"), SNAME("HeaderSmall")));
-
- // TooltipPanel + TooltipLabel
- // TooltipPanel is also used for custom tooltips, while TooltipLabel
- // is only relevant for default tooltips.
- Ref<StyleBoxFlat> style_tooltip = style_popup->duplicate();
- style_tooltip->set_shadow_size(0);
- style_tooltip->set_content_margin_all(default_margin_size * EDSCALE * 0.5);
- style_tooltip->set_bg_color(dark_color_3 * Color(0.8, 0.8, 0.8, 0.9));
- style_tooltip->set_border_width_all(0);
- theme->set_color("font_color", "TooltipLabel", font_hover_color);
- theme->set_color("font_shadow_color", "TooltipLabel", Color(0, 0, 0, 0));
- theme->set_stylebox("panel", "TooltipPanel", style_tooltip);
-
- // PopupPanel
- theme->set_stylebox("panel", "PopupPanel", style_popup);
-
- Ref<StyleBoxFlat> control_editor_popup_style = style_popup->duplicate();
- control_editor_popup_style->set_shadow_size(0);
- control_editor_popup_style->set_content_margin(SIDE_LEFT, default_margin_size * EDSCALE);
- control_editor_popup_style->set_content_margin(SIDE_TOP, default_margin_size * EDSCALE);
- control_editor_popup_style->set_content_margin(SIDE_RIGHT, default_margin_size * EDSCALE);
- control_editor_popup_style->set_content_margin(SIDE_BOTTOM, default_margin_size * EDSCALE);
- control_editor_popup_style->set_border_width_all(0);
-
- theme->set_stylebox("panel", "ControlEditorPopupPanel", control_editor_popup_style);
- theme->set_type_variation("ControlEditorPopupPanel", "PopupPanel");
-
- // SpinBox
- theme->set_icon("updown", "SpinBox", theme->get_icon(SNAME("GuiSpinboxUpdown"), EditorStringName(EditorIcons)));
- theme->set_icon("updown_disabled", "SpinBox", theme->get_icon(SNAME("GuiSpinboxUpdownDisabled"), EditorStringName(EditorIcons)));
-
- // ProgressBar
- theme->set_stylebox("background", "ProgressBar", make_stylebox(theme->get_icon(SNAME("GuiProgressBar"), EditorStringName(EditorIcons)), 4, 4, 4, 4, 0, 0, 0, 0));
- theme->set_stylebox("fill", "ProgressBar", make_stylebox(theme->get_icon(SNAME("GuiProgressFill"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 2, 1, 2, 1));
- theme->set_color("font_color", "ProgressBar", font_color);
- theme->set_color("font_outline_color", "ProgressBar", font_outline_color);
- theme->set_constant("outline_size", "ProgressBar", 0);
-
- // GraphEdit
- theme->set_stylebox("panel", "GraphEdit", style_tree_bg);
- Ref<StyleBoxFlat> graph_toolbar_style = make_flat_stylebox(dark_color_1 * Color(1, 1, 1, 0.6), 4, 2, 4, 2, 3);
- theme->set_stylebox("menu_panel", "GraphEdit", graph_toolbar_style);
-
- if (dark_theme) {
- theme->set_color("grid_major", "GraphEdit", Color(1.0, 1.0, 1.0, 0.1));
- theme->set_color("grid_minor", "GraphEdit", Color(1.0, 1.0, 1.0, 0.05));
- } else {
- theme->set_color("grid_major", "GraphEdit", Color(0.0, 0.0, 0.0, 0.15));
- theme->set_color("grid_minor", "GraphEdit", Color(0.0, 0.0, 0.0, 0.07));
- }
- theme->set_color("selection_fill", "GraphEdit", theme->get_color(SNAME("box_selection_fill_color"), EditorStringName(Editor)));
- theme->set_color("selection_stroke", "GraphEdit", theme->get_color(SNAME("box_selection_stroke_color"), EditorStringName(Editor)));
- theme->set_color("activity", "GraphEdit", accent_color);
-
- theme->set_icon("zoom_out", "GraphEdit", theme->get_icon(SNAME("ZoomLess"), EditorStringName(EditorIcons)));
- theme->set_icon("zoom_in", "GraphEdit", theme->get_icon(SNAME("ZoomMore"), EditorStringName(EditorIcons)));
- theme->set_icon("zoom_reset", "GraphEdit", theme->get_icon(SNAME("ZoomReset"), EditorStringName(EditorIcons)));
- theme->set_icon("grid_toggle", "GraphEdit", theme->get_icon(SNAME("GridToggle"), EditorStringName(EditorIcons)));
- theme->set_icon("minimap_toggle", "GraphEdit", theme->get_icon(SNAME("GridMinimap"), EditorStringName(EditorIcons)));
- theme->set_icon("snapping_toggle", "GraphEdit", theme->get_icon(SNAME("SnapGrid"), EditorStringName(EditorIcons)));
- theme->set_icon("layout", "GraphEdit", theme->get_icon(SNAME("GridLayout"), EditorStringName(EditorIcons)));
-
- // GraphEditMinimap
- Ref<StyleBoxFlat> style_minimap_bg = make_flat_stylebox(dark_color_1, 0, 0, 0, 0);
- style_minimap_bg->set_border_color(dark_color_3);
- style_minimap_bg->set_border_width_all(1);
- theme->set_stylebox("panel", "GraphEditMinimap", style_minimap_bg);
-
- Ref<StyleBoxFlat> style_minimap_camera;
- Ref<StyleBoxFlat> style_minimap_node;
- if (dark_theme) {
- style_minimap_camera = make_flat_stylebox(Color(0.65, 0.65, 0.65, 0.2), 0, 0, 0, 0);
- style_minimap_camera->set_border_color(Color(0.65, 0.65, 0.65, 0.45));
- style_minimap_node = make_flat_stylebox(Color(1, 1, 1), 0, 0, 0, 0);
- } else {
- style_minimap_camera = make_flat_stylebox(Color(0.38, 0.38, 0.38, 0.2), 0, 0, 0, 0);
- style_minimap_camera->set_border_color(Color(0.38, 0.38, 0.38, 0.45));
- style_minimap_node = make_flat_stylebox(Color(0, 0, 0), 0, 0, 0, 0);
- }
- style_minimap_camera->set_border_width_all(1);
- style_minimap_node->set_anti_aliased(false);
- theme->set_stylebox("camera", "GraphEditMinimap", style_minimap_camera);
- theme->set_stylebox("node", "GraphEditMinimap", style_minimap_node);
-
- Color minimap_resizer_color;
- if (dark_theme) {
- minimap_resizer_color = Color(1, 1, 1, 0.65);
- } else {
- minimap_resizer_color = Color(0, 0, 0, 0.65);
- }
- theme->set_icon("resizer", "GraphEditMinimap", theme->get_icon(SNAME("GuiResizerTopLeft"), EditorStringName(EditorIcons)));
- theme->set_color("resizer_color", "GraphEditMinimap", minimap_resizer_color);
-
- // GraphNode
-
- const int gn_margin_top = 2;
- const int gn_margin_side = 2;
- const int gn_margin_bottom = 2;
-
- Color graphnode_bg = dark_color_3;
- if (!dark_theme) {
- graphnode_bg = prop_section_color;
- }
- const Color graph_node_selected_border_color = graphnode_bg.lerp(accent_color, 0.275);
-
- const Color graphnode_frame_bg = graphnode_bg.lerp(style_tree_bg->get_bg_color(), 0.3);
-
- Ref<StyleBoxFlat> graphn_sb_panel = make_flat_stylebox(graphnode_frame_bg, gn_margin_side, gn_margin_top, gn_margin_side, gn_margin_bottom, corner_width);
- graphn_sb_panel->set_border_width_all(border_width);
- graphn_sb_panel->set_border_color(graphnode_bg);
- graphn_sb_panel->set_corner_radius_individual(0, 0, corner_radius * EDSCALE, corner_radius * EDSCALE);
- graphn_sb_panel->set_expand_margin(SIDE_TOP, 17 * EDSCALE);
-
- Ref<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);
- graphn_sb_panel_selected->set_border_width_all(2 * EDSCALE + border_width);
- graphn_sb_panel_selected->set_border_color(graph_node_selected_border_color);
- graphn_sb_panel_selected->set_corner_radius_individual(0, 0, corner_radius * EDSCALE, corner_radius * EDSCALE);
- graphn_sb_panel_selected->set_expand_margin(SIDE_TOP, 17 * EDSCALE);
-
- const int gn_titlebar_margin_left = 12;
- const int gn_titlebar_margin_right = 4; // The rest is for the close button.
- Ref<StyleBoxFlat> graphn_sb_titlebar = make_flat_stylebox(graphnode_bg, gn_titlebar_margin_left, gn_margin_top, gn_titlebar_margin_right, 0, corner_width);
- graphn_sb_titlebar->set_expand_margin(SIDE_TOP, 2 * EDSCALE);
- graphn_sb_titlebar->set_corner_radius_individual(corner_radius * EDSCALE, corner_radius * EDSCALE, 0, 0);
-
- Ref<StyleBoxFlat> graphn_sb_titlebar_selected = make_flat_stylebox(graph_node_selected_border_color, gn_titlebar_margin_left, gn_margin_top, gn_titlebar_margin_right, 0, corner_width);
- graphn_sb_titlebar_selected->set_corner_radius_individual(corner_radius * EDSCALE, corner_radius * EDSCALE, 0, 0);
- graphn_sb_titlebar_selected->set_expand_margin(SIDE_TOP, 2 * EDSCALE);
- Ref<StyleBoxEmpty> graphn_sb_slot = make_empty_stylebox(12, 0, 12, 0);
-
- theme->set_stylebox("panel", "GraphElement", graphn_sb_panel);
- theme->set_stylebox("panel_selected", "GraphElement", graphn_sb_panel_selected);
- theme->set_stylebox("titlebar", "GraphElement", graphn_sb_titlebar);
- theme->set_stylebox("titlebar_selected", "GraphElement", graphn_sb_titlebar_selected);
-
- // GraphNode's title Label.
- theme->set_type_variation("GraphNodeTitleLabel", "Label");
-
- theme->set_stylebox("normal", "GraphNodeTitleLabel", make_empty_stylebox(0, 0, 0, 0));
- theme->set_color("font_color", "GraphNodeTitleLabel", font_color);
- theme->set_constant("line_spacing", "GraphNodeTitleLabel", 3 * EDSCALE);
-
- Color graphnode_decoration_color = dark_color_1.inverted();
-
- theme->set_color("resizer_color", "GraphElement", graphnode_decoration_color);
- theme->set_icon("resizer", "GraphElement", theme->get_icon(SNAME("GuiResizer"), EditorStringName(EditorIcons)));
-
- // GraphNode.
- theme->set_stylebox("panel", "GraphNode", graphn_sb_panel);
- theme->set_stylebox("panel_selected", "GraphNode", graphn_sb_panel_selected);
- theme->set_stylebox("titlebar", "GraphNode", graphn_sb_titlebar);
- theme->set_stylebox("titlebar_selected", "GraphNode", graphn_sb_titlebar_selected);
- theme->set_stylebox("slot", "GraphNode", graphn_sb_slot);
-
- theme->set_color("resizer_color", "GraphNode", graphnode_decoration_color);
-
- theme->set_constant("port_h_offset", "GraphNode", 0);
- theme->set_constant("separation", "GraphNode", 1 * EDSCALE);
-
- Ref<ImageTexture> port_icon = theme->get_icon(SNAME("GuiGraphNodePort"), EditorStringName(EditorIcons));
- // The true size is 24x24 This is necessary for sharp port icons at high zoom levels in GraphEdit (up to ~200%).
- port_icon->set_size_override(Size2(12, 12));
- theme->set_icon("port", "GraphNode", port_icon);
-
- // StateMachine graph
- theme->set_stylebox("panel", "GraphStateMachine", style_tree_bg);
- theme->set_stylebox("error_panel", "GraphStateMachine", style_tree_bg);
- theme->set_color("error_color", "GraphStateMachine", error_color);
-
- const int sm_margin_side = 10 * EDSCALE;
-
- Ref<StyleBoxFlat> sm_node_style = make_flat_stylebox(dark_color_3 * Color(1, 1, 1, 0.7), sm_margin_side, 24 * EDSCALE, sm_margin_side, gn_margin_bottom, corner_width);
- sm_node_style->set_border_width_all(border_width);
- sm_node_style->set_border_color(graphnode_bg);
-
- Ref<StyleBoxFlat> sm_node_selected_style = make_flat_stylebox(graphnode_bg * Color(1, 1, 1, 0.9), sm_margin_side, 24 * EDSCALE, sm_margin_side, gn_margin_bottom, corner_width);
- sm_node_selected_style->set_border_width_all(2 * EDSCALE + border_width);
- sm_node_selected_style->set_border_color(accent_color * Color(1, 1, 1, 0.9));
- sm_node_selected_style->set_shadow_size(8 * EDSCALE);
- sm_node_selected_style->set_shadow_color(shadow_color);
-
- Ref<StyleBoxFlat> sm_node_playing_style = sm_node_selected_style->duplicate();
- sm_node_playing_style->set_border_color(warning_color);
- sm_node_playing_style->set_shadow_color(warning_color * Color(1, 1, 1, 0.2));
-
- theme->set_stylebox("node_frame", "GraphStateMachine", sm_node_style);
- theme->set_stylebox("node_frame_selected", "GraphStateMachine", sm_node_selected_style);
- theme->set_stylebox("node_frame_playing", "GraphStateMachine", sm_node_playing_style);
-
- Ref<StyleBoxFlat> sm_node_start_style = sm_node_style->duplicate();
- sm_node_start_style->set_border_width_all(1 * EDSCALE);
- sm_node_start_style->set_border_color(success_color.lightened(0.24));
- theme->set_stylebox("node_frame_start", "GraphStateMachine", sm_node_start_style);
-
- Ref<StyleBoxFlat> sm_node_end_style = sm_node_style->duplicate();
- sm_node_end_style->set_border_width_all(1 * EDSCALE);
- sm_node_end_style->set_border_color(error_color);
- theme->set_stylebox("node_frame_end", "GraphStateMachine", sm_node_end_style);
-
- theme->set_font("node_title_font", "GraphStateMachine", theme->get_font(SNAME("font"), SNAME("Label")));
- theme->set_font_size("node_title_font_size", "GraphStateMachine", theme->get_font_size(SNAME("font_size"), SNAME("Label")));
- theme->set_color("node_title_font_color", "GraphStateMachine", font_color);
-
- theme->set_color("transition_color", "GraphStateMachine", font_color);
- theme->set_color("transition_disabled_color", "GraphStateMachine", font_color * Color(1, 1, 1, 0.2));
- theme->set_color("transition_icon_color", "GraphStateMachine", Color(1, 1, 1));
- theme->set_color("transition_icon_disabled_color", "GraphStateMachine", Color(1, 1, 1, 0.2));
- theme->set_color("highlight_color", "GraphStateMachine", accent_color);
- theme->set_color("highlight_disabled_color", "GraphStateMachine", accent_color * Color(1, 1, 1, 0.6));
- theme->set_color("guideline_color", "GraphStateMachine", font_color * Color(1, 1, 1, 0.3));
-
- theme->set_color("playback_color", "GraphStateMachine", font_color);
- theme->set_color("playback_background_color", "GraphStateMachine", font_color * Color(1, 1, 1, 0.3));
-
- // GridContainer
- theme->set_constant("v_separation", "GridContainer", Math::round(widget_default_margin.y - 2 * EDSCALE));
-
- // FileDialog
- theme->set_icon("folder", "FileDialog", theme->get_icon(SNAME("Folder"), EditorStringName(EditorIcons)));
- theme->set_icon("parent_folder", "FileDialog", theme->get_icon(SNAME("ArrowUp"), EditorStringName(EditorIcons)));
- theme->set_icon("back_folder", "FileDialog", theme->get_icon(SNAME("Back"), EditorStringName(EditorIcons)));
- theme->set_icon("forward_folder", "FileDialog", theme->get_icon(SNAME("Forward"), EditorStringName(EditorIcons)));
- theme->set_icon("reload", "FileDialog", theme->get_icon(SNAME("Reload"), EditorStringName(EditorIcons)));
- theme->set_icon("toggle_hidden", "FileDialog", theme->get_icon(SNAME("GuiVisibilityVisible"), EditorStringName(EditorIcons)));
- // Use a different color for folder icons to make them easier to distinguish from files.
- // On a light theme, the icon will be dark, so we need to lighten it before blending it with the accent color.
- theme->set_color("folder_icon_color", "FileDialog", (dark_theme ? Color(1, 1, 1) : Color(4.25, 4.25, 4.25)).lerp(accent_color, 0.7));
- theme->set_color("files_disabled", "FileDialog", font_disabled_color);
-
- // ColorPicker
- theme->set_constant("margin", "ColorPicker", default_margin_size);
- theme->set_constant("sv_width", "ColorPicker", 256 * EDSCALE);
- theme->set_constant("sv_height", "ColorPicker", 256 * EDSCALE);
- theme->set_constant("h_width", "ColorPicker", 30 * EDSCALE);
- theme->set_constant("label_width", "ColorPicker", 10 * EDSCALE);
- theme->set_constant("center_slider_grabbers", "ColorPicker", 1);
- theme->set_icon("screen_picker", "ColorPicker", theme->get_icon(SNAME("ColorPick"), EditorStringName(EditorIcons)));
- theme->set_icon("shape_circle", "ColorPicker", theme->get_icon(SNAME("PickerShapeCircle"), EditorStringName(EditorIcons)));
- theme->set_icon("shape_rect", "ColorPicker", theme->get_icon(SNAME("PickerShapeRectangle"), EditorStringName(EditorIcons)));
- theme->set_icon("shape_rect_wheel", "ColorPicker", theme->get_icon(SNAME("PickerShapeRectangleWheel"), EditorStringName(EditorIcons)));
- theme->set_icon("add_preset", "ColorPicker", theme->get_icon(SNAME("Add"), EditorStringName(EditorIcons)));
- theme->set_icon("sample_bg", "ColorPicker", theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons)));
- theme->set_icon("sample_revert", "ColorPicker", theme->get_icon(SNAME("Reload"), EditorStringName(EditorIcons)));
- theme->set_icon("overbright_indicator", "ColorPicker", theme->get_icon(SNAME("OverbrightIndicator"), EditorStringName(EditorIcons)));
- theme->set_icon("bar_arrow", "ColorPicker", theme->get_icon(SNAME("ColorPickerBarArrow"), EditorStringName(EditorIcons)));
- theme->set_icon("picker_cursor", "ColorPicker", theme->get_icon(SNAME("PickerCursor"), EditorStringName(EditorIcons)));
-
- // ColorPickerButton
- theme->set_icon("bg", "ColorPickerButton", theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons)));
-
- // ColorPresetButton
- Ref<StyleBoxFlat> preset_sb = make_flat_stylebox(Color(1, 1, 1), 2, 2, 2, 2, 2);
- theme->set_stylebox("preset_fg", "ColorPresetButton", preset_sb);
- theme->set_icon("preset_bg", "ColorPresetButton", theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons)));
- theme->set_icon("overbright_indicator", "ColorPresetButton", theme->get_icon(SNAME("OverbrightIndicator"), EditorStringName(EditorIcons)));
-
- // Information on 3D viewport
- Ref<StyleBoxFlat> style_info_3d_viewport = style_default->duplicate();
- style_info_3d_viewport->set_bg_color(style_info_3d_viewport->get_bg_color() * Color(1, 1, 1, 0.5));
- style_info_3d_viewport->set_border_width_all(0);
- theme->set_stylebox("Information3dViewport", EditorStringName(EditorStyles), style_info_3d_viewport);
-
- // Asset Library.
- theme->set_stylebox("bg", "AssetLib", style_empty);
- theme->set_stylebox("panel", "AssetLib", style_content_panel);
- theme->set_color("status_color", "AssetLib", Color(0.5, 0.5, 0.5));
- theme->set_icon("dismiss", "AssetLib", theme->get_icon(SNAME("Close"), EditorStringName(EditorIcons)));
-
- // Theme editor.
- theme->set_color("preview_picker_overlay_color", "ThemeEditor", Color(0.1, 0.1, 0.1, 0.25));
- Color theme_preview_picker_bg_color = accent_color;
- theme_preview_picker_bg_color.a = 0.2;
- Ref<StyleBoxFlat> theme_preview_picker_sb = make_flat_stylebox(theme_preview_picker_bg_color, 0, 0, 0, 0);
- theme_preview_picker_sb->set_border_color(accent_color);
- theme_preview_picker_sb->set_border_width_all(1.0 * EDSCALE);
- theme->set_stylebox("preview_picker_overlay", "ThemeEditor", theme_preview_picker_sb);
- Color theme_preview_picker_label_bg_color = accent_color;
- theme_preview_picker_label_bg_color.set_v(0.5);
- Ref<StyleBoxFlat> theme_preview_picker_label_sb = make_flat_stylebox(theme_preview_picker_label_bg_color, 4.0, 1.0, 4.0, 3.0);
- theme->set_stylebox("preview_picker_label", "ThemeEditor", theme_preview_picker_label_sb);
-
- // Dictionary editor add item.
- // Expand to the left and right by 4px to compensate for the dictionary editor margins.
- Ref<StyleBoxFlat> style_dictionary_add_item = make_flat_stylebox(prop_subsection_color, 0, 4, 0, 4, corner_radius);
- style_dictionary_add_item->set_expand_margin(SIDE_LEFT, 4 * EDSCALE);
- style_dictionary_add_item->set_expand_margin(SIDE_RIGHT, 4 * EDSCALE);
- theme->set_stylebox("DictionaryAddItem", EditorStringName(EditorStyles), style_dictionary_add_item);
-
- Ref<StyleBoxEmpty> vshader_label_style = make_empty_stylebox(2, 1, 2, 1);
- theme->set_stylebox("label_style", "VShaderEditor", vshader_label_style);
-
- // Project manager.
- theme->set_stylebox("search_panel", "ProjectManager", style_tree_bg);
- theme->set_constant("sidebar_button_icon_separation", "ProjectManager", int(6 * EDSCALE));
-
- // adaptive script theme constants
- // for comments and elements with lower relevance
- const Color dim_color = Color(font_color, 0.5);
-
- const float mono_value = mono_color.r;
- const Color alpha1 = Color(mono_value, mono_value, mono_value, 0.07);
- const Color alpha2 = Color(mono_value, mono_value, mono_value, 0.14);
- const Color alpha3 = Color(mono_value, mono_value, mono_value, 0.27);
-
- const Color symbol_color = dark_theme ? Color(0.67, 0.79, 1) : Color(0, 0, 0.61);
- const Color keyword_color = dark_theme ? Color(1.0, 0.44, 0.52) : Color(0.9, 0.135, 0.51);
- const Color control_flow_keyword_color = dark_theme ? Color(1.0, 0.55, 0.8) : Color(0.743, 0.12, 0.8);
- const Color base_type_color = dark_theme ? Color(0.26, 1.0, 0.76) : Color(0, 0.6, 0.2);
- const Color engine_type_color = dark_theme ? Color(0.56, 1, 0.86) : Color(0.11, 0.55, 0.4);
- const Color user_type_color = dark_theme ? Color(0.78, 1, 0.93) : Color(0.18, 0.45, 0.4);
- const Color comment_color = dark_theme ? dim_color : Color(0.08, 0.08, 0.08, 0.5);
- const Color doc_comment_color = dark_theme ? Color(0.6, 0.7, 0.8, 0.8) : Color(0.15, 0.15, 0.4, 0.7);
- const Color string_color = dark_theme ? Color(1, 0.93, 0.63) : Color(0.6, 0.42, 0);
-
- // Use the brightest background color on a light theme (which generally uses a negative contrast rate).
- const Color te_background_color = dark_theme ? background_color : dark_color_3;
- const Color completion_background_color = dark_theme ? base_color : background_color;
- const Color completion_selected_color = alpha1;
- const Color completion_existing_color = alpha2;
- // Same opacity as the scroll grabber editor icon.
- const Color completion_scroll_color = Color(mono_value, mono_value, mono_value, 0.29);
- const Color completion_scroll_hovered_color = Color(mono_value, mono_value, mono_value, 0.4);
- const Color completion_font_color = font_color;
- const Color text_color = font_color;
- const Color line_number_color = dim_color;
- const Color safe_line_number_color = dark_theme ? (dim_color * Color(1, 1.2, 1, 1.5)) : Color(0, 0.4, 0, 0.75);
- const Color caret_color = mono_color;
- const Color caret_background_color = mono_color.inverted();
- const Color text_selected_color = Color(0, 0, 0, 0);
- const Color brace_mismatch_color = dark_theme ? error_color : Color(1, 0.08, 0, 1);
- const Color current_line_color = alpha1;
- const Color line_length_guideline_color = dark_theme ? base_color : background_color;
- const Color word_highlighted_color = alpha1;
- const Color number_color = dark_theme ? Color(0.63, 1, 0.88) : Color(0, 0.55, 0.28, 1);
- const Color function_color = dark_theme ? Color(0.34, 0.7, 1.0) : Color(0, 0.225, 0.9, 1);
- const Color member_variable_color = dark_theme ? Color(0.34, 0.7, 1.0).lerp(mono_color, 0.6) : Color(0, 0.4, 0.68, 1);
- const Color mark_color = Color(error_color.r, error_color.g, error_color.b, 0.3);
- const Color bookmark_color = Color(0.08, 0.49, 0.98);
- const Color breakpoint_color = dark_theme ? error_color : Color(1, 0.27, 0.2, 1);
- const Color executing_line_color = Color(0.98, 0.89, 0.27);
- const Color code_folding_color = alpha3;
- const Color folded_code_region_color = Color(0.68, 0.46, 0.77, 0.2);
- const Color search_result_color = alpha1;
- const Color search_result_border_color = dark_theme ? Color(0.41, 0.61, 0.91, 0.38) : Color(0, 0.4, 1, 0.38);
-
- EditorSettings *setting = EditorSettings::get_singleton();
- String text_editor_color_theme = setting->get("text_editor/theme/color_theme");
- if (text_editor_color_theme == "Default") {
- setting->set_initial_value("text_editor/theme/highlighting/symbol_color", symbol_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/keyword_color", keyword_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/control_flow_keyword_color", control_flow_keyword_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/base_type_color", base_type_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/engine_type_color", engine_type_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/user_type_color", user_type_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/comment_color", comment_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/doc_comment_color", doc_comment_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/string_color", string_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/background_color", te_background_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/completion_background_color", completion_background_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/completion_selected_color", completion_selected_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/completion_existing_color", completion_existing_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/completion_scroll_color", completion_scroll_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/completion_scroll_hovered_color", completion_scroll_hovered_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/completion_font_color", completion_font_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/text_color", text_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/line_number_color", line_number_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/safe_line_number_color", safe_line_number_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/caret_color", caret_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/caret_background_color", caret_background_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/text_selected_color", text_selected_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/selection_color", selection_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/brace_mismatch_color", brace_mismatch_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/current_line_color", current_line_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/line_length_guideline_color", line_length_guideline_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/word_highlighted_color", word_highlighted_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/number_color", number_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/function_color", function_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/member_variable_color", member_variable_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/mark_color", mark_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/bookmark_color", bookmark_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/breakpoint_color", breakpoint_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/executing_line_color", executing_line_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/code_folding_color", code_folding_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/folded_code_region_color", folded_code_region_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/search_result_color", search_result_color, true);
- setting->set_initial_value("text_editor/theme/highlighting/search_result_border_color", search_result_border_color, true);
- } else if (text_editor_color_theme == "Godot 2") {
- setting->load_text_editor_theme();
- }
-
- // Now theme is loaded, apply it to CodeEdit.
- theme->set_font("font", "CodeEdit", theme->get_font(SNAME("source"), EditorStringName(EditorFonts)));
- theme->set_font_size("font_size", "CodeEdit", theme->get_font_size(SNAME("source_size"), EditorStringName(EditorFonts)));
-
- Ref<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);
- theme->set_stylebox("normal", "CodeEdit", code_edit_stylebox);
- theme->set_stylebox("read_only", "CodeEdit", code_edit_stylebox);
- theme->set_stylebox("focus", "CodeEdit", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty)));
-
- theme->set_icon("tab", "CodeEdit", theme->get_icon(SNAME("GuiTab"), EditorStringName(EditorIcons)));
- theme->set_icon("space", "CodeEdit", theme->get_icon(SNAME("GuiSpace"), EditorStringName(EditorIcons)));
- theme->set_icon("folded", "CodeEdit", theme->get_icon(SNAME("CodeFoldedRightArrow"), EditorStringName(EditorIcons)));
- theme->set_icon("can_fold", "CodeEdit", theme->get_icon(SNAME("CodeFoldDownArrow"), EditorStringName(EditorIcons)));
- theme->set_icon("folded_code_region", "CodeEdit", theme->get_icon(SNAME("CodeRegionFoldedRightArrow"), EditorStringName(EditorIcons)));
- theme->set_icon("can_fold_code_region", "CodeEdit", theme->get_icon(SNAME("CodeRegionFoldDownArrow"), EditorStringName(EditorIcons)));
- theme->set_icon("executing_line", "CodeEdit", theme->get_icon(SNAME("TextEditorPlay"), EditorStringName(EditorIcons)));
- theme->set_icon("breakpoint", "CodeEdit", theme->get_icon(SNAME("Breakpoint"), EditorStringName(EditorIcons)));
-
- theme->set_constant("line_spacing", "CodeEdit", EDITOR_GET("text_editor/appearance/whitespace/line_spacing"));
-
- theme->set_color("background_color", "CodeEdit", Color(0, 0, 0, 0));
- theme->set_color("completion_background_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_background_color"));
- theme->set_color("completion_selected_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_selected_color"));
- theme->set_color("completion_existing_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_existing_color"));
- theme->set_color("completion_scroll_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_scroll_color"));
- theme->set_color("completion_scroll_hovered_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_scroll_hovered_color"));
- theme->set_color("font_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/text_color"));
- theme->set_color("line_number_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/line_number_color"));
- theme->set_color("caret_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/caret_color"));
- theme->set_color("font_selected_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/text_selected_color"));
- theme->set_color("selection_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/selection_color"));
- theme->set_color("brace_mismatch_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/brace_mismatch_color"));
- theme->set_color("current_line_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/current_line_color"));
- theme->set_color("line_length_guideline_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/line_length_guideline_color"));
- theme->set_color("word_highlighted_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/word_highlighted_color"));
- theme->set_color("bookmark_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/bookmark_color"));
- theme->set_color("breakpoint_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/breakpoint_color"));
- theme->set_color("executing_line_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/executing_line_color"));
- theme->set_color("code_folding_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/code_folding_color"));
- theme->set_color("folded_code_region_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/folded_code_region_color"));
- theme->set_color("search_result_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/search_result_color"));
- theme->set_color("search_result_border_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/search_result_border_color"));
-
- OS::get_singleton()->benchmark_end_measure("EditorTheme", "Create Editor Theme");
-
- return theme;
-}
-
-Ref<Theme> create_custom_theme(const Ref<Theme> p_theme) {
- Ref<Theme> theme = create_editor_theme(p_theme);
-
- OS::get_singleton()->benchmark_begin_measure("EditorTheme", "Create Custom Theme");
-
- const String custom_theme_path = EDITOR_GET("interface/theme/custom_theme");
- if (!custom_theme_path.is_empty()) {
- Ref<Theme> custom_theme = ResourceLoader::load(custom_theme_path);
- if (custom_theme.is_valid()) {
- theme->merge_with(custom_theme);
- }
- }
-
- OS::get_singleton()->benchmark_end_measure("EditorTheme", "Create Custom Theme");
- return theme;
-}
-
-/**
- * Returns the SVG code for the default project icon.
- */
-String get_default_project_icon() {
- for (int i = 0; i < editor_icons_count; i++) {
- if (strcmp(editor_icons_names[i], "DefaultProjectIcon") == 0) {
- return String(editor_icons_sources[i]);
- }
- }
- return String();
-}
diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp
index 855d610d72..ee25893a30 100644
--- a/editor/export/editor_export_platform.cpp
+++ b/editor/export/editor_export_platform.cpp
@@ -40,11 +40,11 @@
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/export/editor_export.h"
#include "editor/plugins/script_editor_plugin.h"
+#include "editor/themes/editor_scale.h"
#include "editor_export_plugin.h"
#include "scene/resources/image_texture.h"
#include "scene/resources/packed_scene.h"
diff --git a/editor/export/export_template_manager.cpp b/editor/export/export_template_manager.cpp
index 26ed7c46fb..69ad076f8a 100644
--- a/editor/export/export_template_manager.cpp
+++ b/editor/export/export_template_manager.cpp
@@ -36,10 +36,10 @@
#include "core/version.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/progress_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/file_dialog.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/separator.h"
@@ -758,7 +758,7 @@ void ExportTemplateManager::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED: {
current_value->add_theme_font_override("font", get_theme_font(SNAME("main"), EditorStringName(EditorFonts)));
current_missing_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), EditorStringName(Editor)));
- current_installed_label->add_theme_color_override("font_color", get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor)));
+ current_installed_label->add_theme_color_override("font_color", get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor)));
mirror_options_button->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl")));
} break;
diff --git a/editor/export/project_export.cpp b/editor/export/project_export.cpp
index 2ec1363ced..63bd87e6cc 100644
--- a/editor/export/project_export.cpp
+++ b/editor/export/project_export.cpp
@@ -35,12 +35,12 @@
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
#include "editor/editor_properties.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/export/editor_export.h"
#include "editor/gui/editor_file_dialog.h"
#include "editor/import/resource_importer_texture_settings.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/check_box.h"
#include "scene/gui/check_button.h"
#include "scene/gui/item_list.h"
@@ -824,7 +824,7 @@ void ProjectExportDialog::_setup_item_for_file_mode(TreeItem *p_item, EditorExpo
p_item->set_cell_mode(1, TreeItem::CELL_MODE_STRING);
p_item->set_editable(1, false);
p_item->set_selectable(1, false);
- p_item->set_custom_color(1, get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor)));
+ p_item->set_custom_color(1, get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor)));
} else {
p_item->set_checked(0, true);
p_item->set_cell_mode(1, TreeItem::CELL_MODE_CUSTOM);
diff --git a/editor/fbx_importer_manager.cpp b/editor/fbx_importer_manager.cpp
index 5922cbf312..7199ef3842 100644
--- a/editor/fbx_importer_manager.cpp
+++ b/editor/fbx_importer_manager.cpp
@@ -32,9 +32,9 @@
#include "core/config/project_settings.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/link_button.h"
void FBXImporterManager::_notification(int p_what) {
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 6f8b46cce0..0aa9a3bfee 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -42,7 +42,6 @@
#include "editor/editor_feature_profile.h"
#include "editor/editor_node.h"
#include "editor/editor_resource_preview.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/gui/editor_dir_dialog.h"
@@ -53,6 +52,7 @@
#include "editor/scene_create_dialog.h"
#include "editor/scene_tree_dock.h"
#include "editor/shader_create_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/item_list.h"
#include "scene/gui/label.h"
#include "scene/gui/line_edit.h"
@@ -865,18 +865,7 @@ void FileSystemDock::_search(EditorFileSystemDirectory *p_path, List<FileInfo> *
struct FileSystemDock::FileInfoTypeComparator {
bool operator()(const FileInfo &p_a, const FileInfo &p_b) const {
- // Uses the extension, then the icon name to distinguish file types.
- String icon_path_a = "";
- String icon_path_b = "";
- Ref<Texture2D> icon_a = EditorNode::get_singleton()->get_class_icon(p_a.type);
- if (icon_a.is_valid()) {
- icon_path_a = icon_a->get_name();
- }
- Ref<Texture2D> icon_b = EditorNode::get_singleton()->get_class_icon(p_b.type);
- if (icon_b.is_valid()) {
- icon_path_b = icon_b->get_name();
- }
- return NaturalNoCaseComparator()(p_a.name.get_extension() + icon_path_a + p_a.name.get_basename(), p_b.name.get_extension() + icon_path_b + p_b.name.get_basename());
+ return NaturalNoCaseComparator()(p_a.name.get_extension() + p_a.type + p_a.name.get_basename(), p_b.name.get_extension() + p_b.type + p_b.name.get_basename());
}
};
@@ -3665,6 +3654,70 @@ void FileSystemDock::_bind_methods() {
ADD_SIGNAL(MethodInfo("display_mode_changed"));
}
+void FileSystemDock::save_layout_to_config(Ref<ConfigFile> p_layout, const String &p_section) const {
+ p_layout->set_value(p_section, "dock_filesystem_h_split_offset", get_h_split_offset());
+ p_layout->set_value(p_section, "dock_filesystem_v_split_offset", get_v_split_offset());
+ p_layout->set_value(p_section, "dock_filesystem_display_mode", get_display_mode());
+ p_layout->set_value(p_section, "dock_filesystem_file_sort", get_file_sort());
+ p_layout->set_value(p_section, "dock_filesystem_file_list_display_mode", get_file_list_display_mode());
+ PackedStringArray selected_files = get_selected_paths();
+ p_layout->set_value(p_section, "dock_filesystem_selected_paths", selected_files);
+ Vector<String> uncollapsed_paths = get_uncollapsed_paths();
+ p_layout->set_value(p_section, "dock_filesystem_uncollapsed_paths", uncollapsed_paths);
+}
+
+void FileSystemDock::load_layout_from_config(Ref<ConfigFile> p_layout, const String &p_section) {
+ if (p_layout->has_section_key(p_section, "dock_filesystem_h_split_offset")) {
+ int fs_h_split_ofs = p_layout->get_value(p_section, "dock_filesystem_h_split_offset");
+ set_h_split_offset(fs_h_split_ofs);
+ }
+
+ if (p_layout->has_section_key(p_section, "dock_filesystem_v_split_offset")) {
+ int fs_v_split_ofs = p_layout->get_value(p_section, "dock_filesystem_v_split_offset");
+ set_v_split_offset(fs_v_split_ofs);
+ }
+
+ if (p_layout->has_section_key(p_section, "dock_filesystem_display_mode")) {
+ DisplayMode dock_filesystem_display_mode = DisplayMode(int(p_layout->get_value(p_section, "dock_filesystem_display_mode")));
+ set_display_mode(dock_filesystem_display_mode);
+ }
+
+ if (p_layout->has_section_key(p_section, "dock_filesystem_file_sort")) {
+ FileSortOption dock_filesystem_file_sort = FileSortOption(int(p_layout->get_value(p_section, "dock_filesystem_file_sort")));
+ set_file_sort(dock_filesystem_file_sort);
+ }
+
+ if (p_layout->has_section_key(p_section, "dock_filesystem_file_list_display_mode")) {
+ FileListDisplayMode dock_filesystem_file_list_display_mode = FileListDisplayMode(int(p_layout->get_value(p_section, "dock_filesystem_file_list_display_mode")));
+ set_file_list_display_mode(dock_filesystem_file_list_display_mode);
+ }
+
+ if (p_layout->has_section_key(p_section, "dock_filesystem_selected_paths")) {
+ PackedStringArray dock_filesystem_selected_paths = p_layout->get_value(p_section, "dock_filesystem_selected_paths");
+ for (int i = 0; i < dock_filesystem_selected_paths.size(); i++) {
+ select_file(dock_filesystem_selected_paths[i]);
+ }
+ }
+
+ // Restore collapsed state.
+ PackedStringArray uncollapsed_tis;
+ if (p_layout->has_section_key(p_section, "dock_filesystem_uncollapsed_paths")) {
+ uncollapsed_tis = p_layout->get_value(p_section, "dock_filesystem_uncollapsed_paths");
+ } else {
+ uncollapsed_tis = { "res://" };
+ }
+
+ if (!uncollapsed_tis.is_empty()) {
+ for (int i = 0; i < uncollapsed_tis.size(); i++) {
+ TreeItem *uncollapsed_ti = get_tree_control()->get_item_with_metadata(uncollapsed_tis[i], 0);
+ if (uncollapsed_ti) {
+ uncollapsed_ti->set_collapsed(false);
+ }
+ }
+ get_tree_control()->queue_redraw();
+ }
+}
+
FileSystemDock::FileSystemDock() {
singleton = this;
set_name("FileSystem");
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index 5fe1389e2a..6c69acb953 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -394,13 +394,13 @@ public:
void select_file(const String &p_file);
void set_display_mode(DisplayMode p_display_mode);
- DisplayMode get_display_mode() { return display_mode; }
+ DisplayMode get_display_mode() const { return display_mode; }
void set_file_sort(FileSortOption p_file_sort);
- FileSortOption get_file_sort() { return file_sort; }
+ FileSortOption get_file_sort() const { return file_sort; }
void set_file_list_display_mode(FileListDisplayMode p_mode);
- FileListDisplayMode get_file_list_display_mode() { return file_list_display_mode; };
+ FileListDisplayMode get_file_list_display_mode() const { return file_list_display_mode; };
Tree *get_tree_control() { return tree; }
@@ -408,6 +408,9 @@ public:
void remove_resource_tooltip_plugin(const Ref<EditorResourceTooltipPlugin> &p_plugin);
Control *create_tooltip_for_path(const String &p_path) const;
+ void save_layout_to_config(Ref<ConfigFile> p_layout, const String &p_section) const;
+ void load_layout_from_config(Ref<ConfigFile> p_layout, const String &p_section);
+
FileSystemDock();
~FileSystemDock();
};
diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp
index a81aa971f3..c708e77719 100644
--- a/editor/find_in_files.cpp
+++ b/editor/find_in_files.cpp
@@ -34,8 +34,8 @@
#include "core/io/dir_access.h"
#include "core/os/os.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_string_names.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/check_box.h"
diff --git a/editor/group_settings_editor.cpp b/editor/group_settings_editor.cpp
index 42e117f4c1..634192ab50 100644
--- a/editor/group_settings_editor.cpp
+++ b/editor/group_settings_editor.cpp
@@ -31,13 +31,13 @@
#include "group_settings_editor.h"
#include "core/config/project_settings.h"
-#include "editor/editor_scale.h"
+#include "editor/editor_file_system.h"
+#include "editor/editor_node.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/filesystem_dock.h"
#include "editor/gui/editor_validation_panel.h"
#include "editor/scene_tree_dock.h"
-#include "editor_file_system.h"
-#include "editor_node.h"
+#include "editor/themes/editor_scale.h"
#include "scene/resources/packed_scene.h"
void GroupSettingsEditor::_notification(int p_what) {
diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp
index 77a867f34b..723a7c8901 100644
--- a/editor/groups_editor.cpp
+++ b/editor/groups_editor.cpp
@@ -31,12 +31,12 @@
#include "groups_editor.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_validation_panel.h"
#include "editor/project_settings_editor.h"
#include "editor/scene_tree_dock.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/box_container.h"
#include "scene/gui/check_button.h"
#include "scene/gui/grid_container.h"
diff --git a/editor/gui/editor_file_dialog.cpp b/editor/gui/editor_file_dialog.cpp
index 9764574d04..4d1fd1f7b7 100644
--- a/editor/gui/editor_file_dialog.cpp
+++ b/editor/gui/editor_file_dialog.cpp
@@ -38,9 +38,9 @@
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
#include "editor/editor_resource_preview.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/filesystem_dock.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/center_container.h"
#include "scene/gui/label.h"
#include "scene/gui/margin_container.h"
diff --git a/editor/gui/editor_object_selector.cpp b/editor/gui/editor_object_selector.cpp
index 9acd38bcf4..c97d68fb35 100644
--- a/editor/gui/editor_object_selector.cpp
+++ b/editor/gui/editor_object_selector.cpp
@@ -32,9 +32,9 @@
#include "editor/editor_data.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_string_names.h"
#include "editor/multi_node_edit.h"
+#include "editor/themes/editor_scale.h"
Size2 EditorObjectSelector::get_minimum_size() const {
Ref<Font> font = get_theme_font(SNAME("font"));
diff --git a/editor/gui/editor_scene_tabs.cpp b/editor/gui/editor_scene_tabs.cpp
index 7f8f2fd8a3..915b161372 100644
--- a/editor/gui/editor_scene_tabs.cpp
+++ b/editor/gui/editor_scene_tabs.cpp
@@ -32,11 +32,11 @@
#include "editor/editor_node.h"
#include "editor/editor_resource_preview.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/inspector_dock.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/panel.h"
diff --git a/editor/gui/editor_spin_slider.cpp b/editor/gui/editor_spin_slider.cpp
index 051e4340bc..8401f08391 100644
--- a/editor/gui/editor_spin_slider.cpp
+++ b/editor/gui/editor_spin_slider.cpp
@@ -33,8 +33,8 @@
#include "core/input/input.h"
#include "core/math/expression.h"
#include "core/os/keyboard.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/themes/editor_scale.h"
String EditorSpinSlider::get_tooltip(const Point2 &p_pos) const {
if (grabber->is_visible()) {
diff --git a/editor/gui/editor_toaster.cpp b/editor/gui/editor_toaster.cpp
index ac54a5a371..48e1c56e83 100644
--- a/editor/gui/editor_toaster.cpp
+++ b/editor/gui/editor_toaster.cpp
@@ -30,9 +30,9 @@
#include "editor_toaster.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/button.h"
#include "scene/gui/label.h"
#include "scene/gui/panel_container.h"
diff --git a/editor/gui/editor_validation_panel.cpp b/editor/gui/editor_validation_panel.cpp
index 14fe05e906..c08af1915f 100644
--- a/editor/gui/editor_validation_panel.cpp
+++ b/editor/gui/editor_validation_panel.cpp
@@ -30,8 +30,8 @@
#include "editor_validation_panel.h"
-#include "editor/editor_scale.h"
#include "editor/editor_string_names.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/label.h"
diff --git a/editor/gui/editor_zoom_widget.cpp b/editor/gui/editor_zoom_widget.cpp
index 7d522761f3..6db4c5047e 100644
--- a/editor/gui/editor_zoom_widget.cpp
+++ b/editor/gui/editor_zoom_widget.cpp
@@ -31,8 +31,8 @@
#include "editor_zoom_widget.h"
#include "core/os/keyboard.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/themes/editor_scale.h"
void EditorZoomWidget::_update_zoom_label() {
String zoom_text;
diff --git a/editor/gui/scene_tree_editor.cpp b/editor/gui/scene_tree_editor.cpp
index 766a507260..7a9df26fa7 100644
--- a/editor/gui/scene_tree_editor.cpp
+++ b/editor/gui/scene_tree_editor.cpp
@@ -34,7 +34,6 @@
#include "core/object/script_language.h"
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
@@ -42,6 +41,7 @@
#include "editor/plugins/animation_player_editor_plugin.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
#include "editor/plugins/script_editor_plugin.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/flow_container.h"
#include "scene/gui/label.h"
#include "scene/gui/tab_container.h"
@@ -235,7 +235,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
item->add_button(0, get_editor_theme_icon(SNAME("Script")), BUTTON_SCRIPT);
} else {
//has no script (or script is a custom type)
- _set_item_custom_color(item, get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor)));
+ _set_item_custom_color(item, get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor)));
item->set_selectable(0, false);
if (!scr.is_null()) { // make sure to mark the script if a custom type
@@ -267,7 +267,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
item->set_selectable(0, marked_selectable);
_set_item_custom_color(item, get_theme_color(SNAME("accent_color"), EditorStringName(Editor)));
} else if (!p_node->can_process()) {
- _set_item_custom_color(item, get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor)));
+ _set_item_custom_color(item, get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor)));
} else if (!marked_selectable && !marked_children_selectable) {
Node *node = p_node;
while (node) {
@@ -492,7 +492,7 @@ void SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
}
if (!valid) {
- _set_item_custom_color(item, get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor)));
+ _set_item_custom_color(item, get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor)));
item->set_selectable(0, false);
}
}
@@ -718,7 +718,7 @@ bool SceneTreeEditor::_update_filter(TreeItem *p_parent, bool p_scroll_to_select
}
p_parent->set_selectable(0, true);
} else if (keep_for_children) {
- p_parent->set_custom_color(0, get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor)));
+ p_parent->set_custom_color(0, get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor)));
p_parent->set_selectable(0, false);
p_parent->deselect(0);
}
diff --git a/editor/icons/GuiHsplitter.svg b/editor/icons/GuiHsplitter.svg
index 6d1f7e785c..cf42f057c6 100644
--- a/editor/icons/GuiHsplitter.svg
+++ b/editor/icons/GuiHsplitter.svg
@@ -1 +1 @@
-<svg height="64" viewBox="0 0 8 64" width="8" xmlns="http://www.w3.org/2000/svg"><path d="M4 2v60" fill="none" stroke="#fff" stroke-linecap="round" stroke-opacity=".4" stroke-width="2"/></svg>
+<svg height="64" viewBox="0 0 2 64" width="2" xmlns="http://www.w3.org/2000/svg"><path d="M1 2v60" fill="none" stroke="#fff" stroke-linecap="round" stroke-opacity=".4" stroke-width="2"/></svg>
diff --git a/editor/icons/GuiVsplitter.svg b/editor/icons/GuiVsplitter.svg
index cadd231579..b7850e76f0 100644
--- a/editor/icons/GuiVsplitter.svg
+++ b/editor/icons/GuiVsplitter.svg
@@ -1 +1 @@
-<svg height="8" viewBox="0 0 64 8" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M2 4h60" fill="none" stroke="#fff" stroke-linecap="round" stroke-opacity=".4" stroke-width="2"/></svg>
+<svg height="2" viewBox="0 0 64 2" width="64" xmlns="http://www.w3.org/2000/svg"><path d="M2 1h60" fill="none" stroke="#fff" stroke-linecap="round" stroke-opacity=".4" stroke-width="2"/></svg>
diff --git a/editor/icons/SCsub b/editor/icons/SCsub
index dd4243d750..cbbfe1d7ea 100644
--- a/editor/icons/SCsub
+++ b/editor/icons/SCsub
@@ -3,7 +3,6 @@
Import("env")
import os
-
import editor_icons_builders
@@ -23,4 +22,4 @@ for path in env.module_icons_paths:
else:
icon_sources += Glob(path + "/*.svg") # Custom.
-env.Alias("editor_icons", [env.MakeEditorIconsBuilder("#editor/editor_icons.gen.h", icon_sources)])
+env.Alias("editor_icons", [env.MakeEditorIconsBuilder("#editor/themes/editor_icons.gen.h", icon_sources)])
diff --git a/editor/icons/TileMapLayer.svg b/editor/icons/TileMapLayer.svg
new file mode 100644
index 0000000000..1903a87e3b
--- /dev/null
+++ b/editor/icons/TileMapLayer.svg
@@ -0,0 +1 @@
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 7v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2z" fill="#8da5f3"/></svg> \ No newline at end of file
diff --git a/editor/icons/editor_icons_builders.py b/editor/icons/editor_icons_builders.py
index 359245b6d7..378eb323db 100644
--- a/editor/icons/editor_icons_builders.py
+++ b/editor/icons/editor_icons_builders.py
@@ -1,4 +1,5 @@
-"""Functions used to generate source files during build time
+"""
+Functions used to generate source files during build time
All such functions are invoked in a subprocess on Windows to prevent build flakiness.
diff --git a/editor/import/3d/scene_import_settings.cpp b/editor/import/3d/scene_import_settings.cpp
index 4ecc6dedbd..736f941aa4 100644
--- a/editor/import/3d/scene_import_settings.cpp
+++ b/editor/import/3d/scene_import_settings.cpp
@@ -34,10 +34,10 @@
#include "editor/editor_file_system.h"
#include "editor/editor_inspector.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/gui/editor_file_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "scene/3d/importer_mesh_instance_3d.h"
#include "scene/animation/animation_player.h"
#include "scene/resources/importer_mesh.h"
diff --git a/editor/import/audio_stream_import_settings.cpp b/editor/import/audio_stream_import_settings.cpp
index bc96191d33..a62ac97244 100644
--- a/editor/import/audio_stream_import_settings.cpp
+++ b/editor/import/audio_stream_import_settings.cpp
@@ -31,8 +31,8 @@
#include "audio_stream_import_settings.h"
#include "editor/audio_stream_preview.h"
#include "editor/editor_file_system.h"
-#include "editor/editor_scale.h"
#include "editor/editor_string_names.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/check_box.h"
AudioStreamImportSettingsDialog *AudioStreamImportSettingsDialog::singleton = nullptr;
diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp
index ad65fcebd7..5e6ed02de9 100644
--- a/editor/import/dynamic_font_import_settings.cpp
+++ b/editor/import/dynamic_font_import_settings.cpp
@@ -36,10 +36,10 @@
#include "editor/editor_locale_dialog.h"
#include "editor/editor_node.h"
#include "editor/editor_property_name_processor.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/gui/editor_file_dialog.h"
+#include "editor/themes/editor_scale.h"
/*************************************************************************/
/* Settings data */
diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp
index 7f27be99f7..cdfc85cf6f 100644
--- a/editor/import/resource_importer_texture.cpp
+++ b/editor/import/resource_importer_texture.cpp
@@ -36,10 +36,10 @@
#include "core/version.h"
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/gui/editor_toaster.h"
#include "editor/import/resource_importer_texture_settings.h"
+#include "editor/themes/editor_scale.h"
#include "scene/resources/compressed_texture.h"
void ResourceImporterTexture::_texture_reimport_roughness(const Ref<CompressedTexture2D> &p_tex, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_channel) {
diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp
index 5996b459a5..0ceece263c 100644
--- a/editor/import_dock.cpp
+++ b/editor/import_dock.cpp
@@ -33,10 +33,10 @@
#include "core/config/project_settings.h"
#include "editor/editor_node.h"
#include "editor/editor_resource_preview.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
+#include "editor/themes/editor_scale.h"
class ImportDockParameters : public Object {
GDCLASS(ImportDockParameters, Object);
diff --git a/editor/input_event_configuration_dialog.cpp b/editor/input_event_configuration_dialog.cpp
index db7922233e..0f483fcaef 100644
--- a/editor/input_event_configuration_dialog.cpp
+++ b/editor/input_event_configuration_dialog.cpp
@@ -30,9 +30,9 @@
#include "editor/input_event_configuration_dialog.h"
#include "core/input/input_map.h"
-#include "editor/editor_scale.h"
#include "editor/editor_string_names.h"
#include "editor/event_listener_line_edit.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/check_box.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/option_button.h"
diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp
index 1b413c0978..e1640af47b 100644
--- a/editor/inspector_dock.cpp
+++ b/editor/inspector_dock.cpp
@@ -31,7 +31,6 @@
#include "inspector_dock.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
@@ -39,6 +38,7 @@
#include "editor/gui/editor_file_dialog.h"
#include "editor/gui/editor_object_selector.h"
#include "editor/plugins/script_editor_plugin.h"
+#include "editor/themes/editor_scale.h"
InspectorDock *InspectorDock::singleton = nullptr;
diff --git a/editor/localization_editor.cpp b/editor/localization_editor.cpp
index 46c6ef5712..8bdd5a3102 100644
--- a/editor/localization_editor.cpp
+++ b/editor/localization_editor.cpp
@@ -32,12 +32,12 @@
#include "core/config/project_settings.h"
#include "core/string/translation.h"
-#include "editor/editor_scale.h"
#include "editor/editor_translation_parser.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/filesystem_dock.h"
#include "editor/gui/editor_file_dialog.h"
#include "editor/pot_generator.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/control.h"
void LocalizationEditor::_notification(int p_what) {
diff --git a/editor/node_dock.cpp b/editor/node_dock.cpp
index db4f5a67e5..1e564f96c0 100644
--- a/editor/node_dock.cpp
+++ b/editor/node_dock.cpp
@@ -30,9 +30,9 @@
#include "node_dock.h"
-#include "connections_dialog.h"
+#include "editor/connections_dialog.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
+#include "editor/themes/editor_scale.h"
void NodeDock::show_groups() {
groups_button->set_pressed(true);
diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp
index 041a121a3a..5c2c059c98 100644
--- a/editor/plugin_config_dialog.cpp
+++ b/editor/plugin_config_dialog.cpp
@@ -35,9 +35,9 @@
#include "core/object/script_language.h"
#include "editor/editor_node.h"
#include "editor/editor_plugin.h"
-#include "editor/editor_scale.h"
#include "editor/gui/editor_validation_panel.h"
#include "editor/project_settings_editor.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/grid_container.h"
void PluginConfigDialog::_clear_fields() {
diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp
index a15875fd93..2c86314ae2 100644
--- a/editor/plugins/abstract_polygon_2d_editor.cpp
+++ b/editor/plugins/abstract_polygon_2d_editor.cpp
@@ -34,10 +34,10 @@
#include "core/math/geometry_2d.h"
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/button.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/separator.h"
diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp
index ed1df4b07f..5875b46c19 100644
--- a/editor/plugins/animation_blend_space_1d_editor.cpp
+++ b/editor/plugins/animation_blend_space_1d_editor.cpp
@@ -32,11 +32,11 @@
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_file_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "scene/animation/animation_blend_tree.h"
#include "scene/gui/button.h"
#include "scene/gui/check_box.h"
diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp
index 057170098d..9d922f4608 100644
--- a/editor/plugins/animation_blend_space_2d_editor.cpp
+++ b/editor/plugins/animation_blend_space_2d_editor.cpp
@@ -36,11 +36,11 @@
#include "core/math/geometry_2d.h"
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_file_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "scene/animation/animation_blend_tree.h"
#include "scene/animation/animation_player.h"
#include "scene/gui/button.h"
diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp
index 5ffb89ac65..8786c4cb20 100644
--- a/editor/plugins/animation_blend_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp
@@ -36,11 +36,11 @@
#include "core/os/keyboard.h"
#include "editor/editor_inspector.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_file_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "scene/3d/skeleton_3d.h"
#include "scene/animation/animation_player.h"
#include "scene/gui/check_box.h"
diff --git a/editor/plugins/animation_library_editor.cpp b/editor/plugins/animation_library_editor.cpp
index c302226357..58b1dbde8a 100644
--- a/editor/plugins/animation_library_editor.cpp
+++ b/editor/plugins/animation_library_editor.cpp
@@ -30,11 +30,11 @@
#include "animation_library_editor.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_file_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "scene/animation/animation_mixer.h"
void AnimationLibraryEditor::set_animation_mixer(Object *p_mixer) {
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index fe2ce70735..b08d2e966d 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -36,7 +36,6 @@
#include "core/io/resource_saver.h"
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_file_dialog.h"
@@ -44,6 +43,7 @@
#include "editor/plugins/canvas_item_editor_plugin.h" // For onion skinning.
#include "editor/plugins/node_3d_editor_plugin.h" // For onion skinning.
#include "editor/scene_tree_dock.h"
+#include "editor/themes/editor_scale.h"
#include "scene/animation/animation_tree.h"
#include "scene/gui/separator.h"
#include "scene/main/window.h"
diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp
index 0e61a7e29f..bbfc1f2f99 100644
--- a/editor/plugins/animation_state_machine_editor.cpp
+++ b/editor/plugins/animation_state_machine_editor.cpp
@@ -36,10 +36,10 @@
#include "core/math/geometry_2d.h"
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_file_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "scene/animation/animation_blend_tree.h"
#include "scene/animation/animation_player.h"
#include "scene/gui/menu_button.h"
diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp
index efee22a9a9..7269395baf 100644
--- a/editor/plugins/animation_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_tree_editor_plugin.cpp
@@ -40,8 +40,8 @@
#include "core/math/delaunay_2d.h"
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/gui/editor_file_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "scene/animation/animation_blend_tree.h"
#include "scene/animation/animation_player.h"
#include "scene/gui/button.h"
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index 36a0b46d92..2012955686 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -37,11 +37,11 @@
#include "core/version.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/gui/editor_file_dialog.h"
#include "editor/project_settings_editor.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/menu_button.h"
#include "scene/resources/image_texture.h"
@@ -417,7 +417,6 @@ void EditorAssetLibraryItemDownload::configure(const String &p_title, int p_asse
void EditorAssetLibraryItemDownload::_notification(int p_what) {
switch (p_what) {
- case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("AssetLib")));
status->add_theme_color_override("font_color", get_theme_color(SNAME("status_color"), SNAME("AssetLib")));
diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp
index 2be9528019..9b3f24c625 100644
--- a/editor/plugins/audio_stream_editor_plugin.cpp
+++ b/editor/plugins/audio_stream_editor_plugin.cpp
@@ -31,9 +31,9 @@
#include "audio_stream_editor_plugin.h"
#include "editor/audio_stream_preview.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
+#include "editor/themes/editor_scale.h"
#include "scene/resources/audio_stream_wav.h"
// AudioStreamEditor
diff --git a/editor/plugins/bit_map_editor_plugin.cpp b/editor/plugins/bit_map_editor_plugin.cpp
index f2423cb803..f1d86de537 100644
--- a/editor/plugins/bit_map_editor_plugin.cpp
+++ b/editor/plugins/bit_map_editor_plugin.cpp
@@ -30,7 +30,7 @@
#include "bit_map_editor_plugin.h"
-#include "editor/editor_scale.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/label.h"
#include "scene/gui/texture_rect.h"
#include "scene/resources/image_texture.h"
diff --git a/editor/plugins/bone_map_editor_plugin.cpp b/editor/plugins/bone_map_editor_plugin.cpp
index 153f192838..38573fbaa7 100644
--- a/editor/plugins/bone_map_editor_plugin.cpp
+++ b/editor/plugins/bone_map_editor_plugin.cpp
@@ -30,12 +30,12 @@
#include "bone_map_editor_plugin.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/import/3d/post_import_plugin_skeleton_renamer.h"
#include "editor/import/3d/post_import_plugin_skeleton_rest_fixer.h"
#include "editor/import/3d/post_import_plugin_skeleton_track_organizer.h"
#include "editor/import/3d/scene_import_settings.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/aspect_ratio_container.h"
#include "scene/gui/separator.h"
#include "scene/gui/texture_rect.h"
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index f16aff555c..6c776ad9b3 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -35,7 +35,6 @@
#include "core/os/keyboard.h"
#include "editor/debugger/editor_debugger_node.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
@@ -45,6 +44,7 @@
#include "editor/plugins/animation_player_editor_plugin.h"
#include "editor/plugins/script_editor_plugin.h"
#include "editor/scene_tree_dock.h"
+#include "editor/themes/editor_scale.h"
#include "scene/2d/polygon_2d.h"
#include "scene/2d/skeleton_2d.h"
#include "scene/2d/sprite_2d.h"
diff --git a/editor/plugins/control_editor_plugin.cpp b/editor/plugins/control_editor_plugin.cpp
index 0688ed959e..5b0831eeb8 100644
--- a/editor/plugins/control_editor_plugin.cpp
+++ b/editor/plugins/control_editor_plugin.cpp
@@ -31,11 +31,11 @@
#include "control_editor_plugin.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/grid_container.h"
#include "scene/gui/separator.h"
diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp
index 72f6784836..ea32b659d7 100644
--- a/editor/plugins/curve_editor_plugin.cpp
+++ b/editor/plugins/curve_editor_plugin.cpp
@@ -36,11 +36,11 @@
#include "core/os/keyboard.h"
#include "editor/editor_interface.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_spin_slider.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/flow_container.h"
#include "scene/gui/menu_button.h"
#include "scene/gui/popup_menu.h"
diff --git a/editor/plugins/debugger_editor_plugin.cpp b/editor/plugins/debugger_editor_plugin.cpp
index 41eae444f7..b9bde65f94 100644
--- a/editor/plugins/debugger_editor_plugin.cpp
+++ b/editor/plugins/debugger_editor_plugin.cpp
@@ -35,9 +35,9 @@
#include "editor/debugger/editor_debugger_server.h"
#include "editor/debugger/editor_file_server.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/plugins/script_editor_plugin.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/menu_button.h"
DebuggerEditorPlugin::DebuggerEditorPlugin(PopupMenu *p_debug_menu) {
diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp
index 015a4915a8..90bd117543 100644
--- a/editor/plugins/editor_preview_plugins.cpp
+++ b/editor/plugins/editor_preview_plugins.cpp
@@ -36,8 +36,8 @@
#include "core/object/script_language.h"
#include "core/os/os.h"
#include "editor/editor_paths.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
+#include "editor/themes/editor_scale.h"
#include "scene/resources/atlas_texture.h"
#include "scene/resources/bit_map.h"
#include "scene/resources/font.h"
diff --git a/editor/plugins/editor_resource_tooltip_plugins.cpp b/editor/plugins/editor_resource_tooltip_plugins.cpp
index 36852e79b5..fab8ee9f59 100644
--- a/editor/plugins/editor_resource_tooltip_plugins.cpp
+++ b/editor/plugins/editor_resource_tooltip_plugins.cpp
@@ -31,7 +31,7 @@
#include "editor_resource_tooltip_plugins.h"
#include "editor/editor_resource_preview.h"
-#include "editor/editor_scale.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/box_container.h"
#include "scene/gui/label.h"
#include "scene/gui/texture_rect.h"
diff --git a/editor/plugins/font_config_plugin.cpp b/editor/plugins/font_config_plugin.cpp
index a0500bdb48..d719850204 100644
--- a/editor/plugins/font_config_plugin.cpp
+++ b/editor/plugins/font_config_plugin.cpp
@@ -30,9 +30,9 @@
#include "font_config_plugin.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/import/dynamic_font_import_settings.h"
+#include "editor/themes/editor_scale.h"
/*************************************************************************/
/* EditorPropertyFontMetaObject */
diff --git a/editor/plugins/gradient_editor_plugin.cpp b/editor/plugins/gradient_editor_plugin.cpp
index e696b900d0..d8f9664e8d 100644
--- a/editor/plugins/gradient_editor_plugin.cpp
+++ b/editor/plugins/gradient_editor_plugin.cpp
@@ -30,15 +30,15 @@
#include "gradient_editor_plugin.h"
-#include "canvas_item_editor_plugin.h"
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_spin_slider.h"
-#include "node_3d_editor_plugin.h"
+#include "editor/plugins/canvas_item_editor_plugin.h"
+#include "editor/plugins/node_3d_editor_plugin.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/color_picker.h"
#include "scene/gui/flow_container.h"
#include "scene/gui/popup.h"
diff --git a/editor/plugins/gradient_texture_2d_editor_plugin.cpp b/editor/plugins/gradient_texture_2d_editor_plugin.cpp
index 5952185cc0..bb6096ea34 100644
--- a/editor/plugins/gradient_texture_2d_editor_plugin.cpp
+++ b/editor/plugins/gradient_texture_2d_editor_plugin.cpp
@@ -31,9 +31,9 @@
#include "gradient_texture_2d_editor_plugin.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_spin_slider.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/flow_container.h"
diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp
index 2a712caf92..b7c4479505 100644
--- a/editor/plugins/material_editor_plugin.cpp
+++ b/editor/plugins/material_editor_plugin.cpp
@@ -32,9 +32,9 @@
#include "core/config/project_settings.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
+#include "editor/themes/editor_scale.h"
#include "scene/3d/camera_3d.h"
#include "scene/3d/light_3d.h"
#include "scene/3d/mesh_instance_3d.h"
diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp
index 729ca5d7f9..0324b1d4f7 100644
--- a/editor/plugins/mesh_editor_plugin.cpp
+++ b/editor/plugins/mesh_editor_plugin.cpp
@@ -31,7 +31,7 @@
#include "mesh_editor_plugin.h"
#include "core/config/project_settings.h"
-#include "editor/editor_scale.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/button.h"
#include "scene/main/viewport.h"
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
index 04be44ffc8..9669f992a8 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
@@ -31,10 +31,10 @@
#include "mesh_instance_3d_editor_plugin.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/node_3d_editor_plugin.h"
+#include "editor/themes/editor_scale.h"
#include "scene/3d/collision_shape_3d.h"
#include "scene/3d/navigation_region_3d.h"
#include "scene/3d/physics_body_3d.h"
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index 0f6ea71571..455376b659 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -32,8 +32,8 @@
#define NODE_3D_EDITOR_PLUGIN_H
#include "editor/editor_plugin.h"
-#include "editor/editor_scale.h"
#include "editor/plugins/node_3d_editor_gizmos.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/spin_box.h"
diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp
index 6f44dfc755..a772dba6ae 100644
--- a/editor/plugins/path_2d_editor_plugin.cpp
+++ b/editor/plugins/path_2d_editor_plugin.cpp
@@ -34,9 +34,9 @@
#include "core/io/file_access.h"
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/menu_button.h"
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index 148ba7d7ca..e56fc94a55 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -33,11 +33,11 @@
#include "core/input/input_event.h"
#include "core/math/geometry_2d.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_zoom_widget.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
+#include "editor/themes/editor_scale.h"
#include "scene/2d/skeleton_2d.h"
#include "scene/gui/check_box.h"
#include "scene/gui/dialogs.h"
diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp
index d9f5aee82c..9b31e40e94 100644
--- a/editor/plugins/resource_preloader_editor_plugin.cpp
+++ b/editor/plugins/resource_preloader_editor_plugin.cpp
@@ -34,10 +34,10 @@
#include "core/io/resource_loader.h"
#include "editor/editor_interface.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_file_dialog.h"
+#include "editor/themes/editor_scale.h"
void ResourcePreloaderEditor::_notification(int p_what) {
switch (p_what) {
diff --git a/editor/plugins/root_motion_editor_plugin.cpp b/editor/plugins/root_motion_editor_plugin.cpp
index b54a2f717d..13928710bb 100644
--- a/editor/plugins/root_motion_editor_plugin.cpp
+++ b/editor/plugins/root_motion_editor_plugin.cpp
@@ -31,7 +31,7 @@
#include "root_motion_editor_plugin.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
+#include "editor/themes/editor_scale.h"
#include "scene/3d/skeleton_3d.h"
#include "scene/animation/animation_mixer.h"
#include "scene/gui/button.h"
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 9a8164a3cf..55191f44d4 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -45,7 +45,6 @@
#include "editor/editor_interface.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
-#include "editor/editor_scale.h"
#include "editor/editor_script.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
@@ -58,6 +57,7 @@
#include "editor/node_dock.h"
#include "editor/plugins/shader_editor_plugin.h"
#include "editor/plugins/text_shader_editor.h"
+#include "editor/themes/editor_scale.h"
#include "editor/window_wrapper.h"
#include "scene/main/node.h"
#include "scene/main/window.h"
@@ -1001,7 +1001,10 @@ void ScriptEditor::_res_saved_callback(const Ref<Resource> &p_res) {
}
_update_script_names();
- trigger_live_script_reload();
+ Ref<Script> scr = p_res;
+ if (scr.is_valid()) {
+ trigger_live_script_reload(scr->get_path());
+ }
}
void ScriptEditor::_scene_saved_callback(const String &p_path) {
@@ -1029,16 +1032,33 @@ void ScriptEditor::_scene_saved_callback(const String &p_path) {
}
}
-void ScriptEditor::trigger_live_script_reload() {
+void ScriptEditor::trigger_live_script_reload(const String &p_script_path) {
+ if (!script_paths_to_reload.has(p_script_path)) {
+ script_paths_to_reload.append(p_script_path);
+ }
if (!pending_auto_reload && auto_reload_running_scripts) {
callable_mp(this, &ScriptEditor::_live_auto_reload_running_scripts).call_deferred();
pending_auto_reload = true;
}
}
+void ScriptEditor::trigger_live_script_reload_all() {
+ if (!pending_auto_reload && auto_reload_running_scripts) {
+ call_deferred(SNAME("_live_auto_reload_running_scripts"));
+ pending_auto_reload = true;
+ reload_all_scripts = true;
+ }
+}
+
void ScriptEditor::_live_auto_reload_running_scripts() {
pending_auto_reload = false;
- EditorDebuggerNode::get_singleton()->reload_scripts();
+ if (reload_all_scripts) {
+ EditorDebuggerNode::get_singleton()->reload_all_scripts();
+ } else {
+ EditorDebuggerNode::get_singleton()->reload_scripts(script_paths_to_reload);
+ }
+ reload_all_scripts = false;
+ script_paths_to_reload.clear();
}
bool ScriptEditor::_test_script_times_on_disk(Ref<Resource> p_for_script) {
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index 4a814ea1bc..68eb23c838 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -382,6 +382,8 @@ class ScriptEditor : public PanelContainer {
bool pending_auto_reload;
bool auto_reload_running_scripts;
+ bool reload_all_scripts = false;
+ Vector<String> script_paths_to_reload;
void _live_auto_reload_running_scripts();
void _update_selected_editor_menu();
@@ -542,7 +544,8 @@ public:
void clear_docs_from_script(const Ref<Script> &p_script);
void update_docs_from_script(const Ref<Script> &p_script);
- void trigger_live_script_reload();
+ void trigger_live_script_reload(const String &p_script_path);
+ void trigger_live_script_reload_all();
bool can_take_away_focus() const;
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index 38f3d865d4..5bd6f83616 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -36,10 +36,10 @@
#include "editor/debugger/editor_debugger_node.h"
#include "editor/editor_command_palette.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/gui/editor_toaster.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/rich_text_label.h"
#include "scene/gui/split_container.h"
@@ -824,7 +824,7 @@ void ScriptEditor::_update_modified_scripts_for_external_editor(Ref<Script> p_fo
scr->set_last_modified_time(rel_scr->get_last_modified_time());
scr->update_exports();
- trigger_live_script_reload();
+ trigger_live_script_reload(scr->get_path());
}
}
}
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 6d6da69405..5798ff9d99 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -32,7 +32,6 @@
#include "editor/editor_command_palette.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/filesystem_dock.h"
@@ -40,6 +39,7 @@
#include "editor/plugins/text_shader_editor.h"
#include "editor/plugins/visual_shader_editor_plugin.h"
#include "editor/shader_create_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "editor/window_wrapper.h"
#include "scene/gui/item_list.h"
#include "scene/gui/texture_rect.h"
diff --git a/editor/plugins/shader_file_editor_plugin.cpp b/editor/plugins/shader_file_editor_plugin.cpp
index d68b3bde14..69ad274114 100644
--- a/editor/plugins/shader_file_editor_plugin.cpp
+++ b/editor/plugins/shader_file_editor_plugin.cpp
@@ -35,9 +35,9 @@
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/item_list.h"
#include "scene/gui/split_container.h"
#include "servers/display_server.h"
diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp
index c816220bd2..53fdde9e14 100644
--- a/editor/plugins/skeleton_3d_editor_plugin.cpp
+++ b/editor/plugins/skeleton_3d_editor_plugin.cpp
@@ -34,12 +34,12 @@
#include "editor/editor_node.h"
#include "editor/editor_properties.h"
#include "editor/editor_properties_vector.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/animation_player_editor_plugin.h"
-#include "node_3d_editor_plugin.h"
+#include "editor/plugins/node_3d_editor_plugin.h"
+#include "editor/themes/editor_scale.h"
#include "scene/3d/collision_shape_3d.h"
#include "scene/3d/joint_3d.h"
#include "scene/3d/mesh_instance_3d.h"
diff --git a/editor/plugins/sprite_2d_editor_plugin.cpp b/editor/plugins/sprite_2d_editor_plugin.cpp
index d343f80420..c1e7070451 100644
--- a/editor/plugins/sprite_2d_editor_plugin.cpp
+++ b/editor/plugins/sprite_2d_editor_plugin.cpp
@@ -33,11 +33,11 @@
#include "canvas_item_editor_plugin.h"
#include "core/math/geometry_2d.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_zoom_widget.h"
#include "editor/scene_tree_dock.h"
+#include "editor/themes/editor_scale.h"
#include "scene/2d/collision_polygon_2d.h"
#include "scene/2d/light_occluder_2d.h"
#include "scene/2d/mesh_instance_2d.h"
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index f4fa4b14bb..3672142b35 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -35,12 +35,12 @@
#include "core/os/keyboard.h"
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_file_dialog.h"
#include "editor/scene_tree_dock.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/center_container.h"
#include "scene/gui/flow_container.h"
#include "scene/gui/margin_container.h"
diff --git a/editor/plugins/style_box_editor_plugin.cpp b/editor/plugins/style_box_editor_plugin.cpp
index 9b1c208a9f..6ecbff3bb4 100644
--- a/editor/plugins/style_box_editor_plugin.cpp
+++ b/editor/plugins/style_box_editor_plugin.cpp
@@ -30,7 +30,7 @@
#include "style_box_editor_plugin.h"
-#include "editor/editor_scale.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/button.h"
#include "scene/resources/style_box_texture.h"
diff --git a/editor/plugins/text_shader_editor.cpp b/editor/plugins/text_shader_editor.cpp
index e5b9e3854f..98d83b6e95 100644
--- a/editor/plugins/text_shader_editor.cpp
+++ b/editor/plugins/text_shader_editor.cpp
@@ -32,11 +32,11 @@
#include "core/version_generated.gen.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/filesystem_dock.h"
#include "editor/project_settings_editor.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/split_container.h"
#include "servers/rendering/shader_preprocessor.h"
#include "servers/rendering/shader_types.h"
diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp
index 9d640bf0dc..38d9bb84f4 100644
--- a/editor/plugins/texture_editor_plugin.cpp
+++ b/editor/plugins/texture_editor_plugin.cpp
@@ -30,8 +30,8 @@
#include "texture_editor_plugin.h"
-#include "editor/editor_scale.h"
#include "editor/editor_string_names.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/label.h"
#include "scene/gui/texture_rect.h"
#include "scene/resources/animated_texture.h"
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index 73de15631a..09f6bf884e 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -33,10 +33,10 @@
#include "core/input/input.h"
#include "core/os/keyboard.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/check_box.h"
#include "scene/gui/option_button.h"
#include "scene/gui/panel_container.h"
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index cbe0f115d3..8c3fe82f36 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -34,12 +34,12 @@
#include "editor/editor_help.h"
#include "editor/editor_node.h"
#include "editor/editor_resource_picker.h"
-#include "editor/editor_scale.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_file_dialog.h"
#include "editor/inspector_dock.h"
#include "editor/progress_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/check_button.h"
#include "scene/gui/color_picker.h"
#include "scene/gui/item_list.h"
@@ -852,10 +852,9 @@ bool ThemeItemImportTree::has_selected_items() const {
void ThemeItemImportTree::_notification(int p_what) {
switch (p_what) {
- case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
select_icons_warning_icon->set_texture(get_editor_theme_icon(SNAME("StatusWarning")));
- select_icons_warning->add_theme_color_override("font_color", get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor)));
+ select_icons_warning->add_theme_color_override("font_color", get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor)));
import_items_filter->set_right_icon(get_editor_theme_icon(SNAME("Search")));
@@ -2470,7 +2469,7 @@ HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_
item_rename_cancel_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_canceled).bind(p_data_type, p_item_name, item_name_container));
item_rename_cancel_button->hide();
} else {
- item_name->add_theme_color_override("font_color", get_theme_color(SNAME("disabled_font_color"), EditorStringName(Editor)));
+ item_name->add_theme_color_override("font_color", get_theme_color(SNAME("font_disabled_color"), EditorStringName(Editor)));
Button *item_override_button = memnew(Button);
item_override_button->set_icon(get_editor_theme_icon(SNAME("Add")));
diff --git a/editor/plugins/theme_editor_preview.cpp b/editor/plugins/theme_editor_preview.cpp
index 9825be9ae8..205a5e8a20 100644
--- a/editor/plugins/theme_editor_preview.cpp
+++ b/editor/plugins/theme_editor_preview.cpp
@@ -34,8 +34,8 @@
#include "core/input/input.h"
#include "core/math/math_funcs.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_string_names.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/button.h"
#include "scene/gui/check_box.h"
#include "scene/gui/check_button.h"
diff --git a/editor/plugins/tiles/atlas_merging_dialog.cpp b/editor/plugins/tiles/atlas_merging_dialog.cpp
index 62b4993947..d03445b412 100644
--- a/editor/plugins/tiles/atlas_merging_dialog.cpp
+++ b/editor/plugins/tiles/atlas_merging_dialog.cpp
@@ -31,9 +31,9 @@
#include "atlas_merging_dialog.h"
#include "editor/editor_properties_vector.h"
-#include "editor/editor_scale.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_file_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/control.h"
#include "scene/gui/split_container.h"
#include "scene/resources/image_texture.h"
diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp
index 039213e545..721186ef82 100644
--- a/editor/plugins/tiles/tile_atlas_view.cpp
+++ b/editor/plugins/tiles/tile_atlas_view.cpp
@@ -32,15 +32,14 @@
#include "core/input/input.h"
#include "core/os/keyboard.h"
+#include "editor/editor_settings.h"
+#include "editor/themes/editor_scale.h"
#include "scene/2d/tile_map.h"
#include "scene/gui/box_container.h"
#include "scene/gui/label.h"
#include "scene/gui/panel.h"
#include "scene/gui/view_panner.h"
-#include "editor/editor_scale.h"
-#include "editor/editor_settings.h"
-
void TileAtlasView::gui_input(const Ref<InputEvent> &p_event) {
if (panner->gui_input(p_event)) {
accept_event();
diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp
index 8e4c26bd15..bd44c2965b 100644
--- a/editor/plugins/tiles/tile_data_editors.cpp
+++ b/editor/plugins/tiles/tile_data_editors.cpp
@@ -37,10 +37,10 @@
#include "editor/editor_node.h"
#include "editor/editor_properties.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/control.h"
#include "scene/gui/label.h"
diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp
index c0aa5b8efa..c34878b54e 100644
--- a/editor/plugins/tiles/tile_map_editor.cpp
+++ b/editor/plugins/tiles/tile_map_editor.cpp
@@ -34,10 +34,10 @@
#include "editor/editor_node.h"
#include "editor/editor_resource_preview.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
+#include "editor/themes/editor_scale.h"
#include "scene/2d/camera_2d.h"
#include "scene/gui/center_container.h"
diff --git a/editor/plugins/tiles/tile_proxies_manager_dialog.cpp b/editor/plugins/tiles/tile_proxies_manager_dialog.cpp
index ba431dfa2f..4a0b5e2117 100644
--- a/editor/plugins/tiles/tile_proxies_manager_dialog.cpp
+++ b/editor/plugins/tiles/tile_proxies_manager_dialog.cpp
@@ -31,9 +31,9 @@
#include "tile_proxies_manager_dialog.h"
#include "editor/editor_properties_vector.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/popup_menu.h"
#include "scene/gui/separator.h"
diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
index ed6664c528..e3710adc83 100644
--- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp
@@ -34,13 +34,13 @@
#include "editor/editor_inspector.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_toaster.h"
#include "editor/plugins/tiles/tile_set_editor.h"
#include "editor/progress_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
@@ -735,7 +735,7 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() {
tile_data_editors["probability"] = tile_data_probability_editor;
}
- Color disabled_color = get_theme_color("disabled_font_color", EditorStringName(Editor));
+ Color disabled_color = get_theme_color("font_disabled_color", EditorStringName(Editor));
// --- Physics ---
ADD_TILE_DATA_EDITOR_GROUP(TTR("Physics"));
diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp
index bdde662ce1..c43995d167 100644
--- a/editor/plugins/tiles/tile_set_editor.cpp
+++ b/editor/plugins/tiles/tile_set_editor.cpp
@@ -36,10 +36,10 @@
#include "editor/editor_file_system.h"
#include "editor/editor_inspector.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_file_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/box_container.h"
#include "scene/gui/control.h"
diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
index 7f6616fe34..4895e1d291 100644
--- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
+++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp
@@ -33,11 +33,11 @@
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
#include "editor/editor_resource_preview.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_file_dialog.h"
#include "editor/plugins/tiles/tile_set_editor.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/button.h"
#include "scene/gui/item_list.h"
diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp
index e7e94fdefa..057e6443d6 100644
--- a/editor/plugins/tiles/tiles_editor_plugin.cpp
+++ b/editor/plugins/tiles/tiles_editor_plugin.cpp
@@ -36,10 +36,10 @@
#include "editor/editor_interface.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
+#include "editor/themes/editor_scale.h"
#include "scene/2d/tile_map.h"
#include "scene/gui/box_container.h"
diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp
index 2fa54ac1dc..d8d70e5b7d 100644
--- a/editor/plugins/version_control_editor_plugin.cpp
+++ b/editor/plugins/version_control_editor_plugin.cpp
@@ -33,14 +33,15 @@
#include "core/config/project_settings.h"
#include "core/os/keyboard.h"
#include "core/os/time.h"
+#include "editor/editor_dock_manager.h"
#include "editor/editor_file_system.h"
#include "editor/editor_interface.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/filesystem_dock.h"
#include "editor/plugins/script_editor_plugin.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/separator.h"
#define CHECK_PLUGIN_INITIALIZED() \
@@ -909,7 +910,7 @@ void VersionControlEditorPlugin::fetch_available_vcs_plugin_names() {
}
void VersionControlEditorPlugin::register_editor() {
- EditorNode::get_singleton()->add_control_to_dock(EditorNode::DOCK_SLOT_RIGHT_UL, version_commit_dock);
+ EditorDockManager::get_singleton()->add_control_to_dock(EditorDockManager::DOCK_SLOT_RIGHT_UL, version_commit_dock);
version_control_dock_button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Version Control"), version_control_dock);
@@ -929,7 +930,7 @@ void VersionControlEditorPlugin::shut_down() {
memdelete(EditorVCSInterface::get_singleton());
EditorVCSInterface::set_singleton(nullptr);
- EditorNode::get_singleton()->remove_control_from_dock(version_commit_dock);
+ EditorDockManager::get_singleton()->remove_control_from_dock(version_commit_dock);
EditorNode::get_singleton()->remove_bottom_panel_item(version_control_dock);
_set_vcs_ui_state(false);
diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp
index 24b76526c6..6de37172b3 100644
--- a/editor/plugins/visual_shader_editor_plugin.cpp
+++ b/editor/plugins/visual_shader_editor_plugin.cpp
@@ -37,7 +37,6 @@
#include "editor/editor_node.h"
#include "editor/editor_properties.h"
#include "editor/editor_properties_vector.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
@@ -45,6 +44,7 @@
#include "editor/inspector_dock.h"
#include "editor/plugins/curve_editor_plugin.h"
#include "editor/plugins/shader_editor_plugin.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/button.h"
#include "scene/gui/check_box.h"
#include "scene/gui/code_edit.h"
diff --git a/editor/progress_dialog.cpp b/editor/progress_dialog.cpp
index c0dfc18072..ff8343fbeb 100644
--- a/editor/progress_dialog.cpp
+++ b/editor/progress_dialog.cpp
@@ -33,7 +33,7 @@
#include "core/os/os.h"
#include "editor/editor_interface.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
+#include "editor/themes/editor_scale.h"
#include "main/main.h"
#include "servers/display_server.h"
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index c986ce215a..e7277bad6a 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -42,13 +42,14 @@
#include "core/string/translation.h"
#include "core/version.h"
#include "editor/editor_paths.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
-#include "editor/editor_themes.h"
#include "editor/editor_vcs_interface.h"
#include "editor/gui/editor_file_dialog.h"
#include "editor/plugins/asset_library_editor_plugin.h"
+#include "editor/themes/editor_icons.h"
+#include "editor/themes/editor_scale.h"
+#include "editor/themes/editor_theme_manager.h"
#include "main/main.h"
#include "scene/gui/center_container.h"
#include "scene/gui/check_box.h"
@@ -2879,9 +2880,8 @@ ProjectManager::ProjectManager() {
Control::set_root_layout_direction(pm_root_dir);
Window::set_root_layout_direction(pm_root_dir);
- EditorColorMap::create();
- EditorTheme::initialize();
- Ref<Theme> theme = create_custom_theme();
+ EditorThemeManager::initialize();
+ Ref<Theme> theme = EditorThemeManager::generate_theme();
DisplayServer::set_early_window_clear_color_override(true, theme->get_color(SNAME("background"), EditorStringName(Editor)));
set_theme(theme);
@@ -3317,8 +3317,7 @@ ProjectManager::~ProjectManager() {
EditorSettings::destroy();
}
- EditorColorMap::finish();
- EditorTheme::finalize();
+ EditorThemeManager::finalize();
}
void ProjectTag::_notification(int p_what) {
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 1b0d791ff1..e59bb76ff4 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -33,11 +33,11 @@
#include "core/config/project_settings.h"
#include "editor/editor_log.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/export/editor_export.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/check_button.h"
#include "servers/movie_writer/movie_writer.h"
diff --git a/editor/property_selector.cpp b/editor/property_selector.cpp
index 87dbbd599d..be5f309704 100644
--- a/editor/property_selector.cpp
+++ b/editor/property_selector.cpp
@@ -34,7 +34,7 @@
#include "editor/doc_tools.h"
#include "editor/editor_help.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/rich_text_label.h"
#include "scene/gui/tree.h"
diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp
index a3a16dccd8..07cb96b9bc 100644
--- a/editor/rename_dialog.cpp
+++ b/editor/rename_dialog.cpp
@@ -35,12 +35,11 @@
#include "core/string/print_string.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
-#include "editor/editor_themes.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/plugins/script_editor_plugin.h"
+#include "editor/themes/editor_scale.h"
#include "modules/regex/regex.h"
#include "scene/gui/check_box.h"
#include "scene/gui/check_button.h"
diff --git a/editor/scene_create_dialog.cpp b/editor/scene_create_dialog.cpp
index be558101cf..ef700d8352 100644
--- a/editor/scene_create_dialog.cpp
+++ b/editor/scene_create_dialog.cpp
@@ -33,9 +33,9 @@
#include "core/io/dir_access.h"
#include "editor/create_dialog.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_string_names.h"
#include "editor/gui/editor_validation_panel.h"
+#include "editor/themes/editor_scale.h"
#include "scene/2d/node_2d.h"
#include "scene/3d/node_3d.h"
#include "scene/gui/box_container.h"
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 6bad5d1c2e..9d1c0d6c62 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -40,7 +40,6 @@
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
#include "editor/editor_quick_open.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
@@ -55,6 +54,7 @@
#include "editor/plugins/script_editor_plugin.h"
#include "editor/reparent_dialog.h"
#include "editor/shader_create_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "scene/animation/animation_tree.h"
#include "scene/gui/check_box.h"
#include "scene/main/window.h"
diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp
index 25e17ccd2a..1da8fa49b4 100644
--- a/editor/script_create_dialog.cpp
+++ b/editor/script_create_dialog.cpp
@@ -38,11 +38,11 @@
#include "editor/editor_file_system.h"
#include "editor/editor_node.h"
#include "editor/editor_paths.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/gui/editor_file_dialog.h"
#include "editor/gui/editor_validation_panel.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/grid_container.h"
#include "scene/gui/line_edit.h"
diff --git a/editor/shader_create_dialog.cpp b/editor/shader_create_dialog.cpp
index fb91d139a7..8d77b14ab0 100644
--- a/editor/shader_create_dialog.cpp
+++ b/editor/shader_create_dialog.cpp
@@ -31,9 +31,9 @@
#include "shader_create_dialog.h"
#include "core/config/project_settings.h"
-#include "editor/editor_scale.h"
#include "editor/gui/editor_file_dialog.h"
#include "editor/gui/editor_validation_panel.h"
+#include "editor/themes/editor_scale.h"
#include "scene/resources/shader_include.h"
#include "scene/resources/visual_shader.h"
#include "servers/rendering/shader_types.h"
diff --git a/editor/surface_upgrade_tool.cpp b/editor/surface_upgrade_tool.cpp
index d914303b4e..4edfb92b01 100644
--- a/editor/surface_upgrade_tool.cpp
+++ b/editor/surface_upgrade_tool.cpp
@@ -33,9 +33,9 @@
#include "editor/editor_file_system.h"
#include "editor/editor_log.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/gui/editor_toaster.h"
+#include "editor/themes/editor_scale.h"
#include "scene/scene_string_names.h"
#include "servers/rendering_server.h"
diff --git a/editor/themes/SCsub b/editor/themes/SCsub
new file mode 100644
index 0000000000..41b20f8a78
--- /dev/null
+++ b/editor/themes/SCsub
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+
+Import("env")
+
+import glob
+import editor_theme_builders
+
+
+# Fonts
+flist = glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.ttf")
+flist.extend(glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.otf"))
+flist.extend(glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.woff"))
+flist.extend(glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.woff2"))
+flist.sort()
+env.Depends("#editor/themes/builtin_fonts.gen.h", flist)
+env.CommandNoCache(
+ "#editor/themes/builtin_fonts.gen.h",
+ flist,
+ env.Run(editor_theme_builders.make_fonts_header, "Generating builtin fonts header."),
+)
+
+env.add_source_files(env.editor_sources, "*.cpp")
diff --git a/editor/themes/editor_color_map.cpp b/editor/themes/editor_color_map.cpp
new file mode 100644
index 0000000000..0b3a237244
--- /dev/null
+++ b/editor/themes/editor_color_map.cpp
@@ -0,0 +1,204 @@
+/**************************************************************************/
+/* editor_color_map.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "editor_color_map.h"
+
+HashMap<Color, Color> EditorColorMap::color_conversion_map;
+HashSet<StringName> EditorColorMap::color_conversion_exceptions;
+
+void EditorColorMap::add_conversion_color_pair(const String p_from_color, const String p_to_color) {
+ color_conversion_map[Color::html(p_from_color)] = Color::html(p_to_color);
+}
+
+void EditorColorMap::add_conversion_exception(const StringName &p_icon_name) {
+ color_conversion_exceptions.insert(p_icon_name);
+}
+
+void EditorColorMap::create() {
+ // Some of the colors below are listed for completeness sake.
+ // This can be a basis for proper palette validation later.
+
+ // Convert: FROM TO
+ add_conversion_color_pair("#478cbf", "#478cbf"); // Godot Blue
+ add_conversion_color_pair("#414042", "#414042"); // Godot Gray
+
+ add_conversion_color_pair("#ffffff", "#414141"); // Pure white
+ add_conversion_color_pair("#fefefe", "#fefefe"); // Forced light color
+ add_conversion_color_pair("#000000", "#bfbfbf"); // Pure black
+ add_conversion_color_pair("#010101", "#010101"); // Forced dark color
+
+ // Keep pure RGB colors as is, but list them for explicitness.
+ add_conversion_color_pair("#ff0000", "#ff0000"); // Pure red
+ add_conversion_color_pair("#00ff00", "#00ff00"); // Pure green
+ add_conversion_color_pair("#0000ff", "#0000ff"); // Pure blue
+
+ // GUI Colors
+ add_conversion_color_pair("#e0e0e0", "#5a5a5a"); // Common icon color
+ add_conversion_color_pair("#808080", "#808080"); // GUI disabled color
+ add_conversion_color_pair("#b3b3b3", "#363636"); // GUI disabled light color
+ add_conversion_color_pair("#699ce8", "#699ce8"); // GUI highlight color
+ add_conversion_color_pair("#f9f9f9", "#606060"); // Scrollbar grabber highlight color
+
+ add_conversion_color_pair("#c38ef1", "#a85de9"); // Animation
+ add_conversion_color_pair("#8da5f3", "#3d64dd"); // 2D
+ add_conversion_color_pair("#7582a8", "#6d83c8"); // 2D Abstract
+ add_conversion_color_pair("#fc7f7f", "#cd3838"); // 3D
+ add_conversion_color_pair("#b56d6d", "#be6a6a"); // 3D Abstract
+ add_conversion_color_pair("#8eef97", "#2fa139"); // GUI Control
+ add_conversion_color_pair("#76ad7b", "#64a66a"); // GUI Control Abstract
+
+ add_conversion_color_pair("#5fb2ff", "#0079f0"); // Selection (blue)
+ add_conversion_color_pair("#003e7a", "#2b74bb"); // Selection (darker blue)
+ add_conversion_color_pair("#f7f5cf", "#615f3a"); // Gizmo (yellow)
+
+ // Rainbow
+ add_conversion_color_pair("#ff4545", "#ff2929"); // Red
+ add_conversion_color_pair("#ffe345", "#ffe337"); // Yellow
+ add_conversion_color_pair("#80ff45", "#74ff34"); // Green
+ add_conversion_color_pair("#45ffa2", "#2cff98"); // Aqua
+ add_conversion_color_pair("#45d7ff", "#22ccff"); // Blue
+ add_conversion_color_pair("#8045ff", "#702aff"); // Purple
+ add_conversion_color_pair("#ff4596", "#ff2781"); // Pink
+
+ // Audio gradients
+ add_conversion_color_pair("#e1da5b", "#d6cf4b"); // Yellow
+
+ add_conversion_color_pair("#62aeff", "#1678e0"); // Frozen gradient top
+ add_conversion_color_pair("#75d1e6", "#41acc5"); // Frozen gradient middle
+ add_conversion_color_pair("#84ffee", "#49ccba"); // Frozen gradient bottom
+
+ add_conversion_color_pair("#f70000", "#c91616"); // Color track red
+ add_conversion_color_pair("#eec315", "#d58c0b"); // Color track orange
+ add_conversion_color_pair("#dbee15", "#b7d10a"); // Color track yellow
+ add_conversion_color_pair("#288027", "#218309"); // Color track green
+
+ // Other objects
+ add_conversion_color_pair("#ffca5f", "#fea900"); // Mesh resource (orange)
+ add_conversion_color_pair("#2998ff", "#68b6ff"); // Shape resource (blue)
+ add_conversion_color_pair("#a2d2ff", "#4998e3"); // Shape resource (light blue)
+ add_conversion_color_pair("#69c4d4", "#29a3cc"); // Input event highlight (light blue)
+
+ // Animation editor tracks
+ // The property track icon color is set by the common icon color.
+ add_conversion_color_pair("#ea7940", "#bd5e2c"); // 3D Position track
+ add_conversion_color_pair("#ff2b88", "#bd165f"); // 3D Rotation track
+ add_conversion_color_pair("#eac840", "#bd9d1f"); // 3D Scale track
+ add_conversion_color_pair("#3cf34e", "#16a827"); // Call Method track
+ add_conversion_color_pair("#2877f6", "#236be6"); // Bezier Curve track
+ add_conversion_color_pair("#eae440", "#9f9722"); // Audio Playback track
+ add_conversion_color_pair("#a448f0", "#9853ce"); // Animation Playback track
+ add_conversion_color_pair("#5ad5c4", "#0a9c88"); // Blend Shape track
+
+ // Control layouts
+ add_conversion_color_pair("#d6d6d6", "#474747"); // Highlighted part
+ add_conversion_color_pair("#474747", "#d6d6d6"); // Background part
+ add_conversion_color_pair("#919191", "#6e6e6e"); // Border part
+
+ // TileSet editor icons
+ add_conversion_color_pair("#fce00e", "#aa8d24"); // New Single Tile
+ add_conversion_color_pair("#0e71fc", "#0350bd"); // New Autotile
+ add_conversion_color_pair("#c6ced4", "#828f9b"); // New Atlas
+
+ // Variant types
+ add_conversion_color_pair("#41ecad", "#25e3a0"); // Variant
+ add_conversion_color_pair("#6f91f0", "#6d8eeb"); // bool
+ add_conversion_color_pair("#5abbef", "#4fb2e9"); // int/uint
+ add_conversion_color_pair("#35d4f4", "#27ccf0"); // float
+ add_conversion_color_pair("#4593ec", "#4690e7"); // String
+ add_conversion_color_pair("#ee5677", "#ee7991"); // AABB
+ add_conversion_color_pair("#e0e0e0", "#5a5a5a"); // Array
+ add_conversion_color_pair("#e1ec41", "#b2bb19"); // Basis
+ add_conversion_color_pair("#54ed9e", "#57e99f"); // Dictionary
+ add_conversion_color_pair("#417aec", "#6993ec"); // NodePath
+ add_conversion_color_pair("#55f3e3", "#12d5c3"); // Object
+ add_conversion_color_pair("#f74949", "#f77070"); // Plane
+ add_conversion_color_pair("#44bd44", "#46b946"); // Projection
+ add_conversion_color_pair("#ec418e", "#ec69a3"); // Quaternion
+ add_conversion_color_pair("#f1738f", "#ee758e"); // Rect2
+ add_conversion_color_pair("#41ec80", "#2ce573"); // RID
+ add_conversion_color_pair("#b9ec41", "#96ce1a"); // Transform2D
+ add_conversion_color_pair("#f68f45", "#f49047"); // Transform3D
+ add_conversion_color_pair("#ac73f1", "#ad76ee"); // Vector2
+ add_conversion_color_pair("#de66f0", "#dc6aed"); // Vector3
+ add_conversion_color_pair("#f066bd", "#ed6abd"); // Vector4
+
+ // Visual shaders
+ add_conversion_color_pair("#77ce57", "#67c046"); // Vector funcs
+ add_conversion_color_pair("#ea686c", "#d95256"); // Vector transforms
+ add_conversion_color_pair("#eac968", "#d9b64f"); // Textures and cubemaps
+ add_conversion_color_pair("#cf68ea", "#c050dd"); // Functions and expressions
+
+ // These icons should not be converted.
+ add_conversion_exception("EditorPivot");
+ add_conversion_exception("EditorHandle");
+ add_conversion_exception("Editor3DHandle");
+ add_conversion_exception("EditorBoneHandle");
+ add_conversion_exception("Godot");
+ add_conversion_exception("Sky");
+ add_conversion_exception("EditorControlAnchor");
+ add_conversion_exception("DefaultProjectIcon");
+ add_conversion_exception("ZoomMore");
+ add_conversion_exception("ZoomLess");
+ add_conversion_exception("ZoomReset");
+ add_conversion_exception("LockViewport");
+ add_conversion_exception("GroupViewport");
+ add_conversion_exception("StatusError");
+ add_conversion_exception("StatusSuccess");
+ add_conversion_exception("StatusWarning");
+ add_conversion_exception("OverbrightIndicator");
+ add_conversion_exception("MaterialPreviewCube");
+ add_conversion_exception("MaterialPreviewSphere");
+ add_conversion_exception("MaterialPreviewLight1");
+ add_conversion_exception("MaterialPreviewLight2");
+
+ // GUI
+ add_conversion_exception("GuiChecked");
+ add_conversion_exception("GuiRadioChecked");
+ add_conversion_exception("GuiIndeterminate");
+ add_conversion_exception("GuiCloseCustomizable");
+ add_conversion_exception("GuiGraphNodePort");
+ add_conversion_exception("GuiResizer");
+ add_conversion_exception("GuiMiniCheckerboard");
+
+ /// Code Editor.
+ add_conversion_exception("GuiTab");
+ add_conversion_exception("GuiSpace");
+ add_conversion_exception("CodeFoldedRightArrow");
+ add_conversion_exception("CodeFoldDownArrow");
+ add_conversion_exception("CodeRegionFoldedRightArrow");
+ add_conversion_exception("CodeRegionFoldDownArrow");
+ add_conversion_exception("TextEditorPlay");
+ add_conversion_exception("Breakpoint");
+}
+
+void EditorColorMap::finish() {
+ color_conversion_map.clear();
+ color_conversion_exceptions.clear();
+}
diff --git a/editor/editor_themes.h b/editor/themes/editor_color_map.h
index 7d913ccc40..4debd37faf 100644
--- a/editor/editor_themes.h
+++ b/editor/themes/editor_color_map.h
@@ -1,5 +1,5 @@
/**************************************************************************/
-/* editor_themes.h */
+/* editor_color_map.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,11 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
-#ifndef EDITOR_THEMES_H
-#define EDITOR_THEMES_H
+#ifndef EDITOR_COLOR_MAP_H
+#define EDITOR_COLOR_MAP_H
-#include "scene/resources/texture.h"
-#include "scene/resources/theme.h"
+#include "core/math/color.h"
+#include "core/string/string_name.h"
+#include "core/templates/hash_map.h"
+#include "core/templates/hash_set.h"
// The default icon theme is designed to be used for a dark theme. This map stores
// Color values to convert to other colors for better readability on a light theme.
@@ -55,27 +57,4 @@ public:
static void finish();
};
-class EditorTheme : public Theme {
- GDCLASS(EditorTheme, Theme);
-
- static Vector<StringName> editor_theme_types;
-
-public:
- virtual Color get_color(const StringName &p_name, const StringName &p_theme_type) const override;
- virtual int get_constant(const StringName &p_name, const StringName &p_theme_type) const override;
- virtual Ref<Font> get_font(const StringName &p_name, const StringName &p_theme_type) const override;
- virtual int get_font_size(const StringName &p_name, const StringName &p_theme_type) const override;
- virtual Ref<Texture2D> get_icon(const StringName &p_name, const StringName &p_theme_type) const override;
- virtual Ref<StyleBox> get_stylebox(const StringName &p_name, const StringName &p_theme_type) const override;
-
- static void initialize();
- static void finalize();
-};
-
-Ref<Theme> create_editor_theme(Ref<Theme> p_theme = nullptr);
-
-Ref<Theme> create_custom_theme(Ref<Theme> p_theme = nullptr);
-
-String get_default_project_icon();
-
-#endif // EDITOR_THEMES_H
+#endif // EDITOR_COLOR_MAP_H
diff --git a/editor/editor_fonts.cpp b/editor/themes/editor_fonts.cpp
index 1e1dff61b9..fc3631653c 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/themes/editor_fonts.cpp
@@ -30,11 +30,11 @@
#include "editor_fonts.h"
-#include "builtin_fonts.gen.h"
#include "core/io/dir_access.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
+#include "editor/themes/builtin_fonts.gen.h"
+#include "editor/themes/editor_scale.h"
#include "scene/resources/font.h"
Ref<FontFile> load_external_font(const String &p_path, TextServer::Hinting p_hinting, TextServer::FontAntialiasing p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) {
@@ -106,7 +106,7 @@ Ref<FontVariation> make_bold_font(const Ref<Font> &p_font, double p_embolden, Ty
return font_var;
}
-void editor_register_fonts(Ref<Theme> p_theme) {
+void editor_register_fonts(const Ref<Theme> &p_theme) {
OS::get_singleton()->benchmark_begin_measure("EditorTheme", "Register Fonts");
Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
diff --git a/editor/editor_fonts.h b/editor/themes/editor_fonts.h
index 1705879f59..b612797df1 100644
--- a/editor/editor_fonts.h
+++ b/editor/themes/editor_fonts.h
@@ -33,6 +33,6 @@
#include "scene/resources/theme.h"
-void editor_register_fonts(Ref<Theme> p_theme);
+void editor_register_fonts(const Ref<Theme> &p_theme);
#endif // EDITOR_FONTS_H
diff --git a/editor/themes/editor_icons.cpp b/editor/themes/editor_icons.cpp
new file mode 100644
index 0000000000..bb767747f3
--- /dev/null
+++ b/editor/themes/editor_icons.cpp
@@ -0,0 +1,252 @@
+/**************************************************************************/
+/* editor_icons.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "editor_icons.h"
+
+#include "editor/editor_settings.h"
+#include "editor/editor_string_names.h"
+#include "editor/themes/editor_color_map.h"
+#include "editor/themes/editor_icons.gen.h"
+#include "editor/themes/editor_scale.h"
+#include "scene/resources/image_texture.h"
+#include "scene/resources/texture.h"
+
+#include "modules/modules_enabled.gen.h" // For svg.
+#ifdef MODULE_SVG_ENABLED
+#include "modules/svg/image_loader_svg.h"
+#endif
+
+void editor_configure_icons(bool p_dark_theme) {
+#ifdef MODULE_SVG_ENABLED
+ if (p_dark_theme) {
+ ImageLoaderSVG::set_forced_color_map(HashMap<Color, Color>());
+ } else {
+ ImageLoaderSVG::set_forced_color_map(EditorColorMap::get_color_conversion_map());
+ }
+#else
+ WARN_PRINT("SVG support disabled, editor icons won't be rendered.");
+#endif
+}
+
+// See also `generate_icon()` in `scene/theme/default_theme.cpp`.
+Ref<ImageTexture> editor_generate_icon(int p_index, float p_scale, float p_saturation, const HashMap<Color, Color> &p_convert_colors = HashMap<Color, Color>()) {
+ Ref<Image> img = memnew(Image);
+
+#ifdef MODULE_SVG_ENABLED
+ // Upsample icon generation only if the editor scale isn't an integer multiplier.
+ // Generating upsampled icons is slower, and the benefit is hardly visible
+ // with integer editor scales.
+ const bool upsample = !Math::is_equal_approx(Math::round(p_scale), p_scale);
+ Error err = ImageLoaderSVG::create_image_from_string(img, editor_icons_sources[p_index], p_scale, upsample, p_convert_colors);
+ ERR_FAIL_COND_V_MSG(err != OK, Ref<ImageTexture>(), "Failed generating icon, unsupported or invalid SVG data in editor theme.");
+ if (p_saturation != 1.0) {
+ img->adjust_bcs(1.0, 1.0, p_saturation);
+ }
+#else
+ // If the SVG module is disabled, we can't really display the UI well, but at least we won't crash.
+ // 16 pixels is used as it's the most common base size for Godot icons.
+ img = Image::create_empty(16 * p_scale, 16 * p_scale, false, Image::FORMAT_RGBA8);
+#endif
+
+ return ImageTexture::create_from_image(img);
+}
+
+float get_gizmo_handle_scale(const String &gizmo_handle_name = "") {
+ const float scale_gizmo_handles_for_touch = EDITOR_GET("interface/touchscreen/scale_gizmo_handles");
+ if (scale_gizmo_handles_for_touch > 1.0f) {
+ // The names of the icons that require additional scaling.
+ static HashSet<StringName> gizmo_to_scale;
+ if (gizmo_to_scale.is_empty()) {
+ gizmo_to_scale.insert("EditorHandle");
+ gizmo_to_scale.insert("EditorHandleAdd");
+ gizmo_to_scale.insert("EditorHandleDisabled");
+ gizmo_to_scale.insert("EditorCurveHandle");
+ gizmo_to_scale.insert("EditorPathSharpHandle");
+ gizmo_to_scale.insert("EditorPathSmoothHandle");
+ }
+
+ if (gizmo_to_scale.has(gizmo_handle_name)) {
+ return EDSCALE * scale_gizmo_handles_for_touch;
+ }
+ }
+
+ return EDSCALE;
+}
+
+void editor_register_icons(const Ref<Theme> &p_theme, bool p_dark_theme, float p_icon_saturation, int p_thumb_size, bool p_only_thumbs) {
+ const String benchmark_key = vformat("Generate Icons (%s)", (p_only_thumbs ? "Only Thumbs" : "All"));
+ OS::get_singleton()->benchmark_begin_measure("EditorTheme", benchmark_key);
+
+ // Before we register the icons, we adjust their colors and saturation.
+ // Most icons follow the standard rules for color conversion to follow the editor
+ // theme's polarity (dark/light). We also adjust the saturation for most icons,
+ // following the editor setting.
+ // Some icons are excluded from this conversion, and instead use the configured
+ // accent color to replace their innate accent color to match the editor theme.
+ // And then some icons are completely excluded from the conversion.
+
+ // Standard color conversion map.
+ HashMap<Color, Color> color_conversion_map;
+ // Icons by default are set up for the dark theme, so if the theme is light,
+ // we apply the dark-to-light color conversion map.
+ if (!p_dark_theme) {
+ for (KeyValue<Color, Color> &E : EditorColorMap::get_color_conversion_map()) {
+ color_conversion_map[E.key] = E.value;
+ }
+ }
+ // These colors should be converted even if we are using a dark theme.
+ const Color error_color = p_theme->get_color(SNAME("error_color"), EditorStringName(Editor));
+ const Color success_color = p_theme->get_color(SNAME("success_color"), EditorStringName(Editor));
+ const Color warning_color = p_theme->get_color(SNAME("warning_color"), EditorStringName(Editor));
+ color_conversion_map[Color::html("#ff5f5f")] = error_color;
+ color_conversion_map[Color::html("#5fff97")] = success_color;
+ color_conversion_map[Color::html("#ffdd65")] = warning_color;
+
+ // The names of the icons to exclude from the standard color conversion.
+ HashSet<StringName> conversion_exceptions = EditorColorMap::get_color_conversion_exceptions();
+
+ // The names of the icons to exclude when adjusting for saturation.
+ HashSet<StringName> saturation_exceptions;
+ saturation_exceptions.insert("DefaultProjectIcon");
+ saturation_exceptions.insert("Godot");
+ saturation_exceptions.insert("Logo");
+
+ // Accent color conversion map.
+ // It is used on some icons (checkbox, radio, toggle, etc.), regardless of the dark
+ // or light mode.
+ HashMap<Color, Color> accent_color_map;
+ HashSet<StringName> accent_color_icons;
+
+ const Color accent_color = p_theme->get_color(SNAME("accent_color"), EditorStringName(Editor));
+ accent_color_map[Color::html("699ce8")] = accent_color;
+ if (accent_color.get_luminance() > 0.75) {
+ accent_color_map[Color::html("ffffff")] = Color(0.2, 0.2, 0.2);
+ }
+
+ accent_color_icons.insert("GuiChecked");
+ accent_color_icons.insert("GuiRadioChecked");
+ accent_color_icons.insert("GuiIndeterminate");
+ accent_color_icons.insert("GuiToggleOn");
+ accent_color_icons.insert("GuiToggleOnMirrored");
+ accent_color_icons.insert("PlayOverlay");
+
+ // Generate icons.
+ if (!p_only_thumbs) {
+ for (int i = 0; i < editor_icons_count; i++) {
+ Ref<ImageTexture> icon;
+
+ const String &editor_icon_name = editor_icons_names[i];
+ if (accent_color_icons.has(editor_icon_name)) {
+ icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name), 1.0, accent_color_map);
+ } else {
+ float saturation = p_icon_saturation;
+ if (saturation_exceptions.has(editor_icon_name)) {
+ saturation = 1.0;
+ }
+
+ if (conversion_exceptions.has(editor_icon_name)) {
+ icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name), saturation);
+ } else {
+ icon = editor_generate_icon(i, get_gizmo_handle_scale(editor_icon_name), saturation, color_conversion_map);
+ }
+ }
+
+ p_theme->set_icon(editor_icon_name, EditorStringName(EditorIcons), icon);
+ }
+ }
+
+ // Generate thumbnail icons with the given thumbnail size.
+ // See editor\icons\editor_icons_builders.py for the code that determines which icons are thumbnails.
+ if (p_thumb_size >= 64) {
+ const float scale = (float)p_thumb_size / 64.0 * EDSCALE;
+ for (int i = 0; i < editor_bg_thumbs_count; i++) {
+ const int index = editor_bg_thumbs_indices[i];
+ Ref<ImageTexture> icon;
+
+ if (accent_color_icons.has(editor_icons_names[index])) {
+ icon = editor_generate_icon(index, scale, 1.0, accent_color_map);
+ } else {
+ float saturation = p_icon_saturation;
+ if (saturation_exceptions.has(editor_icons_names[index])) {
+ saturation = 1.0;
+ }
+
+ if (conversion_exceptions.has(editor_icons_names[index])) {
+ icon = editor_generate_icon(index, scale, saturation);
+ } else {
+ icon = editor_generate_icon(index, scale, saturation, color_conversion_map);
+ }
+ }
+
+ p_theme->set_icon(editor_icons_names[index], EditorStringName(EditorIcons), icon);
+ }
+ } else {
+ const float scale = (float)p_thumb_size / 32.0 * EDSCALE;
+ for (int i = 0; i < editor_md_thumbs_count; i++) {
+ const int index = editor_md_thumbs_indices[i];
+ Ref<ImageTexture> icon;
+
+ if (accent_color_icons.has(editor_icons_names[index])) {
+ icon = editor_generate_icon(index, scale, 1.0, accent_color_map);
+ } else {
+ float saturation = p_icon_saturation;
+ if (saturation_exceptions.has(editor_icons_names[index])) {
+ saturation = 1.0;
+ }
+
+ if (conversion_exceptions.has(editor_icons_names[index])) {
+ icon = editor_generate_icon(index, scale, saturation);
+ } else {
+ icon = editor_generate_icon(index, scale, saturation, color_conversion_map);
+ }
+ }
+
+ p_theme->set_icon(editor_icons_names[index], EditorStringName(EditorIcons), icon);
+ }
+ }
+ OS::get_singleton()->benchmark_end_measure("EditorTheme", benchmark_key);
+}
+
+void editor_copy_icons(const Ref<Theme> &p_theme, const Ref<Theme> &p_old_theme) {
+ for (int i = 0; i < editor_icons_count; i++) {
+ p_theme->set_icon(editor_icons_names[i], EditorStringName(EditorIcons), p_old_theme->get_icon(editor_icons_names[i], EditorStringName(EditorIcons)));
+ }
+}
+
+// Returns the SVG code for the default project icon.
+String get_default_project_icon() {
+ // FIXME: This icon can probably be predefined in editor_icons.gen.h so we don't have to look up.
+ for (int i = 0; i < editor_icons_count; i++) {
+ if (strcmp(editor_icons_names[i], "DefaultProjectIcon") == 0) {
+ return String(editor_icons_sources[i]);
+ }
+ }
+ return String();
+}
diff --git a/editor/themes/editor_icons.h b/editor/themes/editor_icons.h
new file mode 100644
index 0000000000..2094ebf27c
--- /dev/null
+++ b/editor/themes/editor_icons.h
@@ -0,0 +1,42 @@
+/**************************************************************************/
+/* editor_icons.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef EDITOR_ICONS_H
+#define EDITOR_ICONS_H
+
+#include "scene/resources/theme.h"
+
+void editor_configure_icons(bool p_dark_theme);
+void editor_register_icons(const Ref<Theme> &p_theme, bool p_dark_theme, float p_icon_saturation, int p_thumb_size, bool p_only_thumbs = false);
+void editor_copy_icons(const Ref<Theme> &p_theme, const Ref<Theme> &p_old_theme);
+
+String get_default_project_icon();
+
+#endif // EDITOR_ICONS_H
diff --git a/editor/editor_scale.cpp b/editor/themes/editor_scale.cpp
index 0670e98e2c..0670e98e2c 100644
--- a/editor/editor_scale.cpp
+++ b/editor/themes/editor_scale.cpp
diff --git a/editor/editor_scale.h b/editor/themes/editor_scale.h
index b3583fdcee..b3583fdcee 100644
--- a/editor/editor_scale.h
+++ b/editor/themes/editor_scale.h
diff --git a/editor/themes/editor_theme.cpp b/editor/themes/editor_theme.cpp
new file mode 100644
index 0000000000..ab7c808303
--- /dev/null
+++ b/editor/themes/editor_theme.cpp
@@ -0,0 +1,131 @@
+/**************************************************************************/
+/* editor_theme.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "editor_theme.h"
+
+#include "editor/editor_string_names.h"
+#include "scene/theme/theme_db.h"
+
+Vector<StringName> EditorTheme::editor_theme_types;
+
+// TODO: Refactor these and corresponding Theme methods to use the bool get_xxx(r_value) pattern internally.
+
+// Keep in sync with Theme::get_color.
+Color EditorTheme::get_color(const StringName &p_name, const StringName &p_theme_type) const {
+ if (color_map.has(p_theme_type) && color_map[p_theme_type].has(p_name)) {
+ return color_map[p_theme_type][p_name];
+ } else {
+ if (editor_theme_types.has(p_theme_type)) {
+ WARN_PRINT(vformat("Trying to access a non-existing editor theme color '%s' in '%s'.", p_name, p_theme_type));
+ }
+ return Color();
+ }
+}
+
+// Keep in sync with Theme::get_constant.
+int EditorTheme::get_constant(const StringName &p_name, const StringName &p_theme_type) const {
+ if (constant_map.has(p_theme_type) && constant_map[p_theme_type].has(p_name)) {
+ return constant_map[p_theme_type][p_name];
+ } else {
+ if (editor_theme_types.has(p_theme_type)) {
+ WARN_PRINT(vformat("Trying to access a non-existing editor theme constant '%s' in '%s'.", p_name, p_theme_type));
+ }
+ return 0;
+ }
+}
+
+// Keep in sync with Theme::get_font.
+Ref<Font> EditorTheme::get_font(const StringName &p_name, const StringName &p_theme_type) const {
+ if (font_map.has(p_theme_type) && font_map[p_theme_type].has(p_name) && font_map[p_theme_type][p_name].is_valid()) {
+ return font_map[p_theme_type][p_name];
+ } else if (has_default_font()) {
+ if (editor_theme_types.has(p_theme_type)) {
+ WARN_PRINT(vformat("Trying to access a non-existing editor theme font '%s' in '%s'.", p_name, p_theme_type));
+ }
+ return default_font;
+ } else {
+ if (editor_theme_types.has(p_theme_type)) {
+ WARN_PRINT(vformat("Trying to access a non-existing editor theme font '%s' in '%s'.", p_name, p_theme_type));
+ }
+ return ThemeDB::get_singleton()->get_fallback_font();
+ }
+}
+
+// Keep in sync with Theme::get_font_size.
+int EditorTheme::get_font_size(const StringName &p_name, const StringName &p_theme_type) const {
+ 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)) {
+ return font_size_map[p_theme_type][p_name];
+ } else if (has_default_font_size()) {
+ if (editor_theme_types.has(p_theme_type)) {
+ WARN_PRINT(vformat("Trying to access a non-existing editor theme font size '%s' in '%s'.", p_name, p_theme_type));
+ }
+ return default_font_size;
+ } else {
+ if (editor_theme_types.has(p_theme_type)) {
+ WARN_PRINT(vformat("Trying to access a non-existing editor theme font size '%s' in '%s'.", p_name, p_theme_type));
+ }
+ return ThemeDB::get_singleton()->get_fallback_font_size();
+ }
+}
+
+// Keep in sync with Theme::get_icon.
+Ref<Texture2D> EditorTheme::get_icon(const StringName &p_name, const StringName &p_theme_type) const {
+ if (icon_map.has(p_theme_type) && icon_map[p_theme_type].has(p_name) && icon_map[p_theme_type][p_name].is_valid()) {
+ return icon_map[p_theme_type][p_name];
+ } else {
+ if (editor_theme_types.has(p_theme_type)) {
+ WARN_PRINT(vformat("Trying to access a non-existing editor theme icon '%s' in '%s'.", p_name, p_theme_type));
+ }
+ return ThemeDB::get_singleton()->get_fallback_icon();
+ }
+}
+
+// Keep in sync with Theme::get_stylebox.
+Ref<StyleBox> EditorTheme::get_stylebox(const StringName &p_name, const StringName &p_theme_type) const {
+ if (style_map.has(p_theme_type) && style_map[p_theme_type].has(p_name) && style_map[p_theme_type][p_name].is_valid()) {
+ return style_map[p_theme_type][p_name];
+ } else {
+ if (editor_theme_types.has(p_theme_type)) {
+ WARN_PRINT(vformat("Trying to access a non-existing editor theme stylebox '%s' in '%s'.", p_name, p_theme_type));
+ }
+ return ThemeDB::get_singleton()->get_fallback_stylebox();
+ }
+}
+
+void EditorTheme::initialize() {
+ editor_theme_types.append(EditorStringName(Editor));
+ editor_theme_types.append(EditorStringName(EditorFonts));
+ editor_theme_types.append(EditorStringName(EditorIcons));
+ editor_theme_types.append(EditorStringName(EditorStyles));
+}
+
+void EditorTheme::finalize() {
+ editor_theme_types.clear();
+}
diff --git a/editor/themes/editor_theme.h b/editor/themes/editor_theme.h
new file mode 100644
index 0000000000..41a60fdf96
--- /dev/null
+++ b/editor/themes/editor_theme.h
@@ -0,0 +1,53 @@
+/**************************************************************************/
+/* editor_theme.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef EDITOR_THEME_H
+#define EDITOR_THEME_H
+
+#include "scene/resources/theme.h"
+
+class EditorTheme : public Theme {
+ GDCLASS(EditorTheme, Theme);
+
+ static Vector<StringName> editor_theme_types;
+
+public:
+ virtual Color get_color(const StringName &p_name, const StringName &p_theme_type) const override;
+ virtual int get_constant(const StringName &p_name, const StringName &p_theme_type) const override;
+ virtual Ref<Font> get_font(const StringName &p_name, const StringName &p_theme_type) const override;
+ virtual int get_font_size(const StringName &p_name, const StringName &p_theme_type) const override;
+ virtual Ref<Texture2D> get_icon(const StringName &p_name, const StringName &p_theme_type) const override;
+ virtual Ref<StyleBox> get_stylebox(const StringName &p_name, const StringName &p_theme_type) const override;
+
+ static void initialize();
+ static void finalize();
+};
+
+#endif // EDITOR_THEME_H
diff --git a/editor/themes/editor_theme_builders.py b/editor/themes/editor_theme_builders.py
new file mode 100644
index 0000000000..19b346db58
--- /dev/null
+++ b/editor/themes/editor_theme_builders.py
@@ -0,0 +1,41 @@
+"""
+Functions used to generate source files during build time
+
+All such functions are invoked in a subprocess on Windows to prevent build flakiness.
+
+"""
+
+import os
+from platform_methods import subprocess_main
+
+
+def make_fonts_header(target, source, env):
+ dst = target[0]
+
+ g = open(dst, "w", encoding="utf-8")
+
+ g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
+ g.write("#ifndef _EDITOR_FONTS_H\n")
+ g.write("#define _EDITOR_FONTS_H\n")
+
+ # Saving uncompressed, since FreeType will reference from memory pointer.
+ for i in range(len(source)):
+ with open(source[i], "rb") as f:
+ buf = f.read()
+
+ name = os.path.splitext(os.path.basename(source[i]))[0]
+
+ g.write("static const int _font_" + name + "_size = " + str(len(buf)) + ";\n")
+ g.write("static const unsigned char _font_" + name + "[] = {\n")
+ for j in range(len(buf)):
+ g.write("\t" + str(buf[j]) + ",\n")
+
+ g.write("};\n")
+
+ g.write("#endif")
+
+ g.close()
+
+
+if __name__ == "__main__":
+ subprocess_main(globals())
diff --git a/editor/themes/editor_theme_manager.cpp b/editor/themes/editor_theme_manager.cpp
new file mode 100644
index 0000000000..4ce323c763
--- /dev/null
+++ b/editor/themes/editor_theme_manager.cpp
@@ -0,0 +1,2232 @@
+/**************************************************************************/
+/* editor_theme_manager.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "editor_theme_manager.h"
+
+#include "core/error/error_macros.h"
+#include "core/io/resource_loader.h"
+#include "editor/editor_settings.h"
+#include "editor/editor_string_names.h"
+#include "editor/themes/editor_color_map.h"
+#include "editor/themes/editor_fonts.h"
+#include "editor/themes/editor_icons.h"
+#include "editor/themes/editor_scale.h"
+#include "editor/themes/editor_theme.h"
+#include "scene/resources/image_texture.h"
+#include "scene/resources/style_box_flat.h"
+#include "scene/resources/style_box_line.h"
+#include "scene/resources/style_box_texture.h"
+#include "scene/resources/texture.h"
+
+// Helper methods.
+
+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) {
+ Ref<StyleBoxTexture> style(memnew(StyleBoxTexture));
+ style->set_texture(p_texture);
+ style->set_texture_margin_individual(p_left * EDSCALE, p_top * EDSCALE, p_right * EDSCALE, p_bottom * EDSCALE);
+ 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);
+ style->set_draw_center(p_draw_center);
+ return style;
+}
+
+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) {
+ Ref<StyleBoxEmpty> style(memnew(StyleBoxEmpty));
+ style->set_content_margin_individual(p_margin_left * EDSCALE, p_margin_top * EDSCALE, p_margin_right * EDSCALE, p_margin_bottom * EDSCALE);
+ return style;
+}
+
+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) {
+ Ref<StyleBoxFlat> style(memnew(StyleBoxFlat));
+ style->set_bg_color(p_color);
+ // Adjust level of detail based on the corners' effective sizes.
+ style->set_corner_detail(Math::ceil(0.8 * p_corner_width * EDSCALE));
+ style->set_corner_radius_all(p_corner_width * EDSCALE);
+ style->set_content_margin_individual(p_margin_left * EDSCALE, p_margin_top * EDSCALE, p_margin_right * EDSCALE, p_margin_bottom * EDSCALE);
+ // Work around issue about antialiased edges being blurrier (GH-35279).
+ style->set_anti_aliased(false);
+ return style;
+}
+
+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) {
+ Ref<StyleBoxLine> style(memnew(StyleBoxLine));
+ style->set_color(p_color);
+ style->set_grow_begin(p_grow_begin);
+ style->set_grow_end(p_grow_end);
+ style->set_thickness(p_thickness);
+ style->set_vertical(p_vertical);
+ return style;
+}
+
+// Theme generation and population routines.
+
+Ref<Theme> EditorThemeManager::_create_base_theme(const Ref<Theme> &p_old_theme) {
+ OS::get_singleton()->benchmark_begin_measure("EditorTheme", "Create Base Theme");
+
+ Ref<EditorTheme> theme = memnew(EditorTheme);
+ ThemeConfiguration config = _create_theme_config(theme);
+ _create_shared_styles(theme, config);
+
+ // FIXME: Make the comparison more robust and fix imprecision issues by hashing affecting values.
+ // TODO: Refactor the icons check into their respective file, and add a similar check for fonts.
+
+ // Register editor icons.
+ // If settings are comparable to the old theme, then just copy existing icons over.
+ // Otherwise, regenerate them. Also check if we need to regenerate "thumb" icons.
+ bool keep_old_icons = false;
+ bool regenerate_thumb_icons = true;
+ if (p_old_theme != nullptr) {
+ // We check editor scale, theme dark/light mode, icon saturation, and accent color.
+
+ // That doesn't really work as expected, since theme constants are integers, and scales are floats.
+ // So this check will never work when changing between 100-199% values.
+ const float prev_scale = (float)p_old_theme->get_constant(SNAME("scale"), EditorStringName(Editor));
+ const bool prev_dark_theme = (bool)p_old_theme->get_constant(SNAME("dark_theme"), EditorStringName(Editor));
+ const Color prev_accent_color = p_old_theme->get_color(SNAME("accent_color"), EditorStringName(Editor));
+ const float prev_icon_saturation = p_old_theme->get_color(SNAME("icon_saturation"), EditorStringName(Editor)).r;
+ const float prev_gizmo_handle_scale = (float)p_old_theme->get_constant(SNAME("gizmo_handle_scale"), EditorStringName(Editor));
+
+ keep_old_icons = (Math::is_equal_approx(prev_scale, EDSCALE) &&
+ Math::is_equal_approx(prev_gizmo_handle_scale, config.gizmo_handle_scale) &&
+ prev_dark_theme == config.dark_theme &&
+ prev_accent_color == config.accent_color &&
+ prev_icon_saturation == config.icon_saturation);
+
+ const double prev_thumb_size = (double)p_old_theme->get_constant(SNAME("thumb_size"), EditorStringName(Editor));
+
+ regenerate_thumb_icons = !Math::is_equal_approx(prev_thumb_size, config.thumb_size);
+ }
+
+ // External functions, see editor_icons.cpp.
+ editor_configure_icons(config.dark_theme);
+ if (keep_old_icons) {
+ editor_copy_icons(theme, p_old_theme);
+ } else {
+ editor_register_icons(theme, config.dark_theme, config.icon_saturation, config.thumb_size, false);
+ }
+ if (regenerate_thumb_icons) {
+ editor_register_icons(theme, config.dark_theme, config.icon_saturation, config.thumb_size, true);
+ }
+
+ // External function, see editor_fonts.cpp.
+ editor_register_fonts(theme);
+
+ _populate_standard_styles(theme, config);
+ _populate_editor_styles(theme, config);
+ _populate_text_editor_styles(theme, config);
+
+ OS::get_singleton()->benchmark_end_measure("EditorTheme", "Create Base Theme");
+ return theme;
+}
+
+EditorThemeManager::ThemeConfiguration EditorThemeManager::_create_theme_config(const Ref<Theme> &p_theme) {
+ ThemeConfiguration config;
+
+ // Basic properties.
+
+ config.preset = EDITOR_GET("interface/theme/preset");
+ config.spacing_preset = EDITOR_GET("interface/theme/spacing_preset");
+ config.dark_theme = EditorSettings::get_singleton()->is_dark_theme();
+
+ config.base_color = EDITOR_GET("interface/theme/base_color");
+ config.accent_color = EDITOR_GET("interface/theme/accent_color");
+ config.contrast = EDITOR_GET("interface/theme/contrast");
+ config.icon_saturation = EDITOR_GET("interface/theme/icon_saturation");
+
+ // Extra properties.
+
+ config.base_spacing = EDITOR_GET("interface/theme/base_spacing");
+ config.extra_spacing = EDITOR_GET("interface/theme/additional_spacing");
+ // Ensure borders are visible when using an editor scale below 100%.
+ config.border_width = CLAMP((int)EDITOR_GET("interface/theme/border_size"), 0, 2) * MAX(1, EDSCALE);
+ config.corner_radius = CLAMP((int)EDITOR_GET("interface/theme/corner_radius"), 0, 6);
+
+ config.draw_extra_borders = EDITOR_GET("interface/theme/draw_extra_borders");
+ config.relationship_line_opacity = EDITOR_GET("interface/theme/relationship_line_opacity");
+ config.thumb_size = EDITOR_GET("filesystem/file_dialog/thumbnail_size");
+ config.class_icon_size = 16 * EDSCALE;
+ config.increase_scrollbar_touch_area = EDITOR_GET("interface/touchscreen/increase_scrollbar_touch_area");
+ config.gizmo_handle_scale = EDITOR_GET("interface/touchscreen/scale_gizmo_handles");
+ config.color_picker_button_height = 28 * EDSCALE;
+
+ config.default_contrast = 0.3; // Make sure to keep this in sync with the editor settings definition.
+
+ // Handle main theme preset.
+ {
+ if (config.preset != "Custom") {
+ Color preset_accent_color;
+ Color preset_base_color;
+ float preset_contrast = 0;
+ bool preset_draw_extra_borders = false;
+
+ // Please use alphabetical order if you're adding a new theme here.
+ if (config.preset == "Breeze Dark") {
+ preset_accent_color = Color(0.26, 0.76, 1.00);
+ preset_base_color = Color(0.24, 0.26, 0.28);
+ preset_contrast = config.default_contrast;
+ } else if (config.preset == "Godot 2") {
+ preset_accent_color = Color(0.53, 0.67, 0.89);
+ preset_base_color = Color(0.24, 0.23, 0.27);
+ preset_contrast = config.default_contrast;
+ } else if (config.preset == "Gray") {
+ preset_accent_color = Color(0.44, 0.73, 0.98);
+ preset_base_color = Color(0.24, 0.24, 0.24);
+ preset_contrast = config.default_contrast;
+ } else if (config.preset == "Light") {
+ preset_accent_color = Color(0.18, 0.50, 1.00);
+ preset_base_color = Color(0.9, 0.9, 0.9);
+ // A negative contrast rate looks better for light themes, since it better follows the natural order of UI "elevation".
+ preset_contrast = -0.06;
+ } else if (config.preset == "Solarized (Dark)") {
+ preset_accent_color = Color(0.15, 0.55, 0.82);
+ preset_base_color = Color(0.04, 0.23, 0.27);
+ preset_contrast = config.default_contrast;
+ } else if (config.preset == "Solarized (Light)") {
+ preset_accent_color = Color(0.15, 0.55, 0.82);
+ preset_base_color = Color(0.89, 0.86, 0.79);
+ // A negative contrast rate looks better for light themes, since it better follows the natural order of UI "elevation".
+ preset_contrast = -0.06;
+ } else if (config.preset == "Black (OLED)") {
+ preset_accent_color = Color(0.45, 0.75, 1.0);
+ preset_base_color = Color(0, 0, 0);
+ // The contrast rate value is irrelevant on a fully black theme.
+ preset_contrast = 0.0;
+ preset_draw_extra_borders = true;
+ } else { // Default
+ preset_accent_color = Color(0.44, 0.73, 0.98);
+ preset_base_color = Color(0.21, 0.24, 0.29);
+ preset_contrast = config.default_contrast;
+ }
+
+ config.accent_color = preset_accent_color;
+ config.base_color = preset_base_color;
+ config.contrast = preset_contrast;
+ config.draw_extra_borders = preset_draw_extra_borders;
+
+ EditorSettings::get_singleton()->set_initial_value("interface/theme/accent_color", config.accent_color);
+ EditorSettings::get_singleton()->set_initial_value("interface/theme/base_color", config.base_color);
+ EditorSettings::get_singleton()->set_initial_value("interface/theme/contrast", config.contrast);
+ EditorSettings::get_singleton()->set_initial_value("interface/theme/draw_extra_borders", config.draw_extra_borders);
+ }
+
+ // Enforce values in case they were adjusted or overridden.
+ EditorSettings::get_singleton()->set_manually("interface/theme/preset", config.preset);
+ EditorSettings::get_singleton()->set_manually("interface/theme/accent_color", config.accent_color);
+ EditorSettings::get_singleton()->set_manually("interface/theme/base_color", config.base_color);
+ EditorSettings::get_singleton()->set_manually("interface/theme/contrast", config.contrast);
+ EditorSettings::get_singleton()->set_manually("interface/theme/draw_extra_borders", config.draw_extra_borders);
+ }
+
+ // Handle theme spacing preset.
+ {
+ if (config.spacing_preset != "Custom") {
+ int preset_base_spacing = 0;
+ int preset_extra_spacing = 0;
+
+ if (config.spacing_preset == "Compact") {
+ preset_base_spacing = 0;
+ preset_extra_spacing = 4;
+ } else if (config.spacing_preset == "Spacious") {
+ preset_base_spacing = 6;
+ preset_extra_spacing = 2;
+ } else { // Default
+ preset_base_spacing = 4;
+ preset_extra_spacing = 0;
+ }
+
+ config.base_spacing = preset_base_spacing;
+ config.extra_spacing = preset_extra_spacing;
+
+ EditorSettings::get_singleton()->set_initial_value("interface/theme/base_spacing", config.base_spacing);
+ EditorSettings::get_singleton()->set_initial_value("interface/theme/additional_spacing", config.extra_spacing);
+ }
+
+ // Enforce values in case they were adjusted or overridden.
+ EditorSettings::get_singleton()->set_manually("interface/theme/spacing_preset", config.spacing_preset);
+ EditorSettings::get_singleton()->set_manually("interface/theme/base_spacing", config.base_spacing);
+ EditorSettings::get_singleton()->set_manually("interface/theme/additional_spacing", config.extra_spacing);
+ }
+
+ // Generated properties.
+
+ config.base_margin = config.base_spacing;
+ config.increased_margin = config.base_spacing + config.extra_spacing;
+ config.separation_margin = (config.base_spacing + config.extra_spacing / 2) * EDSCALE;
+ config.popup_margin = config.base_margin * 3 * EDSCALE;
+ // Make sure content doesn't stick to window decorations; this can be fixed in future with layout changes.
+ config.window_border_margin = MAX(1, config.base_margin * 2);
+ config.top_bar_separation = config.base_margin * 2 * EDSCALE;
+
+ // Force the v_separation to be even so that the spacing on top and bottom is even.
+ // If the vsep is odd and cannot be split into 2 even groups (of pixels), then it will be lopsided.
+ // We add 2 to the vsep to give it some extra spacing which looks a bit more modern (see Windows, for example).
+ const int separation_base = config.increased_margin + 6;
+ config.forced_even_separation = separation_base + (separation_base % 2);
+
+ return config;
+}
+
+void EditorThemeManager::_create_shared_styles(const Ref<Theme> &p_theme, ThemeConfiguration &p_config) {
+ // Colors.
+ {
+ // Base colors.
+
+ p_theme->set_color("base_color", EditorStringName(Editor), p_config.base_color);
+ p_theme->set_color("accent_color", EditorStringName(Editor), p_config.accent_color);
+
+ // White (dark theme) or black (light theme), will be used to generate the rest of the colors
+ p_config.mono_color = p_config.dark_theme ? Color(1, 1, 1) : Color(0, 0, 0);
+
+ // Ensure base colors are in the 0..1 luminance range to avoid 8-bit integer overflow or text rendering issues.
+ // Some places in the editor use 8-bit integer colors.
+ p_config.dark_color_1 = p_config.base_color.lerp(Color(0, 0, 0, 1), p_config.contrast).clamp();
+ p_config.dark_color_2 = p_config.base_color.lerp(Color(0, 0, 0, 1), p_config.contrast * 1.5).clamp();
+ p_config.dark_color_3 = p_config.base_color.lerp(Color(0, 0, 0, 1), p_config.contrast * 2).clamp();
+
+ p_config.contrast_color_1 = p_config.base_color.lerp(p_config.mono_color, MAX(p_config.contrast, p_config.default_contrast));
+ p_config.contrast_color_2 = p_config.base_color.lerp(p_config.mono_color, MAX(p_config.contrast * 1.5, p_config.default_contrast * 1.5));
+
+ p_config.highlight_color = Color(p_config.accent_color.r, p_config.accent_color.g, p_config.accent_color.b, 0.275);
+ p_config.highlight_disabled_color = p_config.highlight_color.lerp(p_config.dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.5);
+
+ p_config.success_color = Color(0.45, 0.95, 0.5);
+ p_config.warning_color = Color(1, 0.87, 0.4);
+ p_config.error_color = Color(1, 0.47, 0.42);
+ if (!p_config.dark_theme) {
+ // Darken some colors to be readable on a light background.
+ p_config.success_color = p_config.success_color.lerp(p_config.mono_color, 0.35);
+ p_config.warning_color = p_config.warning_color.lerp(p_config.mono_color, 0.35);
+ p_config.error_color = p_config.error_color.lerp(p_config.mono_color, 0.25);
+ }
+
+ p_theme->set_color("mono_color", EditorStringName(Editor), p_config.mono_color);
+ p_theme->set_color("dark_color_1", EditorStringName(Editor), p_config.dark_color_1);
+ p_theme->set_color("dark_color_2", EditorStringName(Editor), p_config.dark_color_2);
+ p_theme->set_color("dark_color_3", EditorStringName(Editor), p_config.dark_color_3);
+ p_theme->set_color("contrast_color_1", EditorStringName(Editor), p_config.contrast_color_1);
+ p_theme->set_color("contrast_color_2", EditorStringName(Editor), p_config.contrast_color_2);
+ p_theme->set_color("highlight_color", EditorStringName(Editor), p_config.highlight_color);
+ p_theme->set_color("highlight_disabled_color", EditorStringName(Editor), p_config.highlight_disabled_color);
+ p_theme->set_color("success_color", EditorStringName(Editor), p_config.success_color);
+ p_theme->set_color("warning_color", EditorStringName(Editor), p_config.warning_color);
+ p_theme->set_color("error_color", EditorStringName(Editor), p_config.error_color);
+
+ // Only used when the Draw Extra Borders editor setting is enabled.
+ p_config.extra_border_color_1 = Color(0.5, 0.5, 0.5);
+ p_config.extra_border_color_2 = p_config.dark_theme ? Color(0.3, 0.3, 0.3) : Color(0.7, 0.7, 0.7);
+
+ p_theme->set_color("extra_border_color_1", EditorStringName(Editor), p_config.extra_border_color_1);
+ p_theme->set_color("extra_border_color_2", EditorStringName(Editor), p_config.extra_border_color_2);
+
+ // Font colors.
+
+ p_config.font_color = p_config.mono_color.lerp(p_config.base_color, 0.25);
+ p_config.font_focus_color = p_config.mono_color.lerp(p_config.base_color, 0.125);
+ p_config.font_hover_color = p_config.mono_color.lerp(p_config.base_color, 0.125);
+ p_config.font_pressed_color = p_config.accent_color;
+ p_config.font_hover_pressed_color = p_config.font_hover_color.lerp(p_config.accent_color, 0.74);
+ p_config.font_disabled_color = Color(p_config.mono_color.r, p_config.mono_color.g, p_config.mono_color.b, 0.35);
+ p_config.font_readonly_color = Color(p_config.mono_color.r, p_config.mono_color.g, p_config.mono_color.b, 0.65);
+ p_config.font_placeholder_color = Color(p_config.mono_color.r, p_config.mono_color.g, p_config.mono_color.b, 0.6);
+ p_config.font_outline_color = Color(0, 0, 0, 0);
+
+ p_theme->set_color("font_color", EditorStringName(Editor), p_config.font_color);
+ p_theme->set_color("font_focus_color", EditorStringName(Editor), p_config.font_focus_color);
+ p_theme->set_color("font_hover_color", EditorStringName(Editor), p_config.font_hover_color);
+ p_theme->set_color("font_pressed_color", EditorStringName(Editor), p_config.font_pressed_color);
+ p_theme->set_color("font_hover_pressed_color", EditorStringName(Editor), p_config.font_hover_pressed_color);
+ p_theme->set_color("font_disabled_color", EditorStringName(Editor), p_config.font_disabled_color);
+ p_theme->set_color("font_readonly_color", EditorStringName(Editor), p_config.font_readonly_color);
+ p_theme->set_color("font_placeholder_color", EditorStringName(Editor), p_config.font_placeholder_color);
+ p_theme->set_color("font_outline_color", EditorStringName(Editor), p_config.font_outline_color);
+
+ // Icon colors.
+
+ p_config.icon_normal_color = Color(1, 1, 1);
+ p_config.icon_focus_color = p_config.icon_normal_color * (p_config.dark_theme ? 1.15 : 1.45);
+ p_config.icon_focus_color.a = 1.0;
+ p_config.icon_hover_color = p_config.icon_focus_color;
+ // Make the pressed icon color overbright because icons are not completely white on a dark theme.
+ // On a light theme, icons are dark, so we need to modulate them with an even brighter color.
+ p_config.icon_pressed_color = p_config.accent_color * (p_config.dark_theme ? 1.15 : 3.5);
+ p_config.icon_pressed_color.a = 1.0;
+ p_config.icon_disabled_color = Color(p_config.icon_normal_color, 0.4);
+
+ p_theme->set_color("icon_normal_color", EditorStringName(Editor), p_config.icon_normal_color);
+ p_theme->set_color("icon_focus_color", EditorStringName(Editor), p_config.icon_focus_color);
+ p_theme->set_color("icon_hover_color", EditorStringName(Editor), p_config.icon_hover_color);
+ p_theme->set_color("icon_pressed_color", EditorStringName(Editor), p_config.icon_pressed_color);
+ p_theme->set_color("icon_disabled_color", EditorStringName(Editor), p_config.icon_disabled_color);
+
+ // Additional GUI colors.
+
+ p_config.shadow_color = Color(0, 0, 0, p_config.dark_theme ? 0.3 : 0.1);
+ p_config.selection_color = p_config.accent_color * Color(1, 1, 1, 0.4);
+ p_config.disabled_border_color = p_config.mono_color.inverted().lerp(p_config.base_color, 0.7);
+ p_config.disabled_bg_color = p_config.mono_color.inverted().lerp(p_config.base_color, 0.9);
+ p_config.separator_color = Color(p_config.mono_color.r, p_config.mono_color.g, p_config.mono_color.b, 0.1);
+
+ p_theme->set_color("selection_color", EditorStringName(Editor), p_config.selection_color);
+ p_theme->set_color("disabled_border_color", EditorStringName(Editor), p_config.disabled_border_color);
+ p_theme->set_color("disabled_bg_color", EditorStringName(Editor), p_config.disabled_bg_color);
+ p_theme->set_color("separator_color", EditorStringName(Editor), p_config.separator_color);
+
+ // Additional editor colors.
+
+ p_theme->set_color("box_selection_fill_color", EditorStringName(Editor), p_config.accent_color * Color(1, 1, 1, 0.3));
+ p_theme->set_color("box_selection_stroke_color", EditorStringName(Editor), p_config.accent_color * Color(1, 1, 1, 0.8));
+
+ p_theme->set_color("axis_x_color", EditorStringName(Editor), Color(0.96, 0.20, 0.32));
+ p_theme->set_color("axis_y_color", EditorStringName(Editor), Color(0.53, 0.84, 0.01));
+ p_theme->set_color("axis_z_color", EditorStringName(Editor), Color(0.16, 0.55, 0.96));
+ p_theme->set_color("axis_w_color", EditorStringName(Editor), Color(0.55, 0.55, 0.55));
+
+ const float prop_color_saturation = p_config.accent_color.get_s() * 0.75;
+ const float prop_color_value = p_config.accent_color.get_v();
+
+ p_theme->set_color("property_color_x", EditorStringName(Editor), Color().from_hsv(0.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value));
+ p_theme->set_color("property_color_y", EditorStringName(Editor), Color().from_hsv(1.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value));
+ p_theme->set_color("property_color_z", EditorStringName(Editor), Color().from_hsv(2.0 / 3.0 + 0.05, prop_color_saturation, prop_color_value));
+ p_theme->set_color("property_color_w", EditorStringName(Editor), Color().from_hsv(1.5 / 3.0 + 0.05, prop_color_saturation, prop_color_value));
+
+ // Special colors for rendering methods.
+
+ p_theme->set_color("forward_plus_color", EditorStringName(Editor), Color::hex(0x5d8c3fff));
+ p_theme->set_color("mobile_color", EditorStringName(Editor), Color::hex(0xa5557dff));
+ p_theme->set_color("gl_compatibility_color", EditorStringName(Editor), Color::hex(0x5586a4ff));
+
+ if (p_config.dark_theme) {
+ p_theme->set_color("highend_color", EditorStringName(Editor), Color(1.0, 0.0, 0.0));
+ } else {
+ p_theme->set_color("highend_color", EditorStringName(Editor), Color::hex(0xad1128ff));
+ }
+ }
+
+ // Constants.
+ {
+ // Can't save single float in theme, so using Color.
+ p_theme->set_color("icon_saturation", EditorStringName(Editor), Color(p_config.icon_saturation, p_config.icon_saturation, p_config.icon_saturation));
+
+ // Controls may rely on the scale for their internal drawing logic.
+ p_theme->set_default_base_scale(EDSCALE);
+ p_theme->set_constant("scale", EditorStringName(Editor), EDSCALE);
+
+ p_theme->set_constant("thumb_size", EditorStringName(Editor), p_config.thumb_size);
+ p_theme->set_constant("class_icon_size", EditorStringName(Editor), p_config.class_icon_size);
+ p_theme->set_constant("color_picker_button_height", EditorStringName(Editor), p_config.color_picker_button_height);
+ p_theme->set_constant("gizmo_handle_scale", EditorStringName(Editor), p_config.gizmo_handle_scale);
+
+ p_theme->set_constant("base_margin", EditorStringName(Editor), p_config.base_margin);
+ p_theme->set_constant("increased_margin", EditorStringName(Editor), p_config.increased_margin);
+ p_theme->set_constant("window_border_margin", EditorStringName(Editor), p_config.window_border_margin);
+ p_theme->set_constant("top_bar_separation", EditorStringName(Editor), p_config.top_bar_separation);
+
+ p_theme->set_constant("dark_theme", EditorStringName(Editor), p_config.dark_theme);
+ }
+
+ // Styleboxes.
+ {
+ // This is the basic stylebox, used as a base for most other styleboxes (through `duplicate()`).
+ p_config.base_style = make_flat_stylebox(p_config.base_color, p_config.base_margin, p_config.base_margin, p_config.base_margin, p_config.base_margin, p_config.corner_radius);
+ p_config.base_style->set_border_width_all(p_config.border_width);
+ p_config.base_style->set_border_color(p_config.base_color);
+
+ p_config.base_empty_style = make_empty_stylebox(p_config.base_margin, p_config.base_margin, p_config.base_margin, p_config.base_margin);
+
+ // Button styles.
+ {
+ p_config.widget_margin = Vector2(p_config.increased_margin + 2, p_config.increased_margin + 1) * EDSCALE;
+
+ p_config.button_style = p_config.base_style->duplicate();
+ p_config.button_style->set_content_margin_individual(p_config.widget_margin.x, p_config.widget_margin.y, p_config.widget_margin.x, p_config.widget_margin.y);
+ p_config.button_style->set_bg_color(p_config.dark_color_1);
+ if (p_config.draw_extra_borders) {
+ p_config.button_style->set_border_width_all(Math::round(EDSCALE));
+ p_config.button_style->set_border_color(p_config.extra_border_color_1);
+ } else {
+ p_config.button_style->set_border_color(p_config.dark_color_2);
+ }
+
+ p_config.button_style_disabled = p_config.button_style->duplicate();
+ p_config.button_style_disabled->set_bg_color(p_config.disabled_bg_color);
+ if (p_config.draw_extra_borders) {
+ p_config.button_style_disabled->set_border_color(p_config.extra_border_color_2);
+ } else {
+ p_config.button_style_disabled->set_border_color(p_config.disabled_border_color);
+ }
+
+ p_config.button_style_focus = p_config.button_style->duplicate();
+ p_config.button_style_focus->set_draw_center(false);
+ p_config.button_style_focus->set_border_width_all(Math::round(2 * MAX(1, EDSCALE)));
+ p_config.button_style_focus->set_border_color(p_config.accent_color);
+
+ p_config.button_style_pressed = p_config.button_style->duplicate();
+ p_config.button_style_pressed->set_bg_color(p_config.dark_color_1.darkened(0.125));
+
+ p_config.button_style_hover = p_config.button_style->duplicate();
+ p_config.button_style_hover->set_bg_color(p_config.mono_color * Color(1, 1, 1, 0.11));
+ if (p_config.draw_extra_borders) {
+ p_config.button_style_hover->set_border_color(p_config.extra_border_color_1);
+ } else {
+ p_config.button_style_hover->set_border_color(p_config.mono_color * Color(1, 1, 1, 0.05));
+ }
+ }
+
+ // Windows and popups.
+ {
+ p_config.popup_style = p_config.base_style->duplicate();
+ p_config.popup_style->set_content_margin_all(p_config.popup_margin);
+ p_config.popup_style->set_border_color(p_config.contrast_color_1);
+ p_config.popup_style->set_shadow_color(p_config.shadow_color);
+ p_config.popup_style->set_shadow_size(4 * EDSCALE);
+ // Popups are separate windows by default in the editor. Windows currently don't support per-pixel transparency
+ // in 4.0, and even if it was, it may not always work in practice (e.g. running with compositing disabled).
+ p_config.popup_style->set_corner_radius_all(0);
+
+ p_config.window_style = p_config.popup_style->duplicate();
+ p_config.window_style->set_border_color(p_config.base_color);
+ p_config.window_style->set_border_width(SIDE_TOP, 24 * EDSCALE);
+ p_config.window_style->set_expand_margin(SIDE_TOP, 24 * EDSCALE);
+
+ // Prevent corner artifacts between window title and body.
+ p_config.dialog_style = p_config.base_style->duplicate();
+ p_config.dialog_style->set_corner_radius(CORNER_TOP_LEFT, 0);
+ p_config.dialog_style->set_corner_radius(CORNER_TOP_RIGHT, 0);
+ // Prevent visible line between window title and body.
+ p_config.dialog_style->set_expand_margin(SIDE_BOTTOM, 2 * EDSCALE);
+ }
+
+ // Panels.
+ {
+ p_config.panel_container_style = p_config.button_style->duplicate();
+ p_config.panel_container_style->set_draw_center(false);
+ p_config.panel_container_style->set_border_width_all(0);
+
+ // Content panel for tabs and similar containers.
+
+ // Compensate for the border.
+ const int content_panel_margin = p_config.base_margin * EDSCALE + p_config.border_width;
+
+ p_config.content_panel_style = p_config.base_style->duplicate();
+ p_config.content_panel_style->set_border_color(p_config.dark_color_3);
+ p_config.content_panel_style->set_border_width_all(p_config.border_width);
+ p_config.content_panel_style->set_border_width(Side::SIDE_TOP, 0);
+ p_config.content_panel_style->set_corner_radius(CORNER_TOP_LEFT, 0);
+ p_config.content_panel_style->set_corner_radius(CORNER_TOP_RIGHT, 0);
+ p_config.content_panel_style->set_content_margin_individual(content_panel_margin, 2 * EDSCALE + content_panel_margin, content_panel_margin, content_panel_margin);
+
+ // Trees and similarly inset panels.
+
+ p_config.tree_panel_style = p_config.base_style->duplicate();
+ // Make Trees easier to distinguish from other controls by using a darker background color.
+ p_config.tree_panel_style->set_bg_color(p_config.dark_color_1.lerp(p_config.dark_color_2, 0.5));
+ if (p_config.draw_extra_borders) {
+ p_config.tree_panel_style->set_border_width_all(Math::round(EDSCALE));
+ p_config.tree_panel_style->set_border_color(p_config.extra_border_color_2);
+ } else {
+ p_config.tree_panel_style->set_border_color(p_config.dark_color_3);
+ }
+ }
+ }
+}
+
+void EditorThemeManager::_populate_standard_styles(const Ref<Theme> &p_theme, ThemeConfiguration &p_config) {
+ // Panels.
+ {
+ // Panel.
+ p_theme->set_stylebox("panel", "Panel", make_flat_stylebox(p_config.dark_color_1, 6, 4, 6, 4, p_config.corner_radius));
+
+ // PanelContainer.
+ p_theme->set_stylebox("panel", "PanelContainer", p_config.panel_container_style);
+
+ // TooltipPanel & TooltipLabel.
+ {
+ // TooltipPanel is also used for custom tooltips, while TooltipLabel
+ // is only relevant for default tooltips.
+
+ p_theme->set_color("font_color", "TooltipLabel", p_config.font_hover_color);
+ p_theme->set_color("font_shadow_color", "TooltipLabel", Color(0, 0, 0, 0));
+
+ Ref<StyleBoxFlat> style_tooltip = p_config.popup_style->duplicate();
+ style_tooltip->set_shadow_size(0);
+ style_tooltip->set_content_margin_all(p_config.base_margin * EDSCALE * 0.5);
+ style_tooltip->set_bg_color(p_config.dark_color_3 * Color(0.8, 0.8, 0.8, 0.9));
+ style_tooltip->set_border_width_all(0);
+ p_theme->set_stylebox("panel", "TooltipPanel", style_tooltip);
+ }
+
+ // PopupPanel
+ p_theme->set_stylebox("panel", "PopupPanel", p_config.popup_style);
+ }
+
+ // Buttons.
+ {
+ // Button.
+
+ p_theme->set_stylebox("normal", "Button", p_config.button_style);
+ p_theme->set_stylebox("hover", "Button", p_config.button_style_hover);
+ p_theme->set_stylebox("pressed", "Button", p_config.button_style_pressed);
+ p_theme->set_stylebox("focus", "Button", p_config.button_style_focus);
+ p_theme->set_stylebox("disabled", "Button", p_config.button_style_disabled);
+
+ p_theme->set_color("font_color", "Button", p_config.font_color);
+ p_theme->set_color("font_hover_color", "Button", p_config.font_hover_color);
+ p_theme->set_color("font_hover_pressed_color", "Button", p_config.font_hover_pressed_color);
+ p_theme->set_color("font_focus_color", "Button", p_config.font_focus_color);
+ p_theme->set_color("font_pressed_color", "Button", p_config.font_pressed_color);
+ p_theme->set_color("font_disabled_color", "Button", p_config.font_disabled_color);
+ p_theme->set_color("font_outline_color", "Button", p_config.font_outline_color);
+
+ p_theme->set_color("icon_normal_color", "Button", p_config.icon_normal_color);
+ p_theme->set_color("icon_hover_color", "Button", p_config.icon_hover_color);
+ p_theme->set_color("icon_focus_color", "Button", p_config.icon_focus_color);
+ p_theme->set_color("icon_pressed_color", "Button", p_config.icon_pressed_color);
+ p_theme->set_color("icon_disabled_color", "Button", p_config.icon_disabled_color);
+
+ p_theme->set_constant("h_separation", "Button", 4 * EDSCALE);
+ p_theme->set_constant("outline_size", "Button", 0);
+
+ // MenuButton.
+
+ p_theme->set_stylebox("normal", "MenuButton", p_config.panel_container_style);
+ p_theme->set_stylebox("hover", "MenuButton", p_config.button_style_hover);
+ p_theme->set_stylebox("pressed", "MenuButton", p_config.panel_container_style);
+ p_theme->set_stylebox("focus", "MenuButton", p_config.panel_container_style);
+ p_theme->set_stylebox("disabled", "MenuButton", p_config.panel_container_style);
+
+ p_theme->set_color("font_color", "MenuButton", p_config.font_color);
+ p_theme->set_color("font_hover_color", "MenuButton", p_config.font_hover_color);
+ p_theme->set_color("font_hover_pressed_color", "MenuButton", p_config.font_hover_pressed_color);
+ p_theme->set_color("font_focus_color", "MenuButton", p_config.font_focus_color);
+ p_theme->set_color("font_outline_color", "MenuButton", p_config.font_outline_color);
+
+ p_theme->set_constant("outline_size", "MenuButton", 0);
+
+ // MenuBar.
+
+ p_theme->set_stylebox("normal", "MenuBar", p_config.button_style);
+ p_theme->set_stylebox("hover", "MenuBar", p_config.button_style_hover);
+ p_theme->set_stylebox("pressed", "MenuBar", p_config.button_style_pressed);
+ p_theme->set_stylebox("disabled", "MenuBar", p_config.button_style_disabled);
+
+ p_theme->set_color("font_color", "MenuBar", p_config.font_color);
+ p_theme->set_color("font_hover_color", "MenuBar", p_config.font_hover_color);
+ p_theme->set_color("font_hover_pressed_color", "MenuBar", p_config.font_hover_pressed_color);
+ p_theme->set_color("font_focus_color", "MenuBar", p_config.font_focus_color);
+ p_theme->set_color("font_pressed_color", "MenuBar", p_config.font_pressed_color);
+ p_theme->set_color("font_disabled_color", "MenuBar", p_config.font_disabled_color);
+ p_theme->set_color("font_outline_color", "MenuBar", p_config.font_outline_color);
+
+ p_theme->set_color("icon_normal_color", "MenuBar", p_config.icon_normal_color);
+ p_theme->set_color("icon_hover_color", "MenuBar", p_config.icon_hover_color);
+ p_theme->set_color("icon_focus_color", "MenuBar", p_config.icon_focus_color);
+ p_theme->set_color("icon_pressed_color", "MenuBar", p_config.icon_pressed_color);
+ p_theme->set_color("icon_disabled_color", "MenuBar", p_config.icon_disabled_color);
+
+ p_theme->set_constant("h_separation", "MenuBar", 4 * EDSCALE);
+ p_theme->set_constant("outline_size", "MenuBar", 0);
+
+ // OptionButton.
+ {
+ Ref<StyleBoxFlat> option_button_focus_style = p_config.button_style_focus->duplicate();
+ Ref<StyleBoxFlat> option_button_normal_style = p_config.button_style->duplicate();
+ Ref<StyleBoxFlat> option_button_hover_style = p_config.button_style_hover->duplicate();
+ Ref<StyleBoxFlat> option_button_pressed_style = p_config.button_style_pressed->duplicate();
+ Ref<StyleBoxFlat> option_button_disabled_style = p_config.button_style_disabled->duplicate();
+
+ option_button_focus_style->set_content_margin(SIDE_RIGHT, 4 * EDSCALE);
+ option_button_normal_style->set_content_margin(SIDE_RIGHT, 4 * EDSCALE);
+ option_button_hover_style->set_content_margin(SIDE_RIGHT, 4 * EDSCALE);
+ option_button_pressed_style->set_content_margin(SIDE_RIGHT, 4 * EDSCALE);
+ option_button_disabled_style->set_content_margin(SIDE_RIGHT, 4 * EDSCALE);
+
+ p_theme->set_stylebox("focus", "OptionButton", option_button_focus_style);
+ p_theme->set_stylebox("normal", "OptionButton", p_config.button_style);
+ p_theme->set_stylebox("hover", "OptionButton", p_config.button_style_hover);
+ p_theme->set_stylebox("pressed", "OptionButton", p_config.button_style_pressed);
+ p_theme->set_stylebox("disabled", "OptionButton", p_config.button_style_disabled);
+
+ p_theme->set_stylebox("normal_mirrored", "OptionButton", option_button_normal_style);
+ p_theme->set_stylebox("hover_mirrored", "OptionButton", option_button_hover_style);
+ p_theme->set_stylebox("pressed_mirrored", "OptionButton", option_button_pressed_style);
+ p_theme->set_stylebox("disabled_mirrored", "OptionButton", option_button_disabled_style);
+
+ p_theme->set_color("font_color", "OptionButton", p_config.font_color);
+ p_theme->set_color("font_hover_color", "OptionButton", p_config.font_hover_color);
+ p_theme->set_color("font_hover_pressed_color", "OptionButton", p_config.font_hover_pressed_color);
+ p_theme->set_color("font_focus_color", "OptionButton", p_config.font_focus_color);
+ p_theme->set_color("font_pressed_color", "OptionButton", p_config.font_pressed_color);
+ p_theme->set_color("font_disabled_color", "OptionButton", p_config.font_disabled_color);
+ p_theme->set_color("font_outline_color", "OptionButton", p_config.font_outline_color);
+
+ p_theme->set_color("icon_normal_color", "OptionButton", p_config.icon_normal_color);
+ p_theme->set_color("icon_hover_color", "OptionButton", p_config.icon_hover_color);
+ p_theme->set_color("icon_focus_color", "OptionButton", p_config.icon_focus_color);
+ p_theme->set_color("icon_pressed_color", "OptionButton", p_config.icon_pressed_color);
+ p_theme->set_color("icon_disabled_color", "OptionButton", p_config.icon_disabled_color);
+
+ p_theme->set_icon("arrow", "OptionButton", p_theme->get_icon(SNAME("GuiOptionArrow"), EditorStringName(EditorIcons)));
+ p_theme->set_constant("arrow_margin", "OptionButton", p_config.widget_margin.x - 2 * EDSCALE);
+ p_theme->set_constant("modulate_arrow", "OptionButton", true);
+ p_theme->set_constant("h_separation", "OptionButton", 4 * EDSCALE);
+ p_theme->set_constant("outline_size", "OptionButton", 0);
+ }
+
+ // CheckButton.
+
+ p_theme->set_stylebox("normal", "CheckButton", p_config.panel_container_style);
+ p_theme->set_stylebox("pressed", "CheckButton", p_config.panel_container_style);
+ p_theme->set_stylebox("disabled", "CheckButton", p_config.panel_container_style);
+ p_theme->set_stylebox("hover", "CheckButton", p_config.panel_container_style);
+ p_theme->set_stylebox("hover_pressed", "CheckButton", p_config.panel_container_style);
+
+ p_theme->set_icon("checked", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOn"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("checked_disabled", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOnDisabled"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("unchecked", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOff"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("unchecked_disabled", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOffDisabled"), EditorStringName(EditorIcons)));
+
+ p_theme->set_icon("checked_mirrored", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOnMirrored"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("checked_disabled_mirrored", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOnDisabledMirrored"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("unchecked_mirrored", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOffMirrored"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("unchecked_disabled_mirrored", "CheckButton", p_theme->get_icon(SNAME("GuiToggleOffDisabledMirrored"), EditorStringName(EditorIcons)));
+
+ p_theme->set_color("font_color", "CheckButton", p_config.font_color);
+ p_theme->set_color("font_hover_color", "CheckButton", p_config.font_hover_color);
+ p_theme->set_color("font_hover_pressed_color", "CheckButton", p_config.font_hover_pressed_color);
+ p_theme->set_color("font_focus_color", "CheckButton", p_config.font_focus_color);
+ p_theme->set_color("font_pressed_color", "CheckButton", p_config.font_pressed_color);
+ p_theme->set_color("font_disabled_color", "CheckButton", p_config.font_disabled_color);
+ p_theme->set_color("font_outline_color", "CheckButton", p_config.font_outline_color);
+
+ p_theme->set_color("icon_normal_color", "CheckButton", p_config.icon_normal_color);
+ p_theme->set_color("icon_hover_color", "CheckButton", p_config.icon_hover_color);
+ p_theme->set_color("icon_focus_color", "CheckButton", p_config.icon_focus_color);
+ p_theme->set_color("icon_pressed_color", "CheckButton", p_config.icon_pressed_color);
+ p_theme->set_color("icon_disabled_color", "CheckButton", p_config.icon_disabled_color);
+
+ p_theme->set_constant("h_separation", "CheckButton", 8 * EDSCALE);
+ p_theme->set_constant("check_v_offset", "CheckButton", 0);
+ p_theme->set_constant("outline_size", "CheckButton", 0);
+
+ // CheckBox.
+ {
+ Ref<StyleBoxFlat> checkbox_style = p_config.panel_container_style->duplicate();
+ checkbox_style->set_content_margin_all(p_config.base_margin * EDSCALE);
+
+ p_theme->set_stylebox("normal", "CheckBox", checkbox_style);
+ p_theme->set_stylebox("pressed", "CheckBox", checkbox_style);
+ p_theme->set_stylebox("disabled", "CheckBox", checkbox_style);
+ p_theme->set_stylebox("hover", "CheckBox", checkbox_style);
+ p_theme->set_stylebox("hover_pressed", "CheckBox", checkbox_style);
+ p_theme->set_icon("checked", "CheckBox", p_theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("unchecked", "CheckBox", p_theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("radio_checked", "CheckBox", p_theme->get_icon(SNAME("GuiRadioChecked"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("radio_unchecked", "CheckBox", p_theme->get_icon(SNAME("GuiRadioUnchecked"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("checked_disabled", "CheckBox", p_theme->get_icon(SNAME("GuiCheckedDisabled"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("unchecked_disabled", "CheckBox", p_theme->get_icon(SNAME("GuiUncheckedDisabled"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("radio_checked_disabled", "CheckBox", p_theme->get_icon(SNAME("GuiRadioCheckedDisabled"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("radio_unchecked_disabled", "CheckBox", p_theme->get_icon(SNAME("GuiRadioUncheckedDisabled"), EditorStringName(EditorIcons)));
+
+ p_theme->set_color("font_color", "CheckBox", p_config.font_color);
+ p_theme->set_color("font_hover_color", "CheckBox", p_config.font_hover_color);
+ p_theme->set_color("font_hover_pressed_color", "CheckBox", p_config.font_hover_pressed_color);
+ p_theme->set_color("font_focus_color", "CheckBox", p_config.font_focus_color);
+ p_theme->set_color("font_pressed_color", "CheckBox", p_config.font_pressed_color);
+ p_theme->set_color("font_disabled_color", "CheckBox", p_config.font_disabled_color);
+ p_theme->set_color("font_outline_color", "CheckBox", p_config.font_outline_color);
+
+ p_theme->set_color("icon_normal_color", "CheckBox", p_config.icon_normal_color);
+ p_theme->set_color("icon_hover_color", "CheckBox", p_config.icon_hover_color);
+ p_theme->set_color("icon_focus_color", "CheckBox", p_config.icon_focus_color);
+ p_theme->set_color("icon_pressed_color", "CheckBox", p_config.icon_pressed_color);
+ p_theme->set_color("icon_disabled_color", "CheckBox", p_config.icon_disabled_color);
+
+ p_theme->set_constant("h_separation", "CheckBox", 8 * EDSCALE);
+ p_theme->set_constant("check_v_offset", "CheckBox", 0);
+ p_theme->set_constant("outline_size", "CheckBox", 0);
+ }
+
+ // LinkButton.
+
+ p_theme->set_stylebox("focus", "LinkButton", p_config.base_empty_style);
+ p_theme->set_color("font_color", "LinkButton", p_config.font_color);
+ p_theme->set_color("font_hover_color", "LinkButton", p_config.font_hover_color);
+ p_theme->set_color("font_hover_pressed_color", "LinkButton", p_config.font_hover_pressed_color);
+ p_theme->set_color("font_focus_color", "LinkButton", p_config.font_focus_color);
+ p_theme->set_color("font_pressed_color", "LinkButton", p_config.font_pressed_color);
+ p_theme->set_color("font_disabled_color", "LinkButton", p_config.font_disabled_color);
+ p_theme->set_color("font_outline_color", "LinkButton", p_config.font_outline_color);
+
+ p_theme->set_constant("outline_size", "LinkButton", 0);
+ }
+
+ // Tree & ItemList.
+ {
+ Ref<StyleBoxFlat> style_tree_focus = p_config.base_style->duplicate();
+ style_tree_focus->set_bg_color(p_config.highlight_color);
+ style_tree_focus->set_border_width_all(0);
+
+ Ref<StyleBoxFlat> style_tree_selected = style_tree_focus->duplicate();
+
+ const Color guide_color = p_config.mono_color * Color(1, 1, 1, 0.05);
+
+ // Tree.
+ {
+ p_theme->set_icon("checked", "Tree", p_theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("checked_disabled", "Tree", p_theme->get_icon(SNAME("GuiCheckedDisabled"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("indeterminate", "Tree", p_theme->get_icon(SNAME("GuiIndeterminate"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("indeterminate_disabled", "Tree", p_theme->get_icon(SNAME("GuiIndeterminateDisabled"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("unchecked", "Tree", p_theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("unchecked_disabled", "Tree", p_theme->get_icon(SNAME("GuiUncheckedDisabled"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("arrow", "Tree", p_theme->get_icon(SNAME("GuiTreeArrowDown"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("arrow_collapsed", "Tree", p_theme->get_icon(SNAME("GuiTreeArrowRight"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("arrow_collapsed_mirrored", "Tree", p_theme->get_icon(SNAME("GuiTreeArrowLeft"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("updown", "Tree", p_theme->get_icon(SNAME("GuiTreeUpdown"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("select_arrow", "Tree", p_theme->get_icon(SNAME("GuiDropdown"), EditorStringName(EditorIcons)));
+
+ p_theme->set_stylebox("panel", "Tree", p_config.tree_panel_style);
+ p_theme->set_stylebox("focus", "Tree", p_config.button_style_focus);
+ p_theme->set_stylebox("custom_button", "Tree", make_empty_stylebox());
+ p_theme->set_stylebox("custom_button_pressed", "Tree", make_empty_stylebox());
+ p_theme->set_stylebox("custom_button_hover", "Tree", p_config.button_style);
+
+ p_theme->set_color("custom_button_font_highlight", "Tree", p_config.font_hover_color);
+ p_theme->set_color("font_color", "Tree", p_config.font_color);
+ p_theme->set_color("font_selected_color", "Tree", p_config.mono_color);
+ p_theme->set_color("font_disabled_color", "Tree", p_config.font_disabled_color);
+ p_theme->set_color("font_outline_color", "Tree", p_config.font_outline_color);
+ p_theme->set_color("title_button_color", "Tree", p_config.font_color);
+ p_theme->set_color("drop_position_color", "Tree", p_config.accent_color);
+
+ p_theme->set_constant("v_separation", "Tree", p_config.separation_margin);
+ p_theme->set_constant("h_separation", "Tree", (p_config.increased_margin + 2) * EDSCALE);
+ p_theme->set_constant("guide_width", "Tree", p_config.border_width);
+ p_theme->set_constant("item_margin", "Tree", 3 * p_config.increased_margin * EDSCALE);
+ p_theme->set_constant("inner_item_margin_top", "Tree", p_config.separation_margin);
+ p_theme->set_constant("inner_item_margin_bottom", "Tree", p_config.separation_margin);
+ p_theme->set_constant("inner_item_margin_left", "Tree", p_config.increased_margin * EDSCALE);
+ p_theme->set_constant("inner_item_margin_right", "Tree", p_config.increased_margin * EDSCALE);
+ p_theme->set_constant("button_margin", "Tree", p_config.base_margin * EDSCALE);
+ p_theme->set_constant("scroll_border", "Tree", 40 * EDSCALE);
+ p_theme->set_constant("scroll_speed", "Tree", 12);
+ p_theme->set_constant("outline_size", "Tree", 0);
+ p_theme->set_constant("scrollbar_margin_left", "Tree", 0);
+ p_theme->set_constant("scrollbar_margin_top", "Tree", 0);
+ p_theme->set_constant("scrollbar_margin_right", "Tree", 0);
+ p_theme->set_constant("scrollbar_margin_bottom", "Tree", 0);
+ p_theme->set_constant("scrollbar_h_separation", "Tree", 1 * EDSCALE);
+ p_theme->set_constant("scrollbar_v_separation", "Tree", 1 * EDSCALE);
+
+ Color relationship_line_color = p_config.mono_color * Color(1, 1, 1, p_config.relationship_line_opacity);
+
+ p_theme->set_constant("draw_guides", "Tree", p_config.relationship_line_opacity < 0.01);
+ p_theme->set_color("guide_color", "Tree", guide_color);
+
+ int relationship_line_width = 1;
+ Color parent_line_color = p_config.mono_color * Color(1, 1, 1, CLAMP(p_config.relationship_line_opacity + 0.45, 0.0, 1.0));
+ Color children_line_color = p_config.mono_color * Color(1, 1, 1, CLAMP(p_config.relationship_line_opacity + 0.25, 0.0, 1.0));
+
+ p_theme->set_constant("draw_relationship_lines", "Tree", p_config.relationship_line_opacity >= 0.01);
+ p_theme->set_constant("relationship_line_width", "Tree", relationship_line_width);
+ p_theme->set_constant("parent_hl_line_width", "Tree", relationship_line_width * 2);
+ p_theme->set_constant("children_hl_line_width", "Tree", relationship_line_width);
+ p_theme->set_constant("parent_hl_line_margin", "Tree", relationship_line_width * 3);
+ p_theme->set_color("relationship_line_color", "Tree", relationship_line_color);
+ p_theme->set_color("parent_hl_line_color", "Tree", parent_line_color);
+ p_theme->set_color("children_hl_line_color", "Tree", children_line_color);
+ p_theme->set_color("drop_position_color", "Tree", p_config.accent_color);
+
+ Ref<StyleBoxFlat> style_tree_btn = p_config.base_style->duplicate();
+ style_tree_btn->set_bg_color(p_config.highlight_color);
+ style_tree_btn->set_border_width_all(0);
+ p_theme->set_stylebox("button_pressed", "Tree", style_tree_btn);
+
+ Ref<StyleBoxFlat> style_tree_hover = p_config.base_style->duplicate();
+ style_tree_hover->set_bg_color(p_config.highlight_color * Color(1, 1, 1, 0.4));
+ style_tree_hover->set_border_width_all(0);
+ p_theme->set_stylebox("hover", "Tree", style_tree_hover);
+
+ p_theme->set_stylebox("selected_focus", "Tree", style_tree_focus);
+ p_theme->set_stylebox("selected", "Tree", style_tree_selected);
+
+ Ref<StyleBoxFlat> style_tree_cursor = p_config.base_style->duplicate();
+ style_tree_cursor->set_draw_center(false);
+ style_tree_cursor->set_border_width_all(MAX(1, p_config.border_width));
+ style_tree_cursor->set_border_color(p_config.contrast_color_1);
+
+ Ref<StyleBoxFlat> style_tree_title = p_config.base_style->duplicate();
+ style_tree_title->set_bg_color(p_config.dark_color_3);
+ style_tree_title->set_border_width_all(0);
+ p_theme->set_stylebox("cursor", "Tree", style_tree_cursor);
+ p_theme->set_stylebox("cursor_unfocused", "Tree", style_tree_cursor);
+ p_theme->set_stylebox("title_button_normal", "Tree", style_tree_title);
+ p_theme->set_stylebox("title_button_hover", "Tree", style_tree_title);
+ p_theme->set_stylebox("title_button_pressed", "Tree", style_tree_title);
+ }
+
+ // ItemList.
+ {
+ Ref<StyleBoxFlat> style_itemlist_bg = p_config.base_style->duplicate();
+ style_itemlist_bg->set_content_margin_all(p_config.separation_margin);
+ style_itemlist_bg->set_bg_color(p_config.dark_color_1);
+
+ if (p_config.draw_extra_borders) {
+ style_itemlist_bg->set_border_width_all(Math::round(EDSCALE));
+ style_itemlist_bg->set_border_color(p_config.extra_border_color_2);
+ } else {
+ style_itemlist_bg->set_border_width_all(p_config.border_width);
+ style_itemlist_bg->set_border_color(p_config.dark_color_3);
+ }
+
+ Ref<StyleBoxFlat> style_itemlist_cursor = p_config.base_style->duplicate();
+ style_itemlist_cursor->set_draw_center(false);
+ style_itemlist_cursor->set_border_width_all(p_config.border_width);
+ style_itemlist_cursor->set_border_color(p_config.highlight_color);
+
+ Ref<StyleBoxFlat> style_itemlist_hover = style_tree_selected->duplicate();
+ style_itemlist_hover->set_bg_color(p_config.highlight_color * Color(1, 1, 1, 0.3));
+ style_itemlist_hover->set_border_width_all(0);
+
+ p_theme->set_stylebox("panel", "ItemList", style_itemlist_bg);
+ p_theme->set_stylebox("focus", "ItemList", p_config.button_style_focus);
+ p_theme->set_stylebox("cursor", "ItemList", style_itemlist_cursor);
+ p_theme->set_stylebox("cursor_unfocused", "ItemList", style_itemlist_cursor);
+ p_theme->set_stylebox("selected_focus", "ItemList", style_tree_focus);
+ p_theme->set_stylebox("selected", "ItemList", style_tree_selected);
+ p_theme->set_stylebox("hovered", "ItemList", style_itemlist_hover);
+ p_theme->set_color("font_color", "ItemList", p_config.font_color);
+ p_theme->set_color("font_hovered_color", "ItemList", p_config.mono_color);
+ p_theme->set_color("font_selected_color", "ItemList", p_config.mono_color);
+ p_theme->set_color("font_outline_color", "ItemList", p_config.font_outline_color);
+ p_theme->set_color("guide_color", "ItemList", guide_color);
+ p_theme->set_constant("v_separation", "ItemList", p_config.forced_even_separation * 0.5 * EDSCALE);
+ p_theme->set_constant("h_separation", "ItemList", (p_config.increased_margin + 2) * EDSCALE);
+ p_theme->set_constant("icon_margin", "ItemList", (p_config.increased_margin + 2) * EDSCALE);
+ p_theme->set_constant("line_separation", "ItemList", p_config.separation_margin);
+ p_theme->set_constant("outline_size", "ItemList", 0);
+ }
+ }
+
+ // TabBar & TabContainer.
+ {
+ Ref<StyleBoxFlat> style_tab_base = p_config.button_style->duplicate();
+
+ style_tab_base->set_border_width_all(0);
+ // Don't round the top corners to avoid creating a small blank space between the tabs and the main panel.
+ // This also makes the top highlight look better.
+ style_tab_base->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
+ style_tab_base->set_corner_radius(CORNER_BOTTOM_RIGHT, 0);
+
+ // When using a border width greater than 0, visually line up the left of the selected tab with the underlying panel.
+ style_tab_base->set_expand_margin(SIDE_LEFT, -p_config.border_width);
+
+ style_tab_base->set_content_margin(SIDE_LEFT, p_config.widget_margin.x + 5 * EDSCALE);
+ style_tab_base->set_content_margin(SIDE_RIGHT, p_config.widget_margin.x + 5 * EDSCALE);
+ style_tab_base->set_content_margin(SIDE_BOTTOM, p_config.widget_margin.y);
+ style_tab_base->set_content_margin(SIDE_TOP, p_config.widget_margin.y);
+
+ Ref<StyleBoxFlat> style_tab_selected = style_tab_base->duplicate();
+
+ style_tab_selected->set_bg_color(p_config.base_color);
+ // Add a highlight line at the top of the selected tab.
+ style_tab_selected->set_border_width(SIDE_TOP, Math::round(2 * EDSCALE));
+ // Make the highlight line prominent, but not too prominent as to not be distracting.
+ Color tab_highlight = p_config.dark_color_2.lerp(p_config.accent_color, 0.75);
+ style_tab_selected->set_border_color(tab_highlight);
+ style_tab_selected->set_corner_radius_all(0);
+
+ Ref<StyleBoxFlat> style_tab_hovered = style_tab_base->duplicate();
+
+ style_tab_hovered->set_bg_color(p_config.dark_color_1.lerp(p_config.base_color, 0.4));
+ // Hovered tab has a subtle highlight between normal and selected states.
+ style_tab_hovered->set_corner_radius_all(0);
+
+ Ref<StyleBoxFlat> style_tab_unselected = style_tab_base->duplicate();
+ style_tab_unselected->set_expand_margin(SIDE_BOTTOM, 0);
+ style_tab_unselected->set_bg_color(p_config.dark_color_1);
+ // Add some spacing between unselected tabs to make them easier to distinguish from each other
+ style_tab_unselected->set_border_color(Color(0, 0, 0, 0));
+
+ Ref<StyleBoxFlat> style_tab_disabled = style_tab_base->duplicate();
+ style_tab_disabled->set_expand_margin(SIDE_BOTTOM, 0);
+ style_tab_disabled->set_bg_color(p_config.disabled_bg_color);
+ style_tab_disabled->set_border_color(p_config.disabled_bg_color);
+
+ Ref<StyleBoxFlat> style_tab_focus = p_config.button_style_focus->duplicate();
+
+ Ref<StyleBoxFlat> style_tabbar_background = make_flat_stylebox(p_config.dark_color_1, 0, 0, 0, 0, p_config.corner_radius * EDSCALE);
+ style_tabbar_background->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
+ style_tabbar_background->set_corner_radius(CORNER_BOTTOM_RIGHT, 0);
+ p_theme->set_stylebox("tabbar_background", "TabContainer", style_tabbar_background);
+ p_theme->set_stylebox("panel", "TabContainer", p_config.content_panel_style);
+
+ p_theme->set_stylebox("tab_selected", "TabContainer", style_tab_selected);
+ p_theme->set_stylebox("tab_hovered", "TabContainer", style_tab_hovered);
+ p_theme->set_stylebox("tab_unselected", "TabContainer", style_tab_unselected);
+ p_theme->set_stylebox("tab_disabled", "TabContainer", style_tab_disabled);
+ p_theme->set_stylebox("tab_focus", "TabContainer", style_tab_focus);
+ p_theme->set_stylebox("tab_selected", "TabBar", style_tab_selected);
+ p_theme->set_stylebox("tab_hovered", "TabBar", style_tab_hovered);
+ p_theme->set_stylebox("tab_unselected", "TabBar", style_tab_unselected);
+ p_theme->set_stylebox("tab_disabled", "TabBar", style_tab_disabled);
+ p_theme->set_stylebox("tab_focus", "TabBar", style_tab_focus);
+ p_theme->set_stylebox("button_pressed", "TabBar", p_config.panel_container_style);
+ p_theme->set_stylebox("button_highlight", "TabBar", p_config.panel_container_style);
+
+ p_theme->set_color("font_selected_color", "TabContainer", p_config.font_color);
+ p_theme->set_color("font_hovered_color", "TabContainer", p_config.font_color);
+ p_theme->set_color("font_unselected_color", "TabContainer", p_config.font_disabled_color);
+ p_theme->set_color("font_outline_color", "TabContainer", p_config.font_outline_color);
+ p_theme->set_color("font_selected_color", "TabBar", p_config.font_color);
+ p_theme->set_color("font_hovered_color", "TabBar", p_config.font_color);
+ p_theme->set_color("font_unselected_color", "TabBar", p_config.font_disabled_color);
+ p_theme->set_color("font_outline_color", "TabBar", p_config.font_outline_color);
+ p_theme->set_color("drop_mark_color", "TabContainer", tab_highlight);
+ p_theme->set_color("drop_mark_color", "TabBar", tab_highlight);
+
+ p_theme->set_icon("menu", "TabContainer", p_theme->get_icon(SNAME("GuiTabMenu"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("menu_highlight", "TabContainer", p_theme->get_icon(SNAME("GuiTabMenuHl"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("close", "TabBar", p_theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("increment", "TabContainer", p_theme->get_icon(SNAME("GuiScrollArrowRight"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("decrement", "TabContainer", p_theme->get_icon(SNAME("GuiScrollArrowLeft"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("increment", "TabBar", p_theme->get_icon(SNAME("GuiScrollArrowRight"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("decrement", "TabBar", p_theme->get_icon(SNAME("GuiScrollArrowLeft"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("increment_highlight", "TabBar", p_theme->get_icon(SNAME("GuiScrollArrowRightHl"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("decrement_highlight", "TabBar", p_theme->get_icon(SNAME("GuiScrollArrowLeftHl"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("increment_highlight", "TabContainer", p_theme->get_icon(SNAME("GuiScrollArrowRightHl"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("decrement_highlight", "TabContainer", p_theme->get_icon(SNAME("GuiScrollArrowLeftHl"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("drop_mark", "TabContainer", p_theme->get_icon(SNAME("GuiTabDropMark"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("drop_mark", "TabBar", p_theme->get_icon(SNAME("GuiTabDropMark"), EditorStringName(EditorIcons)));
+
+ p_theme->set_constant("side_margin", "TabContainer", 0);
+ p_theme->set_constant("outline_size", "TabContainer", 0);
+ p_theme->set_constant("h_separation", "TabBar", 4 * EDSCALE);
+ p_theme->set_constant("outline_size", "TabBar", 0);
+ }
+
+ // Separators.
+ p_theme->set_stylebox("separator", "HSeparator", make_line_stylebox(p_config.separator_color, MAX(Math::round(EDSCALE), p_config.border_width)));
+ p_theme->set_stylebox("separator", "VSeparator", make_line_stylebox(p_config.separator_color, MAX(Math::round(EDSCALE), p_config.border_width), 0, 0, true));
+
+ // LineEdit & TextEdit.
+ {
+ Ref<StyleBoxFlat> text_editor_style = p_config.button_style->duplicate();
+ // The original button_style style has an extra 1 pixel offset that makes LineEdits not align with Buttons,
+ // so this compensates for that.
+ text_editor_style->set_content_margin(SIDE_TOP, text_editor_style->get_content_margin(SIDE_TOP) - 1 * EDSCALE);
+
+ // Don't round the bottom corners to make the line look sharper.
+ text_editor_style->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
+ text_editor_style->set_corner_radius(CORNER_BOTTOM_RIGHT, 0);
+
+ if (p_config.draw_extra_borders) {
+ text_editor_style->set_border_width_all(Math::round(EDSCALE));
+ text_editor_style->set_border_color(p_config.extra_border_color_1);
+ } else {
+ // Add a bottom line to make LineEdits more visible, especially in sectioned inspectors
+ // such as the Project Settings.
+ text_editor_style->set_border_width(SIDE_BOTTOM, Math::round(2 * EDSCALE));
+ text_editor_style->set_border_color(p_config.dark_color_2);
+ }
+
+ Ref<StyleBoxFlat> text_editor_disabled_style = text_editor_style->duplicate();
+ text_editor_disabled_style->set_border_color(p_config.disabled_border_color);
+ text_editor_disabled_style->set_bg_color(p_config.disabled_bg_color);
+
+ // LineEdit.
+
+ p_theme->set_stylebox("normal", "LineEdit", text_editor_style);
+ p_theme->set_stylebox("focus", "LineEdit", p_config.button_style_focus);
+ p_theme->set_stylebox("read_only", "LineEdit", text_editor_disabled_style);
+
+ p_theme->set_icon("clear", "LineEdit", p_theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons)));
+
+ p_theme->set_color("font_color", "LineEdit", p_config.font_color);
+ p_theme->set_color("font_selected_color", "LineEdit", p_config.mono_color);
+ p_theme->set_color("font_uneditable_color", "LineEdit", p_config.font_readonly_color);
+ p_theme->set_color("font_placeholder_color", "LineEdit", p_config.font_placeholder_color);
+ p_theme->set_color("font_outline_color", "LineEdit", p_config.font_outline_color);
+ p_theme->set_color("caret_color", "LineEdit", p_config.font_color);
+ p_theme->set_color("selection_color", "LineEdit", p_config.selection_color);
+ p_theme->set_color("clear_button_color", "LineEdit", p_config.font_color);
+ p_theme->set_color("clear_button_color_pressed", "LineEdit", p_config.accent_color);
+
+ p_theme->set_constant("minimum_character_width", "LineEdit", 4);
+ p_theme->set_constant("outline_size", "LineEdit", 0);
+ p_theme->set_constant("caret_width", "LineEdit", 1);
+
+ // TextEdit.
+
+ p_theme->set_stylebox("normal", "TextEdit", text_editor_style);
+ p_theme->set_stylebox("focus", "TextEdit", p_config.button_style_focus);
+ p_theme->set_stylebox("read_only", "TextEdit", text_editor_disabled_style);
+
+ p_theme->set_icon("tab", "TextEdit", p_theme->get_icon(SNAME("GuiTab"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("space", "TextEdit", p_theme->get_icon(SNAME("GuiSpace"), EditorStringName(EditorIcons)));
+
+ p_theme->set_color("font_color", "TextEdit", p_config.font_color);
+ p_theme->set_color("font_readonly_color", "TextEdit", p_config.font_readonly_color);
+ p_theme->set_color("font_placeholder_color", "TextEdit", p_config.font_placeholder_color);
+ p_theme->set_color("font_outline_color", "TextEdit", p_config.font_outline_color);
+ p_theme->set_color("caret_color", "TextEdit", p_config.font_color);
+ p_theme->set_color("selection_color", "TextEdit", p_config.selection_color);
+ p_theme->set_color("background_color", "TextEdit", Color(0, 0, 0, 0));
+
+ p_theme->set_constant("line_spacing", "TextEdit", 4 * EDSCALE);
+ p_theme->set_constant("outline_size", "TextEdit", 0);
+ p_theme->set_constant("caret_width", "TextEdit", 1);
+ }
+
+ // Containers.
+ {
+ p_theme->set_constant("separation", "BoxContainer", p_config.separation_margin);
+ p_theme->set_constant("separation", "HBoxContainer", p_config.separation_margin);
+ p_theme->set_constant("separation", "VBoxContainer", p_config.separation_margin);
+ p_theme->set_constant("margin_left", "MarginContainer", 0);
+ p_theme->set_constant("margin_top", "MarginContainer", 0);
+ p_theme->set_constant("margin_right", "MarginContainer", 0);
+ p_theme->set_constant("margin_bottom", "MarginContainer", 0);
+ p_theme->set_constant("h_separation", "GridContainer", p_config.separation_margin);
+ p_theme->set_constant("v_separation", "GridContainer", p_config.separation_margin);
+ p_theme->set_constant("h_separation", "FlowContainer", p_config.separation_margin);
+ p_theme->set_constant("v_separation", "FlowContainer", p_config.separation_margin);
+ p_theme->set_constant("h_separation", "HFlowContainer", p_config.separation_margin);
+ p_theme->set_constant("v_separation", "HFlowContainer", p_config.separation_margin);
+ p_theme->set_constant("h_separation", "VFlowContainer", p_config.separation_margin);
+ p_theme->set_constant("v_separation", "VFlowContainer", p_config.separation_margin);
+
+ // SplitContainer.
+
+ p_theme->set_icon("h_grabber", "SplitContainer", p_theme->get_icon(SNAME("GuiHsplitter"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("v_grabber", "SplitContainer", p_theme->get_icon(SNAME("GuiVsplitter"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("grabber", "VSplitContainer", p_theme->get_icon(SNAME("GuiVsplitter"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("grabber", "HSplitContainer", p_theme->get_icon(SNAME("GuiHsplitter"), EditorStringName(EditorIcons)));
+
+ p_theme->set_constant("separation", "SplitContainer", p_config.separation_margin);
+ p_theme->set_constant("separation", "HSplitContainer", p_config.separation_margin);
+ p_theme->set_constant("separation", "VSplitContainer", p_config.separation_margin);
+
+ p_theme->set_constant("minimum_grab_thickness", "SplitContainer", p_config.increased_margin * EDSCALE);
+ p_theme->set_constant("minimum_grab_thickness", "HSplitContainer", p_config.increased_margin * EDSCALE);
+ p_theme->set_constant("minimum_grab_thickness", "VSplitContainer", p_config.increased_margin * EDSCALE);
+
+ // GridContainer.
+ p_theme->set_constant("v_separation", "GridContainer", Math::round(p_config.widget_margin.y - 2 * EDSCALE));
+ }
+
+ // Window and dialogs.
+ {
+ // Window.
+
+ p_theme->set_stylebox("embedded_border", "Window", p_config.window_style);
+ p_theme->set_stylebox("embedded_unfocused_border", "Window", p_config.window_style);
+
+ p_theme->set_color("title_color", "Window", p_config.font_color);
+ p_theme->set_icon("close", "Window", p_theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("close_pressed", "Window", p_theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons)));
+ p_theme->set_constant("close_h_offset", "Window", 22 * EDSCALE);
+ p_theme->set_constant("close_v_offset", "Window", 20 * EDSCALE);
+ p_theme->set_constant("title_height", "Window", 24 * EDSCALE);
+ p_theme->set_constant("resize_margin", "Window", 4 * EDSCALE);
+ p_theme->set_font("title_font", "Window", p_theme->get_font(SNAME("title"), EditorStringName(EditorFonts)));
+ p_theme->set_font_size("title_font_size", "Window", p_theme->get_font_size(SNAME("title_size"), EditorStringName(EditorFonts)));
+
+ // AcceptDialog.
+ p_theme->set_stylebox("panel", "AcceptDialog", p_config.dialog_style);
+ p_theme->set_constant("buttons_separation", "AcceptDialog", 8 * EDSCALE);
+
+ // FileDialog.
+ p_theme->set_icon("folder", "FileDialog", p_theme->get_icon(SNAME("Folder"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("parent_folder", "FileDialog", p_theme->get_icon(SNAME("ArrowUp"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("back_folder", "FileDialog", p_theme->get_icon(SNAME("Back"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("forward_folder", "FileDialog", p_theme->get_icon(SNAME("Forward"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("reload", "FileDialog", p_theme->get_icon(SNAME("Reload"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("toggle_hidden", "FileDialog", p_theme->get_icon(SNAME("GuiVisibilityVisible"), EditorStringName(EditorIcons)));
+ // Use a different color for folder icons to make them easier to distinguish from files.
+ // On a light theme, the icon will be dark, so we need to lighten it before blending it with the accent color.
+ p_theme->set_color("folder_icon_color", "FileDialog", (p_config.dark_theme ? Color(1, 1, 1) : Color(4.25, 4.25, 4.25)).lerp(p_config.accent_color, 0.7));
+ p_theme->set_color("files_disabled", "FileDialog", p_config.font_disabled_color);
+
+ // PopupDialog.
+ p_theme->set_stylebox("panel", "PopupDialog", p_config.popup_style);
+
+ // PopupMenu.
+ {
+ Ref<StyleBoxFlat> style_popup_menu = p_config.popup_style->duplicate();
+ // Use 1 pixel for the sides, since if 0 is used, the highlight of hovered items is drawn
+ // on top of the popup border. This causes a 'gap' in the panel border when an item is highlighted,
+ // and it looks weird. 1px solves this.
+ style_popup_menu->set_content_margin_individual(EDSCALE, 2 * EDSCALE, EDSCALE, 2 * EDSCALE);
+ // Always display a border for PopupMenus so they can be distinguished from their background.
+ style_popup_menu->set_border_width_all(EDSCALE);
+ if (p_config.draw_extra_borders) {
+ style_popup_menu->set_border_color(p_config.extra_border_color_2);
+ } else {
+ style_popup_menu->set_border_color(p_config.dark_color_2);
+ }
+ p_theme->set_stylebox("panel", "PopupMenu", style_popup_menu);
+
+ Ref<StyleBoxFlat> style_menu_hover = p_config.button_style_hover->duplicate();
+ // Don't use rounded corners for hover highlights since the StyleBox touches the PopupMenu's edges.
+ style_menu_hover->set_corner_radius_all(0);
+ p_theme->set_stylebox("hover", "PopupMenu", style_menu_hover);
+
+ Ref<StyleBoxLine> style_popup_separator(memnew(StyleBoxLine));
+ style_popup_separator->set_color(p_config.separator_color);
+ style_popup_separator->set_grow_begin(p_config.popup_margin - MAX(Math::round(EDSCALE), p_config.border_width));
+ style_popup_separator->set_grow_end(p_config.popup_margin - MAX(Math::round(EDSCALE), p_config.border_width));
+ style_popup_separator->set_thickness(MAX(Math::round(EDSCALE), p_config.border_width));
+
+ Ref<StyleBoxLine> style_popup_labeled_separator_left(memnew(StyleBoxLine));
+ style_popup_labeled_separator_left->set_grow_begin(p_config.popup_margin - MAX(Math::round(EDSCALE), p_config.border_width));
+ style_popup_labeled_separator_left->set_color(p_config.separator_color);
+ style_popup_labeled_separator_left->set_thickness(MAX(Math::round(EDSCALE), p_config.border_width));
+
+ Ref<StyleBoxLine> style_popup_labeled_separator_right(memnew(StyleBoxLine));
+ style_popup_labeled_separator_right->set_grow_end(p_config.popup_margin - MAX(Math::round(EDSCALE), p_config.border_width));
+ style_popup_labeled_separator_right->set_color(p_config.separator_color);
+ style_popup_labeled_separator_right->set_thickness(MAX(Math::round(EDSCALE), p_config.border_width));
+
+ p_theme->set_stylebox("separator", "PopupMenu", style_popup_separator);
+ p_theme->set_stylebox("labeled_separator_left", "PopupMenu", style_popup_labeled_separator_left);
+ p_theme->set_stylebox("labeled_separator_right", "PopupMenu", style_popup_labeled_separator_right);
+
+ p_theme->set_color("font_color", "PopupMenu", p_config.font_color);
+ p_theme->set_color("font_hover_color", "PopupMenu", p_config.font_hover_color);
+ p_theme->set_color("font_accelerator_color", "PopupMenu", p_config.font_disabled_color);
+ p_theme->set_color("font_disabled_color", "PopupMenu", p_config.font_disabled_color);
+ p_theme->set_color("font_separator_color", "PopupMenu", p_config.font_disabled_color);
+ p_theme->set_color("font_outline_color", "PopupMenu", p_config.font_outline_color);
+
+ p_theme->set_icon("checked", "PopupMenu", p_theme->get_icon(SNAME("GuiChecked"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("unchecked", "PopupMenu", p_theme->get_icon(SNAME("GuiUnchecked"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("radio_checked", "PopupMenu", p_theme->get_icon(SNAME("GuiRadioChecked"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("radio_unchecked", "PopupMenu", p_theme->get_icon(SNAME("GuiRadioUnchecked"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("checked_disabled", "PopupMenu", p_theme->get_icon(SNAME("GuiCheckedDisabled"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("unchecked_disabled", "PopupMenu", p_theme->get_icon(SNAME("GuiUncheckedDisabled"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("radio_checked_disabled", "PopupMenu", p_theme->get_icon(SNAME("GuiRadioCheckedDisabled"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("radio_unchecked_disabled", "PopupMenu", p_theme->get_icon(SNAME("GuiRadioUncheckedDisabled"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("submenu", "PopupMenu", p_theme->get_icon(SNAME("ArrowRight"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("submenu_mirrored", "PopupMenu", p_theme->get_icon(SNAME("ArrowLeft"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("visibility_hidden", "PopupMenu", p_theme->get_icon(SNAME("GuiVisibilityHidden"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("visibility_visible", "PopupMenu", p_theme->get_icon(SNAME("GuiVisibilityVisible"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("visibility_xray", "PopupMenu", p_theme->get_icon(SNAME("GuiVisibilityXray"), EditorStringName(EditorIcons)));
+
+ p_theme->set_constant("v_separation", "PopupMenu", p_config.forced_even_separation * EDSCALE);
+ p_theme->set_constant("outline_size", "PopupMenu", 0);
+ p_theme->set_constant("item_start_padding", "PopupMenu", p_config.separation_margin);
+ p_theme->set_constant("item_end_padding", "PopupMenu", p_config.separation_margin);
+ }
+ }
+
+ // Sliders and scrollbars.
+ {
+ Ref<Texture2D> empty_icon = memnew(ImageTexture);
+
+ // HScrollBar.
+
+ if (p_config.increase_scrollbar_touch_area) {
+ p_theme->set_stylebox("scroll", "HScrollBar", make_line_stylebox(p_config.separator_color, 50));
+ } else {
+ p_theme->set_stylebox("scroll", "HScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, -5, 1, -5, 1));
+ }
+ p_theme->set_stylebox("scroll_focus", "HScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1));
+ p_theme->set_stylebox("grabber", "HScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollGrabber"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1));
+ p_theme->set_stylebox("grabber_highlight", "HScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollGrabberHl"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1));
+ p_theme->set_stylebox("grabber_pressed", "HScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollGrabberPressed"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1));
+
+ p_theme->set_icon("increment", "HScrollBar", empty_icon);
+ p_theme->set_icon("increment_highlight", "HScrollBar", empty_icon);
+ p_theme->set_icon("increment_pressed", "HScrollBar", empty_icon);
+ p_theme->set_icon("decrement", "HScrollBar", empty_icon);
+ p_theme->set_icon("decrement_highlight", "HScrollBar", empty_icon);
+ p_theme->set_icon("decrement_pressed", "HScrollBar", empty_icon);
+
+ // VScrollBar.
+
+ if (p_config.increase_scrollbar_touch_area) {
+ p_theme->set_stylebox("scroll", "VScrollBar", make_line_stylebox(p_config.separator_color, 50, 1, 1, true));
+ } else {
+ p_theme->set_stylebox("scroll", "VScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, -5, 1, -5));
+ }
+ p_theme->set_stylebox("scroll_focus", "VScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollBg"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1));
+ p_theme->set_stylebox("grabber", "VScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollGrabber"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1));
+ p_theme->set_stylebox("grabber_highlight", "VScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollGrabberHl"), EditorStringName(EditorIcons)), 5, 5, 5, 5, 1, 1, 1, 1));
+ p_theme->set_stylebox("grabber_pressed", "VScrollBar", make_stylebox(p_theme->get_icon(SNAME("GuiScrollGrabberPressed"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 1, 1, 1, 1));
+
+ p_theme->set_icon("increment", "VScrollBar", empty_icon);
+ p_theme->set_icon("increment_highlight", "VScrollBar", empty_icon);
+ p_theme->set_icon("increment_pressed", "VScrollBar", empty_icon);
+ p_theme->set_icon("decrement", "VScrollBar", empty_icon);
+ p_theme->set_icon("decrement_highlight", "VScrollBar", empty_icon);
+ p_theme->set_icon("decrement_pressed", "VScrollBar", empty_icon);
+
+ // HSlider.
+ p_theme->set_icon("grabber_highlight", "HSlider", p_theme->get_icon(SNAME("GuiSliderGrabberHl"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("grabber", "HSlider", p_theme->get_icon(SNAME("GuiSliderGrabber"), EditorStringName(EditorIcons)));
+ p_theme->set_stylebox("slider", "HSlider", make_flat_stylebox(p_config.dark_color_3, 0, p_config.base_margin / 2, 0, p_config.base_margin / 2, p_config.corner_radius));
+ p_theme->set_stylebox("grabber_area", "HSlider", make_flat_stylebox(p_config.contrast_color_1, 0, p_config.base_margin / 2, 0, p_config.base_margin / 2, p_config.corner_radius));
+ p_theme->set_stylebox("grabber_area_highlight", "HSlider", make_flat_stylebox(p_config.contrast_color_1, 0, p_config.base_margin / 2, 0, p_config.base_margin / 2));
+ p_theme->set_constant("center_grabber", "HSlider", 0);
+ p_theme->set_constant("grabber_offset", "HSlider", 0);
+
+ // VSlider.
+ p_theme->set_icon("grabber", "VSlider", p_theme->get_icon(SNAME("GuiSliderGrabber"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("grabber_highlight", "VSlider", p_theme->get_icon(SNAME("GuiSliderGrabberHl"), EditorStringName(EditorIcons)));
+ p_theme->set_stylebox("slider", "VSlider", make_flat_stylebox(p_config.dark_color_3, p_config.base_margin / 2, 0, p_config.base_margin / 2, 0, p_config.corner_radius));
+ p_theme->set_stylebox("grabber_area", "VSlider", make_flat_stylebox(p_config.contrast_color_1, p_config.base_margin / 2, 0, p_config.base_margin / 2, 0, p_config.corner_radius));
+ p_theme->set_stylebox("grabber_area_highlight", "VSlider", make_flat_stylebox(p_config.contrast_color_1, p_config.base_margin / 2, 0, p_config.base_margin / 2, 0));
+ p_theme->set_constant("center_grabber", "VSlider", 0);
+ p_theme->set_constant("grabber_offset", "VSlider", 0);
+ }
+
+ // Labels.
+ {
+ // RichTextLabel.
+
+ p_theme->set_stylebox("normal", "RichTextLabel", p_config.tree_panel_style);
+ p_theme->set_stylebox("focus", "RichTextLabel", make_empty_stylebox());
+
+ p_theme->set_color("default_color", "RichTextLabel", p_config.font_color);
+ p_theme->set_color("font_shadow_color", "RichTextLabel", Color(0, 0, 0, 0));
+ p_theme->set_color("font_outline_color", "RichTextLabel", p_config.font_outline_color);
+ p_theme->set_color("selection_color", "RichTextLabel", p_config.selection_color);
+
+ p_theme->set_constant("shadow_offset_x", "RichTextLabel", 1 * EDSCALE);
+ p_theme->set_constant("shadow_offset_y", "RichTextLabel", 1 * EDSCALE);
+ p_theme->set_constant("shadow_outline_size", "RichTextLabel", 1 * EDSCALE);
+ p_theme->set_constant("outline_size", "RichTextLabel", 0);
+
+ // Label.
+
+ p_theme->set_stylebox("normal", "Label", p_config.base_empty_style);
+
+ p_theme->set_color("font_color", "Label", p_config.font_color);
+ p_theme->set_color("font_shadow_color", "Label", Color(0, 0, 0, 0));
+ p_theme->set_color("font_outline_color", "Label", p_config.font_outline_color);
+
+ p_theme->set_constant("shadow_offset_x", "Label", 1 * EDSCALE);
+ p_theme->set_constant("shadow_offset_y", "Label", 1 * EDSCALE);
+ p_theme->set_constant("shadow_outline_size", "Label", 1 * EDSCALE);
+ p_theme->set_constant("line_spacing", "Label", 3 * EDSCALE);
+ p_theme->set_constant("outline_size", "Label", 0);
+ }
+
+ // SpinBox.
+ p_theme->set_icon("updown", "SpinBox", p_theme->get_icon(SNAME("GuiSpinboxUpdown"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("updown_disabled", "SpinBox", p_theme->get_icon(SNAME("GuiSpinboxUpdownDisabled"), EditorStringName(EditorIcons)));
+
+ // ProgressBar.
+ p_theme->set_stylebox("background", "ProgressBar", make_stylebox(p_theme->get_icon(SNAME("GuiProgressBar"), EditorStringName(EditorIcons)), 4, 4, 4, 4, 0, 0, 0, 0));
+ p_theme->set_stylebox("fill", "ProgressBar", make_stylebox(p_theme->get_icon(SNAME("GuiProgressFill"), EditorStringName(EditorIcons)), 6, 6, 6, 6, 2, 1, 2, 1));
+ p_theme->set_color("font_color", "ProgressBar", p_config.font_color);
+ p_theme->set_color("font_outline_color", "ProgressBar", p_config.font_outline_color);
+ p_theme->set_constant("outline_size", "ProgressBar", 0);
+
+ // GraphEdit and related nodes.
+ {
+ // GraphEdit.
+
+ p_theme->set_stylebox("panel", "GraphEdit", p_config.tree_panel_style);
+ p_theme->set_stylebox("menu_panel", "GraphEdit", make_flat_stylebox(p_config.dark_color_1 * Color(1, 1, 1, 0.6), 4, 2, 4, 2, 3));
+
+ if (p_config.dark_theme) {
+ p_theme->set_color("grid_major", "GraphEdit", Color(1.0, 1.0, 1.0, 0.1));
+ p_theme->set_color("grid_minor", "GraphEdit", Color(1.0, 1.0, 1.0, 0.05));
+ } else {
+ p_theme->set_color("grid_major", "GraphEdit", Color(0.0, 0.0, 0.0, 0.15));
+ p_theme->set_color("grid_minor", "GraphEdit", Color(0.0, 0.0, 0.0, 0.07));
+ }
+ p_theme->set_color("selection_fill", "GraphEdit", p_theme->get_color(SNAME("box_selection_fill_color"), EditorStringName(Editor)));
+ p_theme->set_color("selection_stroke", "GraphEdit", p_theme->get_color(SNAME("box_selection_stroke_color"), EditorStringName(Editor)));
+ p_theme->set_color("activity", "GraphEdit", p_config.accent_color);
+
+ p_theme->set_icon("zoom_out", "GraphEdit", p_theme->get_icon(SNAME("ZoomLess"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("zoom_in", "GraphEdit", p_theme->get_icon(SNAME("ZoomMore"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("zoom_reset", "GraphEdit", p_theme->get_icon(SNAME("ZoomReset"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("grid_toggle", "GraphEdit", p_theme->get_icon(SNAME("GridToggle"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("minimap_toggle", "GraphEdit", p_theme->get_icon(SNAME("GridMinimap"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("snapping_toggle", "GraphEdit", p_theme->get_icon(SNAME("SnapGrid"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("layout", "GraphEdit", p_theme->get_icon(SNAME("GridLayout"), EditorStringName(EditorIcons)));
+
+ // GraphEditMinimap.
+ {
+ Ref<StyleBoxFlat> style_minimap_bg = make_flat_stylebox(p_config.dark_color_1, 0, 0, 0, 0);
+ style_minimap_bg->set_border_color(p_config.dark_color_3);
+ style_minimap_bg->set_border_width_all(1);
+ p_theme->set_stylebox("panel", "GraphEditMinimap", style_minimap_bg);
+
+ Ref<StyleBoxFlat> style_minimap_camera;
+ Ref<StyleBoxFlat> style_minimap_node;
+ if (p_config.dark_theme) {
+ style_minimap_camera = make_flat_stylebox(Color(0.65, 0.65, 0.65, 0.2), 0, 0, 0, 0);
+ style_minimap_camera->set_border_color(Color(0.65, 0.65, 0.65, 0.45));
+ style_minimap_node = make_flat_stylebox(Color(1, 1, 1), 0, 0, 0, 0);
+ } else {
+ style_minimap_camera = make_flat_stylebox(Color(0.38, 0.38, 0.38, 0.2), 0, 0, 0, 0);
+ style_minimap_camera->set_border_color(Color(0.38, 0.38, 0.38, 0.45));
+ style_minimap_node = make_flat_stylebox(Color(0, 0, 0), 0, 0, 0, 0);
+ }
+ style_minimap_camera->set_border_width_all(1);
+ style_minimap_node->set_anti_aliased(false);
+ p_theme->set_stylebox("camera", "GraphEditMinimap", style_minimap_camera);
+ p_theme->set_stylebox("node", "GraphEditMinimap", style_minimap_node);
+
+ const Color minimap_resizer_color = p_config.dark_theme ? Color(1, 1, 1, 0.65) : Color(0, 0, 0, 0.65);
+ p_theme->set_icon("resizer", "GraphEditMinimap", p_theme->get_icon(SNAME("GuiResizerTopLeft"), EditorStringName(EditorIcons)));
+ p_theme->set_color("resizer_color", "GraphEditMinimap", minimap_resizer_color);
+ }
+
+ // GraphElement & GraphNode.
+ {
+ const int gn_margin_top = 2;
+ const int gn_margin_side = 2;
+ const int gn_margin_bottom = 2;
+
+ const Color gn_bg_color = p_config.dark_theme ? p_config.dark_color_3 : p_config.dark_color_1.lerp(p_config.mono_color, 0.09);
+ const Color gn_selected_border_color = gn_bg_color.lerp(p_config.accent_color, 0.275);
+ const Color gn_frame_bg = gn_bg_color.lerp(p_config.tree_panel_style->get_bg_color(), 0.3);
+
+ Ref<StyleBoxFlat> gn_panel_style = make_flat_stylebox(gn_frame_bg, gn_margin_side, gn_margin_top, gn_margin_side, gn_margin_bottom, p_config.corner_radius);
+ gn_panel_style->set_border_width_all(p_config.border_width);
+ gn_panel_style->set_border_color(gn_bg_color);
+ gn_panel_style->set_corner_radius_individual(0, 0, p_config.corner_radius * EDSCALE, p_config.corner_radius * EDSCALE);
+ gn_panel_style->set_expand_margin(SIDE_TOP, 17 * EDSCALE);
+
+ Ref<StyleBoxFlat> gn_panel_selected_style = make_flat_stylebox(gn_frame_bg, gn_margin_side, gn_margin_top, gn_margin_side, gn_margin_bottom, p_config.corner_radius);
+ gn_panel_selected_style->set_border_width_all(2 * EDSCALE + p_config.border_width);
+ gn_panel_selected_style->set_border_color(gn_selected_border_color);
+ gn_panel_selected_style->set_corner_radius_individual(0, 0, p_config.corner_radius * EDSCALE, p_config.corner_radius * EDSCALE);
+ gn_panel_selected_style->set_expand_margin(SIDE_TOP, 17 * EDSCALE);
+
+ const int gn_titlebar_margin_left = 12;
+ const int gn_titlebar_margin_right = 4; // The rest is for the close button.
+
+ Ref<StyleBoxFlat> gn_titlebar_style = make_flat_stylebox(gn_bg_color, gn_titlebar_margin_left, gn_margin_top, gn_titlebar_margin_right, 0, p_config.corner_radius);
+ gn_titlebar_style->set_expand_margin(SIDE_TOP, 2 * EDSCALE);
+ gn_titlebar_style->set_corner_radius_individual(p_config.corner_radius * EDSCALE, p_config.corner_radius * EDSCALE, 0, 0);
+
+ Ref<StyleBoxFlat> gn_titlebar_selected_style = make_flat_stylebox(gn_selected_border_color, gn_titlebar_margin_left, gn_margin_top, gn_titlebar_margin_right, 0, p_config.corner_radius);
+ gn_titlebar_selected_style->set_corner_radius_individual(p_config.corner_radius * EDSCALE, p_config.corner_radius * EDSCALE, 0, 0);
+ gn_titlebar_selected_style->set_expand_margin(SIDE_TOP, 2 * EDSCALE);
+
+ Color gn_decoration_color = p_config.dark_color_1.inverted();
+
+ // GraphElement.
+
+ p_theme->set_stylebox("panel", "GraphElement", gn_panel_style);
+ p_theme->set_stylebox("panel_selected", "GraphElement", gn_panel_selected_style);
+ p_theme->set_stylebox("titlebar", "GraphElement", gn_titlebar_style);
+ p_theme->set_stylebox("titlebar_selected", "GraphElement", gn_titlebar_selected_style);
+
+ p_theme->set_color("resizer_color", "GraphElement", gn_decoration_color);
+ p_theme->set_icon("resizer", "GraphElement", p_theme->get_icon(SNAME("GuiResizer"), EditorStringName(EditorIcons)));
+
+ // GraphNode.
+
+ Ref<StyleBoxEmpty> gn_slot_style = make_empty_stylebox(12, 0, 12, 0);
+
+ p_theme->set_stylebox("panel", "GraphNode", gn_panel_style);
+ p_theme->set_stylebox("panel_selected", "GraphNode", gn_panel_selected_style);
+ p_theme->set_stylebox("titlebar", "GraphNode", gn_titlebar_style);
+ p_theme->set_stylebox("titlebar_selected", "GraphNode", gn_titlebar_selected_style);
+ p_theme->set_stylebox("slot", "GraphNode", gn_slot_style);
+
+ p_theme->set_color("resizer_color", "GraphNode", gn_decoration_color);
+
+ p_theme->set_constant("port_h_offset", "GraphNode", 0);
+ p_theme->set_constant("separation", "GraphNode", 1 * EDSCALE);
+
+ Ref<ImageTexture> port_icon = p_theme->get_icon(SNAME("GuiGraphNodePort"), EditorStringName(EditorIcons));
+ // The true size is 24x24 This is necessary for sharp port icons at high zoom levels in GraphEdit (up to ~200%).
+ port_icon->set_size_override(Size2(12, 12));
+ p_theme->set_icon("port", "GraphNode", port_icon);
+
+ // GraphNode's title Label.
+ p_theme->set_type_variation("GraphNodeTitleLabel", "Label");
+ p_theme->set_stylebox("normal", "GraphNodeTitleLabel", make_empty_stylebox(0, 0, 0, 0));
+ p_theme->set_color("font_color", "GraphNodeTitleLabel", p_config.font_color);
+ p_theme->set_constant("line_spacing", "GraphNodeTitleLabel", 3 * EDSCALE);
+ }
+ }
+
+ // ColorPicker and related nodes.
+ {
+ // ColorPicker.
+
+ p_theme->set_constant("margin", "ColorPicker", p_config.base_margin);
+ p_theme->set_constant("sv_width", "ColorPicker", 256 * EDSCALE);
+ p_theme->set_constant("sv_height", "ColorPicker", 256 * EDSCALE);
+ p_theme->set_constant("h_width", "ColorPicker", 30 * EDSCALE);
+ p_theme->set_constant("label_width", "ColorPicker", 10 * EDSCALE);
+ p_theme->set_constant("center_slider_grabbers", "ColorPicker", 1);
+
+ p_theme->set_icon("screen_picker", "ColorPicker", p_theme->get_icon(SNAME("ColorPick"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("shape_circle", "ColorPicker", p_theme->get_icon(SNAME("PickerShapeCircle"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("shape_rect", "ColorPicker", p_theme->get_icon(SNAME("PickerShapeRectangle"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("shape_rect_wheel", "ColorPicker", p_theme->get_icon(SNAME("PickerShapeRectangleWheel"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("add_preset", "ColorPicker", p_theme->get_icon(SNAME("Add"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("sample_bg", "ColorPicker", p_theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("sample_revert", "ColorPicker", p_theme->get_icon(SNAME("Reload"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("overbright_indicator", "ColorPicker", p_theme->get_icon(SNAME("OverbrightIndicator"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("bar_arrow", "ColorPicker", p_theme->get_icon(SNAME("ColorPickerBarArrow"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("picker_cursor", "ColorPicker", p_theme->get_icon(SNAME("PickerCursor"), EditorStringName(EditorIcons)));
+
+ // ColorPickerButton.
+ p_theme->set_icon("bg", "ColorPickerButton", p_theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons)));
+
+ // ColorPresetButton.
+ p_theme->set_stylebox("preset_fg", "ColorPresetButton", make_flat_stylebox(Color(1, 1, 1), 2, 2, 2, 2, 2));
+ p_theme->set_icon("preset_bg", "ColorPresetButton", p_theme->get_icon(SNAME("GuiMiniCheckerboard"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("overbright_indicator", "ColorPresetButton", p_theme->get_icon(SNAME("OverbrightIndicator"), EditorStringName(EditorIcons)));
+ }
+}
+
+void EditorThemeManager::_populate_editor_styles(const Ref<Theme> &p_theme, ThemeConfiguration &p_config) {
+ // Project manager.
+ {
+ p_theme->set_stylebox("search_panel", "ProjectManager", p_config.tree_panel_style);
+ p_theme->set_constant("sidebar_button_icon_separation", "ProjectManager", int(6 * EDSCALE));
+
+ // ProjectTag.
+ {
+ p_theme->set_type_variation("ProjectTag", "Button");
+
+ Ref<StyleBoxFlat> tag = p_config.button_style->duplicate();
+ tag->set_bg_color(p_config.dark_theme ? tag->get_bg_color().lightened(0.2) : tag->get_bg_color().darkened(0.2));
+ tag->set_corner_radius(CORNER_TOP_LEFT, 0);
+ tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
+ tag->set_corner_radius(CORNER_TOP_RIGHT, 4);
+ tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4);
+ p_theme->set_stylebox("normal", "ProjectTag", tag);
+
+ tag = p_config.button_style_hover->duplicate();
+ tag->set_corner_radius(CORNER_TOP_LEFT, 0);
+ tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
+ tag->set_corner_radius(CORNER_TOP_RIGHT, 4);
+ tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4);
+ p_theme->set_stylebox("hover", "ProjectTag", tag);
+
+ tag = p_config.button_style_pressed->duplicate();
+ tag->set_corner_radius(CORNER_TOP_LEFT, 0);
+ tag->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
+ tag->set_corner_radius(CORNER_TOP_RIGHT, 4);
+ tag->set_corner_radius(CORNER_BOTTOM_RIGHT, 4);
+ p_theme->set_stylebox("pressed", "ProjectTag", tag);
+ }
+ }
+
+ // Editor and main screen.
+ {
+ // Editor background.
+ Color background_color_opaque = p_config.dark_color_2;
+ background_color_opaque.a = 1.0;
+ p_theme->set_color("background", EditorStringName(Editor), background_color_opaque);
+ p_theme->set_stylebox("Background", EditorStringName(EditorStyles), make_flat_stylebox(background_color_opaque, p_config.base_margin, p_config.base_margin, p_config.base_margin, p_config.base_margin));
+
+ p_theme->set_stylebox("PanelForeground", EditorStringName(EditorStyles), p_config.base_style);
+
+ // Editor focus.
+ p_theme->set_stylebox("Focus", EditorStringName(EditorStyles), p_config.button_style_focus);
+ // Use a less opaque color to be less distracting for the 2D and 3D editor viewports.
+ Ref<StyleBoxFlat> style_widget_focus_viewport = p_config.button_style_focus->duplicate();
+ style_widget_focus_viewport->set_border_color(p_config.accent_color * Color(1, 1, 1, 0.5));
+ p_theme->set_stylebox("FocusViewport", EditorStringName(EditorStyles), style_widget_focus_viewport);
+
+ // This stylebox is used in 3d and 2d viewports (no borders).
+ Ref<StyleBoxFlat> style_content_panel_vp = p_config.content_panel_style->duplicate();
+ style_content_panel_vp->set_content_margin_individual(p_config.border_width * 2, p_config.base_margin * EDSCALE, p_config.border_width * 2, p_config.border_width * 2);
+ p_theme->set_stylebox("Content", EditorStringName(EditorStyles), style_content_panel_vp);
+
+ // 2D/CanvasItem editor
+ Ref<StyleBoxFlat> style_canvas_editor_info = make_flat_stylebox(Color(0.0, 0.0, 0.0, 0.2));
+ style_canvas_editor_info->set_expand_margin_all(4 * EDSCALE);
+ p_theme->set_stylebox("CanvasItemInfoOverlay", EditorStringName(EditorStyles), style_canvas_editor_info);
+
+ // 3D/Spatial editor.
+ Ref<StyleBoxFlat> style_info_3d_viewport = p_config.base_style->duplicate();
+ style_info_3d_viewport->set_bg_color(style_info_3d_viewport->get_bg_color() * Color(1, 1, 1, 0.5));
+ style_info_3d_viewport->set_border_width_all(0);
+ p_theme->set_stylebox("Information3dViewport", EditorStringName(EditorStyles), style_info_3d_viewport);
+
+ // 2D and 3D contextual toolbar.
+ // Use a custom stylebox to make contextual menu items stand out from the rest.
+ // This helps with editor usability as contextual menu items change when selecting nodes,
+ // even though it may not be immediately obvious at first.
+ Ref<StyleBoxFlat> toolbar_stylebox = memnew(StyleBoxFlat);
+ toolbar_stylebox->set_bg_color(p_config.accent_color * Color(1, 1, 1, 0.1));
+ toolbar_stylebox->set_anti_aliased(false);
+ // Add an underline to the StyleBox, but prevent its minimum vertical size from changing.
+ toolbar_stylebox->set_border_color(p_config.accent_color);
+ toolbar_stylebox->set_border_width(SIDE_BOTTOM, Math::round(2 * EDSCALE));
+ toolbar_stylebox->set_content_margin(SIDE_BOTTOM, 0);
+ toolbar_stylebox->set_expand_margin_individual(4 * EDSCALE, 2 * EDSCALE, 4 * EDSCALE, 4 * EDSCALE);
+ p_theme->set_stylebox("ContextualToolbar", EditorStringName(EditorStyles), toolbar_stylebox);
+
+ // Script editor.
+ p_theme->set_stylebox("ScriptEditorPanel", EditorStringName(EditorStyles), make_empty_stylebox(p_config.base_margin, 0, p_config.base_margin, p_config.base_margin));
+ p_theme->set_stylebox("ScriptEditorPanelFloating", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0));
+ p_theme->set_stylebox("ScriptEditor", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0));
+
+ // Bottom panel.
+ Ref<StyleBoxFlat> style_bottom_panel = p_config.content_panel_style->duplicate();
+ style_bottom_panel->set_corner_radius_all(p_config.corner_radius * EDSCALE);
+ p_theme->set_stylebox("BottomPanel", EditorStringName(EditorStyles), style_bottom_panel);
+
+ // Main menu.
+ p_theme->set_stylebox("MenuHover", EditorStringName(EditorStyles), p_config.button_style_hover);
+ }
+
+ // Editor GUI widgets.
+ {
+ // EditorSpinSlider.
+ p_theme->set_color("label_color", "EditorSpinSlider", p_config.font_color);
+ p_theme->set_color("read_only_label_color", "EditorSpinSlider", p_config.font_readonly_color);
+
+ Ref<StyleBoxFlat> editor_spin_label_bg = p_config.base_style->duplicate();
+ editor_spin_label_bg->set_bg_color(p_config.dark_color_3);
+ editor_spin_label_bg->set_border_width_all(0);
+ p_theme->set_stylebox("label_bg", "EditorSpinSlider", editor_spin_label_bg);
+
+ // Launch Pad and Play buttons
+ Ref<StyleBoxFlat> style_launch_pad = make_flat_stylebox(p_config.dark_color_1, 2 * EDSCALE, 0, 2 * EDSCALE, 0, p_config.corner_radius);
+ style_launch_pad->set_corner_radius_all(p_config.corner_radius * EDSCALE);
+ p_theme->set_stylebox("LaunchPadNormal", EditorStringName(EditorStyles), style_launch_pad);
+ Ref<StyleBoxFlat> style_launch_pad_movie = style_launch_pad->duplicate();
+ style_launch_pad_movie->set_bg_color(p_config.accent_color * Color(1, 1, 1, 0.1));
+ style_launch_pad_movie->set_border_color(p_config.accent_color);
+ style_launch_pad_movie->set_border_width_all(Math::round(2 * EDSCALE));
+ p_theme->set_stylebox("LaunchPadMovieMode", EditorStringName(EditorStyles), style_launch_pad_movie);
+
+ p_theme->set_stylebox("MovieWriterButtonNormal", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0));
+ Ref<StyleBoxFlat> style_write_movie_button = p_config.button_style_pressed->duplicate();
+ style_write_movie_button->set_bg_color(p_config.accent_color);
+ style_write_movie_button->set_corner_radius_all(p_config.corner_radius * EDSCALE);
+ style_write_movie_button->set_content_margin(SIDE_TOP, 0);
+ style_write_movie_button->set_content_margin(SIDE_BOTTOM, 0);
+ style_write_movie_button->set_content_margin(SIDE_LEFT, 0);
+ style_write_movie_button->set_content_margin(SIDE_RIGHT, 0);
+ style_write_movie_button->set_expand_margin(SIDE_RIGHT, 2 * EDSCALE);
+ p_theme->set_stylebox("MovieWriterButtonPressed", EditorStringName(EditorStyles), style_write_movie_button);
+ }
+
+ // Standard GUI variations.
+ {
+ // Custom theme type for MarginContainer with 4px margins.
+ p_theme->set_type_variation("MarginContainer4px", "MarginContainer");
+ p_theme->set_constant("margin_left", "MarginContainer4px", 4 * EDSCALE);
+ p_theme->set_constant("margin_top", "MarginContainer4px", 4 * EDSCALE);
+ p_theme->set_constant("margin_right", "MarginContainer4px", 4 * EDSCALE);
+ p_theme->set_constant("margin_bottom", "MarginContainer4px", 4 * EDSCALE);
+
+ // Header LinkButton variation.
+ p_theme->set_type_variation("HeaderSmallLink", "LinkButton");
+ p_theme->set_font("font", "HeaderSmallLink", p_theme->get_font(SNAME("font"), SNAME("HeaderSmall")));
+ p_theme->set_font_size("font_size", "HeaderSmallLink", p_theme->get_font_size(SNAME("font_size"), SNAME("HeaderSmall")));
+
+ // Flat button variations.
+ {
+ Ref<StyleBoxEmpty> style_flat_button = make_empty_stylebox();
+ for (int i = 0; i < 4; i++) {
+ style_flat_button->set_content_margin((Side)i, p_config.button_style->get_margin((Side)i) + p_config.button_style->get_border_width((Side)i));
+ }
+
+ Ref<StyleBoxFlat> style_flat_button_pressed = p_config.button_style_pressed->duplicate();
+ Color flat_pressed_color = p_config.dark_color_1.lightened(0.24).lerp(p_config.accent_color, 0.2) * Color(0.8, 0.8, 0.8, 0.85);
+ if (p_config.dark_theme) {
+ flat_pressed_color = p_config.dark_color_1.lerp(p_config.accent_color, 0.12) * Color(0.6, 0.6, 0.6, 0.85);
+ }
+ style_flat_button_pressed->set_bg_color(flat_pressed_color);
+
+ p_theme->set_stylebox("normal", "FlatButton", style_flat_button);
+ p_theme->set_stylebox("hover", "FlatButton", style_flat_button);
+ p_theme->set_stylebox("pressed", "FlatButton", style_flat_button_pressed);
+ p_theme->set_stylebox("disabled", "FlatButton", style_flat_button);
+
+ p_theme->set_stylebox("normal", "FlatMenuButton", style_flat_button);
+ p_theme->set_stylebox("hover", "FlatMenuButton", style_flat_button);
+ p_theme->set_stylebox("pressed", "FlatMenuButton", style_flat_button_pressed);
+ p_theme->set_stylebox("disabled", "FlatMenuButton", style_flat_button);
+
+ // Variation for Editor Log filter buttons.
+
+ p_theme->set_type_variation("EditorLogFilterButton", "Button");
+ // When pressed, don't tint the icons with the accent color, just leave them normal.
+ p_theme->set_color("icon_pressed_color", "EditorLogFilterButton", p_config.icon_normal_color);
+ // When unpressed, dim the icons.
+ p_theme->set_color("icon_normal_color", "EditorLogFilterButton", p_config.icon_disabled_color);
+
+ // When pressed, add a small bottom border to the buttons to better show their active state,
+ // similar to active tabs.
+ Ref<StyleBoxFlat> editor_log_button_pressed = style_flat_button_pressed->duplicate();
+ editor_log_button_pressed->set_border_width(SIDE_BOTTOM, 2 * EDSCALE);
+ editor_log_button_pressed->set_border_color(p_config.accent_color);
+ p_theme->set_stylebox("pressed", "EditorLogFilterButton", editor_log_button_pressed);
+ }
+
+ // Complex editor windows.
+ {
+ Ref<StyleBoxFlat> style_complex_window = p_config.window_style->duplicate();
+ style_complex_window->set_bg_color(p_config.dark_color_2);
+ style_complex_window->set_border_color(p_config.dark_color_2);
+ p_theme->set_stylebox("panel", "EditorSettingsDialog", style_complex_window);
+ p_theme->set_stylebox("panel", "ProjectSettingsEditor", style_complex_window);
+ p_theme->set_stylebox("panel", "EditorAbout", style_complex_window);
+ }
+
+ // InspectorActionButton.
+ {
+ p_theme->set_type_variation("InspectorActionButton", "Button");
+
+ const float action_extra_margin = 32 * EDSCALE;
+ p_theme->set_constant("h_separation", "InspectorActionButton", action_extra_margin);
+
+ Color color_inspector_action = p_config.dark_color_1.lerp(p_config.mono_color, 0.12);
+ color_inspector_action.a = 0.5;
+ Ref<StyleBoxFlat> style_inspector_action = p_config.button_style->duplicate();
+ style_inspector_action->set_bg_color(color_inspector_action);
+ style_inspector_action->set_content_margin(SIDE_RIGHT, action_extra_margin);
+ p_theme->set_stylebox("normal", "InspectorActionButton", style_inspector_action);
+
+ style_inspector_action = p_config.button_style_hover->duplicate();
+ style_inspector_action->set_content_margin(SIDE_RIGHT, action_extra_margin);
+ p_theme->set_stylebox("hover", "InspectorActionButton", style_inspector_action);
+
+ style_inspector_action = p_config.button_style_pressed->duplicate();
+ style_inspector_action->set_content_margin(SIDE_RIGHT, action_extra_margin);
+ p_theme->set_stylebox("pressed", "InspectorActionButton", style_inspector_action);
+
+ style_inspector_action = p_config.button_style_disabled->duplicate();
+ style_inspector_action->set_content_margin(SIDE_RIGHT, action_extra_margin);
+ p_theme->set_stylebox("disabled", "InspectorActionButton", style_inspector_action);
+ }
+
+ // Buttons in material previews.
+ {
+ const Color dim_light_color = p_config.icon_normal_color.darkened(0.24);
+ const Color dim_light_highlighted_color = p_config.icon_normal_color.darkened(0.18);
+ Ref<StyleBox> sb_empty_borderless = make_empty_stylebox();
+
+ p_theme->set_type_variation("PreviewLightButton", "Button");
+ // When pressed, don't use the accent color tint. When unpressed, dim the icon.
+ p_theme->set_color("icon_normal_color", "PreviewLightButton", dim_light_color);
+ p_theme->set_color("icon_focus_color", "PreviewLightButton", dim_light_color);
+ p_theme->set_color("icon_pressed_color", "PreviewLightButton", p_config.icon_normal_color);
+ p_theme->set_color("icon_hover_pressed_color", "PreviewLightButton", p_config.icon_normal_color);
+ // Unpressed icon is dim, so use a dim highlight.
+ p_theme->set_color("icon_hover_color", "PreviewLightButton", dim_light_highlighted_color);
+
+ p_theme->set_stylebox("normal", "PreviewLightButton", sb_empty_borderless);
+ p_theme->set_stylebox("hover", "PreviewLightButton", sb_empty_borderless);
+ p_theme->set_stylebox("focus", "PreviewLightButton", sb_empty_borderless);
+ p_theme->set_stylebox("pressed", "PreviewLightButton", sb_empty_borderless);
+ }
+
+ // TabContainerOdd variation.
+ {
+ // Can be used on tabs against the base color background (e.g. nested tabs).
+ p_theme->set_type_variation("TabContainerOdd", "TabContainer");
+
+ Ref<StyleBoxFlat> style_tab_selected_odd = p_theme->get_stylebox(SNAME("tab_selected"), SNAME("TabContainer"))->duplicate();
+ style_tab_selected_odd->set_bg_color(p_config.disabled_bg_color);
+ p_theme->set_stylebox("tab_selected", "TabContainerOdd", style_tab_selected_odd);
+
+ Ref<StyleBoxFlat> style_content_panel_odd = p_config.content_panel_style->duplicate();
+ style_content_panel_odd->set_bg_color(p_config.disabled_bg_color);
+ p_theme->set_stylebox("panel", "TabContainerOdd", style_content_panel_odd);
+ }
+
+ // EditorValidationPanel.
+ p_theme->set_stylebox("panel", "EditorValidationPanel", p_config.tree_panel_style);
+
+ // ControlEditor.
+ {
+ p_theme->set_type_variation("ControlEditorPopupPanel", "PopupPanel");
+
+ Ref<StyleBoxFlat> control_editor_popup_style = p_config.popup_style->duplicate();
+ control_editor_popup_style->set_shadow_size(0);
+ control_editor_popup_style->set_content_margin(SIDE_LEFT, p_config.base_margin * EDSCALE);
+ control_editor_popup_style->set_content_margin(SIDE_TOP, p_config.base_margin * EDSCALE);
+ control_editor_popup_style->set_content_margin(SIDE_RIGHT, p_config.base_margin * EDSCALE);
+ control_editor_popup_style->set_content_margin(SIDE_BOTTOM, p_config.base_margin * EDSCALE);
+ control_editor_popup_style->set_border_width_all(0);
+
+ p_theme->set_stylebox("panel", "ControlEditorPopupPanel", control_editor_popup_style);
+ }
+ }
+
+ // Editor inspector.
+ {
+ // Sub-inspectors.
+ for (int i = 0; i < 16; i++) {
+ Color si_base_color = p_config.accent_color;
+
+ float hue_rotate = (i * 2 % 16) / 16.0;
+ si_base_color.set_hsv(Math::fmod(float(si_base_color.get_h() + hue_rotate), float(1.0)), si_base_color.get_s(), si_base_color.get_v());
+ si_base_color = p_config.accent_color.lerp(si_base_color, float(EDITOR_GET("docks/property_editor/subresource_hue_tint")));
+
+ // Sub-inspector background.
+ Ref<StyleBoxFlat> sub_inspector_bg = p_config.base_style->duplicate();
+ sub_inspector_bg->set_bg_color(p_config.dark_color_1.lerp(si_base_color, 0.08));
+ sub_inspector_bg->set_border_width_all(2 * EDSCALE);
+ sub_inspector_bg->set_border_color(si_base_color * Color(0.7, 0.7, 0.7, 0.8));
+ sub_inspector_bg->set_content_margin_all(4 * EDSCALE);
+ sub_inspector_bg->set_corner_radius(CORNER_TOP_LEFT, 0);
+ sub_inspector_bg->set_corner_radius(CORNER_TOP_RIGHT, 0);
+
+ p_theme->set_stylebox("sub_inspector_bg" + itos(i), EditorStringName(Editor), sub_inspector_bg);
+
+ // EditorProperty background while it has a sub-inspector open.
+ Ref<StyleBoxFlat> bg_color = make_flat_stylebox(si_base_color * Color(0.7, 0.7, 0.7, 0.8), 0, 0, 0, 0, p_config.corner_radius);
+ bg_color->set_anti_aliased(false);
+ bg_color->set_corner_radius(CORNER_BOTTOM_LEFT, 0);
+ bg_color->set_corner_radius(CORNER_BOTTOM_RIGHT, 0);
+
+ p_theme->set_stylebox("sub_inspector_property_bg" + itos(i), EditorStringName(Editor), bg_color);
+ }
+
+ p_theme->set_color("sub_inspector_property_color", EditorStringName(Editor), p_config.dark_theme ? Color(1, 1, 1, 1) : Color(0, 0, 0, 1));
+
+ // EditorProperty.
+
+ Ref<StyleBoxFlat> style_property_bg = p_config.base_style->duplicate();
+ style_property_bg->set_bg_color(p_config.highlight_color);
+ style_property_bg->set_border_width_all(0);
+
+ Ref<StyleBoxFlat> style_property_child_bg = p_config.base_style->duplicate();
+ style_property_child_bg->set_bg_color(p_config.dark_color_2);
+ style_property_child_bg->set_border_width_all(0);
+
+ p_theme->set_stylebox("bg", "EditorProperty", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty)));
+ p_theme->set_stylebox("bg_selected", "EditorProperty", style_property_bg);
+ p_theme->set_stylebox("child_bg", "EditorProperty", style_property_child_bg);
+ p_theme->set_constant("font_offset", "EditorProperty", 8 * EDSCALE);
+ p_theme->set_constant("v_separation", "EditorProperty", p_config.increased_margin * EDSCALE);
+
+ const Color property_color = p_config.font_color.lerp(Color(0.5, 0.5, 0.5), 0.5);
+ const Color readonly_color = property_color.lerp(p_config.dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.25);
+ const Color readonly_warning_color = p_config.error_color.lerp(p_config.dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.25);
+
+ p_theme->set_color("property_color", "EditorProperty", property_color);
+ p_theme->set_color("readonly_color", "EditorProperty", readonly_color);
+ p_theme->set_color("warning_color", "EditorProperty", p_config.warning_color);
+ p_theme->set_color("readonly_warning_color", "EditorProperty", readonly_warning_color);
+
+ Ref<StyleBoxFlat> style_property_group_note = p_config.base_style->duplicate();
+ Color property_group_note_color = p_config.accent_color;
+ property_group_note_color.a = 0.1;
+ style_property_group_note->set_bg_color(property_group_note_color);
+ p_theme->set_stylebox("bg_group_note", "EditorProperty", style_property_group_note);
+
+ // EditorInspectorSection.
+
+ Color inspector_section_color = p_config.font_color.lerp(Color(0.5, 0.5, 0.5), 0.35);
+ p_theme->set_color("font_color", "EditorInspectorSection", inspector_section_color);
+
+ Color inspector_indent_color = p_config.accent_color;
+ inspector_indent_color.a = 0.2;
+ Ref<StyleBoxFlat> inspector_indent_style = make_flat_stylebox(inspector_indent_color, 2.0 * EDSCALE, 0, 2.0 * EDSCALE, 0);
+ p_theme->set_stylebox("indent_box", "EditorInspectorSection", inspector_indent_style);
+ p_theme->set_constant("indent_size", "EditorInspectorSection", 6.0 * EDSCALE);
+
+ Color prop_category_color = p_config.dark_color_1.lerp(p_config.mono_color, 0.12);
+ Color prop_section_color = p_config.dark_color_1.lerp(p_config.mono_color, 0.09);
+ Color prop_subsection_color = p_config.dark_color_1.lerp(p_config.mono_color, 0.06);
+
+ p_theme->set_color("prop_category", EditorStringName(Editor), prop_category_color);
+ p_theme->set_color("prop_section", EditorStringName(Editor), prop_section_color);
+ p_theme->set_color("prop_subsection", EditorStringName(Editor), prop_subsection_color);
+
+ // EditorInspectorCategory.
+
+ Ref<StyleBoxFlat> category_bg = p_config.base_style->duplicate();
+ category_bg->set_bg_color(prop_category_color);
+ category_bg->set_border_color(prop_category_color);
+ p_theme->set_stylebox("bg", "EditorInspectorCategory", category_bg);
+
+ p_theme->set_constant("inspector_margin", EditorStringName(Editor), 12 * EDSCALE);
+
+ // Dictionary editor.
+
+ // Expand to the left and right by 4px to compensate for the dictionary editor margins.
+ Ref<StyleBoxFlat> style_dictionary_add_item = make_flat_stylebox(prop_subsection_color, 0, 4, 0, 4, p_config.corner_radius);
+ style_dictionary_add_item->set_expand_margin(SIDE_LEFT, 4 * EDSCALE);
+ style_dictionary_add_item->set_expand_margin(SIDE_RIGHT, 4 * EDSCALE);
+ p_theme->set_stylebox("DictionaryAddItem", EditorStringName(EditorStyles), style_dictionary_add_item);
+ }
+
+ // Editor help.
+ {
+ Ref<StyleBoxFlat> style_editor_help = p_config.base_style->duplicate();
+ style_editor_help->set_bg_color(p_config.dark_color_2);
+ style_editor_help->set_border_color(p_config.dark_color_3);
+ p_theme->set_stylebox("background", "EditorHelp", style_editor_help);
+
+ const Color kbd_color = p_config.font_color.lerp(Color(0.5, 0.5, 0.5), 0.5);
+
+ p_theme->set_color("title_color", "EditorHelp", p_config.accent_color);
+ p_theme->set_color("headline_color", "EditorHelp", p_config.mono_color);
+ p_theme->set_color("text_color", "EditorHelp", p_config.font_color);
+ p_theme->set_color("comment_color", "EditorHelp", p_config.font_color * Color(1, 1, 1, 0.6));
+ p_theme->set_color("symbol_color", "EditorHelp", p_config.font_color * Color(1, 1, 1, 0.6));
+ p_theme->set_color("value_color", "EditorHelp", p_config.font_color * Color(1, 1, 1, 0.6));
+ p_theme->set_color("qualifier_color", "EditorHelp", p_config.font_color * Color(1, 1, 1, 0.8));
+ p_theme->set_color("type_color", "EditorHelp", p_config.accent_color.lerp(p_config.font_color, 0.5));
+ p_theme->set_color("selection_color", "EditorHelp", p_config.selection_color);
+ p_theme->set_color("link_color", "EditorHelp", p_config.accent_color.lerp(p_config.mono_color, 0.8));
+ p_theme->set_color("code_color", "EditorHelp", p_config.accent_color.lerp(p_config.mono_color, 0.6));
+ p_theme->set_color("kbd_color", "EditorHelp", p_config.accent_color.lerp(kbd_color, 0.6));
+ p_theme->set_color("code_bg_color", "EditorHelp", p_config.dark_color_3);
+ p_theme->set_color("kbd_bg_color", "EditorHelp", p_config.dark_color_1);
+ p_theme->set_color("param_bg_color", "EditorHelp", p_config.dark_color_1);
+ p_theme->set_constant("line_separation", "EditorHelp", Math::round(6 * EDSCALE));
+ p_theme->set_constant("table_h_separation", "EditorHelp", 16 * EDSCALE);
+ p_theme->set_constant("table_v_separation", "EditorHelp", 6 * EDSCALE);
+ p_theme->set_constant("text_highlight_h_padding", "EditorHelp", 1 * EDSCALE);
+ p_theme->set_constant("text_highlight_v_padding", "EditorHelp", 2 * EDSCALE);
+ }
+
+ // Asset Library.
+ p_theme->set_stylebox("bg", "AssetLib", p_config.base_empty_style);
+ p_theme->set_stylebox("panel", "AssetLib", p_config.content_panel_style);
+ p_theme->set_color("status_color", "AssetLib", Color(0.5, 0.5, 0.5)); // FIXME: Use a defined color instead.
+ p_theme->set_icon("dismiss", "AssetLib", p_theme->get_icon(SNAME("Close"), EditorStringName(EditorIcons)));
+
+ // Debugger.
+ {
+ Ref<StyleBoxFlat> debugger_panel_style = p_config.content_panel_style->duplicate();
+ debugger_panel_style->set_border_width(SIDE_BOTTOM, 0);
+ p_theme->set_stylebox("DebuggerPanel", EditorStringName(EditorStyles), debugger_panel_style);
+
+ // This pattern of get_font()->get_height(get_font_size()) is used quite a lot and is very verbose.
+ // FIXME: Introduce Theme::get_font_height() / Control::get_theme_font_height() / Window::get_theme_font_height().
+ const int offset_i1 = p_theme->get_font(SNAME("tab_selected"), SNAME("TabContainer"))->get_height(p_theme->get_font_size(SNAME("tab_selected"), SNAME("TabContainer")));
+ const int offset_i2 = p_theme->get_stylebox(SNAME("tab_selected"), SNAME("TabContainer"))->get_minimum_size().height;
+ const int offset_i3 = p_theme->get_stylebox(SNAME("panel"), SNAME("TabContainer"))->get_content_margin(SIDE_TOP);
+ const int invisible_top_offset = offset_i1 + offset_i2 + offset_i3;
+
+ Ref<StyleBoxFlat> invisible_top_panel_style = p_config.content_panel_style->duplicate();
+ invisible_top_panel_style->set_expand_margin(SIDE_TOP, -invisible_top_offset);
+ invisible_top_panel_style->set_content_margin(SIDE_TOP, 0);
+ p_theme->set_stylebox("BottomPanelDebuggerOverride", EditorStringName(EditorStyles), invisible_top_panel_style);
+ }
+
+ // Resource and node editors.
+ {
+ // TextureRegion editor.
+ Ref<StyleBoxFlat> style_texture_region_bg = p_config.tree_panel_style->duplicate();
+ style_texture_region_bg->set_content_margin_all(0);
+ p_theme->set_stylebox("TextureRegionPreviewBG", EditorStringName(EditorStyles), style_texture_region_bg);
+ p_theme->set_stylebox("TextureRegionPreviewFG", EditorStringName(EditorStyles), make_empty_stylebox(0, 0, 0, 0));
+
+ // Theme editor.
+ {
+ p_theme->set_color("preview_picker_overlay_color", "ThemeEditor", Color(0.1, 0.1, 0.1, 0.25));
+
+ Color theme_preview_picker_bg_color = p_config.accent_color;
+ theme_preview_picker_bg_color.a = 0.2;
+ Ref<StyleBoxFlat> theme_preview_picker_sb = make_flat_stylebox(theme_preview_picker_bg_color, 0, 0, 0, 0);
+ theme_preview_picker_sb->set_border_color(p_config.accent_color);
+ theme_preview_picker_sb->set_border_width_all(1.0 * EDSCALE);
+ p_theme->set_stylebox("preview_picker_overlay", "ThemeEditor", theme_preview_picker_sb);
+
+ Color theme_preview_picker_label_bg_color = p_config.accent_color;
+ theme_preview_picker_label_bg_color.set_v(0.5);
+ Ref<StyleBoxFlat> theme_preview_picker_label_sb = make_flat_stylebox(theme_preview_picker_label_bg_color, 4.0, 1.0, 4.0, 3.0);
+ p_theme->set_stylebox("preview_picker_label", "ThemeEditor", theme_preview_picker_label_sb);
+
+ Ref<StyleBoxFlat> style_theme_preview_tab = p_theme->get_stylebox(SNAME("tab_selected"), SNAME("TabContainerOdd"))->duplicate();
+ style_theme_preview_tab->set_expand_margin(SIDE_BOTTOM, 5 * EDSCALE);
+ p_theme->set_stylebox("ThemeEditorPreviewFG", EditorStringName(EditorStyles), style_theme_preview_tab);
+
+ Ref<StyleBoxFlat> style_theme_preview_bg_tab = p_theme->get_stylebox(SNAME("tab_unselected"), SNAME("TabContainer"))->duplicate();
+ style_theme_preview_bg_tab->set_expand_margin(SIDE_BOTTOM, 2 * EDSCALE);
+ p_theme->set_stylebox("ThemeEditorPreviewBG", EditorStringName(EditorStyles), style_theme_preview_bg_tab);
+ }
+
+ // VisualShader editor.
+ p_theme->set_stylebox("label_style", "VShaderEditor", make_empty_stylebox(2, 1, 2, 1));
+
+ // StateMachine graph.
+ {
+ p_theme->set_stylebox("panel", "GraphStateMachine", p_config.tree_panel_style);
+ p_theme->set_stylebox("error_panel", "GraphStateMachine", p_config.tree_panel_style);
+ p_theme->set_color("error_color", "GraphStateMachine", p_config.error_color);
+
+ const int sm_margin_side = 10 * EDSCALE;
+ const int sm_margin_bottom = 2;
+ const Color sm_bg_color = p_config.dark_theme ? p_config.dark_color_3 : p_config.dark_color_1.lerp(p_config.mono_color, 0.09);
+
+ Ref<StyleBoxFlat> sm_node_style = make_flat_stylebox(p_config.dark_color_3 * Color(1, 1, 1, 0.7), sm_margin_side, 24 * EDSCALE, sm_margin_side, sm_margin_bottom, p_config.corner_radius);
+ sm_node_style->set_border_width_all(p_config.border_width);
+ sm_node_style->set_border_color(sm_bg_color);
+
+ Ref<StyleBoxFlat> sm_node_selected_style = make_flat_stylebox(sm_bg_color * Color(1, 1, 1, 0.9), sm_margin_side, 24 * EDSCALE, sm_margin_side, sm_margin_bottom, p_config.corner_radius);
+ sm_node_selected_style->set_border_width_all(2 * EDSCALE + p_config.border_width);
+ sm_node_selected_style->set_border_color(p_config.accent_color * Color(1, 1, 1, 0.9));
+ sm_node_selected_style->set_shadow_size(8 * EDSCALE);
+ sm_node_selected_style->set_shadow_color(p_config.shadow_color);
+
+ Ref<StyleBoxFlat> sm_node_playing_style = sm_node_selected_style->duplicate();
+ sm_node_playing_style->set_border_color(p_config.warning_color);
+ sm_node_playing_style->set_shadow_color(p_config.warning_color * Color(1, 1, 1, 0.2));
+
+ p_theme->set_stylebox("node_frame", "GraphStateMachine", sm_node_style);
+ p_theme->set_stylebox("node_frame_selected", "GraphStateMachine", sm_node_selected_style);
+ p_theme->set_stylebox("node_frame_playing", "GraphStateMachine", sm_node_playing_style);
+
+ Ref<StyleBoxFlat> sm_node_start_style = sm_node_style->duplicate();
+ sm_node_start_style->set_border_width_all(1 * EDSCALE);
+ sm_node_start_style->set_border_color(p_config.success_color.lightened(0.24));
+ p_theme->set_stylebox("node_frame_start", "GraphStateMachine", sm_node_start_style);
+
+ Ref<StyleBoxFlat> sm_node_end_style = sm_node_style->duplicate();
+ sm_node_end_style->set_border_width_all(1 * EDSCALE);
+ sm_node_end_style->set_border_color(p_config.error_color);
+ p_theme->set_stylebox("node_frame_end", "GraphStateMachine", sm_node_end_style);
+
+ p_theme->set_font("node_title_font", "GraphStateMachine", p_theme->get_font(SNAME("font"), SNAME("Label")));
+ p_theme->set_font_size("node_title_font_size", "GraphStateMachine", p_theme->get_font_size(SNAME("font_size"), SNAME("Label")));
+ p_theme->set_color("node_title_font_color", "GraphStateMachine", p_config.font_color);
+
+ p_theme->set_color("transition_color", "GraphStateMachine", p_config.font_color);
+ p_theme->set_color("transition_disabled_color", "GraphStateMachine", p_config.font_color * Color(1, 1, 1, 0.2));
+ p_theme->set_color("transition_icon_color", "GraphStateMachine", Color(1, 1, 1));
+ p_theme->set_color("transition_icon_disabled_color", "GraphStateMachine", Color(1, 1, 1, 0.2));
+ p_theme->set_color("highlight_color", "GraphStateMachine", p_config.accent_color);
+ p_theme->set_color("highlight_disabled_color", "GraphStateMachine", p_config.accent_color * Color(1, 1, 1, 0.6));
+ p_theme->set_color("guideline_color", "GraphStateMachine", p_config.font_color * Color(1, 1, 1, 0.3));
+
+ p_theme->set_color("playback_color", "GraphStateMachine", p_config.font_color);
+ p_theme->set_color("playback_background_color", "GraphStateMachine", p_config.font_color * Color(1, 1, 1, 0.3));
+ }
+ }
+}
+
+void EditorThemeManager::_generate_text_editor_defaults(ThemeConfiguration &p_config) {
+ // Adaptive colors for comments and elements with lower relevance.
+ const Color dim_color = Color(p_config.font_color, 0.5);
+ const float mono_value = p_config.mono_color.r;
+ const Color alpha1 = Color(mono_value, mono_value, mono_value, 0.07);
+ const Color alpha2 = Color(mono_value, mono_value, mono_value, 0.14);
+ const Color alpha3 = Color(mono_value, mono_value, mono_value, 0.27);
+
+ /* clang-format off */
+ // Syntax highlight token colors.
+ const Color symbol_color = p_config.dark_theme ? Color(0.67, 0.79, 1) : Color(0, 0, 0.61);
+ const Color keyword_color = p_config.dark_theme ? Color(1.0, 0.44, 0.52) : Color(0.9, 0.135, 0.51);
+ const Color control_flow_keyword_color = p_config.dark_theme ? Color(1.0, 0.55, 0.8) : Color(0.743, 0.12, 0.8);
+ const Color base_type_color = p_config.dark_theme ? Color(0.26, 1.0, 0.76) : Color(0, 0.6, 0.2);
+ const Color engine_type_color = p_config.dark_theme ? Color(0.56, 1, 0.86) : Color(0.11, 0.55, 0.4);
+ const Color user_type_color = p_config.dark_theme ? Color(0.78, 1, 0.93) : Color(0.18, 0.45, 0.4);
+ const Color comment_color = p_config.dark_theme ? dim_color : Color(0.08, 0.08, 0.08, 0.5);
+ const Color doc_comment_color = p_config.dark_theme ? Color(0.6, 0.7, 0.8, 0.8) : Color(0.15, 0.15, 0.4, 0.7);
+ const Color string_color = p_config.dark_theme ? Color(1, 0.93, 0.63) : Color(0.6, 0.42, 0);
+
+ // Use the brightest background color on a light theme (which generally uses a negative contrast rate).
+ const Color te_background_color = p_config.dark_theme ? p_config.dark_color_2 : p_config.dark_color_3;
+ const Color completion_background_color = p_config.dark_theme ? p_config.base_color : p_config.dark_color_2;
+ const Color completion_selected_color = alpha1;
+ const Color completion_existing_color = alpha2;
+ // Same opacity as the scroll grabber editor icon.
+ const Color completion_scroll_color = Color(mono_value, mono_value, mono_value, 0.29);
+ const Color completion_scroll_hovered_color = Color(mono_value, mono_value, mono_value, 0.4);
+ const Color completion_font_color = p_config.font_color;
+ const Color text_color = p_config.font_color;
+ const Color line_number_color = dim_color;
+ const Color safe_line_number_color = p_config.dark_theme ? (dim_color * Color(1, 1.2, 1, 1.5)) : Color(0, 0.4, 0, 0.75);
+ const Color caret_color = p_config.mono_color;
+ const Color caret_background_color = p_config.mono_color.inverted();
+ const Color text_selected_color = Color(0, 0, 0, 0);
+ const Color selection_color = p_config.selection_color;
+ const Color brace_mismatch_color = p_config.dark_theme ? p_config.error_color : Color(1, 0.08, 0, 1);
+ const Color current_line_color = alpha1;
+ const Color line_length_guideline_color = p_config.dark_theme ? p_config.base_color : p_config.dark_color_2;
+ const Color word_highlighted_color = alpha1;
+ const Color number_color = p_config.dark_theme ? Color(0.63, 1, 0.88) : Color(0, 0.55, 0.28, 1);
+ const Color function_color = p_config.dark_theme ? Color(0.34, 0.7, 1.0) : Color(0, 0.225, 0.9, 1);
+ const Color member_variable_color = p_config.dark_theme ? Color(0.34, 0.7, 1.0).lerp(p_config.mono_color, 0.6) : Color(0, 0.4, 0.68, 1);
+ const Color mark_color = Color(p_config.error_color.r, p_config.error_color.g, p_config.error_color.b, 0.3);
+ const Color bookmark_color = Color(0.08, 0.49, 0.98);
+ const Color breakpoint_color = p_config.dark_theme ? p_config.error_color : Color(1, 0.27, 0.2, 1);
+ const Color executing_line_color = Color(0.98, 0.89, 0.27);
+ const Color code_folding_color = alpha3;
+ const Color folded_code_region_color = Color(0.68, 0.46, 0.77, 0.2);
+ const Color search_result_color = alpha1;
+ const Color search_result_border_color = p_config.dark_theme ? Color(0.41, 0.61, 0.91, 0.38) : Color(0, 0.4, 1, 0.38);
+ /* clang-format on */
+
+ EditorSettings *setting = EditorSettings::get_singleton();
+
+ /* clang-format off */
+ setting->set_initial_value("text_editor/theme/highlighting/symbol_color", symbol_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/keyword_color", keyword_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/control_flow_keyword_color", control_flow_keyword_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/base_type_color", base_type_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/engine_type_color", engine_type_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/user_type_color", user_type_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/comment_color", comment_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/doc_comment_color", doc_comment_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/string_color", string_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/background_color", te_background_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/completion_background_color", completion_background_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/completion_selected_color", completion_selected_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/completion_existing_color", completion_existing_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/completion_scroll_color", completion_scroll_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/completion_scroll_hovered_color", completion_scroll_hovered_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/completion_font_color", completion_font_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/text_color", text_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/line_number_color", line_number_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/safe_line_number_color", safe_line_number_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/caret_color", caret_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/caret_background_color", caret_background_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/text_selected_color", text_selected_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/selection_color", selection_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/brace_mismatch_color", brace_mismatch_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/current_line_color", current_line_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/line_length_guideline_color", line_length_guideline_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/word_highlighted_color", word_highlighted_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/number_color", number_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/function_color", function_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/member_variable_color", member_variable_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/mark_color", mark_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/bookmark_color", bookmark_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/breakpoint_color", breakpoint_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/executing_line_color", executing_line_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/code_folding_color", code_folding_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/folded_code_region_color", folded_code_region_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/search_result_color", search_result_color, true);
+ setting->set_initial_value("text_editor/theme/highlighting/search_result_border_color", search_result_border_color, true);
+ /* clang-format on */
+}
+
+void EditorThemeManager::_populate_text_editor_styles(const Ref<Theme> &p_theme, ThemeConfiguration &p_config) {
+ String text_editor_color_theme = EditorSettings::get_singleton()->get("text_editor/theme/color_theme");
+ if (text_editor_color_theme == "Default") {
+ _generate_text_editor_defaults(p_config);
+ } else if (text_editor_color_theme == "Godot 2") {
+ EditorSettings::get_singleton()->load_text_editor_theme();
+ }
+
+ // Now theme is loaded, apply it to CodeEdit.
+ p_theme->set_font("font", "CodeEdit", p_theme->get_font(SNAME("source"), EditorStringName(EditorFonts)));
+ p_theme->set_font_size("font_size", "CodeEdit", p_theme->get_font_size(SNAME("source_size"), EditorStringName(EditorFonts)));
+
+ /* clang-format off */
+ p_theme->set_icon("tab", "CodeEdit", p_theme->get_icon(SNAME("GuiTab"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("space", "CodeEdit", p_theme->get_icon(SNAME("GuiSpace"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("folded", "CodeEdit", p_theme->get_icon(SNAME("CodeFoldedRightArrow"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("can_fold", "CodeEdit", p_theme->get_icon(SNAME("CodeFoldDownArrow"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("folded_code_region", "CodeEdit", p_theme->get_icon(SNAME("CodeRegionFoldedRightArrow"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("can_fold_code_region", "CodeEdit", p_theme->get_icon(SNAME("CodeRegionFoldDownArrow"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("executing_line", "CodeEdit", p_theme->get_icon(SNAME("TextEditorPlay"), EditorStringName(EditorIcons)));
+ p_theme->set_icon("breakpoint", "CodeEdit", p_theme->get_icon(SNAME("Breakpoint"), EditorStringName(EditorIcons)));
+ /* clang-format on */
+
+ p_theme->set_constant("line_spacing", "CodeEdit", EDITOR_GET("text_editor/appearance/whitespace/line_spacing"));
+
+ const Color background_color = EDITOR_GET("text_editor/theme/highlighting/background_color");
+ Ref<StyleBoxFlat> code_edit_stylebox = make_flat_stylebox(background_color, p_config.widget_margin.x, p_config.widget_margin.y, p_config.widget_margin.x, p_config.widget_margin.y, p_config.corner_radius);
+ p_theme->set_stylebox("normal", "CodeEdit", code_edit_stylebox);
+ p_theme->set_stylebox("read_only", "CodeEdit", code_edit_stylebox);
+ p_theme->set_stylebox("focus", "CodeEdit", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty)));
+
+ p_theme->set_color("background_color", "CodeEdit", Color(0, 0, 0, 0)); // Unset any color, we use a stylebox.
+
+ /* clang-format off */
+ p_theme->set_color("completion_background_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_background_color"));
+ p_theme->set_color("completion_selected_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_selected_color"));
+ p_theme->set_color("completion_existing_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_existing_color"));
+ p_theme->set_color("completion_scroll_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_scroll_color"));
+ p_theme->set_color("completion_scroll_hovered_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/completion_scroll_hovered_color"));
+ p_theme->set_color("font_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/text_color"));
+ p_theme->set_color("line_number_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/line_number_color"));
+ p_theme->set_color("caret_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/caret_color"));
+ p_theme->set_color("font_selected_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/text_selected_color"));
+ p_theme->set_color("selection_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/selection_color"));
+ p_theme->set_color("brace_mismatch_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/brace_mismatch_color"));
+ p_theme->set_color("current_line_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/current_line_color"));
+ p_theme->set_color("line_length_guideline_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/line_length_guideline_color"));
+ p_theme->set_color("word_highlighted_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/word_highlighted_color"));
+ p_theme->set_color("bookmark_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/bookmark_color"));
+ p_theme->set_color("breakpoint_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/breakpoint_color"));
+ p_theme->set_color("executing_line_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/executing_line_color"));
+ p_theme->set_color("code_folding_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/code_folding_color"));
+ p_theme->set_color("folded_code_region_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/folded_code_region_color"));
+ p_theme->set_color("search_result_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/search_result_color"));
+ p_theme->set_color("search_result_border_color", "CodeEdit", EDITOR_GET("text_editor/theme/highlighting/search_result_border_color"));
+ /* clang-format on */
+}
+
+// Public interface for theme generation.
+
+Ref<Theme> EditorThemeManager::generate_theme(const Ref<Theme> &p_old_theme) {
+ OS::get_singleton()->benchmark_begin_measure("EditorTheme", "Generate Theme");
+
+ Ref<Theme> theme = _create_base_theme(p_old_theme);
+
+ const String custom_theme_path = EDITOR_GET("interface/theme/custom_theme");
+ if (!custom_theme_path.is_empty()) {
+ Ref<Theme> custom_theme = ResourceLoader::load(custom_theme_path);
+ if (custom_theme.is_valid()) {
+ theme->merge_with(custom_theme);
+ }
+ }
+
+ OS::get_singleton()->benchmark_end_measure("EditorTheme", "Generate Theme");
+ return theme;
+}
+
+bool EditorThemeManager::is_generated_theme_outdated() {
+ // This list includes settings used by files in the editor/themes folder.
+ // Note that the editor scale is purposefully omitted because it cannot be changed
+ // without a restart, so there is no point regenerating the theme.
+
+ // TODO: We can use this information more intelligently to do partial theme updates and speed things up.
+ return EditorSettings::get_singleton()->check_changed_settings_in_group("interface/theme") ||
+ EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/font") ||
+ EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/main_font") ||
+ EditorSettings::get_singleton()->check_changed_settings_in_group("interface/editor/code_font") ||
+ EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/theme") ||
+ EditorSettings::get_singleton()->check_changed_settings_in_group("text_editor/help/help") ||
+ EditorSettings::get_singleton()->check_changed_settings_in_group("filesystem/file_dialog/thumbnail_size") ||
+ EditorSettings::get_singleton()->check_changed_settings_in_group("run/output/font_size") ||
+ EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/increase_scrollbar_touch_area") ||
+ EditorSettings::get_singleton()->check_changed_settings_in_group("interface/touchscreen/scale_gizmo_handles");
+}
+
+void EditorThemeManager::initialize() {
+ EditorColorMap::create();
+ EditorTheme::initialize();
+}
+
+void EditorThemeManager::finalize() {
+ EditorColorMap::finish();
+ EditorTheme::finalize();
+}
diff --git a/editor/themes/editor_theme_manager.h b/editor/themes/editor_theme_manager.h
new file mode 100644
index 0000000000..86188ec244
--- /dev/null
+++ b/editor/themes/editor_theme_manager.h
@@ -0,0 +1,150 @@
+/**************************************************************************/
+/* editor_theme_manager.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef EDITOR_THEME_MANAGER_H
+#define EDITOR_THEME_MANAGER_H
+
+#include "scene/resources/style_box_flat.h"
+#include "scene/resources/theme.h"
+
+class EditorThemeManager {
+ struct ThemeConfiguration {
+ // Basic properties.
+
+ String preset;
+ String spacing_preset;
+ bool dark_theme = false;
+
+ Color base_color;
+ Color accent_color;
+ float contrast = 1.0;
+ float icon_saturation = 1.0;
+
+ // Extra properties.
+
+ int base_spacing = 4;
+ int extra_spacing = 0;
+ int border_width = 0;
+ int corner_radius = 3;
+
+ bool draw_extra_borders = false;
+ float relationship_line_opacity = 1.0;
+ int thumb_size = 16;
+ int class_icon_size = 16;
+ bool increase_scrollbar_touch_area = false;
+ float gizmo_handle_scale = 1.0;
+ int color_picker_button_height = 28;
+
+ float default_contrast = 1.0;
+
+ // Generated properties.
+
+ int base_margin = 4;
+ int increased_margin = 4;
+ int separation_margin = 4;
+ int popup_margin = 12;
+ int window_border_margin = 8;
+ int top_bar_separation = 8;
+ int forced_even_separation = 0;
+
+ Color mono_color;
+ Color dark_color_1;
+ Color dark_color_2;
+ Color dark_color_3;
+ Color contrast_color_1;
+ Color contrast_color_2;
+ Color highlight_color;
+ Color highlight_disabled_color;
+ Color success_color;
+ Color warning_color;
+ Color error_color;
+ Color extra_border_color_1;
+ Color extra_border_color_2;
+
+ Color font_color;
+ Color font_focus_color;
+ Color font_hover_color;
+ Color font_pressed_color;
+ Color font_hover_pressed_color;
+ Color font_disabled_color;
+ Color font_readonly_color;
+ Color font_placeholder_color;
+ Color font_outline_color;
+
+ Color icon_normal_color;
+ Color icon_focus_color;
+ Color icon_hover_color;
+ Color icon_pressed_color;
+ Color icon_disabled_color;
+
+ Color shadow_color;
+ Color selection_color;
+ Color disabled_border_color;
+ Color disabled_bg_color;
+ Color separator_color;
+
+ Ref<StyleBoxFlat> base_style;
+ Ref<StyleBoxEmpty> base_empty_style;
+
+ Ref<StyleBoxFlat> button_style;
+ Ref<StyleBoxFlat> button_style_disabled;
+ Ref<StyleBoxFlat> button_style_focus;
+ Ref<StyleBoxFlat> button_style_pressed;
+ Ref<StyleBoxFlat> button_style_hover;
+
+ Ref<StyleBoxFlat> popup_style;
+ Ref<StyleBoxFlat> window_style;
+ Ref<StyleBoxFlat> dialog_style;
+ Ref<StyleBoxFlat> panel_container_style;
+ Ref<StyleBoxFlat> content_panel_style;
+ Ref<StyleBoxFlat> tree_panel_style;
+
+ Vector2 widget_margin;
+ };
+
+ static Ref<Theme> _create_base_theme(const Ref<Theme> &p_old_theme = nullptr);
+ static ThemeConfiguration _create_theme_config(const Ref<Theme> &p_theme);
+
+ static void _create_shared_styles(const Ref<Theme> &p_theme, ThemeConfiguration &p_config);
+ static void _populate_standard_styles(const Ref<Theme> &p_theme, ThemeConfiguration &p_config);
+ static void _populate_editor_styles(const Ref<Theme> &p_theme, ThemeConfiguration &p_config);
+
+ static void _generate_text_editor_defaults(ThemeConfiguration &p_config);
+ static void _populate_text_editor_styles(const Ref<Theme> &p_theme, ThemeConfiguration &p_config);
+
+public:
+ static Ref<Theme> generate_theme(const Ref<Theme> &p_old_theme = nullptr);
+ static bool is_generated_theme_outdated();
+
+ static void initialize();
+ static void finalize();
+};
+
+#endif // EDITOR_THEME_MANAGER_H
diff --git a/editor/window_wrapper.cpp b/editor/window_wrapper.cpp
index aec4005ce5..a085c2e44f 100644
--- a/editor/window_wrapper.cpp
+++ b/editor/window_wrapper.cpp
@@ -31,10 +31,10 @@
#include "window_wrapper.h"
#include "editor/editor_node.h"
-#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "editor/progress_dialog.h"
+#include "editor/themes/editor_scale.h"
#include "scene/gui/box_container.h"
#include "scene/gui/label.h"
#include "scene/gui/panel.h"