Merge pull request #64119 from YuriSizov/theme-init-database

This commit is contained in:
Rémi Verschelde 2022-08-29 14:02:21 +02:00 committed by GitHub
commit e60086f98b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 589 additions and 311 deletions

View file

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

View file

@ -436,7 +436,7 @@
<param index="1" name="theme_type" type="StringName" default="&quot;&quot;" />
<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.
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]
[gdscript]
func _ready():

View file

@ -150,7 +150,7 @@
<description>
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 engine fallback font value, if neither exist.
Returns the engine fallback font value, if neither exist (see [member ThemeDB.fallback_font]).
</description>
</method>
<method name="get_font_list" qualifiers="const">
@ -167,7 +167,7 @@
<description>
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 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>
</method>
<method name="get_font_size_list" qualifiers="const">
@ -195,7 +195,7 @@
<param index="1" name="theme_type" type="StringName" />
<description>
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>
</method>
<method name="get_icon_list" qualifiers="const">
@ -217,7 +217,7 @@
<param index="1" name="theme_type" type="StringName" />
<description>
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>
</method>
<method name="get_stylebox_list" qualifiers="const">
@ -240,7 +240,7 @@
<param index="2" name="theme_type" type="StringName" />
<description>
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.
</description>
</method>
@ -542,15 +542,15 @@
</methods>
<members>
<member name="default_base_scale" type="float" setter="set_default_base_scale" getter="get_default_base_scale" default="0.0">
The default base scale factor of this theme resource. Used by some controls to scale their visual properties based on 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.
</member>
<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.
</member>
<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.
</member>
</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 "editor/editor_settings.h"
#include "scene/resources/theme.h"
#include "scene/theme/theme_db.h"
// Used for a hack preserving Mono properties on non-Mono builds.
#include "modules/modules_enabled.gen.h" // For mono.
@ -567,29 +568,29 @@ void DocTools::generate(bool p_basic_types) {
{
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) {
DocData::ThemeItemDoc tid;
tid.name = E;
tid.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);
}
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) {
DocData::ThemeItemDoc tid;
tid.name = E;
tid.type = "int";
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);
}
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) {
DocData::ThemeItemDoc tid;
tid.name = E;
@ -599,7 +600,7 @@ void DocTools::generate(bool p_basic_types) {
}
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) {
DocData::ThemeItemDoc tid;
tid.name = E;
@ -609,7 +610,7 @@ void DocTools::generate(bool p_basic_types) {
}
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) {
DocData::ThemeItemDoc tid;
tid.name = E;
@ -619,7 +620,7 @@ void DocTools::generate(bool p_basic_types) {
}
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) {
DocData::ThemeItemDoc tid;
tid.name = E;

View file

@ -38,6 +38,7 @@
#include "editor/editor_undo_redo_manager.h"
#include "editor/progress_dialog.h"
#include "scene/gui/color_picker.h"
#include "scene/theme/theme_db.h"
void ThemeItemImportTree::_update_items_tree() {
import_items_tree->clear();
@ -1202,7 +1203,7 @@ void ThemeItemEditorDialog::_dialog_about_to_show() {
_update_edit_types();
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_editor_theme_items->set_edited_theme(edited_theme);
@ -1214,7 +1215,7 @@ void ThemeItemEditorDialog::_dialog_about_to_show() {
}
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;
edited_theme->get_type_list(&theme_types);
@ -1630,7 +1631,7 @@ void ThemeItemEditorDialog::_remove_class_items() {
Theme::DataType data_type = (Theme::DataType)dt;
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) {
if (new_snapshot->has_theme_item_nocheck(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();
new_snapshot->get_theme_item_list(data_type, edited_item_type, &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);
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();
List<StringName> names;
Theme::get_default()->get_type_list(&names);
ThemeDB::get_singleton()->get_default_theme()->get_type_list(&names);
if (include_own_types) {
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);
}
(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>();
for (const StringName &E : names) {
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->get_popup()->connect("about_to_popup", callable_mp(EditorNode::get_singleton(), &EditorNode::setup_color_picker).bind(item_editor->get_picker()));
} 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);
}
@ -2529,7 +2530,7 @@ void ThemeTypeEditor::_update_type_items() {
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));
} 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);
}
@ -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_changed", callable_mp(this, &ThemeTypeEditor::_font_item_changed).bind(E.key));
} else {
if (Theme::get_default()->has_font(E.key, edited_type)) {
item_editor->set_edited_resource(Theme::get_default()->get_font(E.key, edited_type));
if (ThemeDB::get_singleton()->get_default_theme()->has_font(E.key, edited_type)) {
item_editor->set_edited_resource(ThemeDB::get_singleton()->get_default_theme()->get_font(E.key, edited_type));
} else {
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->connect("value_changed", callable_mp(this, &ThemeTypeEditor::_font_size_item_changed).bind(E.key));
} 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);
}
@ -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_changed", callable_mp(this, &ThemeTypeEditor::_icon_item_changed).bind(E.key));
} else {
if (Theme::get_default()->has_icon(E.key, edited_type)) {
item_editor->set_edited_resource(Theme::get_default()->get_icon(E.key, edited_type));
if (ThemeDB::get_singleton()->get_default_theme()->has_icon(E.key, edited_type)) {
item_editor->set_edited_resource(ThemeDB::get_singleton()->get_default_theme()->get_icon(E.key, edited_type));
} else {
item_editor->set_edited_resource(Ref<Resource>());
}
@ -2714,8 +2715,8 @@ void ThemeTypeEditor::_update_type_items() {
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));
} else {
if (Theme::get_default()->has_stylebox(E.key, edited_type)) {
item_editor->set_edited_resource(Theme::get_default()->get_stylebox(E.key, edited_type));
if (ThemeDB::get_singleton()->get_default_theme()->has_stylebox(E.key, edited_type)) {
item_editor->set_edited_resource(ThemeDB::get_singleton()->get_default_theme()->get_stylebox(E.key, edited_type));
} else {
item_editor->set_edited_resource(Ref<Resource>());
}
@ -2770,55 +2771,55 @@ void ThemeTypeEditor::_add_default_type_items() {
{
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) {
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();
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) {
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();
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) {
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();
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) {
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();
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) {
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();
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) {
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) {
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);
} break;
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);
} break;
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);
} break;
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);
} break;
case Theme::DATA_TYPE_ICON: {

View file

@ -40,6 +40,7 @@
#include "scene/gui/color_picker.h"
#include "scene/gui/progress_bar.h"
#include "scene/resources/packed_scene.h"
#include "scene/theme/theme_db.h"
constexpr double REFRESH_TIMER = 1.5;
@ -240,7 +241,7 @@ ThemeEditorPreview::ThemeEditorPreview() {
MarginContainer *preview_root = memnew(MarginContainer);
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_custom_minimum_size(Size2(450, 0) * EDSCALE);
preview_root->set_v_size_flags(SIZE_EXPAND_FILL);

View file

@ -63,6 +63,7 @@
#include "scene/main/window.h"
#include "scene/register_scene_types.h"
#include "scene/resources/packed_scene.h"
#include "scene/theme/theme_db.h"
#include "servers/audio_server.h"
#include "servers/camera_server.h"
#include "servers/display_server.h"
@ -129,6 +130,7 @@ static PhysicsServer3D *physics_server_3d = nullptr;
static PhysicsServer2D *physics_server_2d = nullptr;
static NavigationServer3D *navigation_server_3d = nullptr;
static NavigationServer2D *navigation_server_2d = nullptr;
static ThemeDB *theme_db = nullptr;
// We error out if setup2() doesn't turn this true
static bool _start_success = false;
@ -273,6 +275,16 @@ void finalize_navigation_server() {
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
#ifdef DEBUG_INIT
#define MAIN_PRINT(m_txt) print_line(m_txt)
@ -475,7 +487,8 @@ Error Main::test_setup() {
register_platform_apis();
// 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);
@ -526,6 +539,8 @@ void Main::test_cleanup() {
unregister_driver_types();
unregister_scene_types();
finalize_theme_db();
NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS);
uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS);
unregister_server_types();
@ -2126,7 +2141,8 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
register_platform_apis();
// 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_hotspot", Vector2());
@ -3120,6 +3136,8 @@ void Main::cleanup(bool p_force) {
unregister_driver_types();
unregister_scene_types();
finalize_theme_db();
NativeExtensionManager::get_singleton()->deinitialize_extensions(NativeExtension::INITIALIZATION_LEVEL_SERVERS);
uninitialize_modules(MODULE_INITIALIZATION_LEVEL_SERVERS);
unregister_server_types();

View file

@ -35,6 +35,7 @@
#include "editor/editor_settings.h"
#include "scene/gui/control.h"
#include "scene/main/node.h"
#include "scene/theme/theme_db.h"
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);
if (base && Object::cast_to<Control>(base)) {
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) {
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);
if (base && Object::cast_to<Control>(base)) {
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) {
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);
if (base && Object::cast_to<Control>(base)) {
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) {
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);
if (base && Object::cast_to<Control>(base)) {
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) {
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);
if (base && Object::cast_to<Control>(base)) {
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) {
suggestions.push_back(quoted(E));

View file

@ -34,6 +34,7 @@
#include "scene/main/viewport.h"
#include "scene/resources/theme.h"
#include "scene/scene_string_names.h"
#include "scene/theme/theme_db.h"
void Label3D::_bind_methods() {
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.
if (Theme::get_project_default().is_valid()) {
if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
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) {
if (Theme::get_project_default()->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);
if (ThemeDB::get_singleton()->get_project_theme()->has_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()) {
theme_font = f;
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.
{
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) {
if (Theme::get_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
Ref<Font> f = Theme::get_default()->get_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 = ThemeDB::get_singleton()->get_default_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
if (f.is_valid()) {
theme_font = f;
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.
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()) {
theme_font = f;
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("resources/SCsub")
SConscript("debugger/SCsub")
SConscript("theme/SCsub")
# Build it all as a library
lib = env.add_library("scene", env.scene_sources)

View file

@ -43,6 +43,7 @@
#include "scene/main/canvas_layer.h"
#include "scene/main/window.h"
#include "scene/scene_string_names.h"
#include "scene/theme/theme_db.h"
#include "servers/rendering_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;
String pf = p_function;
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") {
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") {
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") {
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") {
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>();
@ -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 {
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));
@ -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.
// 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);
if (Theme::get_project_default().is_valid()) {
Theme::get_project_default()->get_type_variation_list(get_class_name(), &names);
ThemeDB::get_singleton()->get_default_theme()->get_type_variation_list(get_class_name(), &names);
if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
ThemeDB::get_singleton()->get_project_theme()->get_type_variation_list(get_class_name(), &names);
}
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.
if (Theme::get_project_default().is_valid()) {
if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
for (const StringName &E : p_theme_types) {
if (Theme::get_project_default()->has_theme_item(p_data_type, p_name, E)) {
return Theme::get_project_default()->get_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 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.
for (const StringName &E : p_theme_types) {
if (Theme::get_default()->has_theme_item(p_data_type, p_name, E)) {
return Theme::get_default()->get_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 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.
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) {
@ -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.
if (Theme::get_project_default().is_valid()) {
if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
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;
}
}
@ -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.
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;
}
}
@ -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 {
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()) {
Theme::get_project_default()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list);
if (ThemeDB::get_singleton()->get_project_theme().is_valid() && ThemeDB::get_singleton()->get_project_theme()->get_type_variation_base(data.theme_type_variation) != StringName()) {
ThemeDB::get_singleton()->get_project_theme()->get_type_dependencies(get_class_name(), data.theme_type_variation, p_list);
} 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 {
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.
if (Theme::get_project_default().is_valid()) {
if (Theme::get_project_default()->has_default_base_scale()) {
return Theme::get_project_default()->get_default_base_scale();
if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
if (ThemeDB::get_singleton()->get_project_theme()->has_default_base_scale()) {
return ThemeDB::get_singleton()->get_project_theme()->get_default_base_scale();
}
}
// Lastly, fall back on the default Theme.
if (Theme::get_default()->has_default_base_scale()) {
return Theme::get_default()->get_default_base_scale();
if (ThemeDB::get_singleton()->get_default_theme()->has_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 {
@ -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.
if (Theme::get_project_default().is_valid()) {
if (Theme::get_project_default()->has_default_font()) {
return Theme::get_project_default()->get_default_font();
if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
if (ThemeDB::get_singleton()->get_project_theme()->has_default_font()) {
return ThemeDB::get_singleton()->get_project_theme()->get_default_font();
}
}
// Lastly, fall back on the default Theme.
if (Theme::get_default()->has_default_font()) {
return Theme::get_default()->get_default_font();
if (ThemeDB::get_singleton()->get_default_theme()->has_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 {
@ -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.
if (Theme::get_project_default().is_valid()) {
if (Theme::get_project_default()->has_default_font_size()) {
return Theme::get_project_default()->get_default_font_size();
if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
if (ThemeDB::get_singleton()->get_project_theme()->has_default_font_size()) {
return ThemeDB::get_singleton()->get_project_theme()->get_default_font_size();
}
}
// Lastly, fall back on the default Theme.
if (Theme::get_default()->has_default_font_size()) {
return Theme::get_default()->get_default_font_size();
if (ThemeDB::get_singleton()->get_default_theme()->has_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 {

View file

@ -35,6 +35,7 @@
#include "core/string/translation.h"
#include "scene/gui/control.h"
#include "scene/scene_string_names.h"
#include "scene/theme/theme_db.h"
void Window::set_title(const String &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 {
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()) {
Theme::get_project_default()->get_type_dependencies(get_class_name(), theme_type_variation, p_list);
if (ThemeDB::get_singleton()->get_project_theme().is_valid() && ThemeDB::get_singleton()->get_project_theme()->get_type_variation_base(theme_type_variation) != StringName()) {
ThemeDB::get_singleton()->get_project_theme()->get_type_dependencies(get_class_name(), theme_type_variation, p_list);
} 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 {
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.
// 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);
if (Theme::get_project_default().is_valid()) {
Theme::get_project_default()->get_type_variation_list(get_class_name(), &names);
ThemeDB::get_singleton()->get_default_theme()->get_type_variation_list(get_class_name(), &names);
if (ThemeDB::get_singleton()->get_project_theme().is_valid()) {
ThemeDB::get_singleton()->get_project_theme()->get_type_variation_list(get_class_name(), &names);
}
names.sort_custom<StringName::AlphCompare>();

View file

@ -193,12 +193,14 @@
#include "scene/resources/sky.h"
#include "scene/resources/sky_material.h"
#include "scene/resources/sphere_shape_3d.h"
#include "scene/resources/style_box.h"
#include "scene/resources/surface_tool.h"
#include "scene/resources/syntax_highlighter.h"
#include "scene/resources/text_file.h"
#include "scene/resources/text_line.h"
#include "scene/resources/text_paragraph.h"
#include "scene/resources/texture.h"
#include "scene/resources/theme.h"
#include "scene/resources/tile_set.h"
#include "scene/resources/video_stream.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_3d.h"
#include "scene/scene_string_names.h"
#include "scene/theme/theme_db.h"
#include "scene/main/shader_globals_override.h"
@ -1130,62 +1133,8 @@ void register_scene_types() {
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() {
SceneDebugger::deinitialize();
clear_default_theme();
ResourceLoader::remove_resource_format_loader(resource_loader_texture_layered);
resource_loader_texture_layered.unref();
@ -1227,3 +1176,9 @@ void unregister_scene_types() {
ColorPicker::finish_shaders();
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 unregister_scene_types();
void initialize_theme();
void register_scene_singletons();
#endif // REGISTER_SCENE_TYPES_H

View file

@ -35,6 +35,7 @@
#include "default_theme_icons.gen.h"
#include "scene/resources/font.h"
#include "scene/resources/theme.h"
#include "scene/theme/theme_db.h"
#include "servers/text_server.h"
#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);
Theme::set_default(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);
}
ThemeDB::get_singleton()->set_default_theme(t);
void clear_default_theme() {
Theme::set_project_default(nullptr);
Theme::set_default(nullptr);
Theme::set_fallback_icon(nullptr);
Theme::set_fallback_style(nullptr);
Theme::set_fallback_font(nullptr);
ThemeDB::get_singleton()->set_fallback_base_scale(default_scale);
ThemeDB::get_singleton()->set_fallback_icon(default_icon);
ThemeDB::get_singleton()->set_fallback_stylebox(default_style);
ThemeDB::get_singleton()->set_fallback_font(default_font);
ThemeDB::get_singleton()->set_fallback_font_size(default_font_size * default_scale);
}

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 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

View file

@ -39,6 +39,7 @@
#include "scene/resources/text_line.h"
#include "scene/resources/text_paragraph.h"
#include "scene/resources/theme.h"
#include "scene/theme/theme_db.h"
/*************************************************************************/
/* Font */
@ -2552,13 +2553,13 @@ Ref<Font> FontVariation::_get_base_font_or_default() const {
}
// 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;
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) {
if (Theme::get_project_default()->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);
if (ThemeDB::get_singleton()->get_project_theme()->has_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()) {
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);
@ -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.
if (Theme::get_default().is_valid()) {
if (ThemeDB::get_singleton()->get_default_theme().is_valid()) {
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) {
if (Theme::get_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
Ref<Font> f = Theme::get_default()->get_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 = ThemeDB::get_singleton()->get_default_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
if (f.is_valid()) {
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);
@ -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.
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()) {
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);
@ -2859,13 +2860,13 @@ Ref<Font> SystemFont::_get_base_font_or_default() const {
}
// 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;
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) {
if (Theme::get_project_default()->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);
if (ThemeDB::get_singleton()->get_project_theme()->has_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()) {
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);
@ -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.
if (Theme::get_default().is_valid()) {
if (ThemeDB::get_singleton()->get_default_theme().is_valid()) {
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) {
if (Theme::get_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
Ref<Font> f = Theme::get_default()->get_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 = ThemeDB::get_singleton()->get_default_theme()->get_theme_item(Theme::DATA_TYPE_FONT, "font", E);
if (f.is_valid()) {
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);
@ -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.
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()) {
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);

View file

@ -32,6 +32,7 @@
#include "core/core_string_names.h"
#include "scene/resources/theme.h"
#include "scene/theme/theme_db.h"
#include "servers/rendering_server.h"
#include "thirdparty/misc/clipper.hpp"
#include "thirdparty/misc/polypartition.h"
@ -2984,13 +2985,13 @@ Ref<Font> TextMesh::_get_font_or_default() const {
}
// 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;
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) {
if (Theme::get_project_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
return Theme::get_project_default()->get_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 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.
{
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) {
if (Theme::get_default()->has_theme_item(Theme::DATA_TYPE_FONT, "font", E)) {
return Theme::get_default()->get_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 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.
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) {

View file

@ -31,17 +31,7 @@
#include "theme.h"
#include "core/string/print_string.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;
#include "scene/theme/theme_db.h"
// Dynamic properties.
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.
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;
}
// Static helpers.
bool Theme::is_valid_type_name(const String &p_name) {
for (int i = 0; i < p_name.length(); 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()) {
return icon_map[p_theme_type][p_name];
} 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()) {
return style_map[p_theme_type][p_name];
} 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()) {
return default_font;
} 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()) {
return default_font_size;
} 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;
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.
float default_base_scale = 0.0;
Ref<Font> default_font;
@ -126,24 +115,6 @@ protected:
virtual void reset_state() override;
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_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 "scene/resources/default_theme/default_theme.h"
#include "scene/theme/theme_db.h"
#include "servers/navigation_server_2d.h"
#include "servers/navigation_server_3d.h"
#include "servers/physics_server_2d.h"
@ -179,6 +179,7 @@ struct GodotTestCaseListener : public doctest::IReporter {
PhysicsServer2D *physics_server_2d = nullptr;
NavigationServer3D *navigation_server_3d = nullptr;
NavigationServer2D *navigation_server_2d = nullptr;
ThemeDB *theme_db = nullptr;
void test_case_start(const doctest::TestCaseData &p_in) override {
SignalWatcher::get_singleton()->_clear_signals();
@ -217,7 +218,8 @@ struct GodotTestCaseListener : public doctest::IReporter {
memnew(InputMap);
InputMap::get_singleton()->load_default();
make_default_theme(1.0, Ref<Font>());
theme_db = memnew(ThemeDB);
theme_db->initialize_theme_noproject();
memnew(SceneTree);
SceneTree::get_singleton()->initialize();
@ -247,7 +249,10 @@ struct GodotTestCaseListener : public doctest::IReporter {
memdelete(SceneTree::get_singleton());
}
clear_default_theme();
if (theme_db) {
memdelete(theme_db);
theme_db = nullptr;
}
if (navigation_server_3d) {
memdelete(navigation_server_3d);