Browse Source

Make `TextureButton` and `Button` update on texture change

Ninni Pipping 2 years ago
parent
commit
d4ac3b6ded
4 changed files with 53 additions and 31 deletions
  1. 21 2
      scene/gui/button.cpp
  2. 1 0
      scene/gui/button.h
  3. 28 29
      scene/gui/texture_button.cpp
  4. 3 0
      scene/gui/texture_button.h

+ 21 - 2
scene/gui/button.cpp

@@ -30,6 +30,7 @@
 
 #include "button.h"
 
+#include "core/core_string_names.h"
 #include "core/string/translation.h"
 #include "servers/rendering_server.h"
 
@@ -533,8 +534,26 @@ String Button::get_language() const {
 }
 
 void Button::set_icon(const Ref<Texture2D> &p_icon) {
-	if (icon != p_icon) {
-		icon = p_icon;
+	if (icon == p_icon) {
+		return;
+	}
+
+	if (icon.is_valid()) {
+		icon->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Button::_texture_changed));
+	}
+
+	icon = p_icon;
+
+	if (icon.is_valid()) {
+		icon->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Button::_texture_changed));
+	}
+
+	queue_redraw();
+	update_minimum_size();
+}
+
+void Button::_texture_changed() {
+	if (icon.is_valid()) {
 		queue_redraw();
 		update_minimum_size();
 	}

+ 1 - 0
scene/gui/button.h

@@ -96,6 +96,7 @@ private:
 	Size2 _fit_icon_size(const Size2 &p_size) const;
 
 	void _shape(Ref<TextParagraph> p_paragraph = Ref<TextParagraph>(), String p_text = "");
+	void _texture_changed();
 
 protected:
 	void _set_internal_margin(Side p_side, float p_value);

+ 28 - 29
scene/gui/texture_button.cpp

@@ -30,6 +30,7 @@
 
 #include "texture_button.h"
 
+#include "core/core_string_names.h"
 #include "core/typedefs.h"
 
 #include <stdlib.h>
@@ -294,42 +295,19 @@ void TextureButton::_bind_methods() {
 }
 
 void TextureButton::set_texture_normal(const Ref<Texture2D> &p_normal) {
-	if (normal == p_normal) {
-		return;
-	}
-
-	normal = p_normal;
-	queue_redraw();
-	update_minimum_size();
+	_set_texture(&normal, p_normal);
 }
 
 void TextureButton::set_texture_pressed(const Ref<Texture2D> &p_pressed) {
-	if (pressed == p_pressed) {
-		return;
-	}
-
-	pressed = p_pressed;
-	queue_redraw();
-	update_minimum_size();
+	_set_texture(&pressed, p_pressed);
 }
 
 void TextureButton::set_texture_hover(const Ref<Texture2D> &p_hover) {
-	if (hover == p_hover) {
-		return;
-	}
-
-	hover = p_hover;
-	queue_redraw();
-	update_minimum_size();
+	_set_texture(&hover, p_hover);
 }
 
 void TextureButton::set_texture_disabled(const Ref<Texture2D> &p_disabled) {
-	if (disabled == p_disabled) {
-		return;
-	}
-
-	disabled = p_disabled;
-	queue_redraw();
+	_set_texture(&disabled, p_disabled);
 }
 
 void TextureButton::set_click_mask(const Ref<BitMap> &p_click_mask) {
@@ -337,8 +315,7 @@ void TextureButton::set_click_mask(const Ref<BitMap> &p_click_mask) {
 		return;
 	}
 	click_mask = p_click_mask;
-	queue_redraw();
-	update_minimum_size();
+	_texture_changed();
 }
 
 Ref<Texture2D> TextureButton::get_texture_normal() const {
@@ -369,6 +346,28 @@ void TextureButton::set_texture_focused(const Ref<Texture2D> &p_focused) {
 	focused = p_focused;
 };
 
+void TextureButton::_set_texture(Ref<Texture2D> *p_destination, const Ref<Texture2D> &p_texture) {
+	DEV_ASSERT(p_destination);
+	Ref<Texture2D> &destination = *p_destination;
+	if (destination == p_texture) {
+		return;
+	}
+	if (destination.is_valid()) {
+		destination->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TextureButton::_texture_changed));
+	}
+	destination = p_texture;
+	if (destination.is_valid()) {
+		// Pass `CONNECT_REFERENCE_COUNTED` to avoid early disconnect in case the same texture is assigned to different "slots".
+		destination->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TextureButton::_texture_changed), CONNECT_REFERENCE_COUNTED);
+	}
+	_texture_changed();
+}
+
+void TextureButton::_texture_changed() {
+	queue_redraw();
+	update_minimum_size();
+}
+
 bool TextureButton::get_ignore_texture_size() const {
 	return ignore_texture_size;
 }

+ 3 - 0
scene/gui/texture_button.h

@@ -64,6 +64,9 @@ private:
 	bool hflip = false;
 	bool vflip = false;
 
+	void _set_texture(Ref<Texture2D> *p_destination, const Ref<Texture2D> &p_texture);
+	void _texture_changed();
+
 protected:
 	virtual Size2 get_minimum_size() const override;
 	virtual bool has_point(const Point2 &p_point) const override;