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