diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 666ac88055f..7e4db82193e 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -153,6 +153,9 @@ bool Control::_set(const StringName& p_name, const Variant& p_value) { update(); } else if (name.begins_with("custom_fonts/")) { String dname = name.get_slicec('/',1); + if (data.font_override.has(dname)) { + _unref_font(data.font_override[dname]); + } data.font_override.erase(dname); notification(NOTIFICATION_THEME_CHANGED); update(); @@ -1551,7 +1554,15 @@ void Control::add_style_override(const StringName& p_name, const Ref& void Control::add_font_override(const StringName& p_name, const Ref& p_font) { ERR_FAIL_COND(p_font.is_null()); + if (data.font_override.has(p_name)) { + _unref_font(data.font_override[p_name]); + } data.font_override[p_name]=p_font; + + if (p_font.is_valid()) { + _ref_font(p_font); + } + notification(NOTIFICATION_THEME_CHANGED); update(); } @@ -2244,6 +2255,33 @@ float Control::_get_rotation_deg() const { WARN_PRINT("Deprecated method Control._get_rotation_deg(): This method was renamed to get_rotation_deg. Please adapt your code accordingly, as the old method will be obsoleted."); return get_rotation_deg(); } +//needed to update the control if the font changes.. +void Control::_ref_font( Ref p_sc) { + + if (!data.font_refcount.has(p_sc)) { + data.font_refcount[p_sc]=1; + p_sc->connect("changed",this,"_font_changed"); + } else { + data.font_refcount[p_sc]+=1; + } +} + +void Control::_unref_font(Ref p_sc) { + + ERR_FAIL_COND(!data.font_refcount.has(p_sc)); + data.font_refcount[p_sc]--; + if (data.font_refcount[p_sc]==0) { + p_sc->disconnect("changed",this,"_font_changed"); + data.font_refcount.erase(p_sc); + } +} + +void Control::_font_changed(){ + + update(); + notification(NOTIFICATION_THEME_CHANGED); + minimum_size_changed(); //fonts affect minimum size pretty much almost always +} void Control::set_scale(const Vector2& p_scale){ @@ -2396,6 +2434,8 @@ void Control::_bind_methods() { ObjectTypeDB::bind_method(_MD("minimum_size_changed"), &Control::minimum_size_changed); + ObjectTypeDB::bind_method(_MD("_font_changed"), &Control::_font_changed); + BIND_VMETHOD(MethodInfo("_input_event",PropertyInfo(Variant::INPUT_EVENT,"event"))); BIND_VMETHOD(MethodInfo(Variant::VECTOR2,"get_minimum_size")); BIND_VMETHOD(MethodInfo(Variant::OBJECT,"get_drag_data",PropertyInfo(Variant::VECTOR2,"pos"))); diff --git a/scene/gui/control.h b/scene/gui/control.h index 69ee41f180c..07a28de1ea0 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -153,6 +153,8 @@ private: HashMap, StringNameHasher > font_override; HashMap color_override; HashMap constant_override; + Map< Ref, int> font_refcount; + } data; // used internally @@ -184,6 +186,11 @@ private: void _set_rotation_deg(float p_degrees); float _get_rotation_deg() const; + void _ref_font(Ref p_sc); + void _unref_font( Ref p_sc); + void _font_changed(); + + friend class Viewport; void _modal_stack_remove(); void _modal_set_prev_focus_owner(ObjectID p_prev); diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index 6725f73ad9b..92a6f0c0b9d 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -34,6 +34,32 @@ Ref Theme::default_theme; +void Theme::_emit_theme_changed() { + + emit_changed(); +} + +void Theme::_ref_font( Ref p_sc) { + + if (!font_refcount.has(p_sc)) { + font_refcount[p_sc]=1; + p_sc->connect("changed",this,"_emit_theme_changed"); + } else { + font_refcount[p_sc]+=1; + } +} + +void Theme::_unref_font(Ref p_sc) { + + ERR_FAIL_COND(!font_refcount.has(p_sc)); + font_refcount[p_sc]--; + if (font_refcount[p_sc]==0) { + p_sc->disconnect("changed",this,"_emit_theme_changed"); + font_refcount.erase(p_sc); + } +} + + bool Theme::_set(const StringName& p_name, const Variant& p_value) { String sname=p_name; @@ -392,8 +418,18 @@ void Theme::set_font(const StringName& p_name,const StringName& p_type,const Ref // ERR_FAIL_COND(p_font.is_null()); bool new_value=!font_map.has(p_type) || !font_map[p_type].has(p_name); + + if (!new_value) { + if (font_map[p_type][p_name].is_valid()) { + _unref_font(font_map[p_type][p_name]); + } + } font_map[p_type][p_name]=p_font; + if (p_font.is_valid()) { + _ref_font(p_font); + } + if (new_value) { _change_notify(); emit_changed();; @@ -420,6 +456,10 @@ void Theme::clear_font(const StringName& p_name,const StringName& p_type) { ERR_FAIL_COND(!font_map.has(p_type)); ERR_FAIL_COND(!font_map[p_type].has(p_name)); + if (font_map.has(p_type) && font_map[p_type].has(p_name) && font_map[p_type][p_name].is_valid()) { + _unref_font(font_map[p_type][p_name]); + } + font_map[p_type].erase(p_name); _change_notify(); emit_changed();; @@ -645,6 +685,11 @@ void Theme::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_type_list","type"),&Theme::_get_type_list); + ObjectTypeDB::bind_method(_MD("_emit_theme_changed"),&Theme::_emit_theme_changed); + + + + ObjectTypeDB::bind_method("copy_default_theme",&Theme::copy_default_theme); ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"default_font",PROPERTY_HINT_RESOURCE_TYPE,"Font"),_SCS("set_default_font"),_SCS("get_default_font")); diff --git a/scene/resources/theme.h b/scene/resources/theme.h index 9b84d0e8ad5..1856bd49790 100644 --- a/scene/resources/theme.h +++ b/scene/resources/theme.h @@ -46,6 +46,15 @@ class Theme : public Resource { static Ref default_theme; + + //keep a reference count to font, so each time the font changes, we emit theme changed too + Map< Ref, int> font_refcount; + + void _ref_font(Ref p_sc); + void _unref_font( Ref p_sc); + void _emit_theme_changed(); + + HashMap,StringNameHasher >, StringNameHasher > icon_map; HashMap,StringNameHasher >,StringNameHasher > style_map; HashMap,StringNameHasher >,StringNameHasher > font_map;