1 /*************************************************************************/
2 /* polygon_2d.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
10 /* */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the */
13 /* "Software"), to deal in the Software without restriction, including */
14 /* without limitation the rights to use, copy, modify, merge, publish, */
15 /* distribute, sublicense, and/or sell copies of the Software, and to */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions: */
18 /* */
19 /* The above copyright notice and this permission notice shall be */
20 /* included in all copies or substantial portions of the Software. */
21 /* */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29 /*************************************************************************/
30
31 #include "polygon_2d.h"
32
33 #include "core/math/geometry.h"
34 #include "skeleton_2d.h"
35
36 #ifdef TOOLS_ENABLED
_edit_get_state() const37 Dictionary Polygon2D::_edit_get_state() const {
38 Dictionary state = Node2D::_edit_get_state();
39 state["offset"] = offset;
40 return state;
41 }
42
_edit_set_state(const Dictionary & p_state)43 void Polygon2D::_edit_set_state(const Dictionary &p_state) {
44 Node2D::_edit_set_state(p_state);
45 set_offset(p_state["offset"]);
46 }
47
_edit_set_pivot(const Point2 & p_pivot)48 void Polygon2D::_edit_set_pivot(const Point2 &p_pivot) {
49 set_position(get_transform().xform(p_pivot));
50 set_offset(get_offset() - p_pivot);
51 }
52
_edit_get_pivot() const53 Point2 Polygon2D::_edit_get_pivot() const {
54 return Vector2();
55 }
56
_edit_use_pivot() const57 bool Polygon2D::_edit_use_pivot() const {
58 return true;
59 }
60
_edit_get_rect() const61 Rect2 Polygon2D::_edit_get_rect() const {
62 if (rect_cache_dirty) {
63 int l = polygon.size();
64 PoolVector<Vector2>::Read r = polygon.read();
65 item_rect = Rect2();
66 for (int i = 0; i < l; i++) {
67 Vector2 pos = r[i] + offset;
68 if (i == 0)
69 item_rect.position = pos;
70 else
71 item_rect.expand_to(pos);
72 }
73 rect_cache_dirty = false;
74 }
75
76 return item_rect;
77 }
78
_edit_use_rect() const79 bool Polygon2D::_edit_use_rect() const {
80 return polygon.size() > 0;
81 }
82
_edit_is_selected_on_click(const Point2 & p_point,double p_tolerance) const83 bool Polygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
84
85 Vector<Vector2> polygon2d = Variant(polygon);
86 if (internal_vertices > 0) {
87 polygon2d.resize(polygon2d.size() - internal_vertices);
88 }
89 return Geometry::is_point_in_polygon(p_point - get_offset(), polygon2d);
90 }
91 #endif
92
_skeleton_bone_setup_changed()93 void Polygon2D::_skeleton_bone_setup_changed() {
94 update();
95 }
96
_notification(int p_what)97 void Polygon2D::_notification(int p_what) {
98
99 switch (p_what) {
100
101 case NOTIFICATION_DRAW: {
102
103 if (polygon.size() < 3)
104 return;
105
106 Skeleton2D *skeleton_node = NULL;
107 if (has_node(skeleton)) {
108 skeleton_node = Object::cast_to<Skeleton2D>(get_node(skeleton));
109 }
110
111 ObjectID new_skeleton_id = 0;
112
113 if (skeleton_node) {
114 VS::get_singleton()->canvas_item_attach_skeleton(get_canvas_item(), skeleton_node->get_skeleton());
115 new_skeleton_id = skeleton_node->get_instance_id();
116 } else {
117 VS::get_singleton()->canvas_item_attach_skeleton(get_canvas_item(), RID());
118 }
119
120 if (new_skeleton_id != current_skeleton_id) {
121 Object *old_skeleton = ObjectDB::get_instance(current_skeleton_id);
122 if (old_skeleton) {
123 old_skeleton->disconnect("bone_setup_changed", this, "_skeleton_bone_setup_changed");
124 }
125
126 if (skeleton_node) {
127 skeleton_node->connect("bone_setup_changed", this, "_skeleton_bone_setup_changed");
128 }
129
130 current_skeleton_id = new_skeleton_id;
131 }
132
133 Vector<Vector2> points;
134 Vector<Vector2> uvs;
135 Vector<int> bones;
136 Vector<float> weights;
137
138 int len = polygon.size();
139 if ((invert || polygons.size() == 0) && internal_vertices > 0) {
140 //if no polygons are around, internal vertices must not be drawn, else let them be
141 len -= internal_vertices;
142 }
143
144 if (len <= 0) {
145 return;
146 }
147 points.resize(len);
148
149 {
150
151 PoolVector<Vector2>::Read polyr = polygon.read();
152 for (int i = 0; i < len; i++) {
153 points.write[i] = polyr[i] + offset;
154 }
155 }
156
157 if (invert) {
158
159 Rect2 bounds;
160 int highest_idx = -1;
161 float highest_y = -1e20;
162 float sum = 0;
163
164 for (int i = 0; i < len; i++) {
165 if (i == 0)
166 bounds.position = points[i];
167 else
168 bounds.expand_to(points[i]);
169 if (points[i].y > highest_y) {
170 highest_idx = i;
171 highest_y = points[i].y;
172 }
173 int ni = (i + 1) % len;
174 sum += (points[ni].x - points[i].x) * (points[ni].y + points[i].y);
175 }
176
177 bounds = bounds.grow(invert_border);
178
179 Vector2 ep[7] = {
180 Vector2(points[highest_idx].x, points[highest_idx].y + invert_border),
181 Vector2(bounds.position + bounds.size),
182 Vector2(bounds.position + Vector2(bounds.size.x, 0)),
183 Vector2(bounds.position),
184 Vector2(bounds.position + Vector2(0, bounds.size.y)),
185 Vector2(points[highest_idx].x - CMP_EPSILON, points[highest_idx].y + invert_border),
186 Vector2(points[highest_idx].x - CMP_EPSILON, points[highest_idx].y),
187 };
188
189 if (sum > 0) {
190 SWAP(ep[1], ep[4]);
191 SWAP(ep[2], ep[3]);
192 SWAP(ep[5], ep[0]);
193 SWAP(ep[6], points.write[highest_idx]);
194 }
195
196 points.resize(points.size() + 7);
197 for (int i = points.size() - 1; i >= highest_idx + 7; i--) {
198
199 points.write[i] = points[i - 7];
200 }
201
202 for (int i = 0; i < 7; i++) {
203
204 points.write[highest_idx + i + 1] = ep[i];
205 }
206
207 len = points.size();
208 }
209
210 if (texture.is_valid()) {
211
212 Transform2D texmat(tex_rot, tex_ofs);
213 texmat.scale(tex_scale);
214 Size2 tex_size = texture->get_size();
215
216 uvs.resize(len);
217
218 if (points.size() == uv.size()) {
219
220 PoolVector<Vector2>::Read uvr = uv.read();
221
222 for (int i = 0; i < len; i++) {
223 uvs.write[i] = texmat.xform(uvr[i]) / tex_size;
224 }
225
226 } else {
227 for (int i = 0; i < len; i++) {
228 uvs.write[i] = texmat.xform(points[i]) / tex_size;
229 }
230 }
231 }
232
233 if (skeleton_node && !invert && bone_weights.size()) {
234 //a skeleton is set! fill indices and weights
235 int vc = len;
236 bones.resize(vc * 4);
237 weights.resize(vc * 4);
238
239 int *bonesw = bones.ptrw();
240 float *weightsw = weights.ptrw();
241
242 for (int i = 0; i < vc * 4; i++) {
243 bonesw[i] = 0;
244 weightsw[i] = 0;
245 }
246
247 for (int i = 0; i < bone_weights.size(); i++) {
248 if (bone_weights[i].weights.size() != points.size()) {
249 continue; //different number of vertices, sorry not using.
250 }
251 if (!skeleton_node->has_node(bone_weights[i].path)) {
252 continue; //node does not exist
253 }
254 Bone2D *bone = Object::cast_to<Bone2D>(skeleton_node->get_node(bone_weights[i].path));
255 if (!bone) {
256 continue;
257 }
258
259 int bone_index = bone->get_index_in_skeleton();
260 PoolVector<float>::Read r = bone_weights[i].weights.read();
261 for (int j = 0; j < vc; j++) {
262 if (r[j] == 0.0)
263 continue; //weight is unpainted, skip
264 //find an index with a weight
265 for (int k = 0; k < 4; k++) {
266 if (weightsw[j * 4 + k] < r[j]) {
267 //this is less than this weight, insert weight!
268 for (int l = 3; l > k; l--) {
269 weightsw[j * 4 + l] = weightsw[j * 4 + l - 1];
270 bonesw[j * 4 + l] = bonesw[j * 4 + l - 1];
271 }
272 weightsw[j * 4 + k] = r[j];
273 bonesw[j * 4 + k] = bone_index;
274 break;
275 }
276 }
277 }
278 }
279
280 //normalize the weights
281 for (int i = 0; i < vc; i++) {
282 float tw = 0;
283 for (int j = 0; j < 4; j++) {
284 tw += weightsw[i * 4 + j];
285 }
286 if (tw == 0)
287 continue; //unpainted, do nothing
288
289 //normalize
290 for (int j = 0; j < 4; j++) {
291 weightsw[i * 4 + j] /= tw;
292 }
293 }
294 }
295
296 Vector<Color> colors;
297 if (vertex_colors.size() == points.size()) {
298 colors.resize(len);
299 PoolVector<Color>::Read color_r = vertex_colors.read();
300 for (int i = 0; i < len; i++) {
301 colors.write[i] = color_r[i];
302 }
303 } else {
304 colors.push_back(color);
305 }
306
307 // Vector<int> indices = Geometry::triangulate_polygon(points);
308 // VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, texture.is_valid() ? texture->get_rid() : RID());
309
310 if (invert || polygons.size() == 0) {
311 Vector<int> indices = Geometry::triangulate_polygon(points);
312 if (indices.size()) {
313 VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID(), -1, RID(), antialiased);
314 }
315 } else {
316 //draw individual polygons
317 Vector<int> total_indices;
318 for (int i = 0; i < polygons.size(); i++) {
319 PoolVector<int> src_indices = polygons[i];
320 int ic = src_indices.size();
321 if (ic < 3)
322 continue;
323 PoolVector<int>::Read r = src_indices.read();
324
325 Vector<Vector2> tmp_points;
326 tmp_points.resize(ic);
327
328 for (int j = 0; j < ic; j++) {
329 int idx = r[j];
330 ERR_CONTINUE(idx < 0 || idx >= points.size());
331 tmp_points.write[j] = points[r[j]];
332 }
333 Vector<int> indices = Geometry::triangulate_polygon(tmp_points);
334 int ic2 = indices.size();
335 const int *r2 = indices.ptr();
336
337 int bic = total_indices.size();
338 total_indices.resize(bic + ic2);
339 int *w2 = total_indices.ptrw();
340
341 for (int j = 0; j < ic2; j++) {
342 w2[j + bic] = r[r2[j]];
343 }
344 }
345
346 if (total_indices.size()) {
347 VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), total_indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID(), -1, RID(), antialiased);
348 }
349 }
350
351 } break;
352 }
353 }
354
set_polygon(const PoolVector<Vector2> & p_polygon)355 void Polygon2D::set_polygon(const PoolVector<Vector2> &p_polygon) {
356 polygon = p_polygon;
357 rect_cache_dirty = true;
358 update();
359 }
360
get_polygon() const361 PoolVector<Vector2> Polygon2D::get_polygon() const {
362
363 return polygon;
364 }
365
set_internal_vertex_count(int p_count)366 void Polygon2D::set_internal_vertex_count(int p_count) {
367
368 internal_vertices = p_count;
369 }
370
get_internal_vertex_count() const371 int Polygon2D::get_internal_vertex_count() const {
372 return internal_vertices;
373 }
374
set_uv(const PoolVector<Vector2> & p_uv)375 void Polygon2D::set_uv(const PoolVector<Vector2> &p_uv) {
376
377 uv = p_uv;
378 update();
379 }
380
get_uv() const381 PoolVector<Vector2> Polygon2D::get_uv() const {
382
383 return uv;
384 }
385
set_polygons(const Array & p_polygons)386 void Polygon2D::set_polygons(const Array &p_polygons) {
387
388 polygons = p_polygons;
389 update();
390 }
391
get_polygons() const392 Array Polygon2D::get_polygons() const {
393
394 return polygons;
395 }
396
set_color(const Color & p_color)397 void Polygon2D::set_color(const Color &p_color) {
398
399 color = p_color;
400 update();
401 }
get_color() const402 Color Polygon2D::get_color() const {
403
404 return color;
405 }
406
set_vertex_colors(const PoolVector<Color> & p_colors)407 void Polygon2D::set_vertex_colors(const PoolVector<Color> &p_colors) {
408
409 vertex_colors = p_colors;
410 update();
411 }
get_vertex_colors() const412 PoolVector<Color> Polygon2D::get_vertex_colors() const {
413
414 return vertex_colors;
415 }
416
set_texture(const Ref<Texture> & p_texture)417 void Polygon2D::set_texture(const Ref<Texture> &p_texture) {
418
419 texture = p_texture;
420
421 /*if (texture.is_valid()) {
422 uint32_t flags=texture->get_flags();
423 flags&=~Texture::FLAG_REPEAT;
424 if (tex_tile)
425 flags|=Texture::FLAG_REPEAT;
426
427 texture->set_flags(flags);
428 }*/
429 update();
430 }
get_texture() const431 Ref<Texture> Polygon2D::get_texture() const {
432
433 return texture;
434 }
435
set_texture_offset(const Vector2 & p_offset)436 void Polygon2D::set_texture_offset(const Vector2 &p_offset) {
437
438 tex_ofs = p_offset;
439 update();
440 }
get_texture_offset() const441 Vector2 Polygon2D::get_texture_offset() const {
442
443 return tex_ofs;
444 }
445
set_texture_rotation(float p_rot)446 void Polygon2D::set_texture_rotation(float p_rot) {
447
448 tex_rot = p_rot;
449 update();
450 }
get_texture_rotation() const451 float Polygon2D::get_texture_rotation() const {
452
453 return tex_rot;
454 }
455
set_texture_rotation_degrees(float p_rot)456 void Polygon2D::set_texture_rotation_degrees(float p_rot) {
457
458 set_texture_rotation(Math::deg2rad(p_rot));
459 }
get_texture_rotation_degrees() const460 float Polygon2D::get_texture_rotation_degrees() const {
461
462 return Math::rad2deg(get_texture_rotation());
463 }
464
set_texture_scale(const Size2 & p_scale)465 void Polygon2D::set_texture_scale(const Size2 &p_scale) {
466
467 tex_scale = p_scale;
468 update();
469 }
get_texture_scale() const470 Size2 Polygon2D::get_texture_scale() const {
471
472 return tex_scale;
473 }
474
set_invert(bool p_invert)475 void Polygon2D::set_invert(bool p_invert) {
476
477 invert = p_invert;
478 update();
479 }
get_invert() const480 bool Polygon2D::get_invert() const {
481
482 return invert;
483 }
484
set_antialiased(bool p_antialiased)485 void Polygon2D::set_antialiased(bool p_antialiased) {
486
487 antialiased = p_antialiased;
488 update();
489 }
get_antialiased() const490 bool Polygon2D::get_antialiased() const {
491
492 return antialiased;
493 }
494
set_invert_border(float p_invert_border)495 void Polygon2D::set_invert_border(float p_invert_border) {
496
497 invert_border = p_invert_border;
498 update();
499 }
get_invert_border() const500 float Polygon2D::get_invert_border() const {
501
502 return invert_border;
503 }
504
set_offset(const Vector2 & p_offset)505 void Polygon2D::set_offset(const Vector2 &p_offset) {
506
507 offset = p_offset;
508 rect_cache_dirty = true;
509 update();
510 _change_notify("offset");
511 }
512
get_offset() const513 Vector2 Polygon2D::get_offset() const {
514
515 return offset;
516 }
517
add_bone(const NodePath & p_path,const PoolVector<float> & p_weights)518 void Polygon2D::add_bone(const NodePath &p_path, const PoolVector<float> &p_weights) {
519
520 Bone bone;
521 bone.path = p_path;
522 bone.weights = p_weights;
523 bone_weights.push_back(bone);
524 }
get_bone_count() const525 int Polygon2D::get_bone_count() const {
526 return bone_weights.size();
527 }
get_bone_path(int p_index) const528 NodePath Polygon2D::get_bone_path(int p_index) const {
529 ERR_FAIL_INDEX_V(p_index, bone_weights.size(), NodePath());
530 return bone_weights[p_index].path;
531 }
get_bone_weights(int p_index) const532 PoolVector<float> Polygon2D::get_bone_weights(int p_index) const {
533
534 ERR_FAIL_INDEX_V(p_index, bone_weights.size(), PoolVector<float>());
535 return bone_weights[p_index].weights;
536 }
erase_bone(int p_idx)537 void Polygon2D::erase_bone(int p_idx) {
538
539 ERR_FAIL_INDEX(p_idx, bone_weights.size());
540 bone_weights.remove(p_idx);
541 }
542
clear_bones()543 void Polygon2D::clear_bones() {
544 bone_weights.clear();
545 }
546
set_bone_weights(int p_index,const PoolVector<float> & p_weights)547 void Polygon2D::set_bone_weights(int p_index, const PoolVector<float> &p_weights) {
548 ERR_FAIL_INDEX(p_index, bone_weights.size());
549 bone_weights.write[p_index].weights = p_weights;
550 update();
551 }
set_bone_path(int p_index,const NodePath & p_path)552 void Polygon2D::set_bone_path(int p_index, const NodePath &p_path) {
553 ERR_FAIL_INDEX(p_index, bone_weights.size());
554 bone_weights.write[p_index].path = p_path;
555 update();
556 }
557
_get_bones() const558 Array Polygon2D::_get_bones() const {
559 Array bones;
560 for (int i = 0; i < get_bone_count(); i++) {
561 bones.push_back(get_bone_path(i));
562 bones.push_back(get_bone_weights(i));
563 }
564 return bones;
565 }
_set_bones(const Array & p_bones)566 void Polygon2D::_set_bones(const Array &p_bones) {
567
568 ERR_FAIL_COND(p_bones.size() & 1);
569 clear_bones();
570 for (int i = 0; i < p_bones.size(); i += 2) {
571 add_bone(p_bones[i], p_bones[i + 1]);
572 }
573 }
574
set_skeleton(const NodePath & p_skeleton)575 void Polygon2D::set_skeleton(const NodePath &p_skeleton) {
576 if (skeleton == p_skeleton)
577 return;
578 skeleton = p_skeleton;
579 update();
580 }
581
get_skeleton() const582 NodePath Polygon2D::get_skeleton() const {
583 return skeleton;
584 }
585
_bind_methods()586 void Polygon2D::_bind_methods() {
587
588 ClassDB::bind_method(D_METHOD("set_polygon", "polygon"), &Polygon2D::set_polygon);
589 ClassDB::bind_method(D_METHOD("get_polygon"), &Polygon2D::get_polygon);
590
591 ClassDB::bind_method(D_METHOD("set_uv", "uv"), &Polygon2D::set_uv);
592 ClassDB::bind_method(D_METHOD("get_uv"), &Polygon2D::get_uv);
593
594 ClassDB::bind_method(D_METHOD("set_color", "color"), &Polygon2D::set_color);
595 ClassDB::bind_method(D_METHOD("get_color"), &Polygon2D::get_color);
596
597 ClassDB::bind_method(D_METHOD("set_polygons", "polygons"), &Polygon2D::set_polygons);
598 ClassDB::bind_method(D_METHOD("get_polygons"), &Polygon2D::get_polygons);
599
600 ClassDB::bind_method(D_METHOD("set_vertex_colors", "vertex_colors"), &Polygon2D::set_vertex_colors);
601 ClassDB::bind_method(D_METHOD("get_vertex_colors"), &Polygon2D::get_vertex_colors);
602
603 ClassDB::bind_method(D_METHOD("set_texture", "texture"), &Polygon2D::set_texture);
604 ClassDB::bind_method(D_METHOD("get_texture"), &Polygon2D::get_texture);
605
606 ClassDB::bind_method(D_METHOD("set_texture_offset", "texture_offset"), &Polygon2D::set_texture_offset);
607 ClassDB::bind_method(D_METHOD("get_texture_offset"), &Polygon2D::get_texture_offset);
608
609 ClassDB::bind_method(D_METHOD("set_texture_rotation", "texture_rotation"), &Polygon2D::set_texture_rotation);
610 ClassDB::bind_method(D_METHOD("get_texture_rotation"), &Polygon2D::get_texture_rotation);
611
612 ClassDB::bind_method(D_METHOD("set_texture_rotation_degrees", "texture_rotation"), &Polygon2D::set_texture_rotation_degrees);
613 ClassDB::bind_method(D_METHOD("get_texture_rotation_degrees"), &Polygon2D::get_texture_rotation_degrees);
614
615 ClassDB::bind_method(D_METHOD("set_texture_scale", "texture_scale"), &Polygon2D::set_texture_scale);
616 ClassDB::bind_method(D_METHOD("get_texture_scale"), &Polygon2D::get_texture_scale);
617
618 ClassDB::bind_method(D_METHOD("set_invert", "invert"), &Polygon2D::set_invert);
619 ClassDB::bind_method(D_METHOD("get_invert"), &Polygon2D::get_invert);
620
621 ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &Polygon2D::set_antialiased);
622 ClassDB::bind_method(D_METHOD("get_antialiased"), &Polygon2D::get_antialiased);
623
624 ClassDB::bind_method(D_METHOD("set_invert_border", "invert_border"), &Polygon2D::set_invert_border);
625 ClassDB::bind_method(D_METHOD("get_invert_border"), &Polygon2D::get_invert_border);
626
627 ClassDB::bind_method(D_METHOD("set_offset", "offset"), &Polygon2D::set_offset);
628 ClassDB::bind_method(D_METHOD("get_offset"), &Polygon2D::get_offset);
629
630 ClassDB::bind_method(D_METHOD("add_bone", "path", "weights"), &Polygon2D::add_bone);
631 ClassDB::bind_method(D_METHOD("get_bone_count"), &Polygon2D::get_bone_count);
632 ClassDB::bind_method(D_METHOD("get_bone_path", "index"), &Polygon2D::get_bone_path);
633 ClassDB::bind_method(D_METHOD("get_bone_weights", "index"), &Polygon2D::get_bone_weights);
634 ClassDB::bind_method(D_METHOD("erase_bone", "index"), &Polygon2D::erase_bone);
635 ClassDB::bind_method(D_METHOD("clear_bones"), &Polygon2D::clear_bones);
636 ClassDB::bind_method(D_METHOD("set_bone_path", "index", "path"), &Polygon2D::set_bone_path);
637 ClassDB::bind_method(D_METHOD("set_bone_weights", "index", "weights"), &Polygon2D::set_bone_weights);
638
639 ClassDB::bind_method(D_METHOD("set_skeleton", "skeleton"), &Polygon2D::set_skeleton);
640 ClassDB::bind_method(D_METHOD("get_skeleton"), &Polygon2D::get_skeleton);
641
642 ClassDB::bind_method(D_METHOD("set_internal_vertex_count", "internal_vertex_count"), &Polygon2D::set_internal_vertex_count);
643 ClassDB::bind_method(D_METHOD("get_internal_vertex_count"), &Polygon2D::get_internal_vertex_count);
644
645 ClassDB::bind_method(D_METHOD("_set_bones", "bones"), &Polygon2D::_set_bones);
646 ClassDB::bind_method(D_METHOD("_get_bones"), &Polygon2D::_get_bones);
647
648 ClassDB::bind_method(D_METHOD("_skeleton_bone_setup_changed"), &Polygon2D::_skeleton_bone_setup_changed);
649
650 ADD_PROPERTY(PropertyInfo(Variant::COLOR, "color"), "set_color", "get_color");
651 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
652 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased"), "set_antialiased", "get_antialiased");
653 ADD_GROUP("Texture", "");
654 ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture");
655 ADD_GROUP("Texture", "texture_");
656 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "texture_offset"), "set_texture_offset", "get_texture_offset");
657 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "texture_scale"), "set_texture_scale", "get_texture_scale");
658 ADD_PROPERTY(PropertyInfo(Variant::REAL, "texture_rotation_degrees", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater"), "set_texture_rotation_degrees", "get_texture_rotation_degrees");
659 ADD_PROPERTY(PropertyInfo(Variant::REAL, "texture_rotation", PROPERTY_HINT_NONE, "", 0), "set_texture_rotation", "get_texture_rotation");
660 ADD_GROUP("Skeleton", "");
661 ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Skeleton2D"), "set_skeleton", "get_skeleton");
662
663 ADD_GROUP("Invert", "invert_");
664 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "invert_enable"), "set_invert", "get_invert");
665 ADD_PROPERTY(PropertyInfo(Variant::REAL, "invert_border", PROPERTY_HINT_RANGE, "0.1,16384,0.1"), "set_invert_border", "get_invert_border");
666
667 ADD_GROUP("Data", "");
668 ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "polygon"), "set_polygon", "get_polygon");
669 ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "uv"), "set_uv", "get_uv");
670 ADD_PROPERTY(PropertyInfo(Variant::POOL_COLOR_ARRAY, "vertex_colors"), "set_vertex_colors", "get_vertex_colors");
671 ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons"), "set_polygons", "get_polygons");
672 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bones", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_bones", "_get_bones");
673 ADD_PROPERTY(PropertyInfo(Variant::INT, "internal_vertex_count", PROPERTY_HINT_RANGE, "0,1000"), "set_internal_vertex_count", "get_internal_vertex_count");
674 }
675
Polygon2D()676 Polygon2D::Polygon2D() {
677
678 invert = 0;
679 invert_border = 100;
680 antialiased = false;
681 tex_rot = 0;
682 tex_tile = true;
683 tex_scale = Vector2(1, 1);
684 color = Color(1, 1, 1);
685 rect_cache_dirty = true;
686 internal_vertices = 0;
687 current_skeleton_id = 0;
688 }
689