diff --git a/doc/classes/Theme.xml b/doc/classes/Theme.xml
index 2a90deb74e5..ca1ff60c687 100644
--- a/doc/classes/Theme.xml
+++ b/doc/classes/Theme.xml
@@ -275,6 +275,14 @@
Returns [code]false[/code] if the theme does not have [code]node_type[/code].
+
+
+
+
+ Adds missing and overrides existing definitions with values from the [code]other[/code] [Theme].
+ [b]Note:[/b] This modifies the current theme. If you want to merge two themes together without modifying either one, create a new empty theme and merge the other two into it one after another.
+
+
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index b814d7d2444..fa26bec5ed2 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -571,6 +571,11 @@ Ref create_editor_theme(const Ref p_theme) {
theme->set_stylebox("panel", "PanelContainer", style_menu);
theme->set_stylebox("MenuPanel", "EditorStyles", style_menu);
+ // CanvasItem Editor
+ Ref style_canvas_editor_info = make_flat_stylebox(Color(0.0, 0.0, 0.0, 0.2));
+ style_canvas_editor_info->set_expand_margin_size_all(4 * EDSCALE);
+ theme->set_stylebox("CanvasItemInfoOverlay", "EditorStyles", style_canvas_editor_info);
+
// Script Editor
theme->set_stylebox("ScriptEditorPanel", "EditorStyles", make_empty_stylebox(default_margin_size, 0, default_margin_size, default_margin_size));
theme->set_stylebox("ScriptEditor", "EditorStyles", make_empty_stylebox(0, 0, 0, 0));
@@ -1376,15 +1381,14 @@ Ref create_editor_theme(const Ref p_theme) {
}
Ref create_custom_theme(const Ref p_theme) {
- Ref theme;
+ Ref theme = create_editor_theme(p_theme);
- const String custom_theme = EditorSettings::get_singleton()->get("interface/theme/custom_theme");
- if (custom_theme != "") {
- theme = ResourceLoader::load(custom_theme);
- }
-
- if (!theme.is_valid()) {
- theme = create_editor_theme(p_theme);
+ const String custom_theme_path = EditorSettings::get_singleton()->get("interface/theme/custom_theme");
+ if (custom_theme_path != "") {
+ Ref custom_theme = ResourceLoader::load(custom_theme_path);
+ if (custom_theme.is_valid()) {
+ theme->merge_with(custom_theme);
+ }
}
return theme;
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 2f717798158..93441b47636 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -4198,6 +4198,10 @@ void CanvasItemEditor::_notification(int p_what) {
font->set_outline_color(Color(0, 0, 0));
zoom_reset->add_font_override("font", font);
zoom_reset->add_color_override("font_color", Color(1, 1, 1));
+
+ info_overlay->get_theme()->set_stylebox("normal", "Label", get_stylebox("CanvasItemInfoOverlay", "EditorStyles"));
+ warning_child_of_container->add_color_override("font_color", get_color("warning_color", "Editor"));
+ warning_child_of_container->add_font_override("font", get_font("main", "EditorFonts"));
}
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
@@ -5778,20 +5782,13 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
info_overlay->add_constant_override("separation", 10);
viewport_scrollable->add_child(info_overlay);
+ // Make sure all labels inside of the container are styled the same.
Theme *info_overlay_theme = memnew(Theme);
- info_overlay_theme->copy_default_theme();
info_overlay->set_theme(info_overlay_theme);
- StyleBoxFlat *info_overlay_label_stylebox = memnew(StyleBoxFlat);
- info_overlay_label_stylebox->set_bg_color(Color(0.0, 0.0, 0.0, 0.2));
- info_overlay_label_stylebox->set_expand_margin_size_all(4);
- info_overlay_theme->set_stylebox("normal", "Label", info_overlay_label_stylebox);
-
warning_child_of_container = memnew(Label);
warning_child_of_container->hide();
warning_child_of_container->set_text(TTR("Warning: Children of a container get their position and size determined only by their parent."));
- warning_child_of_container->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("warning_color", "Editor"));
- warning_child_of_container->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("main", "EditorFonts"));
add_control_to_info_overlay(warning_child_of_container);
h_scroll = memnew(HScrollBar);
diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp
index c138e07c313..9ec47673bb1 100644
--- a/scene/resources/theme.cpp
+++ b/scene/resources/theme.cpp
@@ -1182,6 +1182,82 @@ void Theme::copy_theme(const Ref &p_other) {
_unfreeze_and_propagate_changes();
}
+void Theme::merge_with(const Ref &p_other) {
+ if (p_other.is_null()) {
+ return;
+ }
+
+ _freeze_change_propagation();
+
+ // Colors.
+ {
+ const StringName *K = nullptr;
+ while ((K = p_other->color_map.next(K))) {
+ const StringName *L = nullptr;
+ while ((L = p_other->color_map[*K].next(L))) {
+ set_color(*L, *K, p_other->color_map[*K][*L]);
+ }
+ }
+ }
+
+ // Constants.
+ {
+ const StringName *K = nullptr;
+ while ((K = p_other->constant_map.next(K))) {
+ const StringName *L = nullptr;
+ while ((L = p_other->constant_map[*K].next(L))) {
+ set_constant(*L, *K, p_other->constant_map[*K][*L]);
+ }
+ }
+ }
+
+ // Fonts.
+ {
+ const StringName *K = nullptr;
+ while ((K = p_other->font_map.next(K))) {
+ const StringName *L = nullptr;
+ while ((L = p_other->font_map[*K].next(L))) {
+ set_font(*L, *K, p_other->font_map[*K][*L]);
+ }
+ }
+ }
+
+ // Icons.
+ {
+ const StringName *K = nullptr;
+ while ((K = p_other->icon_map.next(K))) {
+ const StringName *L = nullptr;
+ while ((L = p_other->icon_map[*K].next(L))) {
+ set_icon(*L, *K, p_other->icon_map[*K][*L]);
+ }
+ }
+ }
+
+ // Shaders.
+ {
+ const StringName *K = nullptr;
+ while ((K = p_other->shader_map.next(K))) {
+ const StringName *L = nullptr;
+ while ((L = p_other->shader_map[*K].next(L))) {
+ set_shader(*L, *K, p_other->shader_map[*K][*L]);
+ }
+ }
+ }
+
+ // Styleboxes.
+ {
+ const StringName *K = nullptr;
+ while ((K = p_other->style_map.next(K))) {
+ const StringName *L = nullptr;
+ while ((L = p_other->style_map[*K].next(L))) {
+ set_stylebox(*L, *K, p_other->style_map[*K][*L]);
+ }
+ }
+ }
+
+ _unfreeze_and_propagate_changes();
+}
+
void Theme::get_type_list(List *p_list) const {
ERR_FAIL_NULL(p_list);
@@ -1281,6 +1357,7 @@ void Theme::_bind_methods() {
ClassDB::bind_method("copy_default_theme", &Theme::copy_default_theme);
ClassDB::bind_method(D_METHOD("copy_theme", "other"), &Theme::copy_theme);
+ ClassDB::bind_method(D_METHOD("merge_with", "other"), &Theme::merge_with);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "default_font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_default_font", "get_default_font");
diff --git a/scene/resources/theme.h b/scene/resources/theme.h
index f85c1f4ba9e..12cbcb660be 100644
--- a/scene/resources/theme.h
+++ b/scene/resources/theme.h
@@ -187,6 +187,7 @@ public:
void copy_default_theme();
void copy_theme(const Ref &p_other);
+ void merge_with(const Ref &p_other);
void clear();
Theme();