The TextureButton's bitmask takes into account the stretch mode selected

When the stretch is tile the mask gets applied to each tile.
This commit is contained in:
MrCdK 2018-01-19 00:01:23 +01:00
parent a1c08b7109
commit 9927b70efb
2 changed files with 61 additions and 10 deletions

View file

@ -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)
return false;
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;
}

View file

@ -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;