Quellcode durchsuchen

Merge pull request #15855 from mrcdk/texture_button_mask_fixes

The TextureButton's bitmask takes into account the stretch mode selected
Rémi Verschelde vor 7 Jahren
Ursprung
Commit
e777751958
2 geänderte Dateien mit 60 neuen und 9 gelöschten Zeilen
  1. 56 9
      scene/gui/texture_button.cpp
  2. 4 0
      scene/gui/texture_button.h

+ 56 - 9
scene/gui/texture_button.cpp

@@ -29,6 +29,8 @@
 /*************************************************************************/
 
 #include "texture_button.h"
+#include "core/typedefs.h"
+#include <stdlib.h>
 
 Size2 TextureButton::get_minimum_size() const {
 
@@ -58,10 +60,50 @@ bool TextureButton::has_point(const Point2 &p_point) const {
 
 	if (click_mask.is_valid()) {
 
-		Point2i p = p_point;
-		if (p.x < 0 || p.x >= click_mask->get_size().width || p.y < 0 || p.y >= click_mask->get_size().height)
+		Point2 point = p_point;
+		Rect2 rect = Rect2();
+		Size2 mask_size = click_mask->get_size();
+
+		if (_tile) {
+			// if the stretch mode is tile we offset the point to keep it inside the mask size
+			rect.size = mask_size;
+			if (_position_rect.has_point(point)) {
+				int cols = (int)Math::ceil(_position_rect.size.x / mask_size.x);
+				int rows = (int)Math::ceil(_position_rect.size.y / mask_size.y);
+				int col = (int)(point.x / mask_size.x) % cols;
+				int row = (int)(point.y / mask_size.y) % rows;
+				point.x -= mask_size.x * col;
+				point.y -= mask_size.y * row;
+			}
+		} else {
+			// we need to transform the point from our scaled / translated image back to our mask image
+			Point2 ofs = _position_rect.position;
+			Size2 scale = mask_size / _position_rect.size;
+
+			switch (stretch_mode) {
+				case STRETCH_KEEP_ASPECT_COVERED: {
+					// if the stretch mode is aspect covered the image uses a texture region so we need to take that into account
+					float min = MIN(scale.x, scale.y);
+					scale.x = min;
+					scale.y = min;
+					ofs -= _texture_region.position / min;
+				} break;
+			}
+
+			// offset and scale the new point position to adjust it to the bitmask size
+			point -= ofs;
+			point *= scale;
+
+			// finally, we need to check if the point is inside a rectangle with a position >= 0,0 and a size <= mask_size
+			rect.position = Point2(MAX(0, _texture_region.position.x), MAX(0, _texture_region.position.y));
+			rect.size = Size2(MIN(mask_size.x, _texture_region.size.x), MIN(mask_size.y, _texture_region.size.y));
+		}
+
+		if (!rect.has_point(point)) {
 			return false;
+		}
 
+		Point2i p = point;
 		return click_mask->get_bit(p);
 	}
 
@@ -118,8 +160,8 @@ void TextureButton::_notification(int p_what) {
 			if (texdraw.is_valid()) {
 				Point2 ofs;
 				Size2 size = texdraw->get_size();
-				Rect2 tex_regin = Rect2(Point2(), texdraw->get_size());
-				bool tile = false;
+				_texture_region = Rect2(Point2(), texdraw->get_size());
+				_tile = false;
 				if (expand) {
 					switch (stretch_mode) {
 						case STRETCH_KEEP:
@@ -130,7 +172,7 @@ void TextureButton::_notification(int p_what) {
 							break;
 						case STRETCH_TILE:
 							size = get_size();
-							tile = true;
+							_tile = true;
 							break;
 						case STRETCH_KEEP_CENTERED:
 							ofs = (get_size() - texdraw->get_size()) / 2;
@@ -161,14 +203,15 @@ void TextureButton::_notification(int p_what) {
 							float scale = scaleSize.width > scaleSize.height ? scaleSize.width : scaleSize.height;
 							Size2 scaledTexSize = tex_size * scale;
 							Point2 ofs = ((scaledTexSize - size) / scale).abs() / 2.0f;
-							tex_regin = Rect2(ofs, size / scale);
+							_texture_region = Rect2(ofs, size / scale);
 						} break;
 					}
 				}
-				if (tile)
-					draw_texture_rect(texdraw, Rect2(ofs, size), tile);
+				_position_rect = Rect2(ofs, size);
+				if (_tile)
+					draw_texture_rect(texdraw, _position_rect, _tile);
 				else
-					draw_texture_rect_region(texdraw, Rect2(ofs, size), tex_regin);
+					draw_texture_rect_region(texdraw, _position_rect, _texture_region);
 			}
 			if (has_focus() && focused.is_valid()) {
 
@@ -299,4 +342,8 @@ TextureButton::StretchMode TextureButton::get_stretch_mode() const {
 TextureButton::TextureButton() {
 	expand = false;
 	stretch_mode = STRETCH_SCALE;
+
+	_texture_region = Rect2();
+	_position_rect = Rect2();
+	_tile = false;
 }

+ 4 - 0
scene/gui/texture_button.h

@@ -58,6 +58,10 @@ private:
 	bool expand;
 	StretchMode stretch_mode;
 
+	Rect2 _texture_region;
+	Rect2 _position_rect;
+	bool _tile;
+
 protected:
 	virtual Size2 get_minimum_size() const;
 	virtual bool has_point(const Point2 &p_point) const;