Add ThemeDB, expose previously static Theme methods

This commit is contained in:
Yuri Sizov 2022-08-08 19:29:36 +03:00
parent c8ef12a03a
commit 6320a0fc18
25 changed files with 589 additions and 311 deletions

View File

@ -1297,6 +1297,9 @@
<member name="TextServerManager" type="TextServerManager" setter="" getter=""> <member name="TextServerManager" type="TextServerManager" setter="" getter="">
The [TextServerManager] singleton. The [TextServerManager] singleton.
</member> </member>
<member name="ThemeDB" type="ThemeDB" setter="" getter="">
The [ThemeDB] singleton.
</member>
<member name="Time" type="Time" setter="" getter=""> <member name="Time" type="Time" setter="" getter="">
The [Time] singleton. The [Time] singleton.
</member> </member>

View File

@ -436,7 +436,7 @@
<param index="1" name="theme_type" type="StringName" default="&quot;&quot;" /> <param index="1" name="theme_type" type="StringName" default="&quot;&quot;" />
<description> <description>
Returns a [Color] from the first matching [Theme] in the tree if that [Theme] has a color item with the specified [param name] and [param theme_type]. If [param theme_type] is omitted the class name of the current control is used as the type, or [member theme_type_variation] if it is defined. If the type is a class name its parent classes are also checked, in order of inheritance. If the type is a variation its base types are checked, in order of dependency, then the control's class name and its parent classes are checked. Returns a [Color] from the first matching [Theme] in the tree if that [Theme] has a color item with the specified [param name] and [param theme_type]. If [param theme_type] is omitted the class name of the current control is used as the type, or [member theme_type_variation] if it is defined. If the type is a class name its parent classes are also checked, in order of inheritance. If the type is a variation its base types are checked, in order of dependency, then the control's class name and its parent classes are checked.
For the current control its local overrides are considered first (see [method add_theme_color_override]), then its assigned [member theme]. After the current control, each parent control and its assigned [member theme] are considered; controls without a [member theme] assigned are skipped. If no matching [Theme] is found in the tree, a custom project [Theme] (see [member ProjectSettings.gui/theme/custom]) and the default [Theme] are used. For the current control its local overrides are considered first (see [method add_theme_color_override]), then its assigned [member theme]. After the current control, each parent control and its assigned [member theme] are considered; controls without a [member theme] assigned are skipped. If no matching [Theme] is found in the tree, the custom project [Theme] (see [member ProjectSettings.gui/theme/custom]) and the default [Theme] are used (see [ThemeDB]).
[codeblocks] [codeblocks]
[gdscript] [gdscript]
func _ready(): func _ready():

View File

@ -150,7 +150,7 @@
<description> <description>
Returns the [Font] property defined by [param name] and [param theme_type], if it exists. Returns the [Font] property defined by [param name] and [param theme_type], if it exists.
Returns the default theme font if the property doesn't exist and the default theme font is set up (see [member default_font]). Use [method has_font] to check for existence of the property and [method has_default_font] to check for existence of the default theme font. Returns the default theme font if the property doesn't exist and the default theme font is set up (see [member default_font]). Use [method has_font] to check for existence of the property and [method has_default_font] to check for existence of the default theme font.
Returns the engine fallback font value, if neither exist. Returns the engine fallback font value, if neither exist (see [member ThemeDB.fallback_font]).
</description> </description>
</method> </method>
<method name="get_font_list" qualifiers="const"> <method name="get_font_list" qualifiers="const">
@ -167,7 +167,7 @@
<description> <description>
Returns the font size property defined by [param name] and [param theme_type], if it exists. Returns the font size property defined by [param name] and [param theme_type], if it exists.
Returns the default theme font size if the property doesn't exist and the default theme font size is set up (see [member default_font_size]). Use [method has_font_size] to check for existence of the property and [method has_default_font_size] to check for existence of the default theme font. Returns the default theme font size if the property doesn't exist and the default theme font size is set up (see [member default_font_size]). Use [method has_font_size] to check for existence of the property and [method has_default_font_size] to check for existence of the default theme font.
Returns the engine fallback font size value, if neither exist. Returns the engine fallback font size value, if neither exist (see [member ThemeDB.fallback_font_size]).
</description> </description>
</method> </method>
<method name="get_font_size_list" qualifiers="const"> <method name="get_font_size_list" qualifiers="const">
@ -195,7 +195,7 @@
<param index="1" name="theme_type" type="StringName" /> <param index="1" name="theme_type" type="StringName" />
<description> <description>
Returns the icon property defined by [param name] and [param theme_type], if it exists. Returns the icon property defined by [param name] and [param theme_type], if it exists.
Returns the engine fallback icon value if the property doesn't exist. Use [method has_icon] to check for existence. Returns the engine fallback icon value if the property doesn't exist (see [member ThemeDB.fallback_icon]). Use [method has_icon] to check for existence.
</description> </description>
</method> </method>
<method name="get_icon_list" qualifiers="const"> <method name="get_icon_list" qualifiers="const">
@ -217,7 +217,7 @@
<param index="1" name="theme_type" type="StringName" /> <param index="1" name="theme_type" type="StringName" />
<description> <description>
Returns the [StyleBox] property defined by [param name] and [param theme_type], if it exists. Returns the [StyleBox] property defined by [param name] and [param theme_type], if it exists.
Returns the engine fallback stylebox value if the property doesn't exist. Use [method has_stylebox] to check for existence. Returns the engine fallback stylebox value if the property doesn't exist (see [member ThemeDB.fallback_stylebox]). Use [method has_stylebox] to check for existence.
</description> </description>
</method> </method>
<method name="get_stylebox_list" qualifiers="const"> <method name="get_stylebox_list" qualifiers="const">
@ -240,7 +240,7 @@
<param index="2" name="theme_type" type="StringName" /> <param index="2" name="theme_type" type="StringName" />
<description> <description>
Returns the theme property of [param data_type] defined by [param name] and [param theme_type], if it exists. Returns the theme property of [param data_type] defined by [param name] and [param theme_type], if it exists.
Returns the engine fallback icon value if the property doesn't exist. Use [method has_theme_item] to check for existence. Returns the engine fallback icon value if the property doesn't exist (see [ThemeDB]). Use [method has_theme_item] to check for existence.
[b]Note:[/b] This method is analogous to calling the corresponding data type specific method, but can be used for more generalized logic. [b]Note:[/b] This method is analogous to calling the corresponding data type specific method, but can be used for more generalized logic.
</description> </description>
</method> </method>
@ -542,15 +542,15 @@
</methods> </methods>
<members> <members>
<member name="default_base_scale" type="float" setter="set_default_base_scale" getter="get_default_base_scale" default="0.0"> <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 the global scale factor. If this value is set to [code]0.0[/code], the global scale factor is used. The default base scale factor of this theme resource. Used by some controls to scale their visual properties based on the global scale factor. If this value is set to [code]0.0[/code], the global scale factor is used (see [member ThemeDB.fallback_base_scale]).
Use [method has_default_base_scale] to check if this value is valid. Use [method has_default_base_scale] to check if this value is valid.
</member> </member>
<member name="default_font" type="Font" setter="set_default_font" getter="get_default_font"> <member name="default_font" type="Font" setter="set_default_font" getter="get_default_font">
The default font of this theme resource. Used as the default value when trying to fetch a font resource that doesn't exist in this theme or is in invalid state. If the default font is also missing or invalid, the engine fallback value is used. The default font of this theme resource. Used as the default value when trying to fetch a font resource that doesn't exist in this theme or is in invalid state. If the default font is also missing or invalid, the engine fallback value is used (see [member ThemeDB.fallback_font]).
Use [method has_default_font] to check if this value is valid. Use [method has_default_font] to check if this value is valid.
</member> </member>
<member name="default_font_size" type="int" setter="set_default_font_size" getter="get_default_font_size" default="-1"> <member name="default_font_size" type="int" setter="set_default_font_size" getter="get_default_font_size" default="-1">
The default font size of this theme resource. Used as the default value when trying to fetch a font size value that doesn't exist in this theme or is in invalid state. If the default font size is also missing or invalid, the engine fallback value is used. The default font size of this theme resource. Used as the default value when trying to fetch a font size value that doesn't exist in this theme or is in invalid state. If the default font size is also missing or invalid, the engine fallback value is used (see [member ThemeDB.fallback_font_size]).
Values below [code]0[/code] are invalid and can be used to unset the property. Use [method has_default_font_size] to check if this value is valid. Values below [code]0[/code] are invalid and can be used to unset the property. Use [method has_default_font_size] to check if this value is valid.
</member> </member>
</members> </members>

54
doc/classes/ThemeDB.xml Normal file
View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="ThemeDB" inherits="Object" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
An engine singleton providing access to static [Theme] information, such as default and project theme, and fallback values.
</brief_description>
<description>
This engine singleton provides access to static information about [Theme] resources used by the engine and by your projects. You can fetch the default engine theme, as well as your project configured theme.
[ThemeDB] also contains fallback values for theme properties.
</description>
<tutorials>
</tutorials>
<methods>
<method name="get_default_theme">
<return type="Theme" />
<description>
Returns a reference to the default engine [Theme]. This theme resource is responsible for the out-of-the-box look of [Control] nodes and cannot be overridden.
</description>
</method>
<method name="get_project_theme">
<return type="Theme" />
<description>
Returns a reference to the custom project [Theme]. This theme resources allows to override the default engine theme for every control node in the project.
To set the project theme, see [member ProjectSettings.gui/theme/custom].
</description>
</method>
</methods>
<members>
<member name="fallback_base_scale" type="float" setter="set_fallback_base_scale" getter="get_fallback_base_scale" default="1.0">
The fallback base scale factor of every [Control] node and [Theme] resource. Used when no other value is available to the control.
See also [member Theme.default_base_scale].
</member>
<member name="fallback_font" type="Font" setter="set_fallback_font" getter="get_fallback_font">
The fallback font of every [Control] node and [Theme] resource. Used when no other value is available to the control.
See also [member Theme.default_font].
</member>
<member name="fallback_font_size" type="int" setter="set_fallback_font_size" getter="get_fallback_font_size" default="16">
The fallback font size of every [Control] node and [Theme] resource. Used when no other value is available to the control.
See also [member Theme.default_font_size].
</member>
<member name="fallback_icon" type="Texture2D" setter="set_fallback_icon" getter="get_fallback_icon">
The fallback icon of every [Control] node and [Theme] resource. Used when no other value is available to the control.
</member>
<member name="fallback_stylebox" type="StyleBox" setter="set_fallback_stylebox" getter="get_fallback_stylebox">
The fallback stylebox of every [Control] node and [Theme] resource. Used when no other value is available to the control.
</member>
</members>
<signals>
<signal name="fallback_changed">
<description>
Emitted when one of the fallback values had been changed. Use it to refresh the look of controls that may rely on the fallback theme items.
</description>
</signal>
</signals>
</class>

View File

@ -41,6 +41,7 @@
#include "core/version.h" #include "core/version.h"
#include "editor/editor_settings.h" #include "editor/editor_settings.h"
#include "scene/resources/theme.h" #include "scene/resources/theme.h"
#include "scene/theme/theme_db.h"
// Used for a hack preserving Mono properties on non-Mono builds. // Used for a hack preserving Mono properties on non-Mono builds.
#include "modules/modules_enabled.gen.h" // For mono. #include "modules/modules_enabled.gen.h" // For mono.
@ -567,29 +568,29 @@ void DocTools::generate(bool p_basic_types) {
{ {
List<StringName> l; List<StringName> l;
Theme::get_default()->get_color_list(cname, &l); ThemeDB::get_singleton()->get_default_theme()->get_color_list(cname, &l);
for (const StringName &E : l) { for (const StringName &E : l) {
DocData::ThemeItemDoc tid; DocData::ThemeItemDoc tid;
tid.name = E; tid.name = E;
tid.type = "Color"; tid.type = "Color";
tid.data_type = "color"; tid.data_type = "color";
tid.default_value = Variant(Theme::get_default()->get_color(E, cname)).get_construct_string().replace("\n", " "); tid.default_value = Variant(ThemeDB::get_singleton()->get_default_theme()->get_color(E, cname)).get_construct_string().replace("\n", " ");
c.theme_properties.push_back(tid); c.theme_properties.push_back(tid);
} }
l.clear(); l.clear();
Theme::get_default()->get_constant_list(cname, &l); ThemeDB::get_singleton()->get_default_theme()->get_constant_list(cname, &l);
for (const StringName &E : l) { for (const StringName &E : l) {
DocData::ThemeItemDoc tid; DocData::ThemeItemDoc tid;
tid.name = E; tid.name = E;
tid.type = "int"; tid.type = "int";
tid.data_type = "constant"; tid.data_type = "constant";
tid.default_value = itos(Theme::get_default()->get_constant(E, cname)); tid.default_value = itos(ThemeDB::get_singleton()->get_default_theme()->get_constant(E, cname));
c.theme_properties.push_back(tid); c.theme_properties.push_back(tid);
} }
l.clear(); l.clear();
Theme::get_default()->get_font_list(cname, &l); ThemeDB::get_singleton()->get_default_theme()->get_font_list(cname, &l);
for (const StringName &E : l) { for (const StringName &E : l) {
DocData::ThemeItemDoc tid; DocData::ThemeItemDoc tid;
tid.name = E; tid.name = E;
@ -599,7 +600,7 @@ void DocTools::generate(bool p_basic_types) {
} }
l.clear(); l.clear();
Theme::get_default()->get_font_size_list(cname, &l); ThemeDB::get_singleton()->get_default_theme()->get_font_size_list(cname, &l);
for (const StringName &E : l) { for (const StringName &E : l) {
DocData::ThemeItemDoc tid; DocData::ThemeItemDoc tid;
tid.name = E; tid.name = E;
@ -609,7 +610,7 @@ void DocTools::generate(bool p_basic_types) {
} }
l.clear(); l.clear();
Theme::get_default()->get_icon_list(cname, &l); ThemeDB::get_singleton()->get_default_theme()->get_icon_list(cname, &l);
for (const StringName &E : l) { for (const StringName &E : l) {
DocData::ThemeItemDoc tid; DocData::ThemeItemDoc tid;
tid.name = E; tid.name = E;
@ -619,7 +620,7 @@ void DocTools::generate(bool p_basic_types) {
} }
l.clear(); l.clear();
Theme::get_default()->get_stylebox_list(cname, &l); ThemeDB::get_singleton()->get_default_theme()->get_stylebox_list(cname, &l);
for (const StringName &E : l) { for (const StringName &E : l) {
DocData::ThemeItemDoc tid; DocData::ThemeItemDoc tid;
tid.name = E; tid.name = E;

View File

@ -38,6 +38,7 @@
#include "editor/editor_undo_redo_manager.h" #include "editor/editor_undo_redo_manager.h"
#include "editor/progress_dialog.h" #include "editor/progress_dialog.h"
#include "scene/gui/color_picker.h" #include "scene/gui/color_picker.h"
#include "scene/theme/theme_db.h"
void ThemeItemImportTree::_update_items_tree() { void ThemeItemImportTree::_update_items_tree() {
import_items_tree->clear(); import_items_tree->clear();
@ -1202,7 +1203,7 @@ void ThemeItemEditorDialog::_dialog_about_to_show() {
_update_edit_types(); _update_edit_types();
import_default_theme_items->set_edited_theme(edited_theme); import_default_theme_items->set_edited_theme(edited_theme);
import_default_theme_items->set_base_theme(Theme::get_default()); import_default_theme_items->set_base_theme(ThemeDB::get_singleton()->get_default_theme());
import_default_theme_items->reset_item_tree(); import_default_theme_items->reset_item_tree();
import_editor_theme_items->set_edited_theme(edited_theme); import_editor_theme_items->set_edited_theme(edited_theme);
@ -1214,7 +1215,7 @@ void ThemeItemEditorDialog::_dialog_about_to_show() {
} }
void ThemeItemEditorDialog::_update_edit_types() { void ThemeItemEditorDialog::_update_edit_types() {
Ref<Theme> base_theme = Theme::get_default(); Ref<Theme> base_theme = ThemeDB::get_singleton()->get_default_theme();
List<StringName> theme_types; List<StringName> theme_types;
edited_theme->get_type_list(&theme_types); edited_theme->get_type_list(&theme_types);
@ -1630,7 +1631,7 @@ void ThemeItemEditorDialog::_remove_class_items() {
Theme::DataType data_type = (Theme::DataType)dt; Theme::DataType data_type = (Theme::DataType)dt;
names.clear(); names.clear();
Theme::get_default()->get_theme_item_list(data_type, edited_item_type, &names); ThemeDB::get_singleton()->get_default_theme()->get_theme_item_list(data_type, edited_item_type, &names);
for (const StringName &E : names) { for (const StringName &E : names) {
if (new_snapshot->has_theme_item_nocheck(data_type, E, edited_item_type)) { if (new_snapshot->has_theme_item_nocheck(data_type, E, edited_item_type)) {
new_snapshot->clear_theme_item(data_type, E, edited_item_type); new_snapshot->clear_theme_item(data_type, E, edited_item_type);
@ -1668,7 +1669,7 @@ void ThemeItemEditorDialog::_remove_custom_items() {
names.clear(); names.clear();
new_snapshot->get_theme_item_list(data_type, edited_item_type, &names); new_snapshot->get_theme_item_list(data_type, edited_item_type, &names);
for (const StringName &E : names) { for (const StringName &E : names) {
if (!Theme::get_default()->has_theme_item_nocheck(data_type, E, edited_item_type)) { if (!ThemeDB::get_singleton()->get_default_theme()->has_theme_item_nocheck(data_type, E, edited_item_type)) {
new_snapshot->clear_theme_item(data_type, E, edited_item_type); new_snapshot->clear_theme_item(data_type, E, edited_item_type);
if (dt == Theme::DATA_TYPE_STYLEBOX && theme_type_editor->is_stylebox_pinned(edited_theme->get_stylebox(E, edited_item_type))) { if (dt == Theme::DATA_TYPE_STYLEBOX && theme_type_editor->is_stylebox_pinned(edited_theme->get_stylebox(E, edited_item_type))) {
@ -2129,7 +2130,7 @@ void ThemeTypeDialog::_update_add_type_options(const String &p_filter) {
add_type_options->clear(); add_type_options->clear();
List<StringName> names; List<StringName> names;
Theme::get_default()->get_type_list(&names); ThemeDB::get_singleton()->get_default_theme()->get_type_list(&names);
if (include_own_types) { if (include_own_types) {
edited_theme->get_type_list(&names); edited_theme->get_type_list(&names);
} }
@ -2370,7 +2371,7 @@ HashMap<StringName, bool> ThemeTypeEditor::_get_type_items(String p_type_name, v
default_type = edited_theme->get_type_variation_base(p_type_name); default_type = edited_theme->get_type_variation_base(p_type_name);
} }
(Theme::get_default().operator->()->*get_list_func)(default_type, &names); (ThemeDB::get_singleton()->get_default_theme().operator->()->*get_list_func)(default_type, &names);
names.sort_custom<StringName::AlphCompare>(); names.sort_custom<StringName::AlphCompare>();
for (const StringName &E : names) { for (const StringName &E : names) {
items[E] = false; items[E] = false;
@ -2496,7 +2497,7 @@ void ThemeTypeEditor::_update_type_items() {
item_editor->connect("color_changed", callable_mp(this, &ThemeTypeEditor::_color_item_changed).bind(E.key)); item_editor->connect("color_changed", callable_mp(this, &ThemeTypeEditor::_color_item_changed).bind(E.key));
item_editor->get_popup()->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(item_editor->get_picker())); item_editor->get_popup()->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(item_editor->get_picker()));
} else { } else {
item_editor->set_pick_color(Theme::get_default()->get_color(E.key, edited_type)); item_editor->set_pick_color(ThemeDB::get_singleton()->get_default_theme()->get_color(E.key, edited_type));
item_editor->set_disabled(true); item_editor->set_disabled(true);
} }
@ -2529,7 +2530,7 @@ void ThemeTypeEditor::_update_type_items() {
item_editor->set_value(edited_theme->get_constant(E.key, edited_type)); item_editor->set_value(edited_theme->get_constant(E.key, edited_type));
item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_constant_item_changed).bind(E.key)); item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_constant_item_changed).bind(E.key));
} else { } else {
item_editor->set_value(Theme::get_default()->get_constant(E.key, edited_type)); item_editor->set_value(ThemeDB::get_singleton()->get_default_theme()->get_constant(E.key, edited_type));
item_editor->set_editable(false); item_editor->set_editable(false);
} }
@ -2563,8 +2564,8 @@ void ThemeTypeEditor::_update_type_items() {
item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item)); item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item));
item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_font_item_changed).bind(E.key)); item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_font_item_changed).bind(E.key));
} else { } else {
if (Theme::get_default()->has_font(E.key, edited_type)) { if (ThemeDB::get_singleton()->get_default_theme()->has_font(E.key, edited_type)) {
item_editor->set_edited_resource(Theme::get_default()->get_font(E.key, edited_type)); item_editor->set_edited_resource(ThemeDB::get_singleton()->get_default_theme()->get_font(E.key, edited_type));
} else { } else {
item_editor->set_edited_resource(Ref<Resource>()); item_editor->set_edited_resource(Ref<Resource>());
} }
@ -2600,7 +2601,7 @@ void ThemeTypeEditor::_update_type_items() {
item_editor->set_value(edited_theme->get_font_size(E.key, edited_type)); item_editor->set_value(edited_theme->get_font_size(E.key, edited_type));
item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_font_size_item_changed).bind(E.key)); item_editor->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_font_size_item_changed).bind(E.key));
} else { } else {
item_editor->set_value(Theme::get_default()->get_font_size(E.key, edited_type)); item_editor->set_value(ThemeDB::get_singleton()->get_default_theme()->get_font_size(E.key, edited_type));
item_editor->set_editable(false); item_editor->set_editable(false);
} }
@ -2634,8 +2635,8 @@ void ThemeTypeEditor::_update_type_items() {
item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item)); item_editor->connect("resource_selected", callable_mp(this, &ThemeTypeEditor::_edit_resource_item));
item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_icon_item_changed).bind(E.key)); item_editor->connect("resource_changed", callable_mp(this, &ThemeTypeEditor::_icon_item_changed).bind(E.key));
} else { } else {
if (Theme::get_default()->has_icon(E.key, edited_type)) { if (ThemeDB::get_singleton()->get_default_theme()->has_icon(E.key, edited_type)) {
item_editor->set_edited_resource(Theme::get_default()->get_icon(E.key, edited_type)); item_editor->set_edited_resource(ThemeDB::get_singleton()->get_default_theme()->get_icon(E.key, edited_type));
} else { } else {
item_editor->set_edited_resource(Ref<Resource>()); item_editor->set_edited_resource(Ref<Resource>());
} }
@ -2714,8 +2715,8 @@ void ThemeTypeEditor::_update_type_items() {
item_control->add_child(pin_leader_button); item_control->add_child(pin_leader_button);
pin_leader_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_on_pin_leader_button_pressed).bind(item_editor, E.key)); pin_leader_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_on_pin_leader_button_pressed).bind(item_editor, E.key));
} else { } else {
if (Theme::get_default()->has_stylebox(E.key, edited_type)) { if (ThemeDB::get_singleton()->get_default_theme()->has_stylebox(E.key, edited_type)) {
item_editor->set_edited_resource(Theme::get_default()->get_stylebox(E.key, edited_type)); item_editor->set_edited_resource(ThemeDB::get_singleton()->get_default_theme()->get_stylebox(E.key, edited_type));
} else { } else {
item_editor->set_edited_resource(Ref<Resource>()); item_editor->set_edited_resource(Ref<Resource>());
} }
@ -2770,55 +2771,55 @@ void ThemeTypeEditor::_add_default_type_items() {
{ {
names.clear(); names.clear();
Theme::get_default()->get_icon_list(default_type, &names); ThemeDB::get_singleton()->get_default_theme()->get_icon_list(default_type, &names);
for (const StringName &E : names) { for (const StringName &E : names) {
if (!new_snapshot->has_icon(E, edited_type)) { if (!new_snapshot->has_icon(E, edited_type)) {
new_snapshot->set_icon(E, edited_type, Theme::get_default()->get_icon(E, edited_type)); new_snapshot->set_icon(E, edited_type, ThemeDB::get_singleton()->get_default_theme()->get_icon(E, edited_type));
} }
} }
} }
{ {
names.clear(); names.clear();
Theme::get_default()->get_stylebox_list(default_type, &names); ThemeDB::get_singleton()->get_default_theme()->get_stylebox_list(default_type, &names);
for (const StringName &E : names) { for (const StringName &E : names) {
if (!new_snapshot->has_stylebox(E, edited_type)) { if (!new_snapshot->has_stylebox(E, edited_type)) {
new_snapshot->set_stylebox(E, edited_type, Theme::get_default()->get_stylebox(E, edited_type)); new_snapshot->set_stylebox(E, edited_type, ThemeDB::get_singleton()->get_default_theme()->get_stylebox(E, edited_type));
} }
} }
} }
{ {
names.clear(); names.clear();
Theme::get_default()->get_font_list(default_type, &names); ThemeDB::get_singleton()->get_default_theme()->get_font_list(default_type, &names);
for (const StringName &E : names) { for (const StringName &E : names) {
if (!new_snapshot->has_font(E, edited_type)) { if (!new_snapshot->has_font(E, edited_type)) {
new_snapshot->set_font(E, edited_type, Theme::get_default()->get_font(E, edited_type)); new_snapshot->set_font(E, edited_type, ThemeDB::get_singleton()->get_default_theme()->get_font(E, edited_type));
} }
} }
} }
{ {
names.clear(); names.clear();
Theme::get_default()->get_font_size_list(default_type, &names); ThemeDB::get_singleton()->get_default_theme()->get_font_size_list(default_type, &names);
for (const StringName &E : names) { for (const StringName &E : names) {
if (!new_snapshot->has_font_size(E, edited_type)) { if (!new_snapshot->has_font_size(E, edited_type)) {
new_snapshot->set_font_size(E, edited_type, Theme::get_default()->get_font_size(E, edited_type)); new_snapshot->set_font_size(E, edited_type, ThemeDB::get_singleton()->get_default_theme()->get_font_size(E, edited_type));
} }
} }
} }
{ {
names.clear(); names.clear();
Theme::get_default()->get_color_list(default_type, &names); ThemeDB::get_singleton()->get_default_theme()->get_color_list(default_type, &names);
for (const StringName &E : names) { for (const StringName &E : names) {
if (!new_snapshot->has_color(E, edited_type)) { if (!new_snapshot->has_color(E, edited_type)) {
new_snapshot->set_color(E, edited_type, Theme::get_default()->get_color(E, edited_type)); new_snapshot->set_color(E, edited_type, ThemeDB::get_singleton()->get_default_theme()->get_color(E, edited_type));
} }
} }
} }
{ {
names.clear(); names.clear();
Theme::get_default()->get_constant_list(default_type, &names); ThemeDB::get_singleton()->get_default_theme()->get_constant_list(default_type, &names);
for (const StringName &E : names) { for (const StringName &E : names) {
if (!new_snapshot->has_constant(E, edited_type)) { if (!new_snapshot->has_constant(E, edited_type)) {
new_snapshot->set_constant(E, edited_type, Theme::get_default()->get_constant(E, edited_type)); new_snapshot->set_constant(E, edited_type, ThemeDB::get_singleton()->get_default_theme()->get_constant(E, edited_type));
} }
} }
} }
@ -2895,11 +2896,11 @@ void ThemeTypeEditor::_item_override_cbk(int p_data_type, String p_item_name) {
switch (p_data_type) { switch (p_data_type) {
case Theme::DATA_TYPE_COLOR: { case Theme::DATA_TYPE_COLOR: {
ur->add_do_method(*edited_theme, "set_color", p_item_name, edited_type, Theme::get_default()->get_color(p_item_name, edited_type)); ur->add_do_method(*edited_theme, "set_color", p_item_name, edited_type, ThemeDB::get_singleton()->get_default_theme()->get_color(p_item_name, edited_type));
ur->add_undo_method(*edited_theme, "clear_color", p_item_name, edited_type); ur->add_undo_method(*edited_theme, "clear_color", p_item_name, edited_type);
} break; } break;
case Theme::DATA_TYPE_CONSTANT: { case Theme::DATA_TYPE_CONSTANT: {
ur->add_do_method(*edited_theme, "set_constant", p_item_name, edited_type, Theme::get_default()->get_constant(p_item_name, edited_type)); ur->add_do_method(*edited_theme, "set_constant", p_item_name, edited_type, ThemeDB::get_singleton()->get_default_theme()->get_constant(p_item_name, edited_type));
ur->add_undo_method(*edited_theme, "clear_constant", p_item_name, edited_type); ur->add_undo_method(*edited_theme, "clear_constant", p_item_name, edited_type);
} break; } break;
case Theme::DATA_TYPE_FONT: { case Theme::DATA_TYPE_FONT: {
@ -2907,7 +2908,7 @@ void ThemeTypeEditor::_item_override_cbk(int p_data_type, String p_item_name) {
ur->add_undo_method(*edited_theme, "clear_font", p_item_name, edited_type); ur->add_undo_method(*edited_theme, "clear_font", p_item_name, edited_type);
} break; } break;
case Theme::DATA_TYPE_FONT_SIZE: { case Theme::DATA_TYPE_FONT_SIZE: {
ur->add_do_method(*edited_theme, "set_font_size", p_item_name, edited_type, Theme::get_default()->get_font_size(p_item_name, edited_type)); ur->add_do_method(*edited_theme, "set_font_size", p_item_name, edited_type, ThemeDB::get_singleton()->get_default_theme()->get_font_size(p_item_name, edited_type));
ur->add_undo_method(*edited_theme, "clear_font_size", p_item_name, edited_type); ur->add_undo_method(*edited_theme, "clear_font_size", p_item_name, edited_type);
} break; } break;
case Theme::DATA_TYPE_ICON: { case Theme::DATA_TYPE_ICON: {

View File

@ -40,6 +40,7 @@
#include "scene/gui/color_picker.h" #include "scene/gui/color_picker.h"
#include "scene/gui/progress_bar.h" #include "scene/gui/progress_bar.h"
#include "scene/resources/packed_scene.h" #include "scene/resources/packed_scene.h"
#include "scene/theme/theme_db.h"
constexpr double REFRESH_TIMER = 1.5; constexpr double REFRESH_TIMER = 1.5;
@ -240,7 +241,7 @@ ThemeEditorPreview::ThemeEditorPreview() {
MarginContainer *preview_root = memnew(MarginContainer); MarginContainer *preview_root = memnew(MarginContainer);
preview_container->add_child(preview_root); preview_container->add_child(preview_root);
preview_root->set_theme(Theme::get_default()); preview_root->set_theme(ThemeDB::get_singleton()->get_default_theme());
preview_root->set_clip_contents(true); preview_root->set_clip_contents(true);
preview_root->set_custom_minimum_size(Size2(450, 0) * EDSCALE); preview_root->set_custom_minimum_size(Size2(450, 0) * EDSCALE);
preview_root->set_v_size_flags(SIZE_EXPAND_FILL); preview_root->set_v_size_flags(SIZE_EXPAND_FILL);

View File

@ -63,6 +63,7 @@
#include "scene/main/window.h" #include "scene/main/window.h"
#include "scene/register_scene_types.h" #include "scene/register_scene_types.h"
#include "scene/resources/packed_scene.h" #include "scene/resources/packed_scene.h"
#include "scene/theme/theme_db.h"
#include "servers/audio_server.h" #include "servers/audio_server.h"
#include "servers/camera_server.h" #include "servers/camera_server.h"
#include "servers/display_server.h" #include "servers/display_server.h"
@ -129,6 +130,7 @@ static PhysicsServer3D *physics_server_3d = nullptr;
static PhysicsServer2D *physics_server_2d = nullptr; static PhysicsServer2D *physics_server_2d = nullptr;
static NavigationServer3D *navigation_server_3d = nullptr; static NavigationServer3D *navigation_server_3d = nullptr;
static NavigationServer2D *navigation_server_2d = nullptr; static NavigationServer2D *navigation_server_2d = nullptr;
static ThemeDB *theme_db = nullptr;
// We error out if setup2() doesn't turn this true // We error out if setup2() doesn't turn this true
static bool _start_success = false; static bool _start_success = false;
@ -273,6 +275,16 @@ void finalize_navigation_server() {
navigation_server_2d = nullptr; navigation_server_2d = nullptr;
} }
void initialize_theme_db() {
theme_db = memnew(ThemeDB);
theme_db->initialize_theme();
}
void finalize_theme_db() {
memdelete(theme_db);
theme_db = nullptr;
}
//#define DEBUG_INIT //#define DEBUG_INIT
#ifdef DEBUG_INIT #ifdef DEBUG_INIT
#define MAIN_PRINT(m_txt) print_line(m_txt) #define MAIN_PRINT(m_txt) print_line(m_txt)
@ -475,7 +487,8 @@ Error Main::test_setup() {
register_platform_apis(); register_platform_apis();
// Theme needs modules to be initialized so that sub-resources can be loaded. // Theme needs modules to be initialized so that sub-resources can be loaded.
initialize_theme(); initialize_theme_db();
register_scene_singletons();
ERR_FAIL_COND_V(TextServerManager::get_singleton()->get_interface_count() == 0, ERR_CANT_CREATE); ERR_FAIL_COND_V(TextServerManager::get_singleton()->get_interface_count() == 0, ERR_CANT_CREATE);
@ -526,6 +539,8 @@ void Main::test_cleanup() {
unregister_driver_types(); unregister_driver_types();
unregister_scene_types(); unregister_scene_types();
finalize_theme_db();
NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS); NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS);
uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS); uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS);
unregister_server_types(); unregister_server_types();
@ -2126,7 +2141,8 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
register_platform_apis(); register_platform_apis();
// Theme needs modules to be initialized so that sub-resources can be loaded. // Theme needs modules to be initialized so that sub-resources can be loaded.
initialize_theme(); initialize_theme_db();
register_scene_singletons();
GLOBAL_DEF_BASIC("display/mouse_cursor/custom_image", String()); GLOBAL_DEF_BASIC("display/mouse_cursor/custom_image", String());
GLOBAL_DEF_BASIC("display/mouse_cursor/custom_image_hotspot", Vector2()); GLOBAL_DEF_BASIC("display/mouse_cursor/custom_image_hotspot", Vector2());
@ -3120,6 +3136,8 @@ void Main::cleanup(bool p_force) {
unregister_driver_types(); unregister_driver_types();
unregister_scene_types(); unregister_scene_types();
finalize_theme_db();
NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS); NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS);
uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS); uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS);
unregister_server_types(); unregister_server_types();

View File

@ -35,6 +35,7 @@
#include "editor/editor_settings.h" #include "editor/editor_settings.h"
#include "scene/gui/control.h" #include "scene/gui/control.h"
#include "scene/main/node.h" #include "scene/main/node.h"
#include "scene/theme/theme_db.h"
namespace gdmono { namespace gdmono {
@ -195,7 +196,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
Node *base = _try_find_owner_node_in_tree(script); Node *base = _try_find_owner_node_in_tree(script);
if (base && Object::cast_to<Control>(base)) { if (base && Object::cast_to<Control>(base)) {
List<StringName> sn; List<StringName> sn;
Theme::get_default()->get_color_list(base->get_class(), &sn); ThemeDB::get_singleton()->get_default_theme()->get_color_list(base->get_class(), &sn);
for (const StringName &E : sn) { for (const StringName &E : sn) {
suggestions.push_back(quoted(E)); suggestions.push_back(quoted(E));
@ -207,7 +208,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
Node *base = _try_find_owner_node_in_tree(script); Node *base = _try_find_owner_node_in_tree(script);
if (base && Object::cast_to<Control>(base)) { if (base && Object::cast_to<Control>(base)) {
List<StringName> sn; List<StringName> sn;
Theme::get_default()->get_constant_list(base->get_class(), &sn); ThemeDB::get_singleton()->get_default_theme()->get_constant_list(base->get_class(), &sn);
for (const StringName &E : sn) { for (const StringName &E : sn) {
suggestions.push_back(quoted(E)); suggestions.push_back(quoted(E));
@ -219,7 +220,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
Node *base = _try_find_owner_node_in_tree(script); Node *base = _try_find_owner_node_in_tree(script);
if (base && Object::cast_to<Control>(base)) { if (base && Object::cast_to<Control>(base)) {
List<StringName> sn; List<StringName> sn;
Theme::get_default()->get_font_list(base->get_class(), &sn); ThemeDB::get_singleton()->get_default_theme()->get_font_list(base->get_class(), &sn);
for (const StringName &E : sn) { for (const StringName &E : sn) {
suggestions.push_back(quoted(E)); suggestions.push_back(quoted(E));
@ -231,7 +232,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
Node *base = _try_find_owner_node_in_tree(script); Node *base = _try_find_owner_node_in_tree(script);
if (base && Object::cast_to<Control>(base)) { if (base && Object::cast_to<Control>(base)) {
List<StringName> sn; List<StringName> sn;
Theme::get_default()->get_font_size_list(base->get_class(), &sn); ThemeDB::get_singleton()->get_default_theme()->get_font_size_list(base->get_class(), &sn);
for (const StringName &E : sn) { for (const StringName &E : sn) {
suggestions.push_back(quoted(E)); suggestions.push_back(quoted(E));
@ -243,7 +244,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
Node *base = _try_find_owner_node_in_tree(script); Node *base = _try_find_owner_node_in_tree(script);
if (base && Object::cast_to<Control>(base)) { if (base && Object::cast_to<Control>(base)) {
List<StringName> sn; List<StringName> sn;
Theme::get_default()->get_stylebox_list(base->get_class(), &sn); ThemeDB::get_singleton()->get_default_theme()->get_stylebox_list(base->get_class(), &sn);
for (const StringName &E : sn) { for (const StringName &E : sn) {
suggestions.push_back(quoted(E)); suggestions.push_back(quoted(E));

View File

@ -34,6 +34,7 @@
#include "scene/main/viewport.h" #include "scene/main/viewport.h"
#include "scene/resources/theme.h" #include "scene/resources/theme.h"
#include "scene/scene_string_names.h" #include "scene/scene_string_names.h"
#include "scene/theme/theme_db.h"
void Label3D::_bind_methods() { void Label3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_horizontal_alignment", "alignment"), &Label3D::set_horizontal_alignment); ClassDB::bind_method(D_METHOD("set_horizontal_alignment", "alignment"), &Label3D::set_horizontal_alignment);
@ -734,13 +735,13 @@ Ref<Font> Label3D::_get_font_or_default() const {
} }
// Check the project-defined Theme resource. // Check the project-defined Theme resource.
if (Theme::get_project_default().is_valid()) { if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
List<StringName> theme_types; List<StringName> theme_types;
Theme::get_project_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types); ThemeDB::get_singleton()->get_project_theme()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
for (const StringName &E : theme_types) { for (const StringName &E : theme_types) {
if (Theme::get_project_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) { if (ThemeDB::get_singleton()->get_project_theme()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
Ref<Font> f = Theme::get_project_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E); Ref<Font> f = ThemeDB::get_singleton()->get_project_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
if (f.is_valid()) { if (f.is_valid()) {
theme_font = f; theme_font = f;
theme_font->connect(CoreStringNames::get_singleton()->changed, Callable(const_cast<Label3D *>(this), "_font_changed")); theme_font->connect(CoreStringNames::get_singleton()->changed, Callable(const_cast<Label3D *>(this), "_font_changed"));
@ -753,11 +754,11 @@ Ref<Font> Label3D::_get_font_or_default() const {
// Lastly, fall back on the items defined in the default Theme, if they exist. // Lastly, fall back on the items defined in the default Theme, if they exist.
{ {
List<StringName> theme_types; List<StringName> theme_types;
Theme::get_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types); ThemeDB::get_singleton()->get_default_theme()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
for (const StringName &E : theme_types) { for (const StringName &E : theme_types) {
if (Theme::get_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) { if (ThemeDB::get_singleton()->get_default_theme()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
Ref<Font> f = Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E); Ref<Font> f = ThemeDB::get_singleton()->get_default_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
if (f.is_valid()) { if (f.is_valid()) {
theme_font = f; theme_font = f;
theme_font->connect(CoreStringNames::get_singleton()->changed, Callable(const_cast<Label3D *>(this), "_font_changed")); theme_font->connect(CoreStringNames::get_singleton()->changed, Callable(const_cast<Label3D *>(this), "_font_changed"));
@ -768,7 +769,7 @@ Ref<Font> Label3D::_get_font_or_default() const {
} }
// If they don't exist, use any type to return the default/empty value. // If they don't exist, use any type to return the default/empty value.
Ref<Font> f = Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName()); Ref<Font> f = ThemeDB::get_singleton()->get_default_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName());
if (f.is_valid()) { if (f.is_valid()) {
theme_font = f; theme_font = f;
theme_font->connect(CoreStringNames::get_singleton()->changed, Callable(const_cast<Label3D *>(this), "_font_changed")); theme_font->connect(CoreStringNames::get_singleton()->changed, Callable(const_cast<Label3D *>(this), "_font_changed"));

View File

@ -17,6 +17,7 @@ SConscript("animation/SCsub")
SConscript("audio/SCsub") SConscript("audio/SCsub")
SConscript("resources/SCsub") SConscript("resources/SCsub")
SConscript("debugger/SCsub") SConscript("debugger/SCsub")
SConscript("theme/SCsub")
# Build it all as a library # Build it all as a library
lib = env.add_library("scene", env.scene_sources) lib = env.add_library("scene", env.scene_sources)

View File

@ -43,6 +43,7 @@
#include "scene/main/canvas_layer.h" #include "scene/main/canvas_layer.h"
#include "scene/main/window.h" #include "scene/main/window.h"
#include "scene/scene_string_names.h" #include "scene/scene_string_names.h"
#include "scene/theme/theme_db.h"
#include "servers/rendering_server.h" #include "servers/rendering_server.h"
#include "servers/text_server.h" #include "servers/text_server.h"
@ -193,15 +194,15 @@ void Control::get_argument_options(const StringName &p_function, int p_idx, List
List<StringName> sn; List<StringName> sn;
String pf = p_function; String pf = p_function;
if (pf == "add_theme_color_override" || pf == "has_theme_color" || pf == "has_theme_color_override" || pf == "get_theme_color") { if (pf == "add_theme_color_override" || pf == "has_theme_color" || pf == "has_theme_color_override" || pf == "get_theme_color") {
Theme::get_default()->get_color_list(get_class(), &sn); ThemeDB::get_singleton()->get_default_theme()->get_color_list(get_class(), &sn);
} else if (pf == "add_theme_style_override" || pf == "has_theme_style" || pf == "has_theme_style_override" || pf == "get_theme_style") { } else if (pf == "add_theme_style_override" || pf == "has_theme_style" || pf == "has_theme_style_override" || pf == "get_theme_style") {
Theme::get_default()->get_stylebox_list(get_class(), &sn); ThemeDB::get_singleton()->get_default_theme()->get_stylebox_list(get_class(), &sn);
} else if (pf == "add_theme_font_override" || pf == "has_theme_font" || pf == "has_theme_font_override" || pf == "get_theme_font") { } else if (pf == "add_theme_font_override" || pf == "has_theme_font" || pf == "has_theme_font_override" || pf == "get_theme_font") {
Theme::get_default()->get_font_list(get_class(), &sn); ThemeDB::get_singleton()->get_default_theme()->get_font_list(get_class(), &sn);
} else if (pf == "add_theme_font_size_override" || pf == "has_theme_font_size" || pf == "has_theme_font_size_override" || pf == "get_theme_font_size") { } else if (pf == "add_theme_font_size_override" || pf == "has_theme_font_size" || pf == "has_theme_font_size_override" || pf == "get_theme_font_size") {
Theme::get_default()->get_font_size_list(get_class(), &sn); ThemeDB::get_singleton()->get_default_theme()->get_font_size_list(get_class(), &sn);
} else if (pf == "add_theme_constant_override" || pf == "has_theme_constant" || pf == "has_theme_constant_override" || pf == "get_theme_constant") { } else if (pf == "add_theme_constant_override" || pf == "has_theme_constant" || pf == "has_theme_constant_override" || pf == "get_theme_constant") {
Theme::get_default()->get_constant_list(get_class(), &sn); ThemeDB::get_singleton()->get_default_theme()->get_constant_list(get_class(), &sn);
} }
sn.sort_custom<StringName::AlphCompare>(); sn.sort_custom<StringName::AlphCompare>();
@ -344,7 +345,7 @@ bool Control::_get(const StringName &p_name, Variant &r_ret) const {
} }
void Control::_get_property_list(List<PropertyInfo> *p_list) const { void Control::_get_property_list(List<PropertyInfo> *p_list) const {
Ref<Theme> theme = Theme::get_default(); Ref<Theme> theme = ThemeDB::get_singleton()->get_default_theme();
p_list->push_back(PropertyInfo(Variant::NIL, TTRC("Theme Overrides"), PROPERTY_HINT_NONE, "theme_override_", PROPERTY_USAGE_GROUP)); p_list->push_back(PropertyInfo(Variant::NIL, TTRC("Theme Overrides"), PROPERTY_HINT_NONE, "theme_override_", PROPERTY_USAGE_GROUP));
@ -429,9 +430,9 @@ void Control::_validate_property(PropertyInfo &p_property) const {
// Only the default theme and the project theme are used for the list of options. // Only the default theme and the project theme are used for the list of options.
// This is an imposed limitation to simplify the logic needed to leverage those options. // This is an imposed limitation to simplify the logic needed to leverage those options.
Theme::get_default()->get_type_variation_list(get_class_name(), &names); ThemeDB::get_singleton()->get_default_theme()->get_type_variation_list(get_class_name(), &names);
if (Theme::get_project_default().is_valid()) { if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
Theme::get_project_default()->get_type_variation_list(get_class_name(), &names); ThemeDB::get_singleton()->get_project_theme()->get_type_variation_list(get_class_name(), &names);
} }
names.sort_custom<StringName::AlphCompare>(); names.sort_custom<StringName::AlphCompare>();
@ -2419,22 +2420,22 @@ T Control::get_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner
} }
// Secondly, check the project-defined Theme resource. // Secondly, check the project-defined Theme resource.
if (Theme::get_project_default().is_valid()) { if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
for (const StringName &E : p_theme_types) { for (const StringName &E : p_theme_types) {
if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E)) { if (ThemeDB::get_singleton()->get_project_theme()->has_theme_item(p_data_type, p_name, E)) {
return Theme::get_project_default()->get_theme_item(p_data_type, p_name, E); return ThemeDB::get_singleton()->get_project_theme()->get_theme_item(p_data_type, p_name, E);
} }
} }
} }
// Lastly, fall back on the items defined in the default Theme, if they exist. // Lastly, fall back on the items defined in the default Theme, if they exist.
for (const StringName &E : p_theme_types) { for (const StringName &E : p_theme_types) {
if (Theme::get_default()->has_theme_item(p_data_type, p_name, E)) { if (ThemeDB::get_singleton()->get_default_theme()->has_theme_item(p_data_type, p_name, E)) {
return Theme::get_default()->get_theme_item(p_data_type, p_name, E); return ThemeDB::get_singleton()->get_default_theme()->get_theme_item(p_data_type, p_name, E);
} }
} }
// If they don't exist, use any type to return the default/empty value. // If they don't exist, use any type to return the default/empty value.
return Theme::get_default()->get_theme_item(p_data_type, p_name, p_theme_types[0]); return ThemeDB::get_singleton()->get_default_theme()->get_theme_item(p_data_type, p_name, p_theme_types[0]);
} }
bool Control::has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types) { bool Control::has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types) {
@ -2475,9 +2476,9 @@ bool Control::has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_ow
} }
// Secondly, check the project-defined Theme resource. // Secondly, check the project-defined Theme resource.
if (Theme::get_project_default().is_valid()) { if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
for (const StringName &E : p_theme_types) { for (const StringName &E : p_theme_types) {
if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E)) { if (ThemeDB::get_singleton()->get_project_theme()->has_theme_item(p_data_type, p_name, E)) {
return true; return true;
} }
} }
@ -2485,7 +2486,7 @@ bool Control::has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_ow
// Lastly, fall back on the items defined in the default Theme, if they exist. // Lastly, fall back on the items defined in the default Theme, if they exist.
for (const StringName &E : p_theme_types) { for (const StringName &E : p_theme_types) {
if (Theme::get_default()->has_theme_item(p_data_type, p_name, E)) { if (ThemeDB::get_singleton()->get_default_theme()->has_theme_item(p_data_type, p_name, E)) {
return true; return true;
} }
} }
@ -2494,13 +2495,13 @@ bool Control::has_theme_item_in_types(Control *p_theme_owner, Window *p_theme_ow
void Control::_get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const { void Control::_get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const {
if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) { if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == data.theme_type_variation) {
if (Theme::get_project_default().is_valid() && Theme::get_project_default()->get_type_variation_base(data.theme_type_variation) != StringName()) { if (ThemeDB::get_singleton()->get_project_theme().is_valid() && ThemeDB::get_singleton()->get_project_theme()->get_type_variation_base(data.theme_type_variation) != StringName()) {
Theme::get_project_default()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list); ThemeDB::get_singleton()->get_project_theme()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list);
} else { } else {
Theme::get_default()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list); ThemeDB::get_singleton()->get_default_theme()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list);
} }
} else { } else {
Theme::get_default()->get_type_dependencies(p_theme_type, StringName(), p_list); ThemeDB::get_singleton()->get_default_theme()->get_type_dependencies(p_theme_type, StringName(), p_list);
} }
} }
@ -2851,17 +2852,17 @@ float Control::fetch_theme_default_base_scale(Control *p_theme_owner, Window *p_
} }
// Secondly, check the project-defined Theme resource. // Secondly, check the project-defined Theme resource.
if (Theme::get_project_default().is_valid()) { if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
if (Theme::get_project_default()->has_default_base_scale()) { if (ThemeDB::get_singleton()->get_project_theme()->has_default_base_scale()) {
return Theme::get_project_default()->get_default_base_scale(); return ThemeDB::get_singleton()->get_project_theme()->get_default_base_scale();
} }
} }
// Lastly, fall back on the default Theme. // Lastly, fall back on the default Theme.
if (Theme::get_default()->has_default_base_scale()) { if (ThemeDB::get_singleton()->get_default_theme()->has_default_base_scale()) {
return Theme::get_default()->get_default_base_scale(); return ThemeDB::get_singleton()->get_default_theme()->get_default_base_scale();
} }
return Theme::get_fallback_base_scale(); return ThemeDB::get_singleton()->get_fallback_base_scale();
} }
float Control::get_theme_default_base_scale() const { float Control::get_theme_default_base_scale() const {
@ -2902,17 +2903,17 @@ Ref<Font> Control::fetch_theme_default_font(Control *p_theme_owner, Window *p_th
} }
// Secondly, check the project-defined Theme resource. // Secondly, check the project-defined Theme resource.
if (Theme::get_project_default().is_valid()) { if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
if (Theme::get_project_default()->has_default_font()) { if (ThemeDB::get_singleton()->get_project_theme()->has_default_font()) {
return Theme::get_project_default()->get_default_font(); return ThemeDB::get_singleton()->get_project_theme()->get_default_font();
} }
} }
// Lastly, fall back on the default Theme. // Lastly, fall back on the default Theme.
if (Theme::get_default()->has_default_font()) { if (ThemeDB::get_singleton()->get_default_theme()->has_default_font()) {
return Theme::get_default()->get_default_font(); return ThemeDB::get_singleton()->get_default_theme()->get_default_font();
} }
return Theme::get_fallback_font(); return ThemeDB::get_singleton()->get_fallback_font();
} }
Ref<Font> Control::get_theme_default_font() const { Ref<Font> Control::get_theme_default_font() const {
@ -2953,17 +2954,17 @@ int Control::fetch_theme_default_font_size(Control *p_theme_owner, Window *p_the
} }
// Secondly, check the project-defined Theme resource. // Secondly, check the project-defined Theme resource.
if (Theme::get_project_default().is_valid()) { if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
if (Theme::get_project_default()->has_default_font_size()) { if (ThemeDB::get_singleton()->get_project_theme()->has_default_font_size()) {
return Theme::get_project_default()->get_default_font_size(); return ThemeDB::get_singleton()->get_project_theme()->get_default_font_size();
} }
} }
// Lastly, fall back on the default Theme. // Lastly, fall back on the default Theme.
if (Theme::get_default()->has_default_font_size()) { if (ThemeDB::get_singleton()->get_default_theme()->has_default_font_size()) {
return Theme::get_default()->get_default_font_size(); return ThemeDB::get_singleton()->get_default_theme()->get_default_font_size();
} }
return Theme::get_fallback_font_size(); return ThemeDB::get_singleton()->get_fallback_font_size();
} }
int Control::get_theme_default_font_size() const { int Control::get_theme_default_font_size() const {

View File

@ -35,6 +35,7 @@
#include "core/string/translation.h" #include "core/string/translation.h"
#include "scene/gui/control.h" #include "scene/gui/control.h"
#include "scene/scene_string_names.h" #include "scene/scene_string_names.h"
#include "scene/theme/theme_db.h"
void Window::set_title(const String &p_title) { void Window::set_title(const String &p_title) {
title = p_title; title = p_title;
@ -1330,13 +1331,13 @@ StringName Window::get_theme_type_variation() const {
void Window::_get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const { void Window::_get_theme_type_dependencies(const StringName &p_theme_type, List<StringName> *p_list) const {
if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) {
if (Theme::get_project_default().is_valid() && Theme::get_project_default()->get_type_variation_base(theme_type_variation) != StringName()) { if (ThemeDB::get_singleton()->get_project_theme().is_valid() && ThemeDB::get_singleton()->get_project_theme()->get_type_variation_base(theme_type_variation) != StringName()) {
Theme::get_project_default()->get_type_dependencies(get_class_name(), theme_type_variation, p_list); ThemeDB::get_singleton()->get_project_theme()->get_type_dependencies(get_class_name(), theme_type_variation, p_list);
} else { } else {
Theme::get_default()->get_type_dependencies(get_class_name(), theme_type_variation, p_list); ThemeDB::get_singleton()->get_default_theme()->get_type_dependencies(get_class_name(), theme_type_variation, p_list);
} }
} else { } else {
Theme::get_default()->get_type_dependencies(p_theme_type, StringName(), p_list); ThemeDB::get_singleton()->get_default_theme()->get_type_dependencies(p_theme_type, StringName(), p_list);
} }
} }
@ -1522,9 +1523,9 @@ void Window::_validate_property(PropertyInfo &p_property) const {
// Only the default theme and the project theme are used for the list of options. // Only the default theme and the project theme are used for the list of options.
// This is an imposed limitation to simplify the logic needed to leverage those options. // This is an imposed limitation to simplify the logic needed to leverage those options.
Theme::get_default()->get_type_variation_list(get_class_name(), &names); ThemeDB::get_singleton()->get_default_theme()->get_type_variation_list(get_class_name(), &names);
if (Theme::get_project_default().is_valid()) { if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
Theme::get_project_default()->get_type_variation_list(get_class_name(), &names); ThemeDB::get_singleton()->get_project_theme()->get_type_variation_list(get_class_name(), &names);
} }
names.sort_custom<StringName::AlphCompare>(); names.sort_custom<StringName::AlphCompare>();

View File

@ -193,12 +193,14 @@
#include "scene/resources/sky.h" #include "scene/resources/sky.h"
#include "scene/resources/sky_material.h" #include "scene/resources/sky_material.h"
#include "scene/resources/sphere_shape_3d.h" #include "scene/resources/sphere_shape_3d.h"
#include "scene/resources/style_box.h"
#include "scene/resources/surface_tool.h" #include "scene/resources/surface_tool.h"
#include "scene/resources/syntax_highlighter.h" #include "scene/resources/syntax_highlighter.h"
#include "scene/resources/text_file.h" #include "scene/resources/text_file.h"
#include "scene/resources/text_line.h" #include "scene/resources/text_line.h"
#include "scene/resources/text_paragraph.h" #include "scene/resources/text_paragraph.h"
#include "scene/resources/texture.h" #include "scene/resources/texture.h"
#include "scene/resources/theme.h"
#include "scene/resources/tile_set.h" #include "scene/resources/tile_set.h"
#include "scene/resources/video_stream.h" #include "scene/resources/video_stream.h"
#include "scene/resources/visual_shader.h" #include "scene/resources/visual_shader.h"
@ -210,6 +212,7 @@
#include "scene/resources/world_boundary_shape_2d.h" #include "scene/resources/world_boundary_shape_2d.h"
#include "scene/resources/world_boundary_shape_3d.h" #include "scene/resources/world_boundary_shape_3d.h"
#include "scene/scene_string_names.h" #include "scene/scene_string_names.h"
#include "scene/theme/theme_db.h"
#include "scene/main/shader_globals_override.h" #include "scene/main/shader_globals_override.h"
@ -1122,62 +1125,8 @@ void register_scene_types() {
SceneDebugger::initialize(); SceneDebugger::initialize();
} }
void initialize_theme() {
// Allow creating the default theme at a different scale to suit higher/lower base resolutions.
float default_theme_scale = GLOBAL_DEF("gui/theme/default_theme_scale", 1.0);
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_theme_scale", PropertyInfo(Variant::FLOAT, "gui/theme/default_theme_scale", PROPERTY_HINT_RANGE, "0.5,8,0.01", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
String theme_path = GLOBAL_DEF_RST("gui/theme/custom", "");
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom", PropertyInfo(Variant::STRING, "gui/theme/custom", PROPERTY_HINT_FILE, "*.tres,*.res,*.theme", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
String font_path = GLOBAL_DEF_RST("gui/theme/custom_font", "");
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom_font", PropertyInfo(Variant::STRING, "gui/theme/custom_font", PROPERTY_HINT_FILE, "*.tres,*.res", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
TextServer::FontAntialiasing font_antialiasing = (TextServer::FontAntialiasing)(int)GLOBAL_DEF_RST("gui/theme/default_font_antialiasing", 1);
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_antialiasing", PropertyInfo(Variant::INT, "gui/theme/default_font_antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD sub-pixel", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
TextServer::Hinting font_hinting = (TextServer::Hinting)(int)GLOBAL_DEF_RST("gui/theme/default_font_hinting", TextServer::HINTING_LIGHT);
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_hinting", PropertyInfo(Variant::INT, "gui/theme/default_font_hinting", PROPERTY_HINT_ENUM, "None,Light,Normal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
TextServer::SubpixelPositioning font_subpixel_positioning = (TextServer::SubpixelPositioning)(int)GLOBAL_DEF_RST("gui/theme/default_font_subpixel_positioning", TextServer::SUBPIXEL_POSITIONING_AUTO);
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_subpixel_positioning", PropertyInfo(Variant::INT, "gui/theme/default_font_subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
const bool font_msdf = GLOBAL_DEF_RST("gui/theme/default_font_multichannel_signed_distance_field", false);
const bool font_generate_mipmaps = GLOBAL_DEF_RST("gui/theme/default_font_generate_mipmaps", false);
GLOBAL_DEF_RST("gui/theme/lcd_subpixel_layout", 1);
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/lcd_subpixel_layout", PropertyInfo(Variant::INT, "gui/theme/lcd_subpixel_layout", PROPERTY_HINT_ENUM, "Disabled,Horizontal RGB,Horizontal BGR,Vertical RGB,Vertical BGR"));
ProjectSettings::get_singleton()->set_restart_if_changed("gui/theme/lcd_subpixel_layout", false);
Ref<Font> font;
if (!font_path.is_empty()) {
font = ResourceLoader::load(font_path);
if (!font.is_valid()) {
ERR_PRINT("Error loading custom font '" + font_path + "'");
}
}
// Always make the default theme to avoid invalid default font/icon/style in the given theme.
if (RenderingServer::get_singleton()) {
make_default_theme(default_theme_scale, font, font_subpixel_positioning, font_hinting, font_antialiasing, font_msdf, font_generate_mipmaps);
}
if (!theme_path.is_empty()) {
Ref<Theme> theme = ResourceLoader::load(theme_path);
if (theme.is_valid()) {
Theme::set_project_default(theme);
if (font.is_valid()) {
Theme::set_fallback_font(font);
}
} else {
ERR_PRINT("Error loading custom theme '" + theme_path + "'");
}
}
}
void unregister_scene_types() { void unregister_scene_types() {
SceneDebugger::deinitialize(); SceneDebugger::deinitialize();
clear_default_theme();
ResourceLoader::remove_resource_format_loader(resource_loader_texture_layered); ResourceLoader::remove_resource_format_loader(resource_loader_texture_layered);
resource_loader_texture_layered.unref(); resource_loader_texture_layered.unref();
@ -1219,3 +1168,9 @@ void unregister_scene_types() {
ColorPicker::finish_shaders(); ColorPicker::finish_shaders();
SceneStringNames::free(); SceneStringNames::free();
} }
void register_scene_singletons() {
GDREGISTER_CLASS(ThemeDB);
Engine::get_singleton()->add_singleton(Engine::Singleton("ThemeDB", ThemeDB::get_singleton()));
}

View File

@ -33,7 +33,6 @@
void register_scene_types(); void register_scene_types();
void unregister_scene_types(); void unregister_scene_types();
void register_scene_singletons();
void initialize_theme();
#endif // REGISTER_SCENE_TYPES_H #endif // REGISTER_SCENE_TYPES_H

View File

@ -35,6 +35,7 @@
#include "default_theme_icons.gen.h" #include "default_theme_icons.gen.h"
#include "scene/resources/font.h" #include "scene/resources/font.h"
#include "scene/resources/theme.h" #include "scene/resources/theme.h"
#include "scene/theme/theme_db.h"
#include "servers/text_server.h" #include "servers/text_server.h"
#include "modules/modules_enabled.gen.h" // For svg. #include "modules/modules_enabled.gen.h" // For svg.
@ -1101,18 +1102,11 @@ void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPos
fill_default_theme(t, default_font, bold_font, bold_italics_font, italics_font, default_icon, default_style, default_scale); fill_default_theme(t, default_font, bold_font, bold_italics_font, italics_font, default_icon, default_style, default_scale);
Theme::set_default(t); ThemeDB::get_singleton()->set_default_theme(t);
Theme::set_fallback_base_scale(default_scale);
Theme::set_fallback_icon(default_icon);
Theme::set_fallback_style(default_style);
Theme::set_fallback_font(default_font);
Theme::set_fallback_font_size(default_font_size * default_scale);
}
void clear_default_theme() { ThemeDB::get_singleton()->set_fallback_base_scale(default_scale);
Theme::set_project_default(nullptr); ThemeDB::get_singleton()->set_fallback_icon(default_icon);
Theme::set_default(nullptr); ThemeDB::get_singleton()->set_fallback_stylebox(default_style);
Theme::set_fallback_icon(nullptr); ThemeDB::get_singleton()->set_fallback_font(default_font);
Theme::set_fallback_style(nullptr); ThemeDB::get_singleton()->set_fallback_font_size(default_font_size * default_scale);
Theme::set_fallback_font(nullptr);
} }

View File

@ -37,6 +37,5 @@ const int default_font_size = 16;
void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &bold_font, const Ref<Font> &bold_italics_font, const Ref<Font> &italics_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale); void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &bold_font, const Ref<Font> &bold_italics_font, const Ref<Font> &italics_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale);
void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_font_subpixel = TextServer::SUBPIXEL_POSITIONING_AUTO, TextServer::Hinting p_font_hinting = TextServer::HINTING_LIGHT, TextServer::FontAntialiasing p_font_antialiased = TextServer::FONT_ANTIALIASING_GRAY, bool p_font_msdf = false, bool p_font_generate_mipmaps = false); void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_font_subpixel = TextServer::SUBPIXEL_POSITIONING_AUTO, TextServer::Hinting p_font_hinting = TextServer::HINTING_LIGHT, TextServer::FontAntialiasing p_font_antialiased = TextServer::FONT_ANTIALIASING_GRAY, bool p_font_msdf = false, bool p_font_generate_mipmaps = false);
void clear_default_theme();
#endif // DEFAULT_THEME_H #endif // DEFAULT_THEME_H

View File

@ -39,6 +39,7 @@
#include "scene/resources/text_line.h" #include "scene/resources/text_line.h"
#include "scene/resources/text_paragraph.h" #include "scene/resources/text_paragraph.h"
#include "scene/resources/theme.h" #include "scene/resources/theme.h"
#include "scene/theme/theme_db.h"
/*************************************************************************/ /*************************************************************************/
/* Font */ /* Font */
@ -2552,13 +2553,13 @@ Ref<Font> FontVariation::_get_base_font_or_default() const {
} }
// Check the project-defined Theme resource. // Check the project-defined Theme resource.
if (Theme::get_project_default().is_valid()) { if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
List<StringName> theme_types; List<StringName> theme_types;
Theme::get_project_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types); ThemeDB::get_singleton()->get_project_theme()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
for (const StringName &E : theme_types) { for (const StringName &E : theme_types) {
if (Theme::get_project_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) { if (ThemeDB::get_singleton()->get_project_theme()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
Ref<Font> f = Theme::get_project_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E); Ref<Font> f = ThemeDB::get_singleton()->get_project_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
if (f.is_valid()) { if (f.is_valid()) {
theme_font = f; theme_font = f;
theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<FontVariation *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED); theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<FontVariation *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED);
@ -2569,13 +2570,13 @@ Ref<Font> FontVariation::_get_base_font_or_default() const {
} }
// Lastly, fall back on the items defined in the default Theme, if they exist. // Lastly, fall back on the items defined in the default Theme, if they exist.
if (Theme::get_default().is_valid()) { if (ThemeDB::get_singleton()->get_default_theme().is_valid()) {
List<StringName> theme_types; List<StringName> theme_types;
Theme::get_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types); ThemeDB::get_singleton()->get_default_theme()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
for (const StringName &E : theme_types) { for (const StringName &E : theme_types) {
if (Theme::get_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) { if (ThemeDB::get_singleton()->get_default_theme()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
Ref<Font> f = Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E); Ref<Font> f = ThemeDB::get_singleton()->get_default_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
if (f.is_valid()) { if (f.is_valid()) {
theme_font = f; theme_font = f;
theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<FontVariation *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED); theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<FontVariation *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED);
@ -2585,7 +2586,7 @@ Ref<Font> FontVariation::_get_base_font_or_default() const {
} }
// If they don't exist, use any type to return the default/empty value. // If they don't exist, use any type to return the default/empty value.
Ref<Font> f = Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName()); Ref<Font> f = ThemeDB::get_singleton()->get_default_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName());
if (f.is_valid()) { if (f.is_valid()) {
theme_font = f; theme_font = f;
theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<FontVariation *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED); theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<FontVariation *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED);
@ -2859,13 +2860,13 @@ Ref<Font> SystemFont::_get_base_font_or_default() const {
} }
// Check the project-defined Theme resource. // Check the project-defined Theme resource.
if (Theme::get_project_default().is_valid()) { if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
List<StringName> theme_types; List<StringName> theme_types;
Theme::get_project_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types); ThemeDB::get_singleton()->get_project_theme()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
for (const StringName &E : theme_types) { for (const StringName &E : theme_types) {
if (Theme::get_project_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) { if (ThemeDB::get_singleton()->get_project_theme()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
Ref<Font> f = Theme::get_project_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E); Ref<Font> f = ThemeDB::get_singleton()->get_project_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
if (f.is_valid()) { if (f.is_valid()) {
theme_font = f; theme_font = f;
theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<SystemFont *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED); theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<SystemFont *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED);
@ -2876,13 +2877,13 @@ Ref<Font> SystemFont::_get_base_font_or_default() const {
} }
// Lastly, fall back on the items defined in the default Theme, if they exist. // Lastly, fall back on the items defined in the default Theme, if they exist.
if (Theme::get_default().is_valid()) { if (ThemeDB::get_singleton()->get_default_theme().is_valid()) {
List<StringName> theme_types; List<StringName> theme_types;
Theme::get_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types); ThemeDB::get_singleton()->get_default_theme()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
for (const StringName &E : theme_types) { for (const StringName &E : theme_types) {
if (Theme::get_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) { if (ThemeDB::get_singleton()->get_default_theme()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
Ref<Font> f = Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E); Ref<Font> f = ThemeDB::get_singleton()->get_default_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
if (f.is_valid()) { if (f.is_valid()) {
theme_font = f; theme_font = f;
theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<SystemFont *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED); theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<SystemFont *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED);
@ -2892,7 +2893,7 @@ Ref<Font> SystemFont::_get_base_font_or_default() const {
} }
// If they don't exist, use any type to return the default/empty value. // If they don't exist, use any type to return the default/empty value.
Ref<Font> f = Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName()); Ref<Font> f = ThemeDB::get_singleton()->get_default_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName());
if (f.is_valid()) { if (f.is_valid()) {
theme_font = f; theme_font = f;
theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<SystemFont *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED); theme_font->connect(CoreStringNames::get_singleton()->changed, callable_mp(reinterpret_cast<Font *>(const_cast<SystemFont *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED);

View File

@ -32,6 +32,7 @@
#include "core/core_string_names.h" #include "core/core_string_names.h"
#include "scene/resources/theme.h" #include "scene/resources/theme.h"
#include "scene/theme/theme_db.h"
#include "servers/rendering_server.h" #include "servers/rendering_server.h"
#include "thirdparty/misc/clipper.hpp" #include "thirdparty/misc/clipper.hpp"
#include "thirdparty/misc/polypartition.h" #include "thirdparty/misc/polypartition.h"
@ -2984,13 +2985,13 @@ Ref<Font> TextMesh::_get_font_or_default() const {
} }
// Check the project-defined Theme resource. // Check the project-defined Theme resource.
if (Theme::get_project_default().is_valid()) { if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
List<StringName> theme_types; List<StringName> theme_types;
Theme::get_project_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types); ThemeDB::get_singleton()->get_project_theme()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
for (const StringName &E : theme_types) { for (const StringName &E : theme_types) {
if (Theme::get_project_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) { if (ThemeDB::get_singleton()->get_project_theme()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
return Theme::get_project_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E); return ThemeDB::get_singleton()->get_project_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
} }
} }
} }
@ -2998,17 +2999,17 @@ Ref<Font> TextMesh::_get_font_or_default() const {
// Lastly, fall back on the items defined in the default Theme, if they exist. // Lastly, fall back on the items defined in the default Theme, if they exist.
{ {
List<StringName> theme_types; List<StringName> theme_types;
Theme::get_default()->get_type_dependencies(get_class_name(), StringName(), &theme_types); ThemeDB::get_singleton()->get_default_theme()->get_type_dependencies(get_class_name(), StringName(), &theme_types);
for (const StringName &E : theme_types) { for (const StringName &E : theme_types) {
if (Theme::get_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) { if (ThemeDB::get_singleton()->get_default_theme()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
return Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E); return ThemeDB::get_singleton()->get_default_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
} }
} }
} }
// If they don't exist, use any type to return the default/empty value. // If they don't exist, use any type to return the default/empty value.
return Theme::get_default()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName()); return ThemeDB::get_singleton()->get_default_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", StringName());
} }
void TextMesh::set_font_size(int p_size) { void TextMesh::set_font_size(int p_size) {

View File

@ -31,17 +31,7 @@
#include "theme.h" #include "theme.h"
#include "core/string/print_string.h" #include "core/string/print_string.h"
#include "scene/theme/theme_db.h"
// Universal Theme resources used when no other theme has the item.
Ref<Theme> Theme::default_theme;
Ref<Theme> Theme::project_default_theme;
// Universal default values, final fallback for every theme.
float Theme::fallback_base_scale = 1.0;
Ref<Texture2D> Theme::fallback_icon;
Ref<StyleBox> Theme::fallback_style;
Ref<Font> Theme::fallback_font;
int Theme::fallback_font_size = 16;
// Dynamic properties. // Dynamic properties.
bool Theme::_set(const StringName &p_name, const Variant &p_value) { bool Theme::_set(const StringName &p_name, const Variant &p_value) {
@ -185,64 +175,7 @@ void Theme::_get_property_list(List<PropertyInfo> *p_list) const {
} }
} }
// Universal fallback Theme resources. // Static helpers.
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_fallback_base_scale(float p_base_scale) {
fallback_base_scale = p_base_scale;
}
void Theme::set_fallback_icon(const Ref<Texture2D> &p_icon) {
fallback_icon = p_icon;
}
void Theme::set_fallback_style(const Ref<StyleBox> &p_style) {
fallback_style = p_style;
}
void Theme::set_fallback_font(const Ref<Font> &p_font) {
fallback_font = p_font;
}
void Theme::set_fallback_font_size(int p_font_size) {
fallback_font_size = p_font_size;
}
float Theme::get_fallback_base_scale() {
return fallback_base_scale;
}
Ref<Texture2D> Theme::get_fallback_icon() {
return fallback_icon;
}
Ref<StyleBox> Theme::get_fallback_style() {
return fallback_style;
}
Ref<Font> Theme::get_fallback_font() {
return fallback_font;
}
int Theme::get_fallback_font_size() {
return fallback_font_size;
}
bool Theme::is_valid_type_name(const String &p_name) { bool Theme::is_valid_type_name(const String &p_name) {
for (int i = 0; i < p_name.length(); i++) { for (int i = 0; i < p_name.length(); i++) {
if (!is_ascii_identifier_char(p_name[i])) { if (!is_ascii_identifier_char(p_name[i])) {
@ -351,7 +284,7 @@ Ref<Texture2D> Theme::get_icon(const StringName &p_name, const StringName &p_the
if (icon_map.has(p_theme_type) && icon_map[p_theme_type].has(p_name) && icon_map[p_theme_type][p_name].is_valid()) { 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]; return icon_map[p_theme_type][p_name];
} else { } else {
return fallback_icon; return ThemeDB::get_singleton()->get_fallback_icon();
} }
} }
@ -461,7 +394,7 @@ Ref<StyleBox> Theme::get_stylebox(const StringName &p_name, const StringName &p_
if (style_map.has(p_theme_type) && style_map[p_theme_type].has(p_name) && style_map[p_theme_type][p_name].is_valid()) { 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]; return style_map[p_theme_type][p_name];
} else { } else {
return fallback_style; return ThemeDB::get_singleton()->get_fallback_stylebox();
} }
} }
@ -573,7 +506,7 @@ Ref<Font> Theme::get_font(const StringName &p_name, const StringName &p_theme_ty
} else if (has_default_font()) { } else if (has_default_font()) {
return default_font; return default_font;
} else { } else {
return fallback_font; return ThemeDB::get_singleton()->get_fallback_font();
} }
} }
@ -676,7 +609,7 @@ int Theme::get_font_size(const StringName &p_name, const StringName &p_theme_typ
} else if (has_default_font_size()) { } else if (has_default_font_size()) {
return default_font_size; return default_font_size;
} else { } else {
return fallback_font_size; return ThemeDB::get_singleton()->get_fallback_font_size();
} }
} }

View File

@ -102,17 +102,6 @@ protected:
bool _get(const StringName &p_name, Variant &r_ret) const; bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const; void _get_property_list(List<PropertyInfo> *p_list) const;
// 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 fallback_base_scale;
static Ref<Texture2D> fallback_icon;
static Ref<StyleBox> fallback_style;
static Ref<Font> fallback_font;
static int fallback_font_size;
// Default values configurable for each individual theme. // Default values configurable for each individual theme.
float default_base_scale = 0.0; float default_base_scale = 0.0;
Ref<Font> default_font; Ref<Font> default_font;
@ -126,24 +115,6 @@ protected:
virtual void reset_state() override; virtual void reset_state() override;
public: public:
static Ref<Theme> get_default();
static void set_default(const Ref<Theme> &p_default);
static Ref<Theme> get_project_default();
static void set_project_default(const Ref<Theme> &p_project_default);
static void set_fallback_base_scale(float p_base_scale);
static void set_fallback_icon(const Ref<Texture2D> &p_icon);
static void set_fallback_style(const Ref<StyleBox> &p_style);
static void set_fallback_font(const Ref<Font> &p_font);
static void set_fallback_font_size(int p_font_size);
static float get_fallback_base_scale();
static Ref<Texture2D> get_fallback_icon();
static Ref<StyleBox> get_fallback_style();
static Ref<Font> get_fallback_font();
static int get_fallback_font_size();
static bool is_valid_type_name(const String &p_name); static bool is_valid_type_name(const String &p_name);
static bool is_valid_item_name(const String &p_name); static bool is_valid_item_name(const String &p_name);

5
scene/theme/SCsub Normal file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env python
Import("env")
env.add_source_files(env.scene_sources, "*.cpp")

237
scene/theme/theme_db.cpp Normal file
View File

@ -0,0 +1,237 @@
/*************************************************************************/
/* theme_db.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* 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 "theme_db.h"
#include "core/config/project_settings.h"
#include "core/io/resource_loader.h"
#include "scene/resources/default_theme/default_theme.h"
#include "scene/resources/font.h"
#include "scene/resources/style_box.h"
#include "scene/resources/texture.h"
#include "scene/resources/theme.h"
#include "servers/text_server.h"
// Default engine theme creation and configuration.
void ThemeDB::initialize_theme() {
// Allow creating the default theme at a different scale to suit higher/lower base resolutions.
float default_theme_scale = GLOBAL_DEF("gui/theme/default_theme_scale", 1.0);
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_theme_scale", PropertyInfo(Variant::FLOAT, "gui/theme/default_theme_scale", PROPERTY_HINT_RANGE, "0.5,8,0.01", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
String theme_path = GLOBAL_DEF_RST("gui/theme/custom", "");
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom", PropertyInfo(Variant::STRING, "gui/theme/custom", PROPERTY_HINT_FILE, "*.tres,*.res,*.theme", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
String font_path = GLOBAL_DEF_RST("gui/theme/custom_font", "");
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom_font", PropertyInfo(Variant::STRING, "gui/theme/custom_font", PROPERTY_HINT_FILE, "*.tres,*.res", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
TextServer::FontAntialiasing font_antialiasing = (TextServer::FontAntialiasing)(int)GLOBAL_DEF_RST("gui/theme/default_font_antialiasing", 1);
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_antialiasing", PropertyInfo(Variant::INT, "gui/theme/default_font_antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD sub-pixel", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
TextServer::Hinting font_hinting = (TextServer::Hinting)(int)GLOBAL_DEF_RST("gui/theme/default_font_hinting", TextServer::HINTING_LIGHT);
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_hinting", PropertyInfo(Variant::INT, "gui/theme/default_font_hinting", PROPERTY_HINT_ENUM, "None,Light,Normal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
TextServer::SubpixelPositioning font_subpixel_positioning = (TextServer::SubpixelPositioning)(int)GLOBAL_DEF_RST("gui/theme/default_font_subpixel_positioning", TextServer::SUBPIXEL_POSITIONING_AUTO);
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_subpixel_positioning", PropertyInfo(Variant::INT, "gui/theme/default_font_subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED));
const bool font_msdf = GLOBAL_DEF_RST("gui/theme/default_font_multichannel_signed_distance_field", false);
const bool font_generate_mipmaps = GLOBAL_DEF_RST("gui/theme/default_font_generate_mipmaps", false);
GLOBAL_DEF_RST("gui/theme/lcd_subpixel_layout", 1);
ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/lcd_subpixel_layout", PropertyInfo(Variant::INT, "gui/theme/lcd_subpixel_layout", PROPERTY_HINT_ENUM, "Disabled,Horizontal RGB,Horizontal BGR,Vertical RGB,Vertical BGR"));
ProjectSettings::get_singleton()->set_restart_if_changed("gui/theme/lcd_subpixel_layout", false);
Ref<Font> font;
if (!font_path.is_empty()) {
font = ResourceLoader::load(font_path);
if (!font.is_valid()) {
ERR_PRINT("Error loading custom font '" + font_path + "'");
}
}
// Always make the default theme to avoid invalid default font/icon/style in the given theme.
if (RenderingServer::get_singleton()) {
make_default_theme(default_theme_scale, font, font_subpixel_positioning, font_hinting, font_antialiasing, font_msdf, font_generate_mipmaps);
}
if (!theme_path.is_empty()) {
Ref<Theme> theme = ResourceLoader::load(theme_path);
if (theme.is_valid()) {
set_project_theme(theme);
if (font.is_valid()) {
set_fallback_font(font);
}
} else {
ERR_PRINT("Error loading custom theme '" + theme_path + "'");
}
}
}
void ThemeDB::initialize_theme_noproject() {
if (RenderingServer::get_singleton()) {
make_default_theme(1.0, Ref<Font>());
}
}
// Universal fallback Theme resources.
void ThemeDB::set_default_theme(const Ref<Theme> &p_default) {
default_theme = p_default;
}
Ref<Theme> ThemeDB::get_default_theme() {
return default_theme;
}
void ThemeDB::set_project_theme(const Ref<Theme> &p_project_default) {
project_theme = p_project_default;
}
Ref<Theme> ThemeDB::get_project_theme() {
return project_theme;
}
// Universal fallback values for theme item types.
void ThemeDB::set_fallback_base_scale(float p_base_scale) {
if (fallback_base_scale == p_base_scale) {
return;
}
fallback_base_scale = p_base_scale;
emit_signal(SNAME("fallback_changed"));
}
float ThemeDB::get_fallback_base_scale() {
return fallback_base_scale;
}
void ThemeDB::set_fallback_font(const Ref<Font> &p_font) {
if (fallback_font == p_font) {
return;
}
fallback_font = p_font;
emit_signal(SNAME("fallback_changed"));
}
Ref<Font> ThemeDB::get_fallback_font() {
return fallback_font;
}
void ThemeDB::set_fallback_font_size(int p_font_size) {
if (fallback_font_size == p_font_size) {
return;
}
fallback_font_size = p_font_size;
emit_signal(SNAME("fallback_changed"));
}
int ThemeDB::get_fallback_font_size() {
return fallback_font_size;
}
void ThemeDB::set_fallback_icon(const Ref<Texture2D> &p_icon) {
if (fallback_icon == p_icon) {
return;
}
fallback_icon = p_icon;
emit_signal(SNAME("fallback_changed"));
}
Ref<Texture2D> ThemeDB::get_fallback_icon() {
return fallback_icon;
}
void ThemeDB::set_fallback_stylebox(const Ref<StyleBox> &p_stylebox) {
if (fallback_stylebox == p_stylebox) {
return;
}
fallback_stylebox = p_stylebox;
emit_signal(SNAME("fallback_changed"));
}
Ref<StyleBox> ThemeDB::get_fallback_stylebox() {
return fallback_stylebox;
}
// Object methods.
void ThemeDB::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_default_theme"), &ThemeDB::get_default_theme);
ClassDB::bind_method(D_METHOD("get_project_theme"), &ThemeDB::get_project_theme);
ClassDB::bind_method(D_METHOD("set_fallback_base_scale", "base_scale"), &ThemeDB::set_fallback_base_scale);
ClassDB::bind_method(D_METHOD("get_fallback_base_scale"), &ThemeDB::get_fallback_base_scale);
ClassDB::bind_method(D_METHOD("set_fallback_font", "font"), &ThemeDB::set_fallback_font);
ClassDB::bind_method(D_METHOD("get_fallback_font"), &ThemeDB::get_fallback_font);
ClassDB::bind_method(D_METHOD("set_fallback_font_size", "font_size"), &ThemeDB::set_fallback_font_size);
ClassDB::bind_method(D_METHOD("get_fallback_font_size"), &ThemeDB::get_fallback_font_size);
ClassDB::bind_method(D_METHOD("set_fallback_icon", "icon"), &ThemeDB::set_fallback_icon);
ClassDB::bind_method(D_METHOD("get_fallback_icon"), &ThemeDB::get_fallback_icon);
ClassDB::bind_method(D_METHOD("set_fallback_stylebox", "stylebox"), &ThemeDB::set_fallback_stylebox);
ClassDB::bind_method(D_METHOD("get_fallback_stylebox"), &ThemeDB::get_fallback_stylebox);
ADD_GROUP("Fallback values", "fallback_");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fallback_base_scale", PROPERTY_HINT_RANGE, "0.0,2.0,0.01,or_greater"), "set_fallback_base_scale", "get_fallback_base_scale");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "fallback_font", PROPERTY_HINT_RESOURCE_TYPE, "Font", PROPERTY_USAGE_NONE), "set_fallback_font", "get_fallback_font");
ADD_PROPERTY(PropertyInfo(Variant::INT, "fallback_font_size", PROPERTY_HINT_RANGE, "0,256,1,or_greater,suffix:px"), "set_fallback_font_size", "get_fallback_font_size");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "fallback_icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", PROPERTY_USAGE_NONE), "set_fallback_icon", "get_fallback_icon");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "fallback_stylebox", PROPERTY_HINT_RESOURCE_TYPE, "StyleBox", PROPERTY_USAGE_NONE), "set_fallback_stylebox", "get_fallback_stylebox");
ADD_SIGNAL(MethodInfo("fallback_changed"));
}
// Memory management, reference, and initialization
ThemeDB *ThemeDB::singleton = nullptr;
ThemeDB *ThemeDB::get_singleton() {
return singleton;
}
ThemeDB::ThemeDB() {
singleton = this;
// Universal default values, final fallback for every theme.
fallback_base_scale = 1.0;
fallback_font_size = 16;
}
ThemeDB::~ThemeDB() {
default_theme.unref();
project_theme.unref();
fallback_font.unref();
fallback_icon.unref();
fallback_stylebox.unref();
singleton = nullptr;
}

95
scene/theme/theme_db.h Normal file
View File

@ -0,0 +1,95 @@
/*************************************************************************/
/* theme_db.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* 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 THEME_DB_H
#define THEME_DB_H
#include "core/object/class_db.h"
#include "core/object/ref_counted.h"
class Font;
class StyleBox;
class Texture2D;
class Theme;
class ThemeDB : public Object {
GDCLASS(ThemeDB, Object);
static ThemeDB *singleton;
// Universal Theme resources used when no other theme has the item.
Ref<Theme> default_theme;
Ref<Theme> project_theme;
// Universal default values, final fallback for every theme.
float fallback_base_scale;
Ref<Font> fallback_font;
int fallback_font_size;
Ref<Texture2D> fallback_icon;
Ref<StyleBox> fallback_stylebox;
protected:
static void _bind_methods();
public:
void initialize_theme();
void initialize_theme_noproject();
// Universal Theme resources
void set_default_theme(const Ref<Theme> &p_default);
Ref<Theme> get_default_theme();
void set_project_theme(const Ref<Theme> &p_project_default);
Ref<Theme> get_project_theme();
// Universal default values.
void set_fallback_base_scale(float p_base_scale);
float get_fallback_base_scale();
void set_fallback_font(const Ref<Font> &p_font);
Ref<Font> get_fallback_font();
void set_fallback_font_size(int p_font_size);
int get_fallback_font_size();
void set_fallback_icon(const Ref<Texture2D> &p_icon);
Ref<Texture2D> get_fallback_icon();
void set_fallback_stylebox(const Ref<StyleBox> &p_stylebox);
Ref<StyleBox> get_fallback_stylebox();
static ThemeDB *get_singleton();
ThemeDB();
~ThemeDB();
};
#endif // THEME_DB_H

View File

@ -99,7 +99,7 @@
#include "tests/test_macros.h" #include "tests/test_macros.h"
#include "scene/resources/default_theme/default_theme.h" #include "scene/theme/theme_db.h"
#include "servers/navigation_server_2d.h" #include "servers/navigation_server_2d.h"
#include "servers/navigation_server_3d.h" #include "servers/navigation_server_3d.h"
#include "servers/physics_server_2d.h" #include "servers/physics_server_2d.h"
@ -179,6 +179,7 @@ struct GodotTestCaseListener : public doctest::IReporter {
PhysicsServer2D *physics_server_2d = nullptr; PhysicsServer2D *physics_server_2d = nullptr;
NavigationServer3D *navigation_server_3d = nullptr; NavigationServer3D *navigation_server_3d = nullptr;
NavigationServer2D *navigation_server_2d = nullptr; NavigationServer2D *navigation_server_2d = nullptr;
ThemeDB *theme_db = nullptr;
void test_case_start(const doctest::TestCaseData &p_in) override { void test_case_start(const doctest::TestCaseData &p_in) override {
SignalWatcher::get_singleton()->_clear_signals(); SignalWatcher::get_singleton()->_clear_signals();
@ -217,7 +218,8 @@ struct GodotTestCaseListener : public doctest::IReporter {
memnew(InputMap); memnew(InputMap);
InputMap::get_singleton()->load_default(); InputMap::get_singleton()->load_default();
make_default_theme(1.0, Ref<Font>()); theme_db = memnew(ThemeDB);
theme_db->initialize_theme_noproject();
memnew(SceneTree); memnew(SceneTree);
SceneTree::get_singleton()->initialize(); SceneTree::get_singleton()->initialize();
@ -247,7 +249,10 @@ struct GodotTestCaseListener : public doctest::IReporter {
memdelete(SceneTree::get_singleton()); memdelete(SceneTree::get_singleton());
} }
clear_default_theme(); if (theme_db) {
memdelete(theme_db);
theme_db = nullptr;
}
if (navigation_server_3d) { if (navigation_server_3d) {
memdelete(navigation_server_3d); memdelete(navigation_server_3d);