Ver Fonte

Keep track of when fonts change, so theme or controls that use fonts as overrides get properly updated.
closes #4622 , probably closes many other issues too

Juan Linietsky há 9 anos atrás
pai
commit
55b83157e7
4 ficheiros alterados com 101 adições e 0 exclusões
  1. 40 0
      scene/gui/control.cpp
  2. 7 0
      scene/gui/control.h
  3. 45 0
      scene/resources/theme.cpp
  4. 9 0
      scene/resources/theme.h

+ 40 - 0
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<StyleBox>&
 void Control::add_font_override(const StringName& p_name, const Ref<Font>& 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<Font> 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<Font> 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")));

+ 7 - 0
scene/gui/control.h

@@ -153,6 +153,8 @@ private:
 		HashMap<StringName, Ref<Font>, StringNameHasher > font_override;
 		HashMap<StringName, Color, StringNameHasher > color_override;
 		HashMap<StringName, int, StringNameHasher > constant_override;
+		Map< Ref<Font>, 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<Font> p_sc);
+	void _unref_font( Ref<Font> p_sc);
+	void _font_changed();
+
+
 friend class Viewport;
 	void _modal_stack_remove();
 	void _modal_set_prev_focus_owner(ObjectID p_prev);

+ 45 - 0
scene/resources/theme.cpp

@@ -34,6 +34,32 @@
 Ref<Theme> Theme::default_theme;
 
 
+void Theme::_emit_theme_changed() {
+
+	emit_changed();
+}
+
+void  Theme::_ref_font( Ref<Font> 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<Font> 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"));

+ 9 - 0
scene/resources/theme.h

@@ -46,6 +46,15 @@ class Theme : public Resource {
 
 	static Ref<Theme> default_theme;
 
+
+	//keep a reference count to font, so each time the font changes, we emit theme changed too
+	Map< Ref<Font>, int> font_refcount;
+
+	void _ref_font(Ref<Font> p_sc);
+	void _unref_font( Ref<Font> p_sc);
+	void _emit_theme_changed();
+
+
 	HashMap<StringName,HashMap<StringName,Ref<Texture>,StringNameHasher >, StringNameHasher >  icon_map;
 	HashMap<StringName,HashMap<StringName,Ref<StyleBox>,StringNameHasher >,StringNameHasher > style_map;
 	HashMap<StringName,HashMap<StringName,Ref<Font>,StringNameHasher >,StringNameHasher > font_map;