diff options
Diffstat (limited to 'scene/main')
-rw-r--r-- | scene/main/window.cpp | 522 | ||||
-rw-r--r-- | scene/main/window.h | 61 |
2 files changed, 542 insertions, 41 deletions
diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 73436b1658..c71c3e195b 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -40,6 +40,218 @@ #include "scene/theme/theme_db.h" #include "scene/theme/theme_owner.h" +// Dynamic properties. + +bool Window::_set(const StringName &p_name, const Variant &p_value) { + String name = p_name; + if (!name.begins_with("theme_override")) { + return false; + } + + if (p_value.get_type() == Variant::NIL || (p_value.get_type() == Variant::OBJECT && (Object *)p_value == nullptr)) { + if (name.begins_with("theme_override_icons/")) { + String dname = name.get_slicec('/', 1); + if (theme_icon_override.has(dname)) { + theme_icon_override[dname]->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed)); + } + theme_icon_override.erase(dname); + _notify_theme_override_changed(); + } else if (name.begins_with("theme_override_styles/")) { + String dname = name.get_slicec('/', 1); + if (theme_style_override.has(dname)) { + theme_style_override[dname]->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed)); + } + theme_style_override.erase(dname); + _notify_theme_override_changed(); + } else if (name.begins_with("theme_override_fonts/")) { + String dname = name.get_slicec('/', 1); + if (theme_font_override.has(dname)) { + theme_font_override[dname]->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed)); + } + theme_font_override.erase(dname); + _notify_theme_override_changed(); + } else if (name.begins_with("theme_override_font_sizes/")) { + String dname = name.get_slicec('/', 1); + theme_font_size_override.erase(dname); + _notify_theme_override_changed(); + } else if (name.begins_with("theme_override_colors/")) { + String dname = name.get_slicec('/', 1); + theme_color_override.erase(dname); + _notify_theme_override_changed(); + } else if (name.begins_with("theme_override_constants/")) { + String dname = name.get_slicec('/', 1); + theme_constant_override.erase(dname); + _notify_theme_override_changed(); + } else { + return false; + } + + } else { + if (name.begins_with("theme_override_icons/")) { + String dname = name.get_slicec('/', 1); + add_theme_icon_override(dname, p_value); + } else if (name.begins_with("theme_override_styles/")) { + String dname = name.get_slicec('/', 1); + add_theme_style_override(dname, p_value); + } else if (name.begins_with("theme_override_fonts/")) { + String dname = name.get_slicec('/', 1); + add_theme_font_override(dname, p_value); + } else if (name.begins_with("theme_override_font_sizes/")) { + String dname = name.get_slicec('/', 1); + add_theme_font_size_override(dname, p_value); + } else if (name.begins_with("theme_override_colors/")) { + String dname = name.get_slicec('/', 1); + add_theme_color_override(dname, p_value); + } else if (name.begins_with("theme_override_constants/")) { + String dname = name.get_slicec('/', 1); + add_theme_constant_override(dname, p_value); + } else { + return false; + } + } + return true; +} + +bool Window::_get(const StringName &p_name, Variant &r_ret) const { + String sname = p_name; + if (!sname.begins_with("theme_override")) { + return false; + } + + if (sname.begins_with("theme_override_icons/")) { + String name = sname.get_slicec('/', 1); + r_ret = theme_icon_override.has(name) ? Variant(theme_icon_override[name]) : Variant(); + } else if (sname.begins_with("theme_override_styles/")) { + String name = sname.get_slicec('/', 1); + r_ret = theme_style_override.has(name) ? Variant(theme_style_override[name]) : Variant(); + } else if (sname.begins_with("theme_override_fonts/")) { + String name = sname.get_slicec('/', 1); + r_ret = theme_font_override.has(name) ? Variant(theme_font_override[name]) : Variant(); + } else if (sname.begins_with("theme_override_font_sizes/")) { + String name = sname.get_slicec('/', 1); + r_ret = theme_font_size_override.has(name) ? Variant(theme_font_size_override[name]) : Variant(); + } else if (sname.begins_with("theme_override_colors/")) { + String name = sname.get_slicec('/', 1); + r_ret = theme_color_override.has(name) ? Variant(theme_color_override[name]) : Variant(); + } else if (sname.begins_with("theme_override_constants/")) { + String name = sname.get_slicec('/', 1); + r_ret = theme_constant_override.has(name) ? Variant(theme_constant_override[name]) : Variant(); + } else { + return false; + } + + return true; +} + +void Window::_get_property_list(List<PropertyInfo> *p_list) const { + Ref<Theme> default_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)); + + { + List<StringName> names; + default_theme->get_color_list(get_class_name(), &names); + for (const StringName &E : names) { + uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE; + if (theme_color_override.has(E)) { + usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED; + } + + p_list->push_back(PropertyInfo(Variant::COLOR, "theme_override_colors/" + E, PROPERTY_HINT_NONE, "", usage)); + } + } + { + List<StringName> names; + default_theme->get_constant_list(get_class_name(), &names); + for (const StringName &E : names) { + uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE; + if (theme_constant_override.has(E)) { + usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED; + } + + p_list->push_back(PropertyInfo(Variant::INT, "theme_override_constants/" + E, PROPERTY_HINT_RANGE, "-16384,16384", usage)); + } + } + { + List<StringName> names; + default_theme->get_font_list(get_class_name(), &names); + for (const StringName &E : names) { + uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE; + if (theme_font_override.has(E)) { + usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED; + } + + p_list->push_back(PropertyInfo(Variant::OBJECT, "theme_override_fonts/" + E, PROPERTY_HINT_RESOURCE_TYPE, "Font", usage)); + } + } + { + List<StringName> names; + default_theme->get_font_size_list(get_class_name(), &names); + for (const StringName &E : names) { + uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE; + if (theme_font_size_override.has(E)) { + usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED; + } + + p_list->push_back(PropertyInfo(Variant::INT, "theme_override_font_sizes/" + E, PROPERTY_HINT_RANGE, "1,256,1,or_greater,suffix:px", usage)); + } + } + { + List<StringName> names; + default_theme->get_icon_list(get_class_name(), &names); + for (const StringName &E : names) { + uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE; + if (theme_icon_override.has(E)) { + usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED; + } + + p_list->push_back(PropertyInfo(Variant::OBJECT, "theme_override_icons/" + E, PROPERTY_HINT_RESOURCE_TYPE, "Texture2D", usage)); + } + } + { + List<StringName> names; + default_theme->get_stylebox_list(get_class_name(), &names); + for (const StringName &E : names) { + uint32_t usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE; + if (theme_style_override.has(E)) { + usage |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED; + } + + p_list->push_back(PropertyInfo(Variant::OBJECT, "theme_override_styles/" + E, PROPERTY_HINT_RESOURCE_TYPE, "StyleBox", usage)); + } + } +} + +void Window::_validate_property(PropertyInfo &p_property) const { + if (p_property.name == "theme_type_variation") { + List<StringName> names; + + // 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. + 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>(); + + Vector<StringName> unique_names; + String hint_string; + for (const StringName &E : names) { + // Skip duplicate values. + if (unique_names.has(E)) { + continue; + } + + hint_string += String(E) + ","; + unique_names.append(E); + } + + p_property.hint_string = hint_string; + } +} + +// + void Window::set_title(const String &p_title) { title = p_title; @@ -1323,6 +1535,8 @@ void Window::remove_child_notify(Node *p_child) { } } +// Theming. + void Window::set_theme_owner_node(Node *p_node) { theme_owner->set_owner_node(p_node); } @@ -1376,6 +1590,12 @@ void Window::_theme_changed() { } } +void Window::_notify_theme_override_changed() { + if (!bulk_theme_override && is_inside_tree()) { + notification(NOTIFICATION_THEME_CHANGED); + } +} + void Window::_invalidate_theme_cache() { theme_icon_cache.clear(); theme_style_cache.clear(); @@ -1386,6 +1606,9 @@ void Window::_invalidate_theme_cache() { } void Window::_update_theme_item_cache() { + // Request an update on the next frame to reflect theme changes. + // Updating without a delay can cause a lot of lag. + child_controls_changed(); } void Window::set_theme_type_variation(const StringName &p_theme_type) { @@ -1399,7 +1622,16 @@ StringName Window::get_theme_type_variation() const { return theme_type_variation; } +/// Theme property lookup. + Ref<Texture2D> Window::get_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { + const Ref<Texture2D> *tex = theme_icon_override.getptr(p_name); + if (tex) { + return *tex; + } + } + if (theme_icon_cache.has(p_theme_type) && theme_icon_cache[p_theme_type].has(p_name)) { return theme_icon_cache[p_theme_type][p_name]; } @@ -1412,6 +1644,13 @@ Ref<Texture2D> Window::get_theme_icon(const StringName &p_name, const StringName } Ref<StyleBox> Window::get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { + const Ref<StyleBox> *style = theme_style_override.getptr(p_name); + if (style) { + return *style; + } + } + if (theme_style_cache.has(p_theme_type) && theme_style_cache[p_theme_type].has(p_name)) { return theme_style_cache[p_theme_type][p_name]; } @@ -1424,6 +1663,13 @@ Ref<StyleBox> Window::get_theme_stylebox(const StringName &p_name, const StringN } Ref<Font> Window::get_theme_font(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { + const Ref<Font> *font = theme_font_override.getptr(p_name); + if (font) { + return *font; + } + } + if (theme_font_cache.has(p_theme_type) && theme_font_cache[p_theme_type].has(p_name)) { return theme_font_cache[p_theme_type][p_name]; } @@ -1436,6 +1682,13 @@ Ref<Font> Window::get_theme_font(const StringName &p_name, const StringName &p_t } int Window::get_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { + const int *font_size = theme_font_size_override.getptr(p_name); + if (font_size && (*font_size) > 0) { + return *font_size; + } + } + if (theme_font_size_cache.has(p_theme_type) && theme_font_size_cache[p_theme_type].has(p_name)) { return theme_font_size_cache[p_theme_type][p_name]; } @@ -1448,6 +1701,13 @@ int Window::get_theme_font_size(const StringName &p_name, const StringName &p_th } Color Window::get_theme_color(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { + const Color *color = theme_color_override.getptr(p_name); + if (color) { + return *color; + } + } + if (theme_color_cache.has(p_theme_type) && theme_color_cache[p_theme_type].has(p_name)) { return theme_color_cache[p_theme_type][p_name]; } @@ -1460,6 +1720,13 @@ Color Window::get_theme_color(const StringName &p_name, const StringName &p_them } int Window::get_theme_constant(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { + const int *constant = theme_constant_override.getptr(p_name); + if (constant) { + return *constant; + } + } + if (theme_constant_cache.has(p_theme_type) && theme_constant_cache[p_theme_type].has(p_name)) { return theme_constant_cache[p_theme_type][p_name]; } @@ -1472,41 +1739,204 @@ int Window::get_theme_constant(const StringName &p_name, const StringName &p_the } bool Window::has_theme_icon(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { + if (has_theme_icon_override(p_name)) { + return true; + } + } + List<StringName> theme_types; theme_owner->get_theme_type_dependencies(this, p_theme_type, &theme_types); return theme_owner->has_theme_item_in_types(Theme::DATA_TYPE_ICON, p_name, theme_types); } bool Window::has_theme_stylebox(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { + if (has_theme_stylebox_override(p_name)) { + return true; + } + } + List<StringName> theme_types; theme_owner->get_theme_type_dependencies(this, p_theme_type, &theme_types); return theme_owner->has_theme_item_in_types(Theme::DATA_TYPE_STYLEBOX, p_name, theme_types); } bool Window::has_theme_font(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { + if (has_theme_font_override(p_name)) { + return true; + } + } + List<StringName> theme_types; theme_owner->get_theme_type_dependencies(this, p_theme_type, &theme_types); return theme_owner->has_theme_item_in_types(Theme::DATA_TYPE_FONT, p_name, theme_types); } bool Window::has_theme_font_size(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { + if (has_theme_font_size_override(p_name)) { + return true; + } + } + List<StringName> theme_types; theme_owner->get_theme_type_dependencies(this, p_theme_type, &theme_types); return theme_owner->has_theme_item_in_types(Theme::DATA_TYPE_FONT_SIZE, p_name, theme_types); } bool Window::has_theme_color(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { + if (has_theme_color_override(p_name)) { + return true; + } + } + List<StringName> theme_types; theme_owner->get_theme_type_dependencies(this, p_theme_type, &theme_types); return theme_owner->has_theme_item_in_types(Theme::DATA_TYPE_COLOR, p_name, theme_types); } bool Window::has_theme_constant(const StringName &p_name, const StringName &p_theme_type) const { + if (p_theme_type == StringName() || p_theme_type == get_class_name() || p_theme_type == theme_type_variation) { + if (has_theme_constant_override(p_name)) { + return true; + } + } + List<StringName> theme_types; theme_owner->get_theme_type_dependencies(this, p_theme_type, &theme_types); return theme_owner->has_theme_item_in_types(Theme::DATA_TYPE_CONSTANT, p_name, theme_types); } +/// Local property overrides. + +void Window::add_theme_icon_override(const StringName &p_name, const Ref<Texture2D> &p_icon) { + ERR_FAIL_COND(!p_icon.is_valid()); + + if (theme_icon_override.has(p_name)) { + theme_icon_override[p_name]->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed)); + } + + theme_icon_override[p_name] = p_icon; + theme_icon_override[p_name]->connect("changed", callable_mp(this, &Window::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED); + _notify_theme_override_changed(); +} + +void Window::add_theme_style_override(const StringName &p_name, const Ref<StyleBox> &p_style) { + ERR_FAIL_COND(!p_style.is_valid()); + + if (theme_style_override.has(p_name)) { + theme_style_override[p_name]->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed)); + } + + theme_style_override[p_name] = p_style; + theme_style_override[p_name]->connect("changed", callable_mp(this, &Window::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED); + _notify_theme_override_changed(); +} + +void Window::add_theme_font_override(const StringName &p_name, const Ref<Font> &p_font) { + ERR_FAIL_COND(!p_font.is_valid()); + + if (theme_font_override.has(p_name)) { + theme_font_override[p_name]->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed)); + } + + theme_font_override[p_name] = p_font; + theme_font_override[p_name]->connect("changed", callable_mp(this, &Window::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED); + _notify_theme_override_changed(); +} + +void Window::add_theme_font_size_override(const StringName &p_name, int p_font_size) { + theme_font_size_override[p_name] = p_font_size; + _notify_theme_override_changed(); +} + +void Window::add_theme_color_override(const StringName &p_name, const Color &p_color) { + theme_color_override[p_name] = p_color; + _notify_theme_override_changed(); +} + +void Window::add_theme_constant_override(const StringName &p_name, int p_constant) { + theme_constant_override[p_name] = p_constant; + _notify_theme_override_changed(); +} + +void Window::remove_theme_icon_override(const StringName &p_name) { + if (theme_icon_override.has(p_name)) { + theme_icon_override[p_name]->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed)); + } + + theme_icon_override.erase(p_name); + _notify_theme_override_changed(); +} + +void Window::remove_theme_style_override(const StringName &p_name) { + if (theme_style_override.has(p_name)) { + theme_style_override[p_name]->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed)); + } + + theme_style_override.erase(p_name); + _notify_theme_override_changed(); +} + +void Window::remove_theme_font_override(const StringName &p_name) { + if (theme_font_override.has(p_name)) { + theme_font_override[p_name]->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed)); + } + + theme_font_override.erase(p_name); + _notify_theme_override_changed(); +} + +void Window::remove_theme_font_size_override(const StringName &p_name) { + theme_font_size_override.erase(p_name); + _notify_theme_override_changed(); +} + +void Window::remove_theme_color_override(const StringName &p_name) { + theme_color_override.erase(p_name); + _notify_theme_override_changed(); +} + +void Window::remove_theme_constant_override(const StringName &p_name) { + theme_constant_override.erase(p_name); + _notify_theme_override_changed(); +} + +bool Window::has_theme_icon_override(const StringName &p_name) const { + const Ref<Texture2D> *tex = theme_icon_override.getptr(p_name); + return tex != nullptr; +} + +bool Window::has_theme_stylebox_override(const StringName &p_name) const { + const Ref<StyleBox> *style = theme_style_override.getptr(p_name); + return style != nullptr; +} + +bool Window::has_theme_font_override(const StringName &p_name) const { + const Ref<Font> *font = theme_font_override.getptr(p_name); + return font != nullptr; +} + +bool Window::has_theme_font_size_override(const StringName &p_name) const { + const int *font_size = theme_font_size_override.getptr(p_name); + return font_size != nullptr; +} + +bool Window::has_theme_color_override(const StringName &p_name) const { + const Color *color = theme_color_override.getptr(p_name); + return color != nullptr; +} + +bool Window::has_theme_constant_override(const StringName &p_name) const { + const int *constant = theme_constant_override.getptr(p_name); + return constant != nullptr; +} + +/// Default theme properties. + float Window::get_theme_default_base_scale() const { return theme_owner->get_theme_default_base_scale(); } @@ -1519,6 +1949,21 @@ int Window::get_theme_default_font_size() const { return theme_owner->get_theme_default_font_size(); } +/// Bulk actions. + +void Window::begin_bulk_theme_override() { + bulk_theme_override = true; +} + +void Window::end_bulk_theme_override() { + ERR_FAIL_COND(!bulk_theme_override); + + bulk_theme_override = false; + _notify_theme_override_changed(); +} + +// + Rect2i Window::get_parent_rect() const { ERR_FAIL_COND_V(!is_inside_tree(), Rect2i()); if (is_embedded()) { @@ -1611,34 +2056,6 @@ bool Window::is_auto_translating() const { return auto_translate; } -void Window::_validate_property(PropertyInfo &p_property) const { - if (p_property.name == "theme_type_variation") { - List<StringName> names; - - // 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. - 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>(); - - Vector<StringName> unique_names; - String hint_string; - for (const StringName &E : names) { - // Skip duplicate values. - if (unique_names.has(E)) { - continue; - } - - hint_string += String(E) + ","; - unique_names.append(E); - } - - p_property.hint_string = hint_string; - } -} - Transform2D Window::get_screen_transform() const { Transform2D embedder_transform; if (_get_embedder()) { @@ -1733,6 +2150,23 @@ void Window::_bind_methods() { ClassDB::bind_method(D_METHOD("set_theme_type_variation", "theme_type"), &Window::set_theme_type_variation); ClassDB::bind_method(D_METHOD("get_theme_type_variation"), &Window::get_theme_type_variation); + ClassDB::bind_method(D_METHOD("begin_bulk_theme_override"), &Window::begin_bulk_theme_override); + ClassDB::bind_method(D_METHOD("end_bulk_theme_override"), &Window::end_bulk_theme_override); + + ClassDB::bind_method(D_METHOD("add_theme_icon_override", "name", "texture"), &Window::add_theme_icon_override); + ClassDB::bind_method(D_METHOD("add_theme_stylebox_override", "name", "stylebox"), &Window::add_theme_style_override); + ClassDB::bind_method(D_METHOD("add_theme_font_override", "name", "font"), &Window::add_theme_font_override); + ClassDB::bind_method(D_METHOD("add_theme_font_size_override", "name", "font_size"), &Window::add_theme_font_size_override); + ClassDB::bind_method(D_METHOD("add_theme_color_override", "name", "color"), &Window::add_theme_color_override); + ClassDB::bind_method(D_METHOD("add_theme_constant_override", "name", "constant"), &Window::add_theme_constant_override); + + ClassDB::bind_method(D_METHOD("remove_theme_icon_override", "name"), &Window::remove_theme_icon_override); + ClassDB::bind_method(D_METHOD("remove_theme_stylebox_override", "name"), &Window::remove_theme_style_override); + ClassDB::bind_method(D_METHOD("remove_theme_font_override", "name"), &Window::remove_theme_font_override); + ClassDB::bind_method(D_METHOD("remove_theme_font_size_override", "name"), &Window::remove_theme_font_size_override); + ClassDB::bind_method(D_METHOD("remove_theme_color_override", "name"), &Window::remove_theme_color_override); + ClassDB::bind_method(D_METHOD("remove_theme_constant_override", "name"), &Window::remove_theme_constant_override); + ClassDB::bind_method(D_METHOD("get_theme_icon", "name", "theme_type"), &Window::get_theme_icon, DEFVAL("")); ClassDB::bind_method(D_METHOD("get_theme_stylebox", "name", "theme_type"), &Window::get_theme_stylebox, DEFVAL("")); ClassDB::bind_method(D_METHOD("get_theme_font", "name", "theme_type"), &Window::get_theme_font, DEFVAL("")); @@ -1740,6 +2174,13 @@ void Window::_bind_methods() { ClassDB::bind_method(D_METHOD("get_theme_color", "name", "theme_type"), &Window::get_theme_color, DEFVAL("")); ClassDB::bind_method(D_METHOD("get_theme_constant", "name", "theme_type"), &Window::get_theme_constant, DEFVAL("")); + ClassDB::bind_method(D_METHOD("has_theme_icon_override", "name"), &Window::has_theme_icon_override); + ClassDB::bind_method(D_METHOD("has_theme_stylebox_override", "name"), &Window::has_theme_stylebox_override); + ClassDB::bind_method(D_METHOD("has_theme_font_override", "name"), &Window::has_theme_font_override); + ClassDB::bind_method(D_METHOD("has_theme_font_size_override", "name"), &Window::has_theme_font_size_override); + ClassDB::bind_method(D_METHOD("has_theme_color_override", "name"), &Window::has_theme_color_override); + ClassDB::bind_method(D_METHOD("has_theme_constant_override", "name"), &Window::has_theme_constant_override); + ClassDB::bind_method(D_METHOD("has_theme_icon", "name", "theme_type"), &Window::has_theme_icon, DEFVAL("")); ClassDB::bind_method(D_METHOD("has_theme_stylebox", "name", "theme_type"), &Window::has_theme_stylebox, DEFVAL("")); ClassDB::bind_method(D_METHOD("has_theme_font", "name", "theme_type"), &Window::has_theme_font, DEFVAL("")); @@ -1793,13 +2234,13 @@ void Window::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_aspect", PROPERTY_HINT_ENUM, "Ignore,Keep,Keep Width,Keep Height,Expand"), "set_content_scale_aspect", "get_content_scale_aspect"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "content_scale_factor"), "set_content_scale_factor", "get_content_scale_factor"); + ADD_GROUP("Localization", ""); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_translate"), "set_auto_translate", "is_auto_translating"); + ADD_GROUP("Theme", "theme_"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "theme_type_variation", PROPERTY_HINT_ENUM_SUGGESTION), "set_theme_type_variation", "get_theme_type_variation"); - ADD_GROUP("Auto Translate", ""); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_translate"), "set_auto_translate", "is_auto_translating"); - ADD_SIGNAL(MethodInfo("window_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); ADD_SIGNAL(MethodInfo("files_dropped", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files"))); ADD_SIGNAL(MethodInfo("mouse_entered")); @@ -1859,4 +2300,23 @@ Window::Window() { Window::~Window() { memdelete(theme_owner); + + // Resources need to be disconnected. + for (KeyValue<StringName, Ref<Texture2D>> &E : theme_icon_override) { + E.value->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed)); + } + for (KeyValue<StringName, Ref<StyleBox>> &E : theme_style_override) { + E.value->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed)); + } + for (KeyValue<StringName, Ref<Font>> &E : theme_font_override) { + E.value->disconnect("changed", callable_mp(this, &Window::_notify_theme_override_changed)); + } + + // Then override maps can be simply cleared. + theme_icon_override.clear(); + theme_style_override.clear(); + theme_font_override.clear(); + theme_font_size_override.clear(); + theme_color_override.clear(); + theme_constant_override.clear(); } diff --git a/scene/main/window.h b/scene/main/window.h index 48ce9041a4..5024b42587 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -140,6 +140,14 @@ private: Ref<Theme> theme; StringName theme_type_variation; + bool bulk_theme_override = false; + Theme::ThemeIconMap theme_icon_override; + Theme::ThemeStyleMap theme_style_override; + Theme::ThemeFontMap theme_font_override; + Theme::ThemeFontSizeMap theme_font_size_override; + Theme::ThemeColorMap theme_color_override; + Theme::ThemeConstantMap theme_constant_override; + mutable HashMap<StringName, Theme::ThemeIconMap> theme_icon_cache; mutable HashMap<StringName, Theme::ThemeStyleMap> theme_style_cache; mutable HashMap<StringName, Theme::ThemeFontMap> theme_font_cache; @@ -148,6 +156,7 @@ private: mutable HashMap<StringName, Theme::ThemeConstantMap> theme_constant_cache; void _theme_changed(); + void _notify_theme_override_changed(); void _invalidate_theme_cache(); Viewport *embedder = nullptr; @@ -173,6 +182,10 @@ protected: virtual Size2 _get_contents_minimum_size() const; static void _bind_methods(); void _notification(int p_what); + + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; void _validate_property(PropertyInfo &p_property) const; virtual void add_child_notify(Node *p_child) override; @@ -271,16 +284,6 @@ public: void popup_centered(const Size2i &p_minsize = Size2i()); void popup_centered_clamped(const Size2i &p_size = Size2i(), float p_fallback_ratio = 0.75); - void set_theme_owner_node(Node *p_node); - Node *get_theme_owner_node() const; - bool has_theme_owner_node() const; - - void set_theme(const Ref<Theme> &p_theme); - Ref<Theme> get_theme() const; - - void set_theme_type_variation(const StringName &p_theme_type); - StringName get_theme_type_variation() const; - Size2 get_contents_minimum_size() const; void grab_focus(); @@ -296,6 +299,35 @@ public: Rect2i get_usable_parent_rect() const; + // Theming. + + void set_theme_owner_node(Node *p_node); + Node *get_theme_owner_node() const; + bool has_theme_owner_node() const; + + void set_theme(const Ref<Theme> &p_theme); + Ref<Theme> get_theme() const; + + void set_theme_type_variation(const StringName &p_theme_type); + StringName get_theme_type_variation() const; + + void begin_bulk_theme_override(); + void end_bulk_theme_override(); + + void add_theme_icon_override(const StringName &p_name, const Ref<Texture2D> &p_icon); + void add_theme_style_override(const StringName &p_name, const Ref<StyleBox> &p_style); + void add_theme_font_override(const StringName &p_name, const Ref<Font> &p_font); + void add_theme_font_size_override(const StringName &p_name, int p_font_size); + void add_theme_color_override(const StringName &p_name, const Color &p_color); + void add_theme_constant_override(const StringName &p_name, int p_constant); + + void remove_theme_icon_override(const StringName &p_name); + void remove_theme_style_override(const StringName &p_name); + void remove_theme_font_override(const StringName &p_name); + void remove_theme_font_size_override(const StringName &p_name); + void remove_theme_color_override(const StringName &p_name); + void remove_theme_constant_override(const StringName &p_name); + Ref<Texture2D> get_theme_icon(const StringName &p_name, const StringName &p_theme_type = StringName()) const; Ref<StyleBox> get_theme_stylebox(const StringName &p_name, const StringName &p_theme_type = StringName()) const; Ref<Font> get_theme_font(const StringName &p_name, const StringName &p_theme_type = StringName()) const; @@ -303,6 +335,13 @@ public: Color get_theme_color(const StringName &p_name, const StringName &p_theme_type = StringName()) const; int get_theme_constant(const StringName &p_name, const StringName &p_theme_type = StringName()) const; + bool has_theme_icon_override(const StringName &p_name) const; + bool has_theme_stylebox_override(const StringName &p_name) const; + bool has_theme_font_override(const StringName &p_name) const; + bool has_theme_font_size_override(const StringName &p_name) const; + bool has_theme_color_override(const StringName &p_name) const; + bool has_theme_constant_override(const StringName &p_name) const; + bool has_theme_icon(const StringName &p_name, const StringName &p_theme_type = StringName()) const; bool has_theme_stylebox(const StringName &p_name, const StringName &p_theme_type = StringName()) const; bool has_theme_font(const StringName &p_name, const StringName &p_theme_type = StringName()) const; @@ -314,6 +353,8 @@ public: Ref<Font> get_theme_default_font() const; int get_theme_default_font_size() const; + // + virtual Transform2D get_screen_transform() const override; Rect2i get_parent_rect() const; |