Merge pull request #25624 from nekomatata/texture-rect-flip

Add ability to flip TextureRect horizontally or vertically
This commit is contained in:
Rémi Verschelde 2019-04-06 13:15:01 +02:00 committed by GitHub
commit 2db0613fb0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 74 additions and 21 deletions

View File

@ -22,6 +22,12 @@
<member name="texture" type="Texture" setter="set_texture" getter="get_texture">
The node's [Texture] resource.
</member>
<member name="flip_h" type="bool" setter="set_flip_h" getter="is_flipped_h">
If [code]true[/code], texture is flipped horizontally. Default value: [code]false[/code].
</member>
<member name="flip_v" type="bool" setter="set_flip_v" getter="is_flipped_v">
If [code]true[/code], texture is flipped vertically. Default value: [code]false[/code].
</member>
</members>
<constants>
<constant name="STRETCH_SCALE_ON_EXPAND" value="0" enum="StretchMode">

View File

@ -38,30 +38,32 @@ void TextureRect::_notification(int p_what) {
if (texture.is_null())
return;
Size2 size;
Point2 offset;
Rect2 region;
bool tile = false;
switch (stretch_mode) {
case STRETCH_SCALE_ON_EXPAND: {
Size2 s = expand ? get_size() : texture->get_size();
draw_texture_rect(texture, Rect2(Point2(), s), false);
size = expand ? get_size() : texture->get_size();
} break;
case STRETCH_SCALE: {
draw_texture_rect(texture, Rect2(Point2(), get_size()), false);
size = get_size();
} break;
case STRETCH_TILE: {
draw_texture_rect(texture, Rect2(Point2(), get_size()), true);
size = get_size();
tile = true;
} break;
case STRETCH_KEEP: {
draw_texture_rect(texture, Rect2(Point2(), texture->get_size()), false);
size = texture->get_size();
} break;
case STRETCH_KEEP_CENTERED: {
Vector2 ofs = (get_size() - texture->get_size()) / 2;
draw_texture_rect(texture, Rect2(ofs, texture->get_size()), false);
offset = (get_size() - texture->get_size()) / 2;
size = texture->get_size();
} break;
case STRETCH_KEEP_ASPECT_CENTERED:
case STRETCH_KEEP_ASPECT: {
Size2 size = get_size();
size = get_size();
int tex_width = texture->get_width() * size.height / texture->get_height();
int tex_height = size.height;
@ -70,26 +72,35 @@ void TextureRect::_notification(int p_what) {
tex_height = texture->get_height() * tex_width / texture->get_width();
}
int ofs_x = 0;
int ofs_y = 0;
if (stretch_mode == STRETCH_KEEP_ASPECT_CENTERED) {
ofs_x += (size.width - tex_width) / 2;
ofs_y += (size.height - tex_height) / 2;
offset.x += (size.width - tex_width) / 2;
offset.y += (size.height - tex_height) / 2;
}
draw_texture_rect(texture, Rect2(ofs_x, ofs_y, tex_width, tex_height));
size.width = tex_width;
size.height = tex_height;
} break;
case STRETCH_KEEP_ASPECT_COVERED: {
Size2 size = get_size();
size = get_size();
Size2 tex_size = texture->get_size();
Size2 scaleSize(size.width / tex_size.width, size.height / tex_size.height);
float scale = scaleSize.width > scaleSize.height ? scaleSize.width : scaleSize.height;
Size2 scaledTexSize = tex_size * scale;
Point2 ofs = ((scaledTexSize - size) / scale).abs() / 2.0f;
draw_texture_rect_region(texture, Rect2(Point2(), size), Rect2(ofs, size / scale));
region.position = ((scaledTexSize - size) / scale).abs() / 2.0f;
region.size = size / scale;
} break;
}
size.width *= hflip ? -1.0f : 1.0f;
size.height *= vflip ? -1.0f : 1.0f;
if (region.no_area()) {
draw_texture_rect(texture, Rect2(offset, size), tile);
} else {
draw_texture_rect_region(texture, Rect2(offset, size), region);
}
}
}
@ -106,12 +117,18 @@ void TextureRect::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_texture"), &TextureRect::get_texture);
ClassDB::bind_method(D_METHOD("set_expand", "enable"), &TextureRect::set_expand);
ClassDB::bind_method(D_METHOD("has_expand"), &TextureRect::has_expand);
ClassDB::bind_method(D_METHOD("set_flip_h", "enable"), &TextureRect::set_flip_h);
ClassDB::bind_method(D_METHOD("is_flipped_h"), &TextureRect::is_flipped_h);
ClassDB::bind_method(D_METHOD("set_flip_v", "enable"), &TextureRect::set_flip_v);
ClassDB::bind_method(D_METHOD("is_flipped_v"), &TextureRect::is_flipped_v);
ClassDB::bind_method(D_METHOD("set_stretch_mode", "stretch_mode"), &TextureRect::set_stretch_mode);
ClassDB::bind_method(D_METHOD("get_stretch_mode"), &TextureRect::get_stretch_mode);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand"), "set_expand", "has_expand");
ADD_PROPERTY(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Scale On Expand (Compat),Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered,Keep Aspect Covered"), "set_stretch_mode", "get_stretch_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_h"), "set_flip_h", "is_flipped_h");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_v"), "set_flip_v", "is_flipped_v");
BIND_ENUM_CONSTANT(STRETCH_SCALE_ON_EXPAND);
BIND_ENUM_CONSTANT(STRETCH_SCALE);
@ -161,9 +178,31 @@ TextureRect::StretchMode TextureRect::get_stretch_mode() const {
return stretch_mode;
}
void TextureRect::set_flip_h(bool p_flip) {
hflip = p_flip;
update();
}
bool TextureRect::is_flipped_h() const {
return hflip;
}
void TextureRect::set_flip_v(bool p_flip) {
vflip = p_flip;
update();
}
bool TextureRect::is_flipped_v() const {
return vflip;
}
TextureRect::TextureRect() {
expand = false;
hflip = false;
vflip = false;
set_mouse_filter(MOUSE_FILTER_PASS);
stretch_mode = STRETCH_SCALE_ON_EXPAND;
}

View File

@ -53,6 +53,8 @@ public:
private:
bool expand;
bool hflip;
bool vflip;
Ref<Texture> texture;
StretchMode stretch_mode;
@ -71,6 +73,12 @@ public:
void set_stretch_mode(StretchMode p_mode);
StretchMode get_stretch_mode() const;
void set_flip_h(bool p_flip);
bool is_flipped_h() const;
void set_flip_v(bool p_flip);
bool is_flipped_v() const;
TextureRect();
~TextureRect();
};

View File

@ -629,7 +629,7 @@ void VisualServerCanvas::canvas_item_add_texture_rect(RID p_item, const Rect2 &p
if (p_tile) {
rect->flags |= RasterizerCanvas::CANVAS_RECT_TILE;
rect->flags |= RasterizerCanvas::CANVAS_RECT_REGION;
rect->source = Rect2(0, 0, p_rect.size.width, p_rect.size.height);
rect->source = Rect2(0, 0, fabsf(p_rect.size.width), fabsf(p_rect.size.height));
}
if (p_rect.size.x < 0) {