Add ability to flip TextureRect horizontally or vertically

This commit is contained in:
PouleyKetchoupp 2019-02-05 05:12:44 +01:00
parent 869887641f
commit 8b84638322
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"> <member name="texture" type="Texture" setter="set_texture" getter="get_texture">
The node's [Texture] resource. The node's [Texture] resource.
</member> </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> </members>
<constants> <constants>
<constant name="STRETCH_SCALE_ON_EXPAND" value="0" enum="StretchMode"> <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()) if (texture.is_null())
return; return;
Size2 size;
Point2 offset;
Rect2 region;
bool tile = false;
switch (stretch_mode) { switch (stretch_mode) {
case STRETCH_SCALE_ON_EXPAND: { case STRETCH_SCALE_ON_EXPAND: {
Size2 s = expand ? get_size() : texture->get_size(); size = expand ? get_size() : texture->get_size();
draw_texture_rect(texture, Rect2(Point2(), s), false);
} break; } break;
case STRETCH_SCALE: { case STRETCH_SCALE: {
draw_texture_rect(texture, Rect2(Point2(), get_size()), false); size = get_size();
} break; } break;
case STRETCH_TILE: { case STRETCH_TILE: {
draw_texture_rect(texture, Rect2(Point2(), get_size()), true); size = get_size();
tile = true;
} break; } break;
case STRETCH_KEEP: { case STRETCH_KEEP: {
draw_texture_rect(texture, Rect2(Point2(), texture->get_size()), false); size = texture->get_size();
} break; } break;
case STRETCH_KEEP_CENTERED: { case STRETCH_KEEP_CENTERED: {
offset = (get_size() - texture->get_size()) / 2;
Vector2 ofs = (get_size() - texture->get_size()) / 2; size = texture->get_size();
draw_texture_rect(texture, Rect2(ofs, texture->get_size()), false);
} break; } break;
case STRETCH_KEEP_ASPECT_CENTERED: case STRETCH_KEEP_ASPECT_CENTERED:
case STRETCH_KEEP_ASPECT: { case STRETCH_KEEP_ASPECT: {
size = get_size();
Size2 size = get_size();
int tex_width = texture->get_width() * size.height / texture->get_height(); int tex_width = texture->get_width() * size.height / texture->get_height();
int tex_height = size.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(); 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) { if (stretch_mode == STRETCH_KEEP_ASPECT_CENTERED) {
ofs_x += (size.width - tex_width) / 2; offset.x += (size.width - tex_width) / 2;
ofs_y += (size.height - tex_height) / 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; } break;
case STRETCH_KEEP_ASPECT_COVERED: { case STRETCH_KEEP_ASPECT_COVERED: {
Size2 size = get_size(); size = get_size();
Size2 tex_size = texture->get_size(); Size2 tex_size = texture->get_size();
Size2 scaleSize(size.width / tex_size.width, size.height / tex_size.height); Size2 scaleSize(size.width / tex_size.width, size.height / tex_size.height);
float scale = scaleSize.width > scaleSize.height ? scaleSize.width : scaleSize.height; float scale = scaleSize.width > scaleSize.height ? scaleSize.width : scaleSize.height;
Size2 scaledTexSize = tex_size * scale; 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; } 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("get_texture"), &TextureRect::get_texture);
ClassDB::bind_method(D_METHOD("set_expand", "enable"), &TextureRect::set_expand); 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("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("set_stretch_mode", "stretch_mode"), &TextureRect::set_stretch_mode);
ClassDB::bind_method(D_METHOD("get_stretch_mode"), &TextureRect::get_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::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::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::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_ON_EXPAND);
BIND_ENUM_CONSTANT(STRETCH_SCALE); BIND_ENUM_CONSTANT(STRETCH_SCALE);
@ -161,9 +178,31 @@ TextureRect::StretchMode TextureRect::get_stretch_mode() const {
return stretch_mode; 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() { TextureRect::TextureRect() {
expand = false; expand = false;
hflip = false;
vflip = false;
set_mouse_filter(MOUSE_FILTER_PASS); set_mouse_filter(MOUSE_FILTER_PASS);
stretch_mode = STRETCH_SCALE_ON_EXPAND; stretch_mode = STRETCH_SCALE_ON_EXPAND;
} }

View file

@ -53,6 +53,8 @@ public:
private: private:
bool expand; bool expand;
bool hflip;
bool vflip;
Ref<Texture> texture; Ref<Texture> texture;
StretchMode stretch_mode; StretchMode stretch_mode;
@ -71,6 +73,12 @@ public:
void set_stretch_mode(StretchMode p_mode); void set_stretch_mode(StretchMode p_mode);
StretchMode get_stretch_mode() const; 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();
~TextureRect(); ~TextureRect();
}; };

View file

@ -616,7 +616,7 @@ void VisualServerCanvas::canvas_item_add_texture_rect(RID p_item, const Rect2 &p
if (p_tile) { if (p_tile) {
rect->flags |= RasterizerCanvas::CANVAS_RECT_TILE; rect->flags |= RasterizerCanvas::CANVAS_RECT_TILE;
rect->flags |= RasterizerCanvas::CANVAS_RECT_REGION; 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) { if (p_rect.size.x < 0) {