diff options
author | Juan Linietsky <reduzio@gmail.com> | 2014-07-07 17:44:21 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2014-07-07 17:44:21 -0300 |
commit | 9ff6d55822647c87eef392147ea15641d0922d47 (patch) | |
tree | 4a132cccc1ecb9f7de27a94475363fcf527986c6 /scene/2d | |
parent | 3d68949a1cc41b4865618bddde23122f66764ee1 (diff) |
Polygon2D
-=-=-=-=-
Another gift for those who make 2D games:
-Edit polygons, concave or convex, color them, texture them and uv-map them
-Corresponding editor
-Can have a custom pivot, so they are compatible with bones and IK
Diffstat (limited to 'scene/2d')
-rw-r--r-- | scene/2d/path_texture.cpp | 64 | ||||
-rw-r--r-- | scene/2d/path_texture.h | 34 | ||||
-rw-r--r-- | scene/2d/polygon_2d.cpp | 363 | ||||
-rw-r--r-- | scene/2d/polygon_2d.h | 78 |
4 files changed, 539 insertions, 0 deletions
diff --git a/scene/2d/path_texture.cpp b/scene/2d/path_texture.cpp new file mode 100644 index 0000000000..09596083eb --- /dev/null +++ b/scene/2d/path_texture.cpp @@ -0,0 +1,64 @@ +#include "path_texture.h" + + +void PathTexture::set_begin_texture(const Ref<Texture>& p_texture) { + + begin=p_texture; + update(); +} + +Ref<Texture> PathTexture::get_begin_texture() const{ + + return begin; +} + +void PathTexture::set_repeat_texture(const Ref<Texture>& p_texture){ + + repeat=p_texture; + update(); + +} +Ref<Texture> PathTexture::get_repeat_texture() const{ + + return repeat; +} + +void PathTexture::set_end_texture(const Ref<Texture>& p_texture){ + + end=p_texture; + update(); +} +Ref<Texture> PathTexture::get_end_texture() const{ + + return end; +} + +void PathTexture::set_subdivisions(int p_amount){ + + ERR_FAIL_INDEX(p_amount,32); + subdivs=p_amount; + update(); + +} + +int PathTexture::get_subdivisions() const{ + + return subdivs; +} + +void PathTexture::set_overlap(int p_amount){ + + overlap=p_amount; + update(); +} +int PathTexture::get_overlap() const{ + + return overlap; +} + + +PathTexture::PathTexture() { + + overlap=0; + subdivs=1; +} diff --git a/scene/2d/path_texture.h b/scene/2d/path_texture.h new file mode 100644 index 0000000000..0e63758b10 --- /dev/null +++ b/scene/2d/path_texture.h @@ -0,0 +1,34 @@ +#ifndef PATH_TEXTURE_H +#define PATH_TEXTURE_H + +#include "scene/2d/node_2d.h" + +class PathTexture : public Node2D { + OBJ_TYPE( PathTexture, Node2D ); + + Ref<Texture> begin; + Ref<Texture> repeat; + Ref<Texture> end; + int subdivs; + bool overlap; +public: + + void set_begin_texture(const Ref<Texture>& p_texture); + Ref<Texture> get_begin_texture() const; + + void set_repeat_texture(const Ref<Texture>& p_texture); + Ref<Texture> get_repeat_texture() const; + + void set_end_texture(const Ref<Texture>& p_texture); + Ref<Texture> get_end_texture() const; + + void set_subdivisions(int p_amount); + int get_subdivisions() const; + + void set_overlap(int p_amount); + int get_overlap() const; + + PathTexture(); +}; + +#endif // PATH_TEXTURE_H diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp new file mode 100644 index 0000000000..2b4be734af --- /dev/null +++ b/scene/2d/polygon_2d.cpp @@ -0,0 +1,363 @@ +#include "polygon_2d.h" + +Rect2 Polygon2D::get_item_rect() const { + + + if (rect_cache_dirty){ + int l =polygon.size(); + DVector<Vector2>::Read r = polygon.read(); + item_rect=Rect2(); + for(int i=0;i<l;i++) { + Vector2 pos = r[i] + offset; + if (i==0) + item_rect.pos=pos; + else + item_rect.expand_to(pos); + } + item_rect=item_rect.grow(20); + rect_cache_dirty=false; + } + + + return item_rect; + + +} + +void Polygon2D::edit_set_pivot(const Point2& p_pivot) { + + set_offset(p_pivot); +} + +Point2 Polygon2D::edit_get_pivot() const { + + return get_offset(); +} +bool Polygon2D::edit_has_pivot() const { + + return true; +} + +void Polygon2D::_notification(int p_what) { + + + switch(p_what) { + + case NOTIFICATION_DRAW: { + + if (polygon.size()<3) + return; + + Vector<Vector2> points; + Vector<Vector2> uvs; + + points.resize(polygon.size()); + + int len = points.size(); + { + + DVector<Vector2>::Read polyr =polygon.read(); + for(int i=0;i<len;i++) { + points[i]=polyr[i]+offset; + } + } + + if (invert) { + + Rect2 bounds; + int highest_idx=-1; + float highest_y=-1e20; + float sum=0; + + for(int i=0;i<len;i++) { + if (i==0) + bounds.pos=points[i]; + else + bounds.expand_to(points[i]); + if (points[i].y>highest_y) { + highest_idx=i; + highest_y=points[i].y; + } + int ni=(i+1)%len; + sum+=(points[ni].x-points[i].x)*(points[ni].y+points[i].y); + } + + bounds=bounds.grow(invert_border); + + Vector2 ep[7]={ + Vector2(points[highest_idx].x,points[highest_idx].y+invert_border), + Vector2(bounds.pos+bounds.size), + Vector2(bounds.pos+Vector2(bounds.size.x,0)), + Vector2(bounds.pos), + Vector2(bounds.pos+Vector2(0,bounds.size.y)), + Vector2(points[highest_idx].x-CMP_EPSILON,points[highest_idx].y+invert_border), + Vector2(points[highest_idx].x-CMP_EPSILON,points[highest_idx].y), + }; + + + if (sum>0) { + SWAP(ep[1],ep[4]); + SWAP(ep[2],ep[3]); + SWAP(ep[5],ep[0]); + SWAP(ep[6],points[highest_idx]); + } + + points.resize(points.size()+7); + for(int i=points.size()-1;i>=highest_idx+7;i--) { + + points[i]=points[i-7]; + } + + for(int i=0;i<7;i++) { + + points[highest_idx+i+1]=ep[i]; + } + + + len=points.size(); + + } + + if (texture.is_valid()) { + + Matrix32 texmat(tex_rot,tex_ofs); + texmat.scale(tex_scale); + Size2 tex_size=Vector2(1,1); + + tex_size=texture->get_size(); + uvs.resize(points.size()); + + if (points.size()==uv.size()) { + + DVector<Vector2>::Read uvr = uv.read(); + + for(int i=0;i<len;i++) { + uvs[i]=texmat.xform(uvr[i])/tex_size; + } + + } else { + for(int i=0;i<len;i++) { + uvs[i]=texmat.xform(points[i])/tex_size; + } + } + + } + + + Vector<Color> colors; + colors.push_back(color); + Vector<int> indices = Geometry::triangulate_polygon(points); + + VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(),indices,points,colors,uvs,texture.is_valid()?texture->get_rid():RID()); + + } break; + } +} + + +void Polygon2D::set_polygon(const DVector<Vector2>& p_polygon) { + polygon=p_polygon; + rect_cache_dirty=true; + update(); +} + +DVector<Vector2> Polygon2D::get_polygon() const{ + + return polygon; +} + + +void Polygon2D::set_uv(const DVector<Vector2>& p_uv) { + + uv=p_uv; + update(); +} + +DVector<Vector2> Polygon2D::get_uv() const{ + + return uv; +} + +void Polygon2D::set_color(const Color& p_color){ + + color=p_color; + update(); +} +Color Polygon2D::get_color() const{ + + return color; +} + +void Polygon2D::set_texture(const Ref<Texture>& p_texture){ + + texture=p_texture; + + if (texture.is_valid()) { + uint32_t flags=texture->get_flags(); + flags&=~Texture::FLAG_REPEAT; + if (tex_tile) + flags|=Texture::FLAG_REPEAT; + + texture->set_flags(flags); + } + update(); +} +Ref<Texture> Polygon2D::get_texture() const{ + + return texture; +} + + +void Polygon2D::set_texture_offset(const Vector2& p_offset){ + + tex_ofs=p_offset; + update(); +} +Vector2 Polygon2D::get_texture_offset() const{ + + return tex_ofs; +} + +void Polygon2D::set_texture_rotation(float p_rot){ + + tex_rot=p_rot; + update(); +} +float Polygon2D::get_texture_rotation() const{ + + return tex_rot; +} + +void Polygon2D::set_texture_repeat(bool p_enable){ + + tex_tile=p_enable; + if (texture.is_valid()) { + uint32_t flags=texture->get_flags(); + flags&=~Texture::FLAG_REPEAT; + if (p_enable) + flags|=Texture::FLAG_REPEAT; + texture->set_flags(flags); + } + update(); +} +bool Polygon2D::get_texture_repeat() const{ + + return tex_tile; +} + +void Polygon2D::_set_texture_rotationd(float p_rot){ + + set_texture_rotation(Math::deg2rad(p_rot)); +} +float Polygon2D::_get_texture_rotationd() const{ + + return Math::rad2deg(get_texture_rotation()); +} + + +void Polygon2D::set_texture_scale(const Vector2& p_scale){ + + tex_scale=p_scale; + update(); +} +Vector2 Polygon2D::get_texture_scale() const{ + + return tex_scale; +} + +void Polygon2D::set_invert(bool p_invert){ + + invert=p_invert; + update(); +} +bool Polygon2D::get_invert() const{ + + return invert; +} + +void Polygon2D::set_invert_border(float p_invert_border){ + + invert_border=p_invert_border; + update(); +} +float Polygon2D::get_invert_border() const{ + + return invert_border; +} + +void Polygon2D::set_offset(const Vector2& p_offset) { + + offset=p_offset; + rect_cache_dirty=true; + update(); +} + +Vector2 Polygon2D::get_offset() const { + + return offset; +} + + +void Polygon2D::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_polygon","polygon"),&Polygon2D::set_polygon); + ObjectTypeDB::bind_method(_MD("get_polygon"),&Polygon2D::get_polygon); + + ObjectTypeDB::bind_method(_MD("set_uv","uv"),&Polygon2D::set_uv); + ObjectTypeDB::bind_method(_MD("get_uv"),&Polygon2D::get_uv); + + ObjectTypeDB::bind_method(_MD("set_color","color"),&Polygon2D::set_color); + ObjectTypeDB::bind_method(_MD("get_color"),&Polygon2D::get_color); + + ObjectTypeDB::bind_method(_MD("set_texture","texture"),&Polygon2D::set_texture); + ObjectTypeDB::bind_method(_MD("get_texture"),&Polygon2D::get_texture); + + ObjectTypeDB::bind_method(_MD("set_texture_offset","texture_offset"),&Polygon2D::set_texture_offset); + ObjectTypeDB::bind_method(_MD("get_texture_offset"),&Polygon2D::get_texture_offset); + + ObjectTypeDB::bind_method(_MD("set_texture_rotation","texture_rotation"),&Polygon2D::set_texture_rotation); + ObjectTypeDB::bind_method(_MD("get_texture_rotation"),&Polygon2D::get_texture_rotation); + + ObjectTypeDB::bind_method(_MD("_set_texture_rotationd","texture_rotation"),&Polygon2D::_set_texture_rotationd); + ObjectTypeDB::bind_method(_MD("_get_texture_rotationd"),&Polygon2D::_get_texture_rotationd); + + ObjectTypeDB::bind_method(_MD("set_texture_scale","texture_scale"),&Polygon2D::set_texture_scale); + ObjectTypeDB::bind_method(_MD("get_texture_scale"),&Polygon2D::get_texture_scale); + + ObjectTypeDB::bind_method(_MD("set_texture_repeat","enable"),&Polygon2D::set_texture_repeat); + ObjectTypeDB::bind_method(_MD("get_texture_repeat"),&Polygon2D::get_texture_repeat); + + ObjectTypeDB::bind_method(_MD("set_invert","invert"),&Polygon2D::set_invert); + ObjectTypeDB::bind_method(_MD("get_invert"),&Polygon2D::get_invert); + + ObjectTypeDB::bind_method(_MD("set_invert_border","invert_border"),&Polygon2D::set_invert_border); + ObjectTypeDB::bind_method(_MD("get_invert_border"),&Polygon2D::get_invert_border); + + ObjectTypeDB::bind_method(_MD("set_offset","offset"),&Polygon2D::set_offset); + ObjectTypeDB::bind_method(_MD("get_offset"),&Polygon2D::get_offset); + + + + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon")); + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"uv"),_SCS("set_uv"),_SCS("get_uv")); + ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),_SCS("set_color"),_SCS("get_color")); + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"offset"),_SCS("set_offset"),_SCS("get_offset")); + ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture")); + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"texture/offset"),_SCS("set_texture_offset"),_SCS("get_texture_offset")); + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"texture/scale"),_SCS("set_texture_scale"),_SCS("get_texture_scale")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"texture/rotation",PROPERTY_HINT_RANGE,"-1440,1440,0.1"),_SCS("_set_texture_rotationd"),_SCS("_get_texture_rotationd")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"texture/repeat"),_SCS("set_texture_repeat"),_SCS("get_texture_repeat")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"invert/enable"),_SCS("set_invert"),_SCS("get_invert")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"invert/border",PROPERTY_HINT_RANGE,"0.1,16384,0.1"),_SCS("set_invert_border"),_SCS("get_invert_border")); + +} + +Polygon2D::Polygon2D() { + + invert=0; + invert_border=100; + tex_rot=0; + tex_tile=true; + tex_scale=Vector2(1,1); + rect_cache_dirty=true; +} diff --git a/scene/2d/polygon_2d.h b/scene/2d/polygon_2d.h new file mode 100644 index 0000000000..38fa57b9b4 --- /dev/null +++ b/scene/2d/polygon_2d.h @@ -0,0 +1,78 @@ +#ifndef POLYGON_2D_H +#define POLYGON_2D_H + +#include "scene/2d/node_2d.h" + +class Polygon2D : public Node2D { + + OBJ_TYPE(Polygon2D,Node2D); + + DVector<Vector2> polygon; + DVector<Vector2> uv; + Color color; + Ref<Texture> texture; + Vector2 tex_scale; + Vector2 tex_ofs; + bool tex_tile; + float tex_rot; + bool invert; + float invert_border; + + Vector2 offset; + mutable bool rect_cache_dirty; + mutable Rect2 item_rect; + + void _set_texture_rotationd(float p_rot); + float _get_texture_rotationd() const; + +protected: + + void _notification(int p_what); + static void _bind_methods(); +public: + + void set_polygon(const DVector<Vector2>& p_polygon); + DVector<Vector2> get_polygon() const; + + void set_uv(const DVector<Vector2>& p_uv); + DVector<Vector2> get_uv() const; + + void set_color(const Color& p_color); + Color get_color() const; + + void set_texture(const Ref<Texture>& p_texture); + Ref<Texture> get_texture() const; + + void set_texture_offset(const Vector2& p_offset); + Vector2 get_texture_offset() const; + + void set_texture_rotation(float p_rot); + float get_texture_rotation() const; + + void set_texture_scale(const Vector2& p_scale); + Vector2 get_texture_scale() const; + + void set_texture_repeat(bool p_rot); + bool get_texture_repeat() const; + + void set_invert(bool p_rot); + bool get_invert() const; + + void set_invert_border(float p_border); + float get_invert_border() const; + + void set_offset(const Vector2& p_offset); + Vector2 get_offset() const; + + //editor stuff + + virtual void edit_set_pivot(const Point2& p_pivot); + virtual Point2 edit_get_pivot() const; + virtual bool edit_has_pivot() const; + + virtual Rect2 get_item_rect() const; + + Polygon2D(); +}; + +#endif // POLYGON_2D_H |