diff options
| -rw-r--r-- | doc/classes/Control.xml | 21 | ||||
| -rw-r--r-- | doc/classes/Theme.xml | 28 | ||||
| -rw-r--r-- | doc/classes/Window.xml | 15 | ||||
| -rw-r--r-- | editor/editor_themes.cpp | 5 | ||||
| -rw-r--r-- | scene/gui/color_picker.cpp | 53 | ||||
| -rw-r--r-- | scene/gui/color_picker.h | 1 | ||||
| -rw-r--r-- | scene/gui/control.cpp | 154 | ||||
| -rw-r--r-- | scene/gui/control.h | 8 | ||||
| -rw-r--r-- | scene/gui/dialogs.cpp | 6 | ||||
| -rw-r--r-- | scene/gui/gradient_edit.cpp | 41 | ||||
| -rw-r--r-- | scene/gui/gradient_edit.h | 7 | ||||
| -rw-r--r-- | scene/gui/graph_edit.cpp | 16 | ||||
| -rw-r--r-- | scene/gui/line_edit.cpp | 7 | ||||
| -rw-r--r-- | scene/gui/rich_text_label.cpp | 14 | ||||
| -rw-r--r-- | scene/gui/text_edit.cpp | 12 | ||||
| -rw-r--r-- | scene/gui/tree.cpp | 18 | ||||
| -rw-r--r-- | scene/gui/tree.h | 2 | ||||
| -rw-r--r-- | scene/main/window.cpp | 16 | ||||
| -rw-r--r-- | scene/main/window.h | 4 | ||||
| -rw-r--r-- | scene/resources/default_theme/default_theme.cpp | 9 | ||||
| -rw-r--r-- | scene/resources/theme.cpp | 883 | ||||
| -rw-r--r-- | scene/resources/theme.h | 15 | 
22 files changed, 805 insertions, 530 deletions
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index b00bf1c250..6fa59a15ac 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -458,6 +458,27 @@  				See [method get_theme_color] for details.  			</description>  		</method> +		<method name="get_theme_default_base_scale" qualifiers="const"> +			<return type="float" /> +			<description> +				Returns the default base scale value from the first matching [Theme] in the tree if that [Theme] has a valid [member Theme.default_base_scale] value. +				See [method get_theme_color] for details. +			</description> +		</method> +		<method name="get_theme_default_font" qualifiers="const"> +			<return type="Font" /> +			<description> +				Returns the default font from the first matching [Theme] in the tree if that [Theme] has a valid [member Theme.default_font] value. +				See [method get_theme_color] for details. +			</description> +		</method> +		<method name="get_theme_default_font_size" qualifiers="const"> +			<return type="int" /> +			<description> +				Returns the default font size value from the first matching [Theme] in the tree if that [Theme] has a valid [member Theme.default_font_size] value. +				See [method get_theme_color] for details. +			</description> +		</method>  		<method name="get_theme_font" qualifiers="const">  			<return type="Font" />  			<argument index="0" name="name" type="StringName" /> diff --git a/doc/classes/Theme.xml b/doc/classes/Theme.xml index edf5874432..2f5648dda9 100644 --- a/doc/classes/Theme.xml +++ b/doc/classes/Theme.xml @@ -273,6 +273,24 @@  				Returns [code]false[/code] if the theme does not have [code]theme_type[/code].  			</description>  		</method> +		<method name="has_default_base_scale" qualifiers="const"> +			<return type="bool" /> +			<description> +				Returns [code]true[/code] if this theme has a valid [member default_base_scale] value. +			</description> +		</method> +		<method name="has_default_font" qualifiers="const"> +			<return type="bool" /> +			<description> +				Returns [code]true[/code] if this theme has a valid [member default_font] value. +			</description> +		</method> +		<method name="has_default_font_size" qualifiers="const"> +			<return type="bool" /> +			<description> +				Returns [code]true[/code] if this theme has a valid [member default_font_size] value. +			</description> +		</method>  		<method name="has_font" qualifiers="const">  			<return type="bool" />  			<argument index="0" name="name" type="StringName" /> @@ -484,11 +502,17 @@  		</method>  	</methods>  	<members> +		<member name="default_base_scale" type="float" setter="set_default_base_scale" getter="get_default_base_scale" default="0.0"> +			The default base scale factor of this [Theme] resource. Used by some controls to scale their visual properties based on a global scale factor. If this value is set to [code]0.0[/code], the global scale factor is used. +			Use [method has_default_base_scale] to check if this value is valid. +		</member>  		<member name="default_font" type="Font" setter="set_default_font" getter="get_default_font"> -			The theme's default font. +			The default font of this [Theme] resource. Used as a fallback value for font items defined in this theme, but having invalid values. If this value is also invalid, the global default value is used. +			Use [method has_default_font] to check if this value is valid.  		</member>  		<member name="default_font_size" type="int" setter="set_default_font_size" getter="get_default_font_size" default="-1"> -			The theme's default font size. Set to [code]-1[/code] to ignore and use global default. +			The default font size of this [Theme] resource. Used as a fallback value for font size items defined in this theme, but having invalid values. If this value is set to [code]-1[/code], the global default value is used. +			Use [method has_default_font_size] to check if this value is valid.  		</member>  	</members>  	<constants> diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml index 15d844aacb..0653c8b453 100644 --- a/doc/classes/Window.xml +++ b/doc/classes/Window.xml @@ -59,6 +59,21 @@  			<description>  			</description>  		</method> +		<method name="get_theme_default_base_scale" qualifiers="const"> +			<return type="float" /> +			<description> +			</description> +		</method> +		<method name="get_theme_default_font" qualifiers="const"> +			<return type="Font" /> +			<description> +			</description> +		</method> +		<method name="get_theme_default_font_size" qualifiers="const"> +			<return type="int" /> +			<description> +			</description> +		</method>  		<method name="get_theme_font" qualifiers="const">  			<return type="Font" />  			<argument index="0" name="name" type="StringName" /> diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 0579fb4cbd..6efbcbc61e 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -292,7 +292,8 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme =  Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {  	Ref<Theme> theme = Ref<Theme>(memnew(Theme)); -	const float default_contrast = 0.3; +	// Controls may rely on the scale for their internal drawing logic. +	theme->set_default_theme_base_scale(EDSCALE);  	// Theme settings  	Color accent_color = EDITOR_GET("interface/theme/accent_color"); @@ -310,6 +311,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {  	Color preset_base_color;  	float preset_contrast = 0; +	const float default_contrast = 0.3; +  	// Please use alphabetical order if you're adding a new theme here  	// (after "Custom") diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 611035fff9..54548e1941 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -35,7 +35,6 @@  #include "core/os/os.h"  #ifdef TOOLS_ENABLED -#include "editor/editor_scale.h"  #include "editor/editor_settings.h"  #endif  #include "scene/main/window.h" @@ -44,17 +43,7 @@ List<Color> ColorPicker::preset_cache;  void ColorPicker::_notification(int p_what) {  	switch (p_what) { -		case NOTIFICATION_THEME_CHANGED: { -			btn_pick->set_icon(get_theme_icon(SNAME("screen_picker"), SNAME("ColorPicker"))); -			btn_add_preset->set_icon(get_theme_icon(SNAME("add_preset"))); -			_update_presets(); -			_update_controls(); -		} break;  		case NOTIFICATION_ENTER_TREE: { -			btn_pick->set_icon(get_theme_icon(SNAME("screen_picker"), SNAME("ColorPicker"))); -			btn_add_preset->set_icon(get_theme_icon(SNAME("add_preset"))); - -			_update_controls();  			_update_color();  #ifdef TOOLS_ENABLED @@ -71,18 +60,39 @@ void ColorPicker::_notification(int p_what) {  				}  			}  #endif -		} break; -		case NOTIFICATION_PARENTED: { +			[[fallthrough]]; +		} +		case NOTIFICATION_THEME_CHANGED: { +			btn_pick->set_icon(get_theme_icon(SNAME("screen_picker"), SNAME("ColorPicker"))); +			btn_add_preset->set_icon(get_theme_icon(SNAME("add_preset"))); + +			uv_edit->set_custom_minimum_size(Size2(get_theme_constant(SNAME("sv_width")), get_theme_constant(SNAME("sv_height")))); +			w_edit->set_custom_minimum_size(Size2(get_theme_constant(SNAME("h_width")), 0)); + +			wheel_edit->set_custom_minimum_size(Size2(get_theme_constant(SNAME("sv_width")), get_theme_constant(SNAME("sv_height")))); +			wheel_margin->add_theme_constant_override("margin_bottom", 8 * get_theme_default_base_scale()); +  			for (int i = 0; i < 4; i++) { +				labels[i]->set_custom_minimum_size(Size2(get_theme_constant(SNAME("label_width")), 0));  				set_offset((Side)i, get_offset((Side)i) + get_theme_constant(SNAME("margin")));  			} + +			if (Engine::get_singleton()->is_editor_hint()) { +				// Adjust for the width of the "Script" icon. +				text_type->set_custom_minimum_size(Size2(28 * get_theme_default_base_scale(), 0)); +			} + +			_update_presets(); +			_update_controls();  		} break; +  		case NOTIFICATION_VISIBILITY_CHANGED: {  			Popup *p = Object::cast_to<Popup>(get_parent());  			if (p) {  				p->set_size(Size2(get_combined_minimum_size().width + get_theme_constant(SNAME("margin")) * 2, get_combined_minimum_size().height + get_theme_constant(SNAME("margin")) * 2));  			}  		} break; +  		case NOTIFICATION_WM_CLOSE_REQUEST: {  			if (screen != nullptr && screen->is_visible()) {  				screen->hide(); @@ -762,11 +772,7 @@ void ColorPicker::_slider_draw(int p_which) {  	Size2 size = scroll[p_which]->get_size();  	Color left_color;  	Color right_color; -#ifdef TOOLS_ENABLED -	const real_t margin = 4 * EDSCALE; -#else -	const real_t margin = 4; -#endif +	const real_t margin = 4 * get_theme_default_base_scale();  	if (p_which == 3) {  		scroll[p_which]->draw_texture_rect(get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), Rect2(Point2(0, margin), Size2(size.x, margin)), true); @@ -1147,7 +1153,6 @@ ColorPicker::ColorPicker() :  	uv_edit->set_mouse_filter(MOUSE_FILTER_PASS);  	uv_edit->set_h_size_flags(SIZE_EXPAND_FILL);  	uv_edit->set_v_size_flags(SIZE_EXPAND_FILL); -	uv_edit->set_custom_minimum_size(Size2(get_theme_constant(SNAME("sv_width")), get_theme_constant(SNAME("sv_height"))));  	uv_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(0, uv_edit));  	HBoxContainer *hb_smpl = memnew(HBoxContainer); @@ -1219,9 +1224,6 @@ ColorPicker::ColorPicker() :  	text_type->set_text("#");  	text_type->set_tooltip(TTR("Switch between hexadecimal and code values."));  	if (Engine::get_singleton()->is_editor_hint()) { -#ifdef TOOLS_ENABLED -		text_type->set_custom_minimum_size(Size2(28 * EDSCALE, 0)); // Adjust for the width of the "Script" icon. -#endif  		text_type->connect("pressed", callable_mp(this, &ColorPicker::_text_type_toggled));  	} else {  		text_type->set_flat(true); @@ -1236,7 +1238,6 @@ ColorPicker::ColorPicker() :  	wheel_edit->set_h_size_flags(SIZE_EXPAND_FILL);  	wheel_edit->set_v_size_flags(SIZE_EXPAND_FILL); -	wheel_edit->set_custom_minimum_size(Size2(get_theme_constant(SNAME("sv_width")), get_theme_constant(SNAME("sv_height"))));  	hb_edit->add_child(wheel_edit);  	wheel_mat.instantiate(); @@ -1244,12 +1245,7 @@ ColorPicker::ColorPicker() :  	circle_mat.instantiate();  	circle_mat->set_shader(circle_shader); -	MarginContainer *wheel_margin(memnew(MarginContainer)); -#ifdef TOOLS_ENABLED -	wheel_margin->add_theme_constant_override("margin_bottom", 8 * EDSCALE); -#else  	wheel_margin->add_theme_constant_override("margin_bottom", 8); -#endif  	wheel_edit->add_child(wheel_margin);  	wheel_margin->add_child(wheel); @@ -1261,7 +1257,6 @@ ColorPicker::ColorPicker() :  	wheel_uv->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(0, wheel_uv));  	hb_edit->add_child(w_edit); -	w_edit->set_custom_minimum_size(Size2(get_theme_constant(SNAME("h_width")), 0));  	w_edit->set_h_size_flags(SIZE_FILL);  	w_edit->set_v_size_flags(SIZE_EXPAND_FILL);  	w_edit->connect("gui_input", callable_mp(this, &ColorPicker::_w_input)); diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index 67ca007eb5..ad4f5ad5b1 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -81,6 +81,7 @@ private:  	Control *uv_edit = memnew(Control);  	Control *w_edit = memnew(Control);  	AspectRatioContainer *wheel_edit = memnew(AspectRatioContainer); +	MarginContainer *wheel_margin = memnew(MarginContainer);  	Ref<ShaderMaterial> wheel_mat;  	Ref<ShaderMaterial> circle_mat;  	Control *wheel = memnew(Control); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 1b8b5e17ed..e2d3807b40 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -833,11 +833,12 @@ T Control::get_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner  	ERR_FAIL_COND_V_MSG(p_theme_types.size() == 0, T(), "At least one theme type must be specified.");  	// First, look through each control or window node in the branch, until no valid parent can be found. -	// For each control iterate through its inheritance chain and see if p_name exists in any of them. +	// Only nodes with a theme resource attached are considered.  	Control *theme_owner = p_theme_owner;  	Window *theme_owner_window = p_theme_owner_window;  	while (theme_owner || theme_owner_window) { +		// For each theme resource check the theme types provided and see if p_name exists with any of them.  		for (const StringName &E : p_theme_types) {  			if (theme_owner && theme_owner->data.theme->has_theme_item(p_data_type, p_name, E)) {  				return theme_owner->data.theme->get_theme_item(p_data_type, p_name, E); @@ -888,11 +889,12 @@ bool Control::has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_ow  	ERR_FAIL_COND_V_MSG(p_theme_types.size() == 0, false, "At least one theme type must be specified.");  	// First, look through each control or window node in the branch, until no valid parent can be found. -	// For each control iterate through its inheritance chain and see if p_name exists in any of them. +	// Only nodes with a theme resource attached are considered.  	Control *theme_owner = p_theme_owner;  	Window *theme_owner_window = p_theme_owner_window;  	while (theme_owner || theme_owner_window) { +		// For each theme resource check the theme types provided and see if p_name exists with any of them.  		for (const StringName &E : p_theme_types) {  			if (theme_owner && theme_owner->data.theme->has_theme_item(p_data_type, p_name, E)) {  				return true; @@ -1130,6 +1132,150 @@ bool Control::has_theme_constant(const StringName &p_name, const StringName &p_t  	return has_theme_item_in_types(data.theme_owner, data.theme_owner_window, Theme::DATA_TYPE_CONSTANT, p_name, theme_types);  } +float Control::fetch_theme_default_base_scale(Control *p_theme_owner, Window *p_theme_owner_window) { +	// First, look through each control or window node in the branch, until no valid parent can be found. +	// Only nodes with a theme resource attached are considered. +	// For each theme resource see if their assigned theme has the default value defined and valid. +	Control *theme_owner = p_theme_owner; +	Window *theme_owner_window = p_theme_owner_window; + +	while (theme_owner || theme_owner_window) { +		if (theme_owner && theme_owner->data.theme->has_default_theme_base_scale()) { +			return theme_owner->data.theme->get_default_theme_base_scale(); +		} + +		if (theme_owner_window && theme_owner_window->theme->has_default_theme_base_scale()) { +			return theme_owner_window->theme->get_default_theme_base_scale(); +		} + +		Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent(); +		Control *parent_c = Object::cast_to<Control>(parent); +		if (parent_c) { +			theme_owner = parent_c->data.theme_owner; +			theme_owner_window = parent_c->data.theme_owner_window; +		} else { +			Window *parent_w = Object::cast_to<Window>(parent); +			if (parent_w) { +				theme_owner = parent_w->theme_owner; +				theme_owner_window = parent_w->theme_owner_window; +			} else { +				theme_owner = nullptr; +				theme_owner_window = nullptr; +			} +		} +	} + +	// Secondly, check the project-defined Theme resource. +	if (Theme::get_project_default().is_valid()) { +		if (Theme::get_project_default()->has_default_theme_base_scale()) { +			return Theme::get_project_default()->get_default_theme_base_scale(); +		} +	} + +	// Lastly, fall back on the default Theme. +	return Theme::get_default()->get_default_theme_base_scale(); +} + +float Control::get_theme_default_base_scale() const { +	return fetch_theme_default_base_scale(data.theme_owner, data.theme_owner_window); +} + +Ref<Font> Control::fetch_theme_default_font(Control *p_theme_owner, Window *p_theme_owner_window) { +	// First, look through each control or window node in the branch, until no valid parent can be found. +	// Only nodes with a theme resource attached are considered. +	// For each theme resource see if their assigned theme has the default value defined and valid. +	Control *theme_owner = p_theme_owner; +	Window *theme_owner_window = p_theme_owner_window; + +	while (theme_owner || theme_owner_window) { +		if (theme_owner && theme_owner->data.theme->has_default_theme_font()) { +			return theme_owner->data.theme->get_default_theme_font(); +		} + +		if (theme_owner_window && theme_owner_window->theme->has_default_theme_font()) { +			return theme_owner_window->theme->get_default_theme_font(); +		} + +		Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent(); +		Control *parent_c = Object::cast_to<Control>(parent); +		if (parent_c) { +			theme_owner = parent_c->data.theme_owner; +			theme_owner_window = parent_c->data.theme_owner_window; +		} else { +			Window *parent_w = Object::cast_to<Window>(parent); +			if (parent_w) { +				theme_owner = parent_w->theme_owner; +				theme_owner_window = parent_w->theme_owner_window; +			} else { +				theme_owner = nullptr; +				theme_owner_window = nullptr; +			} +		} +	} + +	// Secondly, check the project-defined Theme resource. +	if (Theme::get_project_default().is_valid()) { +		if (Theme::get_project_default()->has_default_theme_font()) { +			return Theme::get_project_default()->get_default_theme_font(); +		} +	} + +	// Lastly, fall back on the default Theme. +	return Theme::get_default()->get_default_theme_font(); +} + +Ref<Font> Control::get_theme_default_font() const { +	return fetch_theme_default_font(data.theme_owner, data.theme_owner_window); +} + +int Control::fetch_theme_default_font_size(Control *p_theme_owner, Window *p_theme_owner_window) { +	// First, look through each control or window node in the branch, until no valid parent can be found. +	// Only nodes with a theme resource attached are considered. +	// For each theme resource see if their assigned theme has the default value defined and valid. +	Control *theme_owner = p_theme_owner; +	Window *theme_owner_window = p_theme_owner_window; + +	while (theme_owner || theme_owner_window) { +		if (theme_owner && theme_owner->data.theme->has_default_theme_font_size()) { +			return theme_owner->data.theme->get_default_theme_font_size(); +		} + +		if (theme_owner_window && theme_owner_window->theme->has_default_theme_font_size()) { +			return theme_owner_window->theme->get_default_theme_font_size(); +		} + +		Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent(); +		Control *parent_c = Object::cast_to<Control>(parent); +		if (parent_c) { +			theme_owner = parent_c->data.theme_owner; +			theme_owner_window = parent_c->data.theme_owner_window; +		} else { +			Window *parent_w = Object::cast_to<Window>(parent); +			if (parent_w) { +				theme_owner = parent_w->theme_owner; +				theme_owner_window = parent_w->theme_owner_window; +			} else { +				theme_owner = nullptr; +				theme_owner_window = nullptr; +			} +		} +	} + +	// Secondly, check the project-defined Theme resource. +	if (Theme::get_project_default().is_valid()) { +		if (Theme::get_project_default()->has_default_theme_font_size()) { +			return Theme::get_project_default()->get_default_theme_font_size(); +		} +	} + +	// Lastly, fall back on the default Theme. +	return Theme::get_default()->get_default_theme_font_size(); +} + +int Control::get_theme_default_font_size() const { +	return fetch_theme_default_font_size(data.theme_owner, data.theme_owner_window); +} +  Rect2 Control::get_parent_anchorable_rect() const {  	if (!is_inside_tree()) {  		return Rect2(); @@ -2789,6 +2935,10 @@ void Control::_bind_methods() {  	ClassDB::bind_method(D_METHOD("has_theme_color", "name", "theme_type"), &Control::has_theme_color, DEFVAL(""));  	ClassDB::bind_method(D_METHOD("has_theme_constant", "name", "theme_type"), &Control::has_theme_constant, DEFVAL("")); +	ClassDB::bind_method(D_METHOD("get_theme_default_base_scale"), &Control::get_theme_default_base_scale); +	ClassDB::bind_method(D_METHOD("get_theme_default_font"), &Control::get_theme_default_font); +	ClassDB::bind_method(D_METHOD("get_theme_default_font_size"), &Control::get_theme_default_font_size); +  	ClassDB::bind_method(D_METHOD("get_parent_control"), &Control::get_parent_control);  	ClassDB::bind_method(D_METHOD("set_h_grow_direction", "direction"), &Control::set_h_grow_direction); diff --git a/scene/gui/control.h b/scene/gui/control.h index 87ff3918cb..bdc06319ea 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -509,6 +509,14 @@ public:  	bool has_theme_color(const StringName &p_name, const StringName &p_theme_type = StringName()) const;  	bool has_theme_constant(const StringName &p_name, const StringName &p_theme_type = StringName()) const; +	static float fetch_theme_default_base_scale(Control *p_theme_owner, Window *p_theme_owner_window); +	static Ref<Font> fetch_theme_default_font(Control *p_theme_owner, Window *p_theme_owner_window); +	static int fetch_theme_default_font_size(Control *p_theme_owner, Window *p_theme_owner_window); + +	float get_theme_default_base_scale() const; +	Ref<Font> get_theme_default_font() const; +	int get_theme_default_font_size() const; +  	/* TOOLTIP */  	void set_tooltip(const String &p_tooltip); diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index 5d98aaa698..71d2778cc3 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -37,7 +37,6 @@  #ifdef TOOLS_ENABLED  #include "editor/editor_node.h" -#include "editor/editor_scale.h"  #include "scene/main/window.h" // Only used to check for more modals when dimming the editor.  #endif @@ -363,8 +362,7 @@ Button *ConfirmationDialog::get_cancel_button() {  ConfirmationDialog::ConfirmationDialog() {  	set_title(TTRC("Please Confirm...")); -#ifdef TOOLS_ENABLED -	set_min_size(Size2(200, 70) * EDSCALE); -#endif +	set_min_size(Size2(200, 70)); +  	cancel = add_cancel_button();  } diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp index 56b8a936e1..5d024d3be7 100644 --- a/scene/gui/gradient_edit.cpp +++ b/scene/gui/gradient_edit.cpp @@ -32,15 +32,6 @@  #include "core/os/keyboard.h" -#ifdef TOOLS_ENABLED -#include "editor/editor_scale.h" -#define SPACING (3 * EDSCALE) -#define POINT_WIDTH (8 * EDSCALE) -#else -#define SPACING 3 -#define POINT_WIDTH 8 -#endif -  GradientEdit::GradientEdit() {  	set_focus_mode(FOCUS_ALL); @@ -53,12 +44,12 @@ GradientEdit::GradientEdit() {  int GradientEdit::_get_point_from_pos(int x) {  	int result = -1; -	int total_w = get_size().width - get_size().height - SPACING; +	int total_w = get_size().width - get_size().height - draw_spacing;  	float min_distance = 1e20;  	for (int i = 0; i < points.size(); i++) {  		//Check if we clicked at point  		float distance = ABS(x - points[i].offset * total_w); -		float min = (POINT_WIDTH / 2 * 1.7); //make it easier to grab +		float min = (draw_point_width / 2 * 1.7); //make it easier to grab  		if (distance <= min && distance < min_distance) {  			result = i;  			min_distance = distance; @@ -129,7 +120,7 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) {  		grabbed = _get_point_from_pos(x);  		if (grabbed != -1) { -			int total_w = get_size().width - get_size().height - SPACING; +			int total_w = get_size().width - get_size().height - draw_spacing;  			Gradient::Point newPoint = points[grabbed];  			newPoint.offset = CLAMP(x / float(total_w), 0, 1); @@ -151,10 +142,10 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) {  	if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) {  		update();  		int x = mb->get_position().x; -		int total_w = get_size().width - get_size().height - SPACING; +		int total_w = get_size().width - get_size().height - draw_spacing;  		//Check if color selector was clicked. -		if (x > total_w + SPACING) { +		if (x > total_w + draw_spacing) {  			_show_color_picker();  			return;  		} @@ -225,7 +216,7 @@ void GradientEdit::gui_input(const Ref<InputEvent> &p_event) {  	Ref<InputEventMouseMotion> mm = p_event;  	if (mm.is_valid() && grabbing) { -		int total_w = get_size().width - get_size().height - SPACING; +		int total_w = get_size().width - get_size().height - draw_spacing;  		int x = mm->get_position().x; @@ -297,6 +288,12 @@ void GradientEdit::_notification(int p_what) {  			picker->connect("color_changed", callable_mp(this, &GradientEdit::_color_changed));  		}  	} + +	if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { +		draw_spacing = BASE_SPACING * get_theme_default_base_scale(); +		draw_point_width = BASE_POINT_WIDTH * get_theme_default_base_scale(); +	} +  	if (p_what == NOTIFICATION_DRAW) {  		int w = get_size().x;  		int h = get_size().y; @@ -305,7 +302,7 @@ void GradientEdit::_notification(int p_what) {  			return; //Safety check. We have division by 'h'. And in any case there is nothing to draw with such size  		} -		int total_w = get_size().width - get_size().height - SPACING; +		int total_w = get_size().width - get_size().height - draw_spacing;  		//Draw checker pattern for ramp  		draw_texture_rect(get_theme_icon(SNAME("GuiMiniCheckerboard"), SNAME("EditorIcons")), Rect2(0, 0, total_w, h), true); @@ -358,7 +355,7 @@ void GradientEdit::_notification(int p_what) {  			col.a = 0.9;  			draw_line(Vector2(points[i].offset * total_w, 0), Vector2(points[i].offset * total_w, h / 2), col); -			Rect2 rect = Rect2(points[i].offset * total_w - POINT_WIDTH / 2, h / 2, POINT_WIDTH, h / 2); +			Rect2 rect = Rect2(points[i].offset * total_w - draw_point_width / 2, h / 2, draw_point_width, h / 2);  			draw_rect(rect, points[i].color, true);  			draw_rect(rect, col, false);  			if (grabbed == i) { @@ -375,15 +372,15 @@ void GradientEdit::_notification(int p_what) {  		}  		//Draw "button" for color selector -		draw_texture_rect(get_theme_icon(SNAME("GuiMiniCheckerboard"), SNAME("EditorIcons")), Rect2(total_w + SPACING, 0, h, h), true); +		draw_texture_rect(get_theme_icon(SNAME("GuiMiniCheckerboard"), SNAME("EditorIcons")), Rect2(total_w + draw_spacing, 0, h, h), true);  		if (grabbed != -1) {  			//Draw with selection color -			draw_rect(Rect2(total_w + SPACING, 0, h, h), points[grabbed].color); +			draw_rect(Rect2(total_w + draw_spacing, 0, h, h), points[grabbed].color);  		} else {  			//if no color selected draw grey color with 'X' on top. -			draw_rect(Rect2(total_w + SPACING, 0, h, h), Color(0.5, 0.5, 0.5, 1)); -			draw_line(Vector2(total_w + SPACING, 0), Vector2(total_w + SPACING + h, h), Color(1, 1, 1, 0.6)); -			draw_line(Vector2(total_w + SPACING, h), Vector2(total_w + SPACING + h, 0), Color(1, 1, 1, 0.6)); +			draw_rect(Rect2(total_w + draw_spacing, 0, h, h), Color(0.5, 0.5, 0.5, 1)); +			draw_line(Vector2(total_w + draw_spacing, 0), Vector2(total_w + draw_spacing + h, h), Color(1, 1, 1, 0.6)); +			draw_line(Vector2(total_w + draw_spacing, h), Vector2(total_w + draw_spacing + h, 0), Color(1, 1, 1, 0.6));  		}  		//Draw borders around color ramp if in focus diff --git a/scene/gui/gradient_edit.h b/scene/gui/gradient_edit.h index a173631963..f3a39daaf6 100644 --- a/scene/gui/gradient_edit.h +++ b/scene/gui/gradient_edit.h @@ -46,6 +46,13 @@ class GradientEdit : public Control {  	int grabbed = -1;  	Vector<Gradient::Point> points; +	// Make sure to use the scaled value below. +	const int BASE_SPACING = 3; +	const int BASE_POINT_WIDTH = 8; + +	int draw_spacing = BASE_SPACING; +	int draw_point_width = BASE_POINT_WIDTH; +  	void _draw_checker(int x, int y, int w, int h);  	void _color_changed(const Color &p_color);  	int _get_point_from_pos(int x); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index d9c08ec272..35e31be9af 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -36,10 +36,6 @@  #include "scene/gui/box_container.h"  #include "scene/gui/button.h" -#ifdef TOOLS_ENABLED -#include "editor/editor_scale.h" -#endif -  constexpr int MINIMAP_OFFSET = 12;  constexpr int MINIMAP_PADDING = 5; @@ -436,6 +432,8 @@ void GraphEdit::_notification(int p_what) {  		snap_button->set_icon(get_theme_icon(SNAME("snap")));  		minimap_button->set_icon(get_theme_icon(SNAME("minimap")));  		layout_button->set_icon(get_theme_icon(SNAME("layout"))); + +		zoom_label->set_custom_minimum_size(Size2(48, 0) * get_theme_default_base_scale());  	}  	if (p_what == NOTIFICATION_READY) {  		Size2 hmin = h_scroll->get_combined_minimum_size(); @@ -816,11 +814,7 @@ void GraphEdit::_draw_connection_line(CanvasItem *p_where, const Vector2 &p_from  		scaled_points.push_back(points[i] * p_zoom);  	} -#ifdef TOOLS_ENABLED -	p_where->draw_polyline_colors(scaled_points, colors, Math::floor(p_width * EDSCALE), lines_antialiased); -#else -	p_where->draw_polyline_colors(scaled_points, colors, p_width, lines_antialiased); -#endif +	p_where->draw_polyline_colors(scaled_points, colors, Math::floor(p_width * get_theme_default_base_scale()), lines_antialiased);  }  void GraphEdit::_connections_layer_draw() { @@ -2272,11 +2266,7 @@ GraphEdit::GraphEdit() {  	zoom_label->set_visible(false);  	zoom_label->set_v_size_flags(Control::SIZE_SHRINK_CENTER);  	zoom_label->set_align(Label::ALIGN_CENTER); -#ifdef TOOLS_ENABLED -	zoom_label->set_custom_minimum_size(Size2(48, 0) * EDSCALE); -#else  	zoom_label->set_custom_minimum_size(Size2(48, 0)); -#endif  	_update_zoom_label();  	zoom_minus = memnew(Button); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 2c1092d8f9..653885aa08 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -40,7 +40,6 @@  #include "servers/display_server.h"  #include "servers/text_server.h"  #ifdef TOOLS_ENABLED -#include "editor/editor_scale.h"  #include "editor/editor_settings.h"  #endif  #include "scene/main/window.h" @@ -713,11 +712,7 @@ void LineEdit::_notification(int p_what) {  				ofs_max -= r_icon->get_width();  			} -#ifdef TOOLS_ENABLED -			int caret_width = Math::round(EDSCALE); -#else -			int caret_width = 1; -#endif +			int caret_width = Math::round(1 * get_theme_default_base_scale());  			// Draw selections rects.  			Vector2 ofs = Point2(x_ofs + scroll_offset, y_ofs); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index bc25177275..4588966d88 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -41,10 +41,6 @@  #include "modules/regex/regex.h"  #endif -#ifdef TOOLS_ENABLED -#include "editor/editor_scale.h" -#endif -  RichTextLabel::Item *RichTextLabel::_get_next_item(Item *p_item, bool p_free) const {  	if (p_free) {  		if (p_item->subitems.size()) { @@ -995,19 +991,13 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o  				Color uc = font_color;  				uc.a *= 0.5;  				float y_off = TS->shaped_text_get_underline_position(rid); -				float underline_width = TS->shaped_text_get_underline_thickness(rid); -#ifdef TOOLS_ENABLED -				underline_width *= EDSCALE; -#endif +				float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();  				draw_line(p_ofs + Vector2(off.x, off.y + y_off), p_ofs + Vector2(off.x + glyphs[i].advance * glyphs[i].repeat, off.y + y_off), uc, underline_width);  			} else if (_find_strikethrough(it)) {  				Color uc = font_color;  				uc.a *= 0.5;  				float y_off = -TS->shaped_text_get_ascent(rid) + TS->shaped_text_get_size(rid).y / 2; -				float underline_width = TS->shaped_text_get_underline_thickness(rid); -#ifdef TOOLS_ENABLED -				underline_width *= EDSCALE; -#endif +				float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();  				draw_line(p_ofs + Vector2(off.x, off.y + y_off), p_ofs + Vector2(off.x + glyphs[i].advance * glyphs[i].repeat, off.y + y_off), uc, underline_width);  			} diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index e2ddc761b8..875049ab4e 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -42,10 +42,6 @@  #include "scene/main/window.h" -#ifdef TOOLS_ENABLED -#include "editor/editor_scale.h" -#endif -  static bool _is_text_char(char32_t c) {  	return !is_symbol(c);  } @@ -1173,12 +1169,8 @@ void TextEdit::_notification(int p_what) {  						}  					} -					// Carets -#ifdef TOOLS_ENABLED -					int caret_width = Math::round(EDSCALE); -#else -					int caret_width = 1; -#endif +					// Carets. +					int caret_width = Math::round(1 * get_theme_default_base_scale());  					if (!clipped && caret.line == line && line_wrap_index == caret_wrap_index) {  						caret.draw_pos.y = ofs_y + ldata->get_line_descent(line_wrap_index); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 7d7596635c..3f041bf65a 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -41,10 +41,6 @@  #include "box_container.h" -#ifdef TOOLS_ENABLED -#include "editor/editor_scale.h" -#endif -  #include <limits.h>  Size2 TreeItem::Cell::get_icon_size() const { @@ -1377,6 +1373,8 @@ void Tree::update_cache() {  	cache.title_button_hover = get_theme_stylebox(SNAME("title_button_hover"));  	cache.title_button_color = get_theme_color(SNAME("title_button_color")); +	cache.base_scale = get_theme_default_base_scale(); +  	v_scroll->set_custom_step(cache.font->get_height(cache.font_size));  } @@ -2046,15 +2044,9 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2  						root_pos -= Point2i(cache.arrow->get_width(), 0);  					} -					float line_width = cache.relationship_line_width; -					float parent_line_width = cache.parent_hl_line_width; -					float children_line_width = cache.children_hl_line_width; - -#ifdef TOOLS_ENABLED -					line_width *= Math::round(EDSCALE); -					parent_line_width *= Math::round(EDSCALE); -					children_line_width *= Math::round(EDSCALE); -#endif +					float line_width = cache.relationship_line_width * Math::round(cache.base_scale); +					float parent_line_width = cache.parent_hl_line_width * Math::round(cache.base_scale); +					float children_line_width = cache.children_hl_line_width * Math::round(cache.base_scale);  					Point2i parent_pos = Point2i(parent_ofs - cache.arrow->get_width() / 2, p_pos.y + label_h / 2 + cache.arrow->get_height() / 2) - cache.offset + p_draw_ofs; diff --git a/scene/gui/tree.h b/scene/gui/tree.h index c4a6b6b058..6ca9458e9b 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -516,6 +516,8 @@ private:  		Color custom_button_font_highlight;  		Color font_outline_color; +		float base_scale = 1.0; +  		int hseparation = 0;  		int vseparation = 0;  		int item_margin = 0; diff --git a/scene/main/window.cpp b/scene/main/window.cpp index ca5a3915d0..a0f62c853f 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -1266,6 +1266,18 @@ bool Window::has_theme_constant(const StringName &p_name, const StringName &p_th  	return Control::has_theme_item_in_types(theme_owner, theme_owner_window, Theme::DATA_TYPE_CONSTANT, p_name, theme_types);  } +float Window::get_theme_default_base_scale() const { +	return Control::fetch_theme_default_base_scale(theme_owner, theme_owner_window); +} + +Ref<Font> Window::get_theme_default_font() const { +	return Control::fetch_theme_default_font(theme_owner, theme_owner_window); +} + +int Window::get_theme_default_font_size() const { +	return Control::fetch_theme_default_font_size(theme_owner, theme_owner_window); +} +  Rect2i Window::get_parent_rect() const {  	ERR_FAIL_COND_V(!is_inside_tree(), Rect2i());  	if (is_embedded()) { @@ -1480,6 +1492,10 @@ void Window::_bind_methods() {  	ClassDB::bind_method(D_METHOD("has_theme_color", "name", "theme_type"), &Window::has_theme_color, DEFVAL(""));  	ClassDB::bind_method(D_METHOD("has_theme_constant", "name", "theme_type"), &Window::has_theme_constant, DEFVAL("")); +	ClassDB::bind_method(D_METHOD("get_theme_default_base_scale"), &Window::get_theme_default_base_scale); +	ClassDB::bind_method(D_METHOD("get_theme_default_font"), &Window::get_theme_default_font); +	ClassDB::bind_method(D_METHOD("get_theme_default_font_size"), &Window::get_theme_default_font_size); +  	ClassDB::bind_method(D_METHOD("set_layout_direction", "direction"), &Window::set_layout_direction);  	ClassDB::bind_method(D_METHOD("get_layout_direction"), &Window::get_layout_direction);  	ClassDB::bind_method(D_METHOD("is_layout_rtl"), &Window::is_layout_rtl); diff --git a/scene/main/window.h b/scene/main/window.h index 4f31d9cd1f..def6eab7b8 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -280,6 +280,10 @@ public:  	bool has_theme_color(const StringName &p_name, const StringName &p_theme_type = StringName()) const;  	bool has_theme_constant(const StringName &p_name, const StringName &p_theme_type = StringName()) const; +	float get_theme_default_base_scale() const; +	Ref<Font> get_theme_default_font() const; +	int get_theme_default_font_size() const; +  	Rect2i get_parent_rect() const;  	virtual DisplayServer::WindowID get_window_id() const override; diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 94cf826477..54bb7a82cf 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -1036,9 +1036,16 @@ void make_default_theme(bool p_hidpi, Ref<Font> p_font) {  	}  	Ref<Font> large_font = default_font; -	fill_default_theme(t, default_font, large_font, default_icon, default_style, p_hidpi ? 2.0 : 1.0); + +	float default_scale = 1.0; +	if (p_hidpi) { +		default_scale = 2.0; +	} + +	fill_default_theme(t, default_font, large_font, default_icon, default_style, default_scale);  	Theme::set_default(t); +	Theme::set_default_base_scale(default_scale);  	Theme::set_default_icon(default_icon);  	Theme::set_default_style(default_style);  	Theme::set_default_font(default_font); diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index e49d883ba4..dd5f0b9c6c 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -29,270 +29,20 @@  /*************************************************************************/  #include "theme.h" -#include "core/io/file_access.h"  #include "core/string/print_string.h" -void Theme::_emit_theme_changed() { -	if (no_change_propagation) { -		return; -	} - -	notify_property_list_changed(); -	emit_changed(); -} - -Vector<String> Theme::_get_icon_list(const String &p_theme_type) const { -	Vector<String> ilret; -	List<StringName> il; - -	get_icon_list(p_theme_type, &il); -	ilret.resize(il.size()); - -	int i = 0; -	String *w = ilret.ptrw(); -	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { -		w[i] = E->get(); -	} -	return ilret; -} - -Vector<String> Theme::_get_icon_type_list() const { -	Vector<String> ilret; -	List<StringName> il; - -	get_icon_type_list(&il); -	ilret.resize(il.size()); - -	int i = 0; -	String *w = ilret.ptrw(); -	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { -		w[i] = E->get(); -	} -	return ilret; -} - -Vector<String> Theme::_get_stylebox_list(const String &p_theme_type) const { -	Vector<String> ilret; -	List<StringName> il; - -	get_stylebox_list(p_theme_type, &il); -	ilret.resize(il.size()); - -	int i = 0; -	String *w = ilret.ptrw(); -	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { -		w[i] = E->get(); -	} -	return ilret; -} - -Vector<String> Theme::_get_stylebox_type_list() const { -	Vector<String> ilret; -	List<StringName> il; - -	get_stylebox_type_list(&il); -	ilret.resize(il.size()); - -	int i = 0; -	String *w = ilret.ptrw(); -	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { -		w[i] = E->get(); -	} -	return ilret; -} - -Vector<String> Theme::_get_font_list(const String &p_theme_type) const { -	Vector<String> ilret; -	List<StringName> il; - -	get_font_list(p_theme_type, &il); -	ilret.resize(il.size()); - -	int i = 0; -	String *w = ilret.ptrw(); -	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { -		w[i] = E->get(); -	} -	return ilret; -} - -Vector<String> Theme::_get_font_type_list() const { -	Vector<String> ilret; -	List<StringName> il; - -	get_font_type_list(&il); -	ilret.resize(il.size()); - -	int i = 0; -	String *w = ilret.ptrw(); -	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { -		w[i] = E->get(); -	} -	return ilret; -} - -Vector<String> Theme::_get_font_size_list(const String &p_theme_type) const { -	Vector<String> ilret; -	List<StringName> il; - -	get_font_size_list(p_theme_type, &il); -	ilret.resize(il.size()); - -	int i = 0; -	String *w = ilret.ptrw(); -	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { -		w[i] = E->get(); -	} -	return ilret; -} - -Vector<String> Theme::_get_font_size_type_list() const { -	Vector<String> ilret; -	List<StringName> il; - -	get_font_size_type_list(&il); -	ilret.resize(il.size()); - -	int i = 0; -	String *w = ilret.ptrw(); -	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { -		w[i] = E->get(); -	} -	return ilret; -} - -Vector<String> Theme::_get_color_list(const String &p_theme_type) const { -	Vector<String> ilret; -	List<StringName> il; - -	get_color_list(p_theme_type, &il); -	ilret.resize(il.size()); - -	int i = 0; -	String *w = ilret.ptrw(); -	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { -		w[i] = E->get(); -	} -	return ilret; -} - -Vector<String> Theme::_get_color_type_list() const { -	Vector<String> ilret; -	List<StringName> il; - -	get_color_type_list(&il); -	ilret.resize(il.size()); - -	int i = 0; -	String *w = ilret.ptrw(); -	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { -		w[i] = E->get(); -	} -	return ilret; -} - -Vector<String> Theme::_get_constant_list(const String &p_theme_type) const { -	Vector<String> ilret; -	List<StringName> il; - -	get_constant_list(p_theme_type, &il); -	ilret.resize(il.size()); - -	int i = 0; -	String *w = ilret.ptrw(); -	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { -		w[i] = E->get(); -	} -	return ilret; -} - -Vector<String> Theme::_get_constant_type_list() const { -	Vector<String> ilret; -	List<StringName> il; - -	get_constant_type_list(&il); -	ilret.resize(il.size()); - -	int i = 0; -	String *w = ilret.ptrw(); -	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { -		w[i] = E->get(); -	} -	return ilret; -} - -Vector<String> Theme::_get_theme_item_list(DataType p_data_type, const String &p_theme_type) const { -	switch (p_data_type) { -		case DATA_TYPE_COLOR: -			return _get_color_list(p_theme_type); -		case DATA_TYPE_CONSTANT: -			return _get_constant_list(p_theme_type); -		case DATA_TYPE_FONT: -			return _get_font_list(p_theme_type); -		case DATA_TYPE_FONT_SIZE: -			return _get_font_size_list(p_theme_type); -		case DATA_TYPE_ICON: -			return _get_icon_list(p_theme_type); -		case DATA_TYPE_STYLEBOX: -			return _get_stylebox_list(p_theme_type); -		case DATA_TYPE_MAX: -			break; // Can't happen, but silences warning. -	} - -	return Vector<String>(); -} - -Vector<String> Theme::_get_theme_item_type_list(DataType p_data_type) const { -	switch (p_data_type) { -		case DATA_TYPE_COLOR: -			return _get_color_type_list(); -		case DATA_TYPE_CONSTANT: -			return _get_constant_type_list(); -		case DATA_TYPE_FONT: -			return _get_font_type_list(); -		case DATA_TYPE_FONT_SIZE: -			return _get_font_size_type_list(); -		case DATA_TYPE_ICON: -			return _get_icon_type_list(); -		case DATA_TYPE_STYLEBOX: -			return _get_stylebox_type_list(); -		case DATA_TYPE_MAX: -			break; // Can't happen, but silences warning. -	} - -	return Vector<String>(); -} - -Vector<String> Theme::_get_type_variation_list(const StringName &p_theme_type) const { -	Vector<String> ilret; -	List<StringName> il; - -	get_type_variation_list(p_theme_type, &il); -	ilret.resize(il.size()); - -	int i = 0; -	String *w = ilret.ptrw(); -	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { -		w[i] = E->get(); -	} -	return ilret; -} - -Vector<String> Theme::_get_type_list() const { -	Vector<String> ilret; -	List<StringName> il; - -	get_type_list(&il); -	ilret.resize(il.size()); +// Universal Theme resources used when no other theme has the item. +Ref<Theme> Theme::default_theme; +Ref<Theme> Theme::project_default_theme; -	int i = 0; -	String *w = ilret.ptrw(); -	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { -		w[i] = E->get(); -	} -	return ilret; -} +// Universal default values, final fallback for every theme. +float Theme::default_base_scale = 1.0; +Ref<Texture2D> Theme::default_icon; +Ref<StyleBox> Theme::default_style; +Ref<Font> Theme::default_font; +int Theme::default_font_size = 16; +// Dynamic properties.  bool Theme::_set(const StringName &p_name, const Variant &p_value) {  	String sname = p_name; @@ -452,6 +202,63 @@ void Theme::_get_property_list(List<PropertyInfo> *p_list) const {  	}  } +// Universal fallback Theme resources. +Ref<Theme> Theme::get_default() { +	return default_theme; +} + +void Theme::set_default(const Ref<Theme> &p_default) { +	default_theme = p_default; +} + +Ref<Theme> Theme::get_project_default() { +	return project_default_theme; +} + +void Theme::set_project_default(const Ref<Theme> &p_project_default) { +	project_default_theme = p_project_default; +} + +// Universal fallback values for theme item types. +void Theme::set_default_base_scale(float p_base_scale) { +	default_base_scale = p_base_scale; +} + +void Theme::set_default_icon(const Ref<Texture2D> &p_icon) { +	default_icon = p_icon; +} + +void Theme::set_default_style(const Ref<StyleBox> &p_style) { +	default_style = p_style; +} + +void Theme::set_default_font(const Ref<Font> &p_font) { +	default_font = p_font; +} + +void Theme::set_default_font_size(int p_font_size) { +	default_font_size = p_font_size; +} + +// Fallback values for theme item types, configurable per theme. +void Theme::set_default_theme_base_scale(float p_base_scale) { +	if (default_theme_base_scale == p_base_scale) { +		return; +	} + +	default_theme_base_scale = p_base_scale; + +	_emit_theme_changed(); +} + +float Theme::get_default_theme_base_scale() const { +	return default_theme_base_scale; +} + +bool Theme::has_default_theme_base_scale() const { +	return default_theme_base_scale > 0.0; +} +  void Theme::set_default_theme_font(const Ref<Font> &p_default_font) {  	if (default_theme_font == p_default_font) {  		return; @@ -474,6 +281,10 @@ Ref<Font> Theme::get_default_theme_font() const {  	return default_theme_font;  } +bool Theme::has_default_theme_font() const { +	return default_theme_font.is_valid(); +} +  void Theme::set_default_theme_font_size(int p_font_size) {  	if (default_theme_font_size == p_font_size) {  		return; @@ -488,45 +299,11 @@ int Theme::get_default_theme_font_size() const {  	return default_theme_font_size;  } -Ref<Theme> Theme::project_default_theme; -Ref<Theme> Theme::default_theme; -Ref<Texture2D> Theme::default_icon; -Ref<StyleBox> Theme::default_style; -Ref<Font> Theme::default_font; -int Theme::default_font_size = 16; - -Ref<Theme> Theme::get_default() { -	return default_theme; -} - -void Theme::set_default(const Ref<Theme> &p_default) { -	default_theme = p_default; -} - -Ref<Theme> Theme::get_project_default() { -	return project_default_theme; -} - -void Theme::set_project_default(const Ref<Theme> &p_project_default) { -	project_default_theme = p_project_default; -} - -void Theme::set_default_icon(const Ref<Texture2D> &p_icon) { -	default_icon = p_icon; -} - -void Theme::set_default_style(const Ref<StyleBox> &p_style) { -	default_style = p_style; -} - -void Theme::set_default_font(const Ref<Font> &p_font) { -	default_font = p_font; -} - -void Theme::set_default_font_size(int p_font_size) { -	default_font_size = p_font_size; +bool Theme::has_default_theme_font_size() const { +	return default_theme_font_size > 0;  } +// Icons.  void Theme::set_icon(const StringName &p_name, const StringName &p_theme_type, const Ref<Texture2D> &p_icon) {  	if (icon_map[p_theme_type].has(p_name) && icon_map[p_theme_type][p_name].is_valid()) {  		icon_map[p_theme_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); @@ -611,6 +388,7 @@ void Theme::get_icon_type_list(List<StringName> *p_list) const {  	}  } +// Styleboxes.  void Theme::set_stylebox(const StringName &p_name, const StringName &p_theme_type, const Ref<StyleBox> &p_style) {  	if (style_map[p_theme_type].has(p_name) && style_map[p_theme_type][p_name].is_valid()) {  		style_map[p_theme_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); @@ -695,6 +473,7 @@ void Theme::get_stylebox_type_list(List<StringName> *p_list) const {  	}  } +// Fonts.  void Theme::set_font(const StringName &p_name, const StringName &p_theme_type, const Ref<Font> &p_font) {  	if (font_map[p_theme_type][p_name].is_valid()) {  		font_map[p_theme_type][p_name]->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); @@ -712,7 +491,7 @@ void Theme::set_font(const StringName &p_name, const StringName &p_theme_type, c  Ref<Font> Theme::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 (default_theme_font.is_valid()) { +	} else if (has_default_theme_font()) {  		return default_theme_font;  	} else {  		return default_font; @@ -720,7 +499,7 @@ Ref<Font> Theme::get_font(const StringName &p_name, const StringName &p_theme_ty  }  bool Theme::has_font(const StringName &p_name, const StringName &p_theme_type) const { -	return ((font_map.has(p_theme_type) && font_map[p_theme_type].has(p_name) && font_map[p_theme_type][p_name].is_valid()) || default_theme_font.is_valid()); +	return ((font_map.has(p_theme_type) && font_map[p_theme_type].has(p_name) && font_map[p_theme_type][p_name].is_valid()) || has_default_theme_font());  }  bool Theme::has_font_nocheck(const StringName &p_name, const StringName &p_theme_type) const { @@ -781,6 +560,7 @@ void Theme::get_font_type_list(List<StringName> *p_list) const {  	}  } +// Font sizes.  void Theme::set_font_size(const StringName &p_name, const StringName &p_theme_type, int p_font_size) {  	font_size_map[p_theme_type][p_name] = p_font_size; @@ -790,7 +570,7 @@ void Theme::set_font_size(const StringName &p_name, const StringName &p_theme_ty  int Theme::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 (default_theme_font_size > 0) { +	} else if (has_default_theme_font_size()) {  		return default_theme_font_size;  	} else {  		return default_font_size; @@ -798,7 +578,7 @@ int Theme::get_font_size(const StringName &p_name, const StringName &p_theme_typ  }  bool Theme::has_font_size(const StringName &p_name, const StringName &p_theme_type) const { -	return ((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)) || (default_theme_font_size > 0)); +	return ((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)) || has_default_theme_font_size());  }  bool Theme::has_font_size_nocheck(const StringName &p_name, const StringName &p_theme_type) const { @@ -855,6 +635,7 @@ void Theme::get_font_size_type_list(List<StringName> *p_list) const {  	}  } +// Colors.  void Theme::set_color(const StringName &p_name, const StringName &p_theme_type, const Color &p_color) {  	color_map[p_theme_type][p_name] = p_color; @@ -927,6 +708,7 @@ void Theme::get_color_type_list(List<StringName> *p_list) const {  	}  } +// Theme constants.  void Theme::set_constant(const StringName &p_name, const StringName &p_theme_type, int p_constant) {  	constant_map[p_theme_type][p_name] = p_constant; @@ -999,6 +781,7 @@ void Theme::get_constant_type_list(List<StringName> *p_list) const {  	}  } +// Generic methods for managing theme items.  void Theme::set_theme_item(DataType p_data_type, const StringName &p_name, const StringName &p_theme_type, const Variant &p_value) {  	switch (p_data_type) {  		case DATA_TYPE_COLOR: { @@ -1230,6 +1013,7 @@ void Theme::get_theme_item_type_list(DataType p_data_type, List<StringName> *p_l  	}  } +// Theme type variations.  void Theme::set_type_variation(const StringName &p_theme_type, const StringName &p_base_type) {  	ERR_FAIL_COND_MSG(p_theme_type == StringName(), "An empty theme type cannot be marked as a variation of another type.");  	ERR_FAIL_COND_MSG(ClassDB::class_exists(p_theme_type), "A type associated with a built-in class cannot be marked as a variation of another type."); @@ -1287,66 +1071,352 @@ void Theme::get_type_variation_list(const StringName &p_base_type, List<StringNa  	}  } -void Theme::_freeze_change_propagation() { -	no_change_propagation = true; -} +// Theme types. +void Theme::get_type_list(List<StringName> *p_list) const { +	ERR_FAIL_NULL(p_list); -void Theme::_unfreeze_and_propagate_changes() { -	no_change_propagation = false; -	_emit_theme_changed(); +	Set<StringName> types; +	const StringName *key = nullptr; + +	// Icons. +	while ((key = icon_map.next(key))) { +		types.insert(*key); +	} + +	key = nullptr; + +	// StyleBoxes. +	while ((key = style_map.next(key))) { +		types.insert(*key); +	} + +	key = nullptr; + +	// Fonts. +	while ((key = font_map.next(key))) { +		types.insert(*key); +	} + +	key = nullptr; + +	// Font sizes. +	while ((key = font_size_map.next(key))) { +		types.insert(*key); +	} + +	key = nullptr; + +	// Colors. +	while ((key = color_map.next(key))) { +		types.insert(*key); +	} + +	key = nullptr; + +	// Constants. +	while ((key = constant_map.next(key))) { +		types.insert(*key); +	} + +	for (Set<StringName>::Element *E = types.front(); E; E = E->next()) { +		p_list->push_back(E->get()); +	}  } -void Theme::clear() { -	// These items need disconnecting. -	{ -		const StringName *K = nullptr; -		while ((K = icon_map.next(K))) { -			const StringName *L = nullptr; -			while ((L = icon_map[*K].next(L))) { -				Ref<Texture2D> icon = icon_map[*K][*L]; -				if (icon.is_valid()) { -					icon->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); -				} +void Theme::get_type_dependencies(const StringName &p_base_type, const StringName &p_type_variation, List<StringName> *p_list) { +	ERR_FAIL_NULL(p_list); + +	// Build the dependency chain for type variations. +	if (p_type_variation != StringName()) { +		StringName variation_name = p_type_variation; +		while (variation_name != StringName()) { +			p_list->push_back(variation_name); +			variation_name = get_type_variation_base(variation_name); + +			// If we have reached the base type dependency, it's safe to stop (assuming no funny business was done to the Theme). +			if (variation_name == p_base_type) { +				break;  			}  		}  	} -	{ -		const StringName *K = nullptr; -		while ((K = style_map.next(K))) { -			const StringName *L = nullptr; -			while ((L = style_map[*K].next(L))) { -				Ref<StyleBox> style = style_map[*K][*L]; -				if (style.is_valid()) { -					style->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); -				} -			} -		} +	// Continue building the chain using native class hierarchy. +	StringName class_name = p_base_type; +	while (class_name != StringName()) { +		p_list->push_back(class_name); +		class_name = ClassDB::get_parent_class_nocheck(class_name);  	} +} -	{ -		const StringName *K = nullptr; -		while ((K = font_map.next(K))) { -			const StringName *L = nullptr; -			while ((L = font_map[*K].next(L))) { -				Ref<Font> font = font_map[*K][*L]; -				if (font.is_valid()) { -					font->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); -				} -			} -		} +// Internal methods for getting lists as a Vector of String (compatible with public API). +Vector<String> Theme::_get_icon_list(const String &p_theme_type) const { +	Vector<String> ilret; +	List<StringName> il; + +	get_icon_list(p_theme_type, &il); +	ilret.resize(il.size()); + +	int i = 0; +	String *w = ilret.ptrw(); +	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { +		w[i] = E->get();  	} +	return ilret; +} -	icon_map.clear(); -	style_map.clear(); -	font_map.clear(); -	font_size_map.clear(); -	color_map.clear(); -	constant_map.clear(); +Vector<String> Theme::_get_icon_type_list() const { +	Vector<String> ilret; +	List<StringName> il; -	variation_map.clear(); -	variation_base_map.clear(); +	get_icon_type_list(&il); +	ilret.resize(il.size()); + +	int i = 0; +	String *w = ilret.ptrw(); +	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { +		w[i] = E->get(); +	} +	return ilret; +} + +Vector<String> Theme::_get_stylebox_list(const String &p_theme_type) const { +	Vector<String> ilret; +	List<StringName> il; + +	get_stylebox_list(p_theme_type, &il); +	ilret.resize(il.size()); + +	int i = 0; +	String *w = ilret.ptrw(); +	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { +		w[i] = E->get(); +	} +	return ilret; +} + +Vector<String> Theme::_get_stylebox_type_list() const { +	Vector<String> ilret; +	List<StringName> il; + +	get_stylebox_type_list(&il); +	ilret.resize(il.size()); + +	int i = 0; +	String *w = ilret.ptrw(); +	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { +		w[i] = E->get(); +	} +	return ilret; +} + +Vector<String> Theme::_get_font_list(const String &p_theme_type) const { +	Vector<String> ilret; +	List<StringName> il; + +	get_font_list(p_theme_type, &il); +	ilret.resize(il.size()); + +	int i = 0; +	String *w = ilret.ptrw(); +	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { +		w[i] = E->get(); +	} +	return ilret; +} + +Vector<String> Theme::_get_font_type_list() const { +	Vector<String> ilret; +	List<StringName> il; + +	get_font_type_list(&il); +	ilret.resize(il.size()); + +	int i = 0; +	String *w = ilret.ptrw(); +	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { +		w[i] = E->get(); +	} +	return ilret; +} + +Vector<String> Theme::_get_font_size_list(const String &p_theme_type) const { +	Vector<String> ilret; +	List<StringName> il; + +	get_font_size_list(p_theme_type, &il); +	ilret.resize(il.size()); + +	int i = 0; +	String *w = ilret.ptrw(); +	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { +		w[i] = E->get(); +	} +	return ilret; +} + +Vector<String> Theme::_get_font_size_type_list() const { +	Vector<String> ilret; +	List<StringName> il; + +	get_font_size_type_list(&il); +	ilret.resize(il.size()); + +	int i = 0; +	String *w = ilret.ptrw(); +	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { +		w[i] = E->get(); +	} +	return ilret; +} + +Vector<String> Theme::_get_color_list(const String &p_theme_type) const { +	Vector<String> ilret; +	List<StringName> il; + +	get_color_list(p_theme_type, &il); +	ilret.resize(il.size()); + +	int i = 0; +	String *w = ilret.ptrw(); +	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { +		w[i] = E->get(); +	} +	return ilret; +} + +Vector<String> Theme::_get_color_type_list() const { +	Vector<String> ilret; +	List<StringName> il; + +	get_color_type_list(&il); +	ilret.resize(il.size()); + +	int i = 0; +	String *w = ilret.ptrw(); +	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { +		w[i] = E->get(); +	} +	return ilret; +} + +Vector<String> Theme::_get_constant_list(const String &p_theme_type) const { +	Vector<String> ilret; +	List<StringName> il; + +	get_constant_list(p_theme_type, &il); +	ilret.resize(il.size()); + +	int i = 0; +	String *w = ilret.ptrw(); +	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { +		w[i] = E->get(); +	} +	return ilret; +} + +Vector<String> Theme::_get_constant_type_list() const { +	Vector<String> ilret; +	List<StringName> il; +	get_constant_type_list(&il); +	ilret.resize(il.size()); + +	int i = 0; +	String *w = ilret.ptrw(); +	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { +		w[i] = E->get(); +	} +	return ilret; +} + +Vector<String> Theme::_get_theme_item_list(DataType p_data_type, const String &p_theme_type) const { +	switch (p_data_type) { +		case DATA_TYPE_COLOR: +			return _get_color_list(p_theme_type); +		case DATA_TYPE_CONSTANT: +			return _get_constant_list(p_theme_type); +		case DATA_TYPE_FONT: +			return _get_font_list(p_theme_type); +		case DATA_TYPE_FONT_SIZE: +			return _get_font_size_list(p_theme_type); +		case DATA_TYPE_ICON: +			return _get_icon_list(p_theme_type); +		case DATA_TYPE_STYLEBOX: +			return _get_stylebox_list(p_theme_type); +		case DATA_TYPE_MAX: +			break; // Can't happen, but silences warning. +	} + +	return Vector<String>(); +} + +Vector<String> Theme::_get_theme_item_type_list(DataType p_data_type) const { +	switch (p_data_type) { +		case DATA_TYPE_COLOR: +			return _get_color_type_list(); +		case DATA_TYPE_CONSTANT: +			return _get_constant_type_list(); +		case DATA_TYPE_FONT: +			return _get_font_type_list(); +		case DATA_TYPE_FONT_SIZE: +			return _get_font_size_type_list(); +		case DATA_TYPE_ICON: +			return _get_icon_type_list(); +		case DATA_TYPE_STYLEBOX: +			return _get_stylebox_type_list(); +		case DATA_TYPE_MAX: +			break; // Can't happen, but silences warning. +	} + +	return Vector<String>(); +} + +Vector<String> Theme::_get_type_variation_list(const StringName &p_theme_type) const { +	Vector<String> ilret; +	List<StringName> il; + +	get_type_variation_list(p_theme_type, &il); +	ilret.resize(il.size()); + +	int i = 0; +	String *w = ilret.ptrw(); +	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { +		w[i] = E->get(); +	} +	return ilret; +} + +Vector<String> Theme::_get_type_list() const { +	Vector<String> ilret; +	List<StringName> il; + +	get_type_list(&il); +	ilret.resize(il.size()); + +	int i = 0; +	String *w = ilret.ptrw(); +	for (List<StringName>::Element *E = il.front(); E; E = E->next(), i++) { +		w[i] = E->get(); +	} +	return ilret; +} + +// Theme bulk manipulations. +void Theme::_emit_theme_changed() { +	if (no_change_propagation) { +		return; +	} + +	notify_property_list_changed(); +	emit_changed(); +} + +void Theme::_freeze_change_propagation() { +	no_change_propagation = true; +} + +void Theme::_unfreeze_and_propagate_changes() { +	no_change_propagation = false;  	_emit_theme_changed();  } @@ -1434,80 +1504,58 @@ void Theme::merge_with(const Ref<Theme> &p_other) {  	_unfreeze_and_propagate_changes();  } -void Theme::get_type_list(List<StringName> *p_list) const { -	ERR_FAIL_NULL(p_list); - -	Set<StringName> types; -	const StringName *key = nullptr; - -	// Icons. -	while ((key = icon_map.next(key))) { -		types.insert(*key); -	} - -	key = nullptr; - -	// StyleBoxes. -	while ((key = style_map.next(key))) { -		types.insert(*key); -	} - -	key = nullptr; - -	// Fonts. -	while ((key = font_map.next(key))) { -		types.insert(*key); -	} - -	key = nullptr; - -	// Font sizes. -	while ((key = font_size_map.next(key))) { -		types.insert(*key); -	} - -	key = nullptr; - -	// Colors. -	while ((key = color_map.next(key))) { -		types.insert(*key); -	} - -	key = nullptr; - -	// Constants. -	while ((key = constant_map.next(key))) { -		types.insert(*key); +void Theme::clear() { +	// These items need disconnecting. +	{ +		const StringName *K = nullptr; +		while ((K = icon_map.next(K))) { +			const StringName *L = nullptr; +			while ((L = icon_map[*K].next(L))) { +				Ref<Texture2D> icon = icon_map[*K][*L]; +				if (icon.is_valid()) { +					icon->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); +				} +			} +		}  	} -	for (Set<StringName>::Element *E = types.front(); E; E = E->next()) { -		p_list->push_back(E->get()); +	{ +		const StringName *K = nullptr; +		while ((K = style_map.next(K))) { +			const StringName *L = nullptr; +			while ((L = style_map[*K].next(L))) { +				Ref<StyleBox> style = style_map[*K][*L]; +				if (style.is_valid()) { +					style->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); +				} +			} +		}  	} -} - -void Theme::get_type_dependencies(const StringName &p_base_type, const StringName &p_type_variation, List<StringName> *p_list) { -	ERR_FAIL_NULL(p_list); -	// Build the dependency chain for type variations. -	if (p_type_variation != StringName()) { -		StringName variation_name = p_type_variation; -		while (variation_name != StringName()) { -			p_list->push_back(variation_name); -			variation_name = get_type_variation_base(variation_name); - -			// If we have reached the base type dependency, it's safe to stop (assuming no funny business was done to the Theme). -			if (variation_name == p_base_type) { -				break; +	{ +		const StringName *K = nullptr; +		while ((K = font_map.next(K))) { +			const StringName *L = nullptr; +			while ((L = font_map[*K].next(L))) { +				Ref<Font> font = font_map[*K][*L]; +				if (font.is_valid()) { +					font->disconnect("changed", callable_mp(this, &Theme::_emit_theme_changed)); +				}  			}  		}  	} -	// Continue building the chain using native class hierarchy. -	StringName class_name = p_base_type; -	while (class_name != StringName()) { -		p_list->push_back(class_name); -		class_name = ClassDB::get_parent_class_nocheck(class_name); -	} +	icon_map.clear(); +	style_map.clear(); +	font_map.clear(); +	font_size_map.clear(); +	color_map.clear(); +	constant_map.clear(); + +	variation_map.clear(); +	variation_base_map.clear(); + +	_emit_theme_changed();  }  void Theme::reset_state() { @@ -1563,11 +1611,17 @@ void Theme::_bind_methods() {  	ClassDB::bind_method(D_METHOD("get_constant_list", "theme_type"), &Theme::_get_constant_list);  	ClassDB::bind_method(D_METHOD("get_constant_type_list"), &Theme::_get_constant_type_list); +	ClassDB::bind_method(D_METHOD("set_default_base_scale", "font_size"), &Theme::set_default_theme_base_scale); +	ClassDB::bind_method(D_METHOD("get_default_base_scale"), &Theme::get_default_theme_base_scale); +	ClassDB::bind_method(D_METHOD("has_default_base_scale"), &Theme::has_default_theme_base_scale); +  	ClassDB::bind_method(D_METHOD("set_default_font", "font"), &Theme::set_default_theme_font);  	ClassDB::bind_method(D_METHOD("get_default_font"), &Theme::get_default_theme_font); +	ClassDB::bind_method(D_METHOD("has_default_font"), &Theme::has_default_theme_font);  	ClassDB::bind_method(D_METHOD("set_default_font_size", "font_size"), &Theme::set_default_theme_font_size);  	ClassDB::bind_method(D_METHOD("get_default_font_size"), &Theme::get_default_theme_font_size); +	ClassDB::bind_method(D_METHOD("has_default_font_size"), &Theme::has_default_theme_font_size);  	ClassDB::bind_method(D_METHOD("set_theme_item", "data_type", "name", "theme_type", "value"), &Theme::set_theme_item);  	ClassDB::bind_method(D_METHOD("get_theme_item", "data_type", "name", "theme_type"), &Theme::get_theme_item); @@ -1588,6 +1642,7 @@ void Theme::_bind_methods() {  	ClassDB::bind_method(D_METHOD("merge_with", "other"), &Theme::merge_with);  	ClassDB::bind_method(D_METHOD("clear"), &Theme::clear); +	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "default_base_scale", PROPERTY_HINT_RANGE, "0.0,2.0,0.01,or_greater"), "set_default_base_scale", "get_default_base_scale");  	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "default_font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_default_font", "get_default_font");  	ADD_PROPERTY(PropertyInfo(Variant::INT, "default_font_size"), "set_default_font_size", "get_default_font_size"); diff --git a/scene/resources/theme.h b/scene/resources/theme.h index 15f21b91b8..50466d99c2 100644 --- a/scene/resources/theme.h +++ b/scene/resources/theme.h @@ -96,13 +96,19 @@ protected:  	bool _get(const StringName &p_name, Variant &r_ret) const;  	void _get_property_list(List<PropertyInfo> *p_list) const; -	static Ref<Theme> project_default_theme; +	// Universal Theme resources used when no other theme has the item.  	static Ref<Theme> default_theme; +	static Ref<Theme> project_default_theme; + +	// Universal default values, final fallback for every theme. +	static float default_base_scale;  	static Ref<Texture2D> default_icon;  	static Ref<StyleBox> default_style;  	static Ref<Font> default_font;  	static int default_font_size; +	// Default values configurable for each individual theme. +	float default_theme_base_scale = 0.0;  	Ref<Font> default_theme_font;  	int default_theme_font_size = -1; @@ -120,16 +126,23 @@ public:  	static Ref<Theme> get_project_default();  	static void set_project_default(const Ref<Theme> &p_project_default); +	static void set_default_base_scale(float p_base_scale);  	static void set_default_icon(const Ref<Texture2D> &p_icon);  	static void set_default_style(const Ref<StyleBox> &p_style);  	static void set_default_font(const Ref<Font> &p_font);  	static void set_default_font_size(int p_font_size); +	void set_default_theme_base_scale(float p_base_scale); +	float get_default_theme_base_scale() const; +	bool has_default_theme_base_scale() const; +  	void set_default_theme_font(const Ref<Font> &p_default_font);  	Ref<Font> get_default_theme_font() const; +	bool has_default_theme_font() const;  	void set_default_theme_font_size(int p_font_size);  	int get_default_theme_font_size() const; +	bool has_default_theme_font_size() const;  	void set_icon(const StringName &p_name, const StringName &p_theme_type, const Ref<Texture2D> &p_icon);  	Ref<Texture2D> get_icon(const StringName &p_name, const StringName &p_theme_type) const;  |