Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/scene/resources/2d/navigation_polygon.cpp
9898 views
1
/**************************************************************************/
2
/* navigation_polygon.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
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 "navigation_polygon.h"
32
33
#include "core/math/geometry_2d.h"
34
#include "core/os/mutex.h"
35
36
#include "thirdparty/misc/polypartition.h"
37
38
#ifdef DEBUG_ENABLED
39
Rect2 NavigationPolygon::_edit_get_rect() const {
40
RWLockRead read_lock(rwlock);
41
if (rect_cache_dirty) {
42
item_rect = Rect2();
43
bool first = true;
44
45
for (int i = 0; i < outlines.size(); i++) {
46
const Vector<Vector2> &outline = outlines[i];
47
const int outline_size = outline.size();
48
if (outline_size < 3) {
49
continue;
50
}
51
const Vector2 *p = outline.ptr();
52
for (int j = 0; j < outline_size; j++) {
53
if (first) {
54
item_rect = Rect2(p[j], Vector2(0, 0));
55
first = false;
56
} else {
57
item_rect.expand_to(p[j]);
58
}
59
}
60
}
61
62
rect_cache_dirty = false;
63
}
64
return item_rect;
65
}
66
67
bool NavigationPolygon::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
68
RWLockRead read_lock(rwlock);
69
for (int i = 0; i < outlines.size(); i++) {
70
const Vector<Vector2> &outline = outlines[i];
71
const int outline_size = outline.size();
72
if (outline_size < 3) {
73
continue;
74
}
75
if (Geometry2D::is_point_in_polygon(p_point, Variant(outline))) {
76
return true;
77
}
78
}
79
return false;
80
}
81
#endif // DEBUG_ENABLED
82
83
void NavigationPolygon::set_vertices(const Vector<Vector2> &p_vertices) {
84
RWLockWrite write_lock(rwlock);
85
{
86
MutexLock lock(navigation_mesh_generation);
87
navigation_mesh.unref();
88
}
89
vertices = p_vertices;
90
rect_cache_dirty = true;
91
}
92
93
Vector<Vector2> NavigationPolygon::get_vertices() const {
94
RWLockRead read_lock(rwlock);
95
return vertices;
96
}
97
98
void NavigationPolygon::_set_polygons(const TypedArray<Vector<int32_t>> &p_array) {
99
RWLockWrite write_lock(rwlock);
100
{
101
MutexLock lock(navigation_mesh_generation);
102
navigation_mesh.unref();
103
}
104
polygons.resize(p_array.size());
105
for (int i = 0; i < p_array.size(); i++) {
106
polygons.write[i] = p_array[i];
107
}
108
}
109
110
TypedArray<Vector<int32_t>> NavigationPolygon::_get_polygons() const {
111
RWLockRead read_lock(rwlock);
112
TypedArray<Vector<int32_t>> ret;
113
ret.resize(polygons.size());
114
for (int i = 0; i < ret.size(); i++) {
115
ret[i] = polygons[i];
116
}
117
118
return ret;
119
}
120
121
void NavigationPolygon::_set_outlines(const TypedArray<Vector<Vector2>> &p_array) {
122
RWLockWrite write_lock(rwlock);
123
outlines.resize(p_array.size());
124
for (int i = 0; i < p_array.size(); i++) {
125
outlines.write[i] = p_array[i];
126
}
127
rect_cache_dirty = true;
128
}
129
130
TypedArray<Vector<Vector2>> NavigationPolygon::_get_outlines() const {
131
RWLockRead read_lock(rwlock);
132
TypedArray<Vector<Vector2>> ret;
133
ret.resize(outlines.size());
134
for (int i = 0; i < ret.size(); i++) {
135
ret[i] = outlines[i];
136
}
137
138
return ret;
139
}
140
141
void NavigationPolygon::add_polygon(const Vector<int> &p_polygon) {
142
RWLockWrite write_lock(rwlock);
143
polygons.push_back(p_polygon);
144
{
145
MutexLock lock(navigation_mesh_generation);
146
navigation_mesh.unref();
147
}
148
}
149
150
void NavigationPolygon::add_outline_at_index(const Vector<Vector2> &p_outline, int p_index) {
151
RWLockWrite write_lock(rwlock);
152
outlines.insert(p_index, p_outline);
153
rect_cache_dirty = true;
154
}
155
156
int NavigationPolygon::get_polygon_count() const {
157
RWLockRead read_lock(rwlock);
158
return polygons.size();
159
}
160
161
Vector<int> NavigationPolygon::get_polygon(int p_idx) {
162
RWLockRead read_lock(rwlock);
163
ERR_FAIL_INDEX_V(p_idx, polygons.size(), Vector<int>());
164
return polygons[p_idx];
165
}
166
167
void NavigationPolygon::clear_polygons() {
168
RWLockWrite write_lock(rwlock);
169
polygons.clear();
170
{
171
MutexLock lock(navigation_mesh_generation);
172
navigation_mesh.unref();
173
}
174
}
175
176
void NavigationPolygon::clear() {
177
RWLockWrite write_lock(rwlock);
178
polygons.clear();
179
vertices.clear();
180
{
181
MutexLock lock(navigation_mesh_generation);
182
navigation_mesh.unref();
183
}
184
}
185
186
void NavigationPolygon::set_data(const Vector<Vector2> &p_vertices, const Vector<Vector<int>> &p_polygons) {
187
RWLockWrite write_lock(rwlock);
188
vertices = p_vertices;
189
polygons = p_polygons;
190
{
191
MutexLock lock(navigation_mesh_generation);
192
navigation_mesh.unref();
193
}
194
}
195
196
void NavigationPolygon::set_data(const Vector<Vector2> &p_vertices, const Vector<Vector<int>> &p_polygons, const Vector<Vector<Vector2>> &p_outlines) {
197
RWLockWrite write_lock(rwlock);
198
vertices = p_vertices;
199
polygons = p_polygons;
200
outlines = p_outlines;
201
rect_cache_dirty = true;
202
{
203
MutexLock lock(navigation_mesh_generation);
204
navigation_mesh.unref();
205
}
206
}
207
208
void NavigationPolygon::get_data(Vector<Vector2> &r_vertices, Vector<Vector<int>> &r_polygons) {
209
RWLockRead read_lock(rwlock);
210
r_vertices = vertices;
211
r_polygons = polygons;
212
}
213
214
void NavigationPolygon::get_data(Vector<Vector2> &r_vertices, Vector<Vector<int>> &r_polygons, Vector<Vector<Vector2>> &r_outlines) {
215
RWLockRead read_lock(rwlock);
216
r_vertices = vertices;
217
r_polygons = polygons;
218
r_outlines = outlines;
219
}
220
221
Ref<NavigationMesh> NavigationPolygon::get_navigation_mesh() {
222
MutexLock lock(navigation_mesh_generation);
223
224
if (navigation_mesh.is_null()) {
225
navigation_mesh.instantiate();
226
Vector<Vector3> verts;
227
Vector<Vector<int>> polys;
228
{
229
verts.resize(get_vertices().size());
230
Vector3 *w = verts.ptrw();
231
232
const Vector2 *r = get_vertices().ptr();
233
234
for (int i(0); i < get_vertices().size(); i++) {
235
w[i] = Vector3(r[i].x, 0.0, r[i].y);
236
}
237
}
238
239
for (int i(0); i < get_polygon_count(); i++) {
240
polys.push_back(get_polygon(i));
241
}
242
243
navigation_mesh->set_data(verts, polys);
244
navigation_mesh->set_cell_size(cell_size); // Needed to not fail the cell size check on the server
245
}
246
247
return navigation_mesh;
248
}
249
250
void NavigationPolygon::set_outlines(const Vector<Vector<Vector2>> &p_outlines) {
251
RWLockWrite write_lock(rwlock);
252
outlines = p_outlines;
253
rect_cache_dirty = true;
254
}
255
256
Vector<Vector<Vector2>> NavigationPolygon::get_outlines() const {
257
RWLockRead read_lock(rwlock);
258
return outlines;
259
}
260
261
void NavigationPolygon::set_polygons(const Vector<Vector<int>> &p_polygons) {
262
RWLockWrite write_lock(rwlock);
263
polygons = p_polygons;
264
{
265
MutexLock lock(navigation_mesh_generation);
266
navigation_mesh.unref();
267
}
268
}
269
270
Vector<Vector<int>> NavigationPolygon::get_polygons() const {
271
RWLockRead read_lock(rwlock);
272
return polygons;
273
}
274
275
void NavigationPolygon::add_outline(const Vector<Vector2> &p_outline) {
276
RWLockWrite write_lock(rwlock);
277
outlines.push_back(p_outline);
278
rect_cache_dirty = true;
279
}
280
281
int NavigationPolygon::get_outline_count() const {
282
RWLockRead read_lock(rwlock);
283
return outlines.size();
284
}
285
286
void NavigationPolygon::set_outline(int p_idx, const Vector<Vector2> &p_outline) {
287
RWLockWrite write_lock(rwlock);
288
ERR_FAIL_INDEX(p_idx, outlines.size());
289
outlines.write[p_idx] = p_outline;
290
rect_cache_dirty = true;
291
}
292
293
void NavigationPolygon::remove_outline(int p_idx) {
294
RWLockWrite write_lock(rwlock);
295
ERR_FAIL_INDEX(p_idx, outlines.size());
296
outlines.remove_at(p_idx);
297
rect_cache_dirty = true;
298
}
299
300
Vector<Vector2> NavigationPolygon::get_outline(int p_idx) const {
301
RWLockRead read_lock(rwlock);
302
ERR_FAIL_INDEX_V(p_idx, outlines.size(), Vector<Vector2>());
303
return outlines[p_idx];
304
}
305
306
void NavigationPolygon::clear_outlines() {
307
RWLockWrite write_lock(rwlock);
308
outlines.clear();
309
rect_cache_dirty = true;
310
}
311
312
#ifndef DISABLE_DEPRECATED
313
void NavigationPolygon::make_polygons_from_outlines() {
314
RWLockWrite write_lock(rwlock);
315
WARN_PRINT("Function make_polygons_from_outlines() is deprecated."
316
"\nUse NavigationServer2D.parse_source_geometry_data() and NavigationServer2D.bake_from_source_geometry_data() instead.");
317
318
{
319
MutexLock lock(navigation_mesh_generation);
320
navigation_mesh.unref();
321
}
322
List<TPPLPoly> in_poly, out_poly;
323
324
Vector2 outside_point(-1e10, -1e10);
325
326
for (int i = 0; i < outlines.size(); i++) {
327
Vector<Vector2> ol = outlines[i];
328
int olsize = ol.size();
329
if (olsize < 3) {
330
continue;
331
}
332
const Vector2 *r = ol.ptr();
333
for (int j = 0; j < olsize; j++) {
334
outside_point = outside_point.max(r[j]);
335
}
336
}
337
338
outside_point += Vector2(0.7239784, 0.819238); //avoid precision issues
339
340
for (int i = 0; i < outlines.size(); i++) {
341
Vector<Vector2> ol = outlines[i];
342
int olsize = ol.size();
343
if (olsize < 3) {
344
continue;
345
}
346
const Vector2 *r = ol.ptr();
347
348
int interscount = 0;
349
//test if this is an outer outline
350
for (int k = 0; k < outlines.size(); k++) {
351
if (i == k) {
352
continue; //no self intersect
353
}
354
355
Vector<Vector2> ol2 = outlines[k];
356
int olsize2 = ol2.size();
357
if (olsize2 < 3) {
358
continue;
359
}
360
const Vector2 *r2 = ol2.ptr();
361
362
for (int l = 0; l < olsize2; l++) {
363
if (Geometry2D::segment_intersects_segment(r[0], outside_point, r2[l], r2[(l + 1) % olsize2], nullptr)) {
364
interscount++;
365
}
366
}
367
}
368
369
bool outer = (interscount % 2) == 0;
370
371
TPPLPoly tp;
372
tp.Init(olsize);
373
for (int j = 0; j < olsize; j++) {
374
tp[j] = r[j];
375
}
376
377
if (outer) {
378
tp.SetOrientation(TPPL_ORIENTATION_CCW);
379
} else {
380
tp.SetOrientation(TPPL_ORIENTATION_CW);
381
tp.SetHole(true);
382
}
383
384
in_poly.push_back(tp);
385
}
386
387
TPPLPartition tpart;
388
if (tpart.ConvexPartition_HM(&in_poly, &out_poly) == 0) { //failed!
389
ERR_PRINT("NavigationPolygon: Convex partition failed! Failed to convert outlines to a valid NavigationPolygon."
390
"\nNavigationPolygon outlines can not overlap vertices or edges inside same outline or with other outlines or have any intersections."
391
"\nAdd the outmost and largest outline first. To add holes inside this outline add the smaller outlines with same winding order.");
392
return;
393
}
394
395
polygons.clear();
396
vertices.clear();
397
398
HashMap<Vector2, int> points;
399
for (const TPPLPoly &tp : out_poly) {
400
Vector<int> p;
401
402
for (int64_t i = 0; i < tp.GetNumPoints(); i++) {
403
HashMap<Vector2, int>::Iterator E = points.find(tp[i]);
404
if (!E) {
405
E = points.insert(tp[i], vertices.size());
406
vertices.push_back(tp[i]);
407
}
408
p.push_back(E->value);
409
}
410
411
polygons.push_back(p);
412
}
413
414
emit_changed();
415
}
416
#endif // DISABLE_DEPRECATED
417
418
void NavigationPolygon::set_cell_size(real_t p_cell_size) {
419
cell_size = p_cell_size;
420
get_navigation_mesh()->set_cell_size(cell_size);
421
}
422
423
real_t NavigationPolygon::get_cell_size() const {
424
return cell_size;
425
}
426
427
void NavigationPolygon::set_border_size(real_t p_value) {
428
ERR_FAIL_COND(p_value < 0.0);
429
border_size = p_value;
430
}
431
432
real_t NavigationPolygon::get_border_size() const {
433
return border_size;
434
}
435
436
void NavigationPolygon::set_sample_partition_type(SamplePartitionType p_value) {
437
ERR_FAIL_INDEX(p_value, SAMPLE_PARTITION_MAX);
438
partition_type = p_value;
439
}
440
441
NavigationPolygon::SamplePartitionType NavigationPolygon::get_sample_partition_type() const {
442
return partition_type;
443
}
444
445
void NavigationPolygon::set_parsed_geometry_type(ParsedGeometryType p_geometry_type) {
446
ERR_FAIL_INDEX(p_geometry_type, PARSED_GEOMETRY_MAX);
447
parsed_geometry_type = p_geometry_type;
448
notify_property_list_changed();
449
}
450
451
NavigationPolygon::ParsedGeometryType NavigationPolygon::get_parsed_geometry_type() const {
452
return parsed_geometry_type;
453
}
454
455
void NavigationPolygon::set_parsed_collision_mask(uint32_t p_mask) {
456
parsed_collision_mask = p_mask;
457
}
458
459
uint32_t NavigationPolygon::get_parsed_collision_mask() const {
460
return parsed_collision_mask;
461
}
462
463
void NavigationPolygon::set_parsed_collision_mask_value(int p_layer_number, bool p_value) {
464
ERR_FAIL_COND_MSG(p_layer_number < 1, "Collision layer number must be between 1 and 32 inclusive.");
465
ERR_FAIL_COND_MSG(p_layer_number > 32, "Collision layer number must be between 1 and 32 inclusive.");
466
uint32_t mask = get_parsed_collision_mask();
467
if (p_value) {
468
mask |= 1 << (p_layer_number - 1);
469
} else {
470
mask &= ~(1 << (p_layer_number - 1));
471
}
472
set_parsed_collision_mask(mask);
473
}
474
475
bool NavigationPolygon::get_parsed_collision_mask_value(int p_layer_number) const {
476
ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Collision layer number must be between 1 and 32 inclusive.");
477
ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Collision layer number must be between 1 and 32 inclusive.");
478
return get_parsed_collision_mask() & (1 << (p_layer_number - 1));
479
}
480
481
void NavigationPolygon::set_source_geometry_mode(SourceGeometryMode p_geometry_mode) {
482
ERR_FAIL_INDEX(p_geometry_mode, SOURCE_GEOMETRY_MAX);
483
source_geometry_mode = p_geometry_mode;
484
notify_property_list_changed();
485
}
486
487
NavigationPolygon::SourceGeometryMode NavigationPolygon::get_source_geometry_mode() const {
488
return source_geometry_mode;
489
}
490
491
void NavigationPolygon::set_source_geometry_group_name(const StringName &p_group_name) {
492
source_geometry_group_name = p_group_name;
493
}
494
495
StringName NavigationPolygon::get_source_geometry_group_name() const {
496
return source_geometry_group_name;
497
}
498
499
void NavigationPolygon::set_agent_radius(real_t p_value) {
500
ERR_FAIL_COND(p_value < 0);
501
agent_radius = p_value;
502
}
503
504
real_t NavigationPolygon::get_agent_radius() const {
505
return agent_radius;
506
}
507
508
void NavigationPolygon::set_baking_rect(const Rect2 &p_rect) {
509
baking_rect = p_rect;
510
emit_changed();
511
}
512
513
Rect2 NavigationPolygon::get_baking_rect() const {
514
return baking_rect;
515
}
516
517
void NavigationPolygon::set_baking_rect_offset(const Vector2 &p_rect_offset) {
518
baking_rect_offset = p_rect_offset;
519
emit_changed();
520
}
521
522
Vector2 NavigationPolygon::get_baking_rect_offset() const {
523
return baking_rect_offset;
524
}
525
526
void NavigationPolygon::_bind_methods() {
527
ClassDB::bind_method(D_METHOD("set_vertices", "vertices"), &NavigationPolygon::set_vertices);
528
ClassDB::bind_method(D_METHOD("get_vertices"), &NavigationPolygon::get_vertices);
529
530
ClassDB::bind_method(D_METHOD("add_polygon", "polygon"), &NavigationPolygon::add_polygon);
531
ClassDB::bind_method(D_METHOD("get_polygon_count"), &NavigationPolygon::get_polygon_count);
532
ClassDB::bind_method(D_METHOD("get_polygon", "idx"), &NavigationPolygon::get_polygon);
533
ClassDB::bind_method(D_METHOD("clear_polygons"), &NavigationPolygon::clear_polygons);
534
ClassDB::bind_method(D_METHOD("get_navigation_mesh"), &NavigationPolygon::get_navigation_mesh);
535
536
ClassDB::bind_method(D_METHOD("add_outline", "outline"), &NavigationPolygon::add_outline);
537
ClassDB::bind_method(D_METHOD("add_outline_at_index", "outline", "index"), &NavigationPolygon::add_outline_at_index);
538
ClassDB::bind_method(D_METHOD("get_outline_count"), &NavigationPolygon::get_outline_count);
539
ClassDB::bind_method(D_METHOD("set_outline", "idx", "outline"), &NavigationPolygon::set_outline);
540
ClassDB::bind_method(D_METHOD("get_outline", "idx"), &NavigationPolygon::get_outline);
541
ClassDB::bind_method(D_METHOD("remove_outline", "idx"), &NavigationPolygon::remove_outline);
542
ClassDB::bind_method(D_METHOD("clear_outlines"), &NavigationPolygon::clear_outlines);
543
#ifndef DISABLE_DEPRECATED
544
ClassDB::bind_method(D_METHOD("make_polygons_from_outlines"), &NavigationPolygon::make_polygons_from_outlines);
545
#endif // DISABLE_DEPRECATED
546
547
ClassDB::bind_method(D_METHOD("_set_polygons", "polygons"), &NavigationPolygon::_set_polygons);
548
ClassDB::bind_method(D_METHOD("_get_polygons"), &NavigationPolygon::_get_polygons);
549
550
ClassDB::bind_method(D_METHOD("_set_outlines", "outlines"), &NavigationPolygon::_set_outlines);
551
ClassDB::bind_method(D_METHOD("_get_outlines"), &NavigationPolygon::_get_outlines);
552
553
ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &NavigationPolygon::set_cell_size);
554
ClassDB::bind_method(D_METHOD("get_cell_size"), &NavigationPolygon::get_cell_size);
555
556
ClassDB::bind_method(D_METHOD("set_border_size", "border_size"), &NavigationPolygon::set_border_size);
557
ClassDB::bind_method(D_METHOD("get_border_size"), &NavigationPolygon::get_border_size);
558
559
ClassDB::bind_method(D_METHOD("set_sample_partition_type", "sample_partition_type"), &NavigationPolygon::set_sample_partition_type);
560
ClassDB::bind_method(D_METHOD("get_sample_partition_type"), &NavigationPolygon::get_sample_partition_type);
561
562
ClassDB::bind_method(D_METHOD("set_parsed_geometry_type", "geometry_type"), &NavigationPolygon::set_parsed_geometry_type);
563
ClassDB::bind_method(D_METHOD("get_parsed_geometry_type"), &NavigationPolygon::get_parsed_geometry_type);
564
565
ClassDB::bind_method(D_METHOD("set_parsed_collision_mask", "mask"), &NavigationPolygon::set_parsed_collision_mask);
566
ClassDB::bind_method(D_METHOD("get_parsed_collision_mask"), &NavigationPolygon::get_parsed_collision_mask);
567
568
ClassDB::bind_method(D_METHOD("set_parsed_collision_mask_value", "layer_number", "value"), &NavigationPolygon::set_parsed_collision_mask_value);
569
ClassDB::bind_method(D_METHOD("get_parsed_collision_mask_value", "layer_number"), &NavigationPolygon::get_parsed_collision_mask_value);
570
571
ClassDB::bind_method(D_METHOD("set_source_geometry_mode", "geometry_mode"), &NavigationPolygon::set_source_geometry_mode);
572
ClassDB::bind_method(D_METHOD("get_source_geometry_mode"), &NavigationPolygon::get_source_geometry_mode);
573
574
ClassDB::bind_method(D_METHOD("set_source_geometry_group_name", "group_name"), &NavigationPolygon::set_source_geometry_group_name);
575
ClassDB::bind_method(D_METHOD("get_source_geometry_group_name"), &NavigationPolygon::get_source_geometry_group_name);
576
577
ClassDB::bind_method(D_METHOD("set_agent_radius", "agent_radius"), &NavigationPolygon::set_agent_radius);
578
ClassDB::bind_method(D_METHOD("get_agent_radius"), &NavigationPolygon::get_agent_radius);
579
580
ClassDB::bind_method(D_METHOD("set_baking_rect", "rect"), &NavigationPolygon::set_baking_rect);
581
ClassDB::bind_method(D_METHOD("get_baking_rect"), &NavigationPolygon::get_baking_rect);
582
ClassDB::bind_method(D_METHOD("set_baking_rect_offset", "rect_offset"), &NavigationPolygon::set_baking_rect_offset);
583
ClassDB::bind_method(D_METHOD("get_baking_rect_offset"), &NavigationPolygon::get_baking_rect_offset);
584
585
ClassDB::bind_method(D_METHOD("clear"), &NavigationPolygon::clear);
586
587
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_vertices", "get_vertices");
588
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_polygons", "_get_polygons");
589
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_outlines", "_get_outlines");
590
591
ADD_GROUP("Sampling", "sample_");
592
ADD_PROPERTY(PropertyInfo(Variant::INT, "sample_partition_type", PROPERTY_HINT_ENUM, "Convex Partition,Triangulate"), "set_sample_partition_type", "get_sample_partition_type");
593
ADD_GROUP("Geometry", "");
594
ADD_PROPERTY(PropertyInfo(Variant::INT, "parsed_geometry_type", PROPERTY_HINT_ENUM, "Mesh Instances,Static Colliders,Meshes and Static Colliders"), "set_parsed_geometry_type", "get_parsed_geometry_type");
595
ADD_PROPERTY(PropertyInfo(Variant::INT, "parsed_collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_parsed_collision_mask", "get_parsed_collision_mask");
596
ADD_PROPERTY_DEFAULT("parsed_collision_mask", 0xFFFFFFFF);
597
ADD_PROPERTY(PropertyInfo(Variant::INT, "source_geometry_mode", PROPERTY_HINT_ENUM, "Root Node Children,Group With Children,Group Explicit"), "set_source_geometry_mode", "get_source_geometry_mode");
598
ADD_PROPERTY(PropertyInfo(Variant::STRING, "source_geometry_group_name"), "set_source_geometry_group_name", "get_source_geometry_group_name");
599
ADD_PROPERTY_DEFAULT("source_geometry_group_name", StringName("navigation_polygon_source_geometry_group"));
600
ADD_GROUP("Cells", "");
601
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size", PROPERTY_HINT_RANGE, "1.0,50.0,1.0,or_greater,suffix:px"), "set_cell_size", "get_cell_size");
602
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "border_size", PROPERTY_HINT_RANGE, "0.0,500.0,1.0,or_greater,suffix:px"), "set_border_size", "get_border_size");
603
ADD_GROUP("Agents", "agent_");
604
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_radius", PROPERTY_HINT_RANGE, "0.0,500.0,0.01,or_greater,suffix:px"), "set_agent_radius", "get_agent_radius");
605
ADD_GROUP("Filters", "");
606
ADD_PROPERTY(PropertyInfo(Variant::RECT2, "baking_rect"), "set_baking_rect", "get_baking_rect");
607
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "baking_rect_offset"), "set_baking_rect_offset", "get_baking_rect_offset");
608
609
BIND_ENUM_CONSTANT(SAMPLE_PARTITION_CONVEX_PARTITION);
610
BIND_ENUM_CONSTANT(SAMPLE_PARTITION_TRIANGULATE);
611
BIND_ENUM_CONSTANT(SAMPLE_PARTITION_MAX);
612
613
BIND_ENUM_CONSTANT(PARSED_GEOMETRY_MESH_INSTANCES);
614
BIND_ENUM_CONSTANT(PARSED_GEOMETRY_STATIC_COLLIDERS);
615
BIND_ENUM_CONSTANT(PARSED_GEOMETRY_BOTH);
616
BIND_ENUM_CONSTANT(PARSED_GEOMETRY_MAX);
617
618
BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_ROOT_NODE_CHILDREN);
619
BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_GROUPS_WITH_CHILDREN);
620
BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_GROUPS_EXPLICIT);
621
BIND_ENUM_CONSTANT(SOURCE_GEOMETRY_MAX);
622
}
623
624
void NavigationPolygon::_validate_property(PropertyInfo &p_property) const {
625
if (p_property.name == "parsed_collision_mask") {
626
if (parsed_geometry_type == PARSED_GEOMETRY_MESH_INSTANCES) {
627
p_property.usage = PROPERTY_USAGE_NONE;
628
return;
629
}
630
}
631
632
if (p_property.name == "parsed_source_group_name") {
633
if (source_geometry_mode == SOURCE_GEOMETRY_ROOT_NODE_CHILDREN) {
634
p_property.usage = PROPERTY_USAGE_NONE;
635
return;
636
}
637
}
638
}
639
640