Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/modules/navigation_2d/2d/godot_navigation_server_2d.cpp
10278 views
1
/**************************************************************************/
2
/* godot_navigation_server_2d.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 "godot_navigation_server_2d.h"
32
33
#include "core/os/mutex.h"
34
#include "scene/main/node.h"
35
#include <cstdint>
36
37
#ifdef CLIPPER2_ENABLED
38
#include "nav_mesh_generator_2d.h"
39
#endif // CLIPPER2_ENABLED
40
41
#define COMMAND_1(F_NAME, T_0, D_0) \
42
struct MERGE(F_NAME, _command_2d) : public SetCommand2D { \
43
T_0 d_0; \
44
MERGE(F_NAME, _command_2d) \
45
(T_0 p_d_0) : \
46
d_0(p_d_0) {} \
47
virtual void exec(GodotNavigationServer2D *p_server) override { \
48
p_server->MERGE(_cmd_, F_NAME)(d_0); \
49
} \
50
}; \
51
void GodotNavigationServer2D::F_NAME(T_0 D_0) { \
52
auto cmd = memnew(MERGE(F_NAME, _command_2d)( \
53
D_0)); \
54
add_command(cmd); \
55
} \
56
void GodotNavigationServer2D::MERGE(_cmd_, F_NAME)(T_0 D_0)
57
58
#define COMMAND_2(F_NAME, T_0, D_0, T_1, D_1) \
59
struct MERGE(F_NAME, _command_2d) : public SetCommand2D { \
60
T_0 d_0; \
61
T_1 d_1; \
62
MERGE(F_NAME, _command_2d) \
63
( \
64
T_0 p_d_0, \
65
T_1 p_d_1) : \
66
d_0(p_d_0), \
67
d_1(p_d_1) {} \
68
virtual void exec(GodotNavigationServer2D *p_server) override { \
69
p_server->MERGE(_cmd_, F_NAME)(d_0, d_1); \
70
} \
71
}; \
72
void GodotNavigationServer2D::F_NAME(T_0 D_0, T_1 D_1) { \
73
auto cmd = memnew(MERGE(F_NAME, _command_2d)( \
74
D_0, \
75
D_1)); \
76
add_command(cmd); \
77
} \
78
void GodotNavigationServer2D::MERGE(_cmd_, F_NAME)(T_0 D_0, T_1 D_1)
79
80
void GodotNavigationServer2D::init() {
81
#ifdef CLIPPER2_ENABLED
82
navmesh_generator_2d = memnew(NavMeshGenerator2D);
83
ERR_FAIL_NULL_MSG(navmesh_generator_2d, "Failed to init NavMeshGenerator2D.");
84
RWLockRead read_lock(geometry_parser_rwlock);
85
navmesh_generator_2d->set_generator_parsers(generator_parsers);
86
#endif // CLIPPER2_ENABLED
87
// TODO
88
}
89
90
void GodotNavigationServer2D::sync() {
91
#ifdef CLIPPER2_ENABLED
92
if (navmesh_generator_2d) {
93
navmesh_generator_2d->sync();
94
}
95
#endif // CLIPPER2_ENABLED
96
// TODO
97
}
98
99
void GodotNavigationServer2D::finish() {
100
#ifdef CLIPPER2_ENABLED
101
if (navmesh_generator_2d) {
102
navmesh_generator_2d->finish();
103
memdelete(navmesh_generator_2d);
104
navmesh_generator_2d = nullptr;
105
}
106
#endif // CLIPPER2_ENABLED
107
// TODO
108
}
109
110
void GodotNavigationServer2D::parse_source_geometry_data(const Ref<NavigationPolygon> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData2D> &p_source_geometry_data, Node *p_root_node, const Callable &p_callback) {
111
ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "The SceneTree can only be parsed on the main thread. Call this function from the main thread or use call_deferred().");
112
ERR_FAIL_COND_MSG(p_navigation_mesh.is_null(), "Invalid navigation polygon.");
113
ERR_FAIL_NULL_MSG(p_root_node, "No parsing root node specified.");
114
ERR_FAIL_COND_MSG(!p_root_node->is_inside_tree(), "The root node needs to be inside the SceneTree.");
115
116
#ifdef CLIPPER2_ENABLED
117
ERR_FAIL_NULL(NavMeshGenerator2D::get_singleton());
118
NavMeshGenerator2D::get_singleton()->parse_source_geometry_data(p_navigation_mesh, p_source_geometry_data, p_root_node, p_callback);
119
#endif // CLIPPER2_ENABLED
120
}
121
122
void GodotNavigationServer2D::bake_from_source_geometry_data(const Ref<NavigationPolygon> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData2D> &p_source_geometry_data, const Callable &p_callback) {
123
ERR_FAIL_COND_MSG(p_navigation_mesh.is_null(), "Invalid navigation polygon.");
124
ERR_FAIL_COND_MSG(p_source_geometry_data.is_null(), "Invalid NavigationMeshSourceGeometryData2D.");
125
126
#ifdef CLIPPER2_ENABLED
127
ERR_FAIL_NULL(NavMeshGenerator2D::get_singleton());
128
NavMeshGenerator2D::get_singleton()->bake_from_source_geometry_data(p_navigation_mesh, p_source_geometry_data, p_callback);
129
#endif // CLIPPER2_ENABLED
130
}
131
132
void GodotNavigationServer2D::bake_from_source_geometry_data_async(const Ref<NavigationPolygon> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData2D> &p_source_geometry_data, const Callable &p_callback) {
133
ERR_FAIL_COND_MSG(p_navigation_mesh.is_null(), "Invalid navigation mesh.");
134
ERR_FAIL_COND_MSG(p_source_geometry_data.is_null(), "Invalid NavigationMeshSourceGeometryData2D.");
135
136
#ifdef CLIPPER2_ENABLED
137
ERR_FAIL_NULL(NavMeshGenerator2D::get_singleton());
138
NavMeshGenerator2D::get_singleton()->bake_from_source_geometry_data_async(p_navigation_mesh, p_source_geometry_data, p_callback);
139
#endif // CLIPPER2_ENABLED
140
}
141
142
bool GodotNavigationServer2D::is_baking_navigation_polygon(Ref<NavigationPolygon> p_navigation_polygon) const {
143
#ifdef CLIPPER2_ENABLED
144
return NavMeshGenerator2D::get_singleton()->is_baking(p_navigation_polygon);
145
#else
146
return false;
147
#endif
148
}
149
150
Vector<Vector2> GodotNavigationServer2D::simplify_path(const Vector<Vector2> &p_path, real_t p_epsilon) {
151
if (p_path.size() <= 2) {
152
return p_path;
153
}
154
155
p_epsilon = MAX(0.0, p_epsilon);
156
157
LocalVector<Vector2> source_path;
158
{
159
source_path.resize(p_path.size());
160
const Vector2 *r = p_path.ptr();
161
for (uint32_t i = 0; i < p_path.size(); i++) {
162
source_path[i] = r[i];
163
}
164
}
165
166
LocalVector<uint32_t> simplified_path_indices = NavMeshQueries2D::get_simplified_path_indices(source_path, p_epsilon);
167
168
uint32_t index_count = simplified_path_indices.size();
169
170
Vector<Vector2> simplified_path;
171
{
172
simplified_path.resize(index_count);
173
Vector2 *w = simplified_path.ptrw();
174
const Vector2 *r = source_path.ptr();
175
for (uint32_t i = 0; i < index_count; i++) {
176
w[i] = r[simplified_path_indices[i]];
177
}
178
}
179
180
return simplified_path;
181
}
182
183
GodotNavigationServer2D::GodotNavigationServer2D() {}
184
185
GodotNavigationServer2D::~GodotNavigationServer2D() {
186
flush_queries();
187
}
188
189
void GodotNavigationServer2D::add_command(SetCommand2D *p_command) {
190
MutexLock lock(commands_mutex);
191
192
commands.push_back(p_command);
193
}
194
195
TypedArray<RID> GodotNavigationServer2D::get_maps() const {
196
TypedArray<RID> all_map_rids;
197
LocalVector<RID> maps_owned = map_owner.get_owned_list();
198
uint32_t map_count = maps_owned.size();
199
if (map_count) {
200
all_map_rids.resize(map_count);
201
for (uint32_t i = 0; i < map_count; i++) {
202
all_map_rids[i] = maps_owned[i];
203
}
204
}
205
return all_map_rids;
206
}
207
208
TypedArray<RID> GodotNavigationServer2D::map_get_links(RID p_map) const {
209
TypedArray<RID> link_rids;
210
const NavMap2D *map = map_owner.get_or_null(p_map);
211
ERR_FAIL_NULL_V(map, link_rids);
212
213
const LocalVector<NavLink2D *> &links = map->get_links();
214
link_rids.resize(links.size());
215
216
for (uint32_t i = 0; i < links.size(); i++) {
217
link_rids[i] = links[i]->get_self();
218
}
219
return link_rids;
220
}
221
222
TypedArray<RID> GodotNavigationServer2D::map_get_regions(RID p_map) const {
223
TypedArray<RID> regions_rids;
224
const NavMap2D *map = map_owner.get_or_null(p_map);
225
ERR_FAIL_NULL_V(map, regions_rids);
226
227
const LocalVector<NavRegion2D *> &regions = map->get_regions();
228
regions_rids.resize(regions.size());
229
230
for (uint32_t i = 0; i < regions.size(); i++) {
231
regions_rids[i] = regions[i]->get_self();
232
}
233
return regions_rids;
234
}
235
236
TypedArray<RID> GodotNavigationServer2D::map_get_agents(RID p_map) const {
237
TypedArray<RID> agents_rids;
238
const NavMap2D *map = map_owner.get_or_null(p_map);
239
ERR_FAIL_NULL_V(map, agents_rids);
240
241
const LocalVector<NavAgent2D *> &agents = map->get_agents();
242
agents_rids.resize(agents.size());
243
244
for (uint32_t i = 0; i < agents.size(); i++) {
245
agents_rids[i] = agents[i]->get_self();
246
}
247
return agents_rids;
248
}
249
250
TypedArray<RID> GodotNavigationServer2D::map_get_obstacles(RID p_map) const {
251
TypedArray<RID> obstacles_rids;
252
const NavMap2D *map = map_owner.get_or_null(p_map);
253
ERR_FAIL_NULL_V(map, obstacles_rids);
254
const LocalVector<NavObstacle2D *> obstacles = map->get_obstacles();
255
obstacles_rids.resize(obstacles.size());
256
for (uint32_t i = 0; i < obstacles.size(); i++) {
257
obstacles_rids[i] = obstacles[i]->get_self();
258
}
259
return obstacles_rids;
260
}
261
262
RID GodotNavigationServer2D::region_get_map(RID p_region) const {
263
NavRegion2D *region = region_owner.get_or_null(p_region);
264
ERR_FAIL_NULL_V(region, RID());
265
266
if (region->get_map()) {
267
return region->get_map()->get_self();
268
}
269
return RID();
270
}
271
272
RID GodotNavigationServer2D::agent_get_map(RID p_agent) const {
273
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
274
ERR_FAIL_NULL_V(agent, RID());
275
276
if (agent->get_map()) {
277
return agent->get_map()->get_self();
278
}
279
return RID();
280
}
281
282
RID GodotNavigationServer2D::map_create() {
283
MutexLock lock(operations_mutex);
284
285
RID rid = map_owner.make_rid();
286
NavMap2D *map = map_owner.get_or_null(rid);
287
map->set_self(rid);
288
return rid;
289
}
290
291
COMMAND_2(map_set_active, RID, p_map, bool, p_active) {
292
NavMap2D *map = map_owner.get_or_null(p_map);
293
ERR_FAIL_NULL(map);
294
295
if (p_active) {
296
if (!map_is_active(p_map)) {
297
active_maps.push_back(map);
298
}
299
} else {
300
int map_index = active_maps.find(map);
301
ERR_FAIL_COND(map_index < 0);
302
active_maps.remove_at(map_index);
303
}
304
}
305
306
bool GodotNavigationServer2D::map_is_active(RID p_map) const {
307
NavMap2D *map = map_owner.get_or_null(p_map);
308
ERR_FAIL_NULL_V(map, false);
309
310
return active_maps.has(map);
311
}
312
313
void GodotNavigationServer2D::map_force_update(RID p_map) {
314
NavMap2D *map = map_owner.get_or_null(p_map);
315
ERR_FAIL_NULL(map);
316
317
flush_queries();
318
319
map->sync();
320
}
321
322
uint32_t GodotNavigationServer2D::map_get_iteration_id(RID p_map) const {
323
NavMap2D *map = map_owner.get_or_null(p_map);
324
ERR_FAIL_NULL_V(map, 0);
325
326
return map->get_iteration_id();
327
}
328
329
COMMAND_2(map_set_use_async_iterations, RID, p_map, bool, p_enabled) {
330
NavMap2D *map = map_owner.get_or_null(p_map);
331
ERR_FAIL_NULL(map);
332
map->set_use_async_iterations(p_enabled);
333
}
334
335
bool GodotNavigationServer2D::map_get_use_async_iterations(RID p_map) const {
336
const NavMap2D *map = map_owner.get_or_null(p_map);
337
ERR_FAIL_NULL_V(map, false);
338
339
return map->get_use_async_iterations();
340
}
341
342
COMMAND_2(map_set_cell_size, RID, p_map, real_t, p_cell_size) {
343
NavMap2D *map = map_owner.get_or_null(p_map);
344
ERR_FAIL_NULL(map);
345
346
map->set_cell_size(p_cell_size);
347
}
348
349
real_t GodotNavigationServer2D::map_get_cell_size(RID p_map) const {
350
const NavMap2D *map = map_owner.get_or_null(p_map);
351
ERR_FAIL_NULL_V(map, 0);
352
353
return map->get_cell_size();
354
}
355
356
COMMAND_2(map_set_merge_rasterizer_cell_scale, RID, p_map, float, p_value) {
357
NavMap2D *map = map_owner.get_or_null(p_map);
358
ERR_FAIL_NULL(map);
359
360
map->set_merge_rasterizer_cell_scale(p_value);
361
}
362
363
float GodotNavigationServer2D::map_get_merge_rasterizer_cell_scale(RID p_map) const {
364
NavMap2D *map = map_owner.get_or_null(p_map);
365
ERR_FAIL_NULL_V(map, false);
366
367
return map->get_merge_rasterizer_cell_scale();
368
}
369
370
COMMAND_2(map_set_use_edge_connections, RID, p_map, bool, p_enabled) {
371
NavMap2D *map = map_owner.get_or_null(p_map);
372
ERR_FAIL_NULL(map);
373
374
map->set_use_edge_connections(p_enabled);
375
}
376
377
bool GodotNavigationServer2D::map_get_use_edge_connections(RID p_map) const {
378
NavMap2D *map = map_owner.get_or_null(p_map);
379
ERR_FAIL_NULL_V(map, false);
380
381
return map->get_use_edge_connections();
382
}
383
384
COMMAND_2(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin) {
385
NavMap2D *map = map_owner.get_or_null(p_map);
386
ERR_FAIL_NULL(map);
387
388
map->set_edge_connection_margin(p_connection_margin);
389
}
390
391
real_t GodotNavigationServer2D::map_get_edge_connection_margin(RID p_map) const {
392
const NavMap2D *map = map_owner.get_or_null(p_map);
393
ERR_FAIL_NULL_V(map, 0);
394
395
return map->get_edge_connection_margin();
396
}
397
398
COMMAND_2(map_set_link_connection_radius, RID, p_map, real_t, p_connection_radius) {
399
NavMap2D *map = map_owner.get_or_null(p_map);
400
ERR_FAIL_NULL(map);
401
402
map->set_link_connection_radius(p_connection_radius);
403
}
404
405
real_t GodotNavigationServer2D::map_get_link_connection_radius(RID p_map) const {
406
const NavMap2D *map = map_owner.get_or_null(p_map);
407
ERR_FAIL_NULL_V(map, 0);
408
409
return map->get_link_connection_radius();
410
}
411
412
Vector<Vector2> GodotNavigationServer2D::map_get_path(RID p_map, Vector2 p_origin, Vector2 p_destination, bool p_optimize, uint32_t p_navigation_layers) {
413
const NavMap2D *map = map_owner.get_or_null(p_map);
414
ERR_FAIL_NULL_V(map, Vector<Vector2>());
415
416
Ref<NavigationPathQueryParameters2D> query_parameters;
417
query_parameters.instantiate();
418
419
query_parameters->set_map(p_map);
420
query_parameters->set_start_position(p_origin);
421
query_parameters->set_target_position(p_destination);
422
query_parameters->set_navigation_layers(p_navigation_layers);
423
query_parameters->set_pathfinding_algorithm(NavigationPathQueryParameters2D::PathfindingAlgorithm::PATHFINDING_ALGORITHM_ASTAR);
424
query_parameters->set_path_postprocessing(NavigationPathQueryParameters2D::PathPostProcessing::PATH_POSTPROCESSING_CORRIDORFUNNEL);
425
if (!p_optimize) {
426
query_parameters->set_path_postprocessing(NavigationPathQueryParameters2D::PATH_POSTPROCESSING_EDGECENTERED);
427
}
428
429
Ref<NavigationPathQueryResult2D> query_result;
430
query_result.instantiate();
431
432
query_path(query_parameters, query_result);
433
434
return query_result->get_path();
435
}
436
437
Vector2 GodotNavigationServer2D::map_get_closest_point(RID p_map, const Vector2 &p_point) const {
438
const NavMap2D *map = map_owner.get_or_null(p_map);
439
ERR_FAIL_NULL_V(map, Vector2());
440
441
return map->get_closest_point(p_point);
442
}
443
444
RID GodotNavigationServer2D::map_get_closest_point_owner(RID p_map, const Vector2 &p_point) const {
445
const NavMap2D *map = map_owner.get_or_null(p_map);
446
ERR_FAIL_NULL_V(map, RID());
447
448
return map->get_closest_point_owner(p_point);
449
}
450
451
Vector2 GodotNavigationServer2D::map_get_random_point(RID p_map, uint32_t p_navigation_layers, bool p_uniformly) const {
452
const NavMap2D *map = map_owner.get_or_null(p_map);
453
ERR_FAIL_NULL_V(map, Vector2());
454
455
return map->get_random_point(p_navigation_layers, p_uniformly);
456
}
457
458
RID GodotNavigationServer2D::region_create() {
459
MutexLock lock(operations_mutex);
460
461
RID rid = region_owner.make_rid();
462
NavRegion2D *reg = region_owner.get_or_null(rid);
463
reg->set_self(rid);
464
return rid;
465
}
466
467
uint32_t GodotNavigationServer2D::region_get_iteration_id(RID p_region) const {
468
NavRegion2D *region = region_owner.get_or_null(p_region);
469
ERR_FAIL_NULL_V(region, 0);
470
471
return region->get_iteration_id();
472
}
473
474
COMMAND_2(region_set_use_async_iterations, RID, p_region, bool, p_enabled) {
475
NavRegion2D *region = region_owner.get_or_null(p_region);
476
ERR_FAIL_NULL(region);
477
region->set_use_async_iterations(p_enabled);
478
}
479
480
bool GodotNavigationServer2D::region_get_use_async_iterations(RID p_region) const {
481
NavRegion2D *region = region_owner.get_or_null(p_region);
482
ERR_FAIL_NULL_V(region, false);
483
484
return region->get_use_async_iterations();
485
}
486
487
COMMAND_2(region_set_enabled, RID, p_region, bool, p_enabled) {
488
NavRegion2D *region = region_owner.get_or_null(p_region);
489
ERR_FAIL_NULL(region);
490
491
region->set_enabled(p_enabled);
492
}
493
494
bool GodotNavigationServer2D::region_get_enabled(RID p_region) const {
495
const NavRegion2D *region = region_owner.get_or_null(p_region);
496
ERR_FAIL_NULL_V(region, false);
497
498
return region->get_enabled();
499
}
500
501
COMMAND_2(region_set_use_edge_connections, RID, p_region, bool, p_enabled) {
502
NavRegion2D *region = region_owner.get_or_null(p_region);
503
ERR_FAIL_NULL(region);
504
505
region->set_use_edge_connections(p_enabled);
506
}
507
508
bool GodotNavigationServer2D::region_get_use_edge_connections(RID p_region) const {
509
NavRegion2D *region = region_owner.get_or_null(p_region);
510
ERR_FAIL_NULL_V(region, false);
511
512
return region->get_use_edge_connections();
513
}
514
515
COMMAND_2(region_set_enter_cost, RID, p_region, real_t, p_enter_cost) {
516
NavRegion2D *region = region_owner.get_or_null(p_region);
517
ERR_FAIL_NULL(region);
518
ERR_FAIL_COND(p_enter_cost < 0.0);
519
520
region->set_enter_cost(p_enter_cost);
521
}
522
523
real_t GodotNavigationServer2D::region_get_enter_cost(RID p_region) const {
524
NavRegion2D *region = region_owner.get_or_null(p_region);
525
ERR_FAIL_NULL_V(region, 0);
526
527
return region->get_enter_cost();
528
}
529
530
COMMAND_2(region_set_travel_cost, RID, p_region, real_t, p_travel_cost) {
531
NavRegion2D *region = region_owner.get_or_null(p_region);
532
ERR_FAIL_NULL(region);
533
ERR_FAIL_COND(p_travel_cost < 0.0);
534
535
region->set_travel_cost(p_travel_cost);
536
}
537
538
real_t GodotNavigationServer2D::region_get_travel_cost(RID p_region) const {
539
NavRegion2D *region = region_owner.get_or_null(p_region);
540
ERR_FAIL_NULL_V(region, 0);
541
542
return region->get_travel_cost();
543
}
544
545
COMMAND_2(region_set_owner_id, RID, p_region, ObjectID, p_owner_id) {
546
NavRegion2D *region = region_owner.get_or_null(p_region);
547
ERR_FAIL_NULL(region);
548
549
region->set_owner_id(p_owner_id);
550
}
551
552
ObjectID GodotNavigationServer2D::region_get_owner_id(RID p_region) const {
553
const NavRegion2D *region = region_owner.get_or_null(p_region);
554
ERR_FAIL_NULL_V(region, ObjectID());
555
556
return region->get_owner_id();
557
}
558
559
bool GodotNavigationServer2D::region_owns_point(RID p_region, const Vector2 &p_point) const {
560
const NavRegion2D *region = region_owner.get_or_null(p_region);
561
ERR_FAIL_NULL_V(region, false);
562
563
if (region->get_map()) {
564
RID closest_point_owner = map_get_closest_point_owner(region->get_map()->get_self(), p_point);
565
return closest_point_owner == region->get_self();
566
}
567
return false;
568
}
569
570
COMMAND_2(region_set_map, RID, p_region, RID, p_map) {
571
NavRegion2D *region = region_owner.get_or_null(p_region);
572
ERR_FAIL_NULL(region);
573
574
NavMap2D *map = map_owner.get_or_null(p_map);
575
576
region->set_map(map);
577
}
578
579
COMMAND_2(region_set_navigation_layers, RID, p_region, uint32_t, p_navigation_layers) {
580
NavRegion2D *region = region_owner.get_or_null(p_region);
581
ERR_FAIL_NULL(region);
582
583
region->set_navigation_layers(p_navigation_layers);
584
}
585
586
uint32_t GodotNavigationServer2D::region_get_navigation_layers(RID p_region) const {
587
NavRegion2D *region = region_owner.get_or_null(p_region);
588
ERR_FAIL_NULL_V(region, 0);
589
590
return region->get_navigation_layers();
591
}
592
593
COMMAND_2(region_set_transform, RID, p_region, Transform2D, p_transform) {
594
NavRegion2D *region = region_owner.get_or_null(p_region);
595
ERR_FAIL_NULL(region);
596
597
region->set_transform(p_transform);
598
}
599
600
Transform2D GodotNavigationServer2D::region_get_transform(RID p_region) const {
601
NavRegion2D *region = region_owner.get_or_null(p_region);
602
ERR_FAIL_NULL_V(region, Transform2D());
603
604
return region->get_transform();
605
}
606
607
void GodotNavigationServer2D::region_set_navigation_polygon(RID p_region, Ref<NavigationPolygon> p_navigation_polygon) {
608
NavRegion2D *region = region_owner.get_or_null(p_region);
609
ERR_FAIL_NULL(region);
610
611
region->set_navigation_mesh(p_navigation_polygon);
612
}
613
614
int GodotNavigationServer2D::region_get_connections_count(RID p_region) const {
615
NavRegion2D *region = region_owner.get_or_null(p_region);
616
ERR_FAIL_NULL_V(region, 0);
617
NavMap2D *map = region->get_map();
618
if (map) {
619
return map->get_region_connections_count(region);
620
}
621
return 0;
622
}
623
624
Vector2 GodotNavigationServer2D::region_get_connection_pathway_start(RID p_region, int p_connection_id) const {
625
NavRegion2D *region = region_owner.get_or_null(p_region);
626
ERR_FAIL_NULL_V(region, Vector2());
627
NavMap2D *map = region->get_map();
628
if (map) {
629
return map->get_region_connection_pathway_start(region, p_connection_id);
630
}
631
return Vector2();
632
}
633
634
Vector2 GodotNavigationServer2D::region_get_connection_pathway_end(RID p_region, int p_connection_id) const {
635
NavRegion2D *region = region_owner.get_or_null(p_region);
636
ERR_FAIL_NULL_V(region, Vector2());
637
NavMap2D *map = region->get_map();
638
if (map) {
639
return map->get_region_connection_pathway_end(region, p_connection_id);
640
}
641
return Vector2();
642
}
643
644
Vector2 GodotNavigationServer2D::region_get_closest_point(RID p_region, const Vector2 &p_point) const {
645
const NavRegion2D *region = region_owner.get_or_null(p_region);
646
ERR_FAIL_NULL_V(region, Vector2());
647
648
return region->get_closest_point_info(p_point).point;
649
}
650
651
Vector2 GodotNavigationServer2D::region_get_random_point(RID p_region, uint32_t p_navigation_layers, bool p_uniformly) const {
652
const NavRegion2D *region = region_owner.get_or_null(p_region);
653
ERR_FAIL_NULL_V(region, Vector2());
654
655
return region->get_random_point(p_navigation_layers, p_uniformly);
656
}
657
658
Rect2 GodotNavigationServer2D::region_get_bounds(RID p_region) const {
659
const NavRegion2D *region = region_owner.get_or_null(p_region);
660
ERR_FAIL_NULL_V(region, Rect2());
661
662
return region->get_bounds();
663
}
664
665
RID GodotNavigationServer2D::link_create() {
666
MutexLock lock(operations_mutex);
667
668
RID rid = link_owner.make_rid();
669
NavLink2D *link = link_owner.get_or_null(rid);
670
link->set_self(rid);
671
return rid;
672
}
673
674
uint32_t GodotNavigationServer2D::link_get_iteration_id(RID p_link) const {
675
NavLink2D *link = link_owner.get_or_null(p_link);
676
ERR_FAIL_NULL_V(link, 0);
677
678
return link->get_iteration_id();
679
}
680
681
COMMAND_2(link_set_map, RID, p_link, RID, p_map) {
682
NavLink2D *link = link_owner.get_or_null(p_link);
683
ERR_FAIL_NULL(link);
684
685
NavMap2D *map = map_owner.get_or_null(p_map);
686
687
link->set_map(map);
688
}
689
690
RID GodotNavigationServer2D::link_get_map(const RID p_link) const {
691
const NavLink2D *link = link_owner.get_or_null(p_link);
692
ERR_FAIL_NULL_V(link, RID());
693
694
if (link->get_map()) {
695
return link->get_map()->get_self();
696
}
697
return RID();
698
}
699
700
COMMAND_2(link_set_enabled, RID, p_link, bool, p_enabled) {
701
NavLink2D *link = link_owner.get_or_null(p_link);
702
ERR_FAIL_NULL(link);
703
704
link->set_enabled(p_enabled);
705
}
706
707
bool GodotNavigationServer2D::link_get_enabled(RID p_link) const {
708
const NavLink2D *link = link_owner.get_or_null(p_link);
709
ERR_FAIL_NULL_V(link, false);
710
711
return link->get_enabled();
712
}
713
714
COMMAND_2(link_set_bidirectional, RID, p_link, bool, p_bidirectional) {
715
NavLink2D *link = link_owner.get_or_null(p_link);
716
ERR_FAIL_NULL(link);
717
718
link->set_bidirectional(p_bidirectional);
719
}
720
721
bool GodotNavigationServer2D::link_is_bidirectional(RID p_link) const {
722
const NavLink2D *link = link_owner.get_or_null(p_link);
723
ERR_FAIL_NULL_V(link, false);
724
725
return link->is_bidirectional();
726
}
727
728
COMMAND_2(link_set_navigation_layers, RID, p_link, uint32_t, p_navigation_layers) {
729
NavLink2D *link = link_owner.get_or_null(p_link);
730
ERR_FAIL_NULL(link);
731
732
link->set_navigation_layers(p_navigation_layers);
733
}
734
735
uint32_t GodotNavigationServer2D::link_get_navigation_layers(const RID p_link) const {
736
const NavLink2D *link = link_owner.get_or_null(p_link);
737
ERR_FAIL_NULL_V(link, 0);
738
739
return link->get_navigation_layers();
740
}
741
742
COMMAND_2(link_set_start_position, RID, p_link, Vector2, p_position) {
743
NavLink2D *link = link_owner.get_or_null(p_link);
744
ERR_FAIL_NULL(link);
745
746
link->set_start_position(p_position);
747
}
748
749
Vector2 GodotNavigationServer2D::link_get_start_position(RID p_link) const {
750
const NavLink2D *link = link_owner.get_or_null(p_link);
751
ERR_FAIL_NULL_V(link, Vector2());
752
753
return link->get_start_position();
754
}
755
756
COMMAND_2(link_set_end_position, RID, p_link, Vector2, p_position) {
757
NavLink2D *link = link_owner.get_or_null(p_link);
758
ERR_FAIL_NULL(link);
759
760
link->set_end_position(p_position);
761
}
762
763
Vector2 GodotNavigationServer2D::link_get_end_position(RID p_link) const {
764
const NavLink2D *link = link_owner.get_or_null(p_link);
765
ERR_FAIL_NULL_V(link, Vector2());
766
767
return link->get_end_position();
768
}
769
770
COMMAND_2(link_set_enter_cost, RID, p_link, real_t, p_enter_cost) {
771
NavLink2D *link = link_owner.get_or_null(p_link);
772
ERR_FAIL_NULL(link);
773
774
link->set_enter_cost(p_enter_cost);
775
}
776
777
real_t GodotNavigationServer2D::link_get_enter_cost(const RID p_link) const {
778
const NavLink2D *link = link_owner.get_or_null(p_link);
779
ERR_FAIL_NULL_V(link, 0);
780
781
return link->get_enter_cost();
782
}
783
784
COMMAND_2(link_set_travel_cost, RID, p_link, real_t, p_travel_cost) {
785
NavLink2D *link = link_owner.get_or_null(p_link);
786
ERR_FAIL_NULL(link);
787
788
link->set_travel_cost(p_travel_cost);
789
}
790
791
real_t GodotNavigationServer2D::link_get_travel_cost(const RID p_link) const {
792
const NavLink2D *link = link_owner.get_or_null(p_link);
793
ERR_FAIL_NULL_V(link, 0);
794
795
return link->get_travel_cost();
796
}
797
798
COMMAND_2(link_set_owner_id, RID, p_link, ObjectID, p_owner_id) {
799
NavLink2D *link = link_owner.get_or_null(p_link);
800
ERR_FAIL_NULL(link);
801
802
link->set_owner_id(p_owner_id);
803
}
804
805
ObjectID GodotNavigationServer2D::link_get_owner_id(RID p_link) const {
806
const NavLink2D *link = link_owner.get_or_null(p_link);
807
ERR_FAIL_NULL_V(link, ObjectID());
808
809
return link->get_owner_id();
810
}
811
812
RID GodotNavigationServer2D::agent_create() {
813
MutexLock lock(operations_mutex);
814
815
RID rid = agent_owner.make_rid();
816
NavAgent2D *agent = agent_owner.get_or_null(rid);
817
agent->set_self(rid);
818
return rid;
819
}
820
821
COMMAND_2(agent_set_avoidance_enabled, RID, p_agent, bool, p_enabled) {
822
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
823
ERR_FAIL_NULL(agent);
824
825
agent->set_avoidance_enabled(p_enabled);
826
}
827
828
bool GodotNavigationServer2D::agent_get_avoidance_enabled(RID p_agent) const {
829
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
830
ERR_FAIL_NULL_V(agent, false);
831
832
return agent->is_avoidance_enabled();
833
}
834
835
COMMAND_2(agent_set_map, RID, p_agent, RID, p_map) {
836
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
837
ERR_FAIL_NULL(agent);
838
839
NavMap2D *map = map_owner.get_or_null(p_map);
840
841
agent->set_map(map);
842
}
843
844
COMMAND_2(agent_set_neighbor_distance, RID, p_agent, real_t, p_distance) {
845
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
846
ERR_FAIL_NULL(agent);
847
848
agent->set_neighbor_distance(p_distance);
849
}
850
851
real_t GodotNavigationServer2D::agent_get_neighbor_distance(RID p_agent) const {
852
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
853
ERR_FAIL_NULL_V(agent, 0);
854
855
return agent->get_neighbor_distance();
856
}
857
858
COMMAND_2(agent_set_max_neighbors, RID, p_agent, int, p_count) {
859
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
860
ERR_FAIL_NULL(agent);
861
862
agent->set_max_neighbors(p_count);
863
}
864
865
int GodotNavigationServer2D::agent_get_max_neighbors(RID p_agent) const {
866
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
867
ERR_FAIL_NULL_V(agent, 0);
868
869
return agent->get_max_neighbors();
870
}
871
872
COMMAND_2(agent_set_time_horizon_agents, RID, p_agent, real_t, p_time_horizon) {
873
ERR_FAIL_COND_MSG(p_time_horizon < 0.0, "Time horizon must be positive.");
874
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
875
ERR_FAIL_NULL(agent);
876
877
agent->set_time_horizon_agents(p_time_horizon);
878
}
879
880
real_t GodotNavigationServer2D::agent_get_time_horizon_agents(RID p_agent) const {
881
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
882
ERR_FAIL_NULL_V(agent, 0);
883
884
return agent->get_time_horizon_agents();
885
}
886
887
COMMAND_2(agent_set_time_horizon_obstacles, RID, p_agent, real_t, p_time_horizon) {
888
ERR_FAIL_COND_MSG(p_time_horizon < 0.0, "Time horizon must be positive.");
889
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
890
ERR_FAIL_NULL(agent);
891
892
agent->set_time_horizon_obstacles(p_time_horizon);
893
}
894
895
real_t GodotNavigationServer2D::agent_get_time_horizon_obstacles(RID p_agent) const {
896
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
897
ERR_FAIL_NULL_V(agent, 0);
898
899
return agent->get_time_horizon_obstacles();
900
}
901
902
COMMAND_2(agent_set_radius, RID, p_agent, real_t, p_radius) {
903
ERR_FAIL_COND_MSG(p_radius < 0.0, "Radius must be positive.");
904
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
905
ERR_FAIL_NULL(agent);
906
907
agent->set_radius(p_radius);
908
}
909
910
real_t GodotNavigationServer2D::agent_get_radius(RID p_agent) const {
911
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
912
ERR_FAIL_NULL_V(agent, 0);
913
914
return agent->get_radius();
915
}
916
917
COMMAND_2(agent_set_max_speed, RID, p_agent, real_t, p_max_speed) {
918
ERR_FAIL_COND_MSG(p_max_speed < 0.0, "Max speed must be positive.");
919
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
920
ERR_FAIL_NULL(agent);
921
922
agent->set_max_speed(p_max_speed);
923
}
924
925
real_t GodotNavigationServer2D::agent_get_max_speed(RID p_agent) const {
926
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
927
ERR_FAIL_NULL_V(agent, 0);
928
929
return agent->get_max_speed();
930
}
931
932
COMMAND_2(agent_set_velocity_forced, RID, p_agent, Vector2, p_velocity) {
933
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
934
ERR_FAIL_NULL(agent);
935
936
agent->set_velocity_forced(p_velocity);
937
}
938
939
COMMAND_2(agent_set_velocity, RID, p_agent, Vector2, p_velocity) {
940
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
941
ERR_FAIL_NULL(agent);
942
943
agent->set_velocity(p_velocity);
944
}
945
946
Vector2 GodotNavigationServer2D::agent_get_velocity(RID p_agent) const {
947
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
948
ERR_FAIL_NULL_V(agent, Vector2());
949
950
return agent->get_velocity();
951
}
952
953
COMMAND_2(agent_set_position, RID, p_agent, Vector2, p_position) {
954
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
955
ERR_FAIL_NULL(agent);
956
957
agent->set_position(p_position);
958
}
959
960
Vector2 GodotNavigationServer2D::agent_get_position(RID p_agent) const {
961
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
962
ERR_FAIL_NULL_V(agent, Vector2());
963
964
return agent->get_position();
965
}
966
967
bool GodotNavigationServer2D::agent_is_map_changed(RID p_agent) const {
968
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
969
ERR_FAIL_NULL_V(agent, false);
970
971
return agent->is_map_changed();
972
}
973
974
COMMAND_2(agent_set_avoidance_callback, RID, p_agent, Callable, p_callback) {
975
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
976
ERR_FAIL_NULL(agent);
977
978
agent->set_avoidance_callback(p_callback);
979
980
if (agent->get_map()) {
981
if (p_callback.is_valid()) {
982
agent->get_map()->set_agent_as_controlled(agent);
983
} else {
984
agent->get_map()->remove_agent_as_controlled(agent);
985
}
986
}
987
}
988
989
bool GodotNavigationServer2D::agent_has_avoidance_callback(RID p_agent) const {
990
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
991
ERR_FAIL_NULL_V(agent, false);
992
993
return agent->has_avoidance_callback();
994
}
995
996
COMMAND_2(agent_set_avoidance_layers, RID, p_agent, uint32_t, p_layers) {
997
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
998
ERR_FAIL_NULL(agent);
999
agent->set_avoidance_layers(p_layers);
1000
}
1001
1002
uint32_t GodotNavigationServer2D::agent_get_avoidance_layers(RID p_agent) const {
1003
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
1004
ERR_FAIL_NULL_V(agent, 0);
1005
1006
return agent->get_avoidance_layers();
1007
}
1008
1009
COMMAND_2(agent_set_avoidance_mask, RID, p_agent, uint32_t, p_mask) {
1010
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
1011
ERR_FAIL_NULL(agent);
1012
agent->set_avoidance_mask(p_mask);
1013
}
1014
1015
uint32_t GodotNavigationServer2D::agent_get_avoidance_mask(RID p_agent) const {
1016
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
1017
ERR_FAIL_NULL_V(agent, 0);
1018
1019
return agent->get_avoidance_mask();
1020
}
1021
1022
COMMAND_2(agent_set_avoidance_priority, RID, p_agent, real_t, p_priority) {
1023
ERR_FAIL_COND_MSG(p_priority < 0.0, "Avoidance priority must be between 0.0 and 1.0 inclusive.");
1024
ERR_FAIL_COND_MSG(p_priority > 1.0, "Avoidance priority must be between 0.0 and 1.0 inclusive.");
1025
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
1026
ERR_FAIL_NULL(agent);
1027
agent->set_avoidance_priority(p_priority);
1028
}
1029
1030
real_t GodotNavigationServer2D::agent_get_avoidance_priority(RID p_agent) const {
1031
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
1032
ERR_FAIL_NULL_V(agent, 0);
1033
1034
return agent->get_avoidance_priority();
1035
}
1036
1037
COMMAND_2(agent_set_paused, RID, p_agent, bool, p_paused) {
1038
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
1039
ERR_FAIL_NULL(agent);
1040
1041
agent->set_paused(p_paused);
1042
}
1043
1044
bool GodotNavigationServer2D::agent_get_paused(RID p_agent) const {
1045
NavAgent2D *agent = agent_owner.get_or_null(p_agent);
1046
ERR_FAIL_NULL_V(agent, false);
1047
1048
return agent->get_paused();
1049
}
1050
1051
RID GodotNavigationServer2D::obstacle_create() {
1052
MutexLock lock(operations_mutex);
1053
1054
RID rid = obstacle_owner.make_rid();
1055
NavObstacle2D *obstacle = obstacle_owner.get_or_null(rid);
1056
obstacle->set_self(rid);
1057
1058
RID agent_rid = agent_owner.make_rid();
1059
NavAgent2D *agent = agent_owner.get_or_null(agent_rid);
1060
agent->set_self(agent_rid);
1061
1062
obstacle->set_agent(agent);
1063
1064
return rid;
1065
}
1066
1067
COMMAND_2(obstacle_set_avoidance_enabled, RID, p_obstacle, bool, p_enabled) {
1068
NavObstacle2D *obstacle = obstacle_owner.get_or_null(p_obstacle);
1069
ERR_FAIL_NULL(obstacle);
1070
1071
obstacle->set_avoidance_enabled(p_enabled);
1072
}
1073
1074
bool GodotNavigationServer2D::obstacle_get_avoidance_enabled(RID p_obstacle) const {
1075
NavObstacle2D *obstacle = obstacle_owner.get_or_null(p_obstacle);
1076
ERR_FAIL_NULL_V(obstacle, false);
1077
1078
return obstacle->is_avoidance_enabled();
1079
}
1080
1081
COMMAND_2(obstacle_set_map, RID, p_obstacle, RID, p_map) {
1082
NavObstacle2D *obstacle = obstacle_owner.get_or_null(p_obstacle);
1083
ERR_FAIL_NULL(obstacle);
1084
1085
NavMap2D *map = map_owner.get_or_null(p_map);
1086
1087
obstacle->set_map(map);
1088
}
1089
1090
RID GodotNavigationServer2D::obstacle_get_map(RID p_obstacle) const {
1091
NavObstacle2D *obstacle = obstacle_owner.get_or_null(p_obstacle);
1092
ERR_FAIL_NULL_V(obstacle, RID());
1093
if (obstacle->get_map()) {
1094
return obstacle->get_map()->get_self();
1095
}
1096
return RID();
1097
}
1098
1099
COMMAND_2(obstacle_set_paused, RID, p_obstacle, bool, p_paused) {
1100
NavObstacle2D *obstacle = obstacle_owner.get_or_null(p_obstacle);
1101
ERR_FAIL_NULL(obstacle);
1102
1103
obstacle->set_paused(p_paused);
1104
}
1105
1106
bool GodotNavigationServer2D::obstacle_get_paused(RID p_obstacle) const {
1107
NavObstacle2D *obstacle = obstacle_owner.get_or_null(p_obstacle);
1108
ERR_FAIL_NULL_V(obstacle, false);
1109
1110
return obstacle->get_paused();
1111
}
1112
1113
COMMAND_2(obstacle_set_radius, RID, p_obstacle, real_t, p_radius) {
1114
ERR_FAIL_COND_MSG(p_radius < 0.0, "Radius must be positive.");
1115
NavObstacle2D *obstacle = obstacle_owner.get_or_null(p_obstacle);
1116
ERR_FAIL_NULL(obstacle);
1117
1118
obstacle->set_radius(p_radius);
1119
}
1120
1121
real_t GodotNavigationServer2D::obstacle_get_radius(RID p_obstacle) const {
1122
NavObstacle2D *obstacle = obstacle_owner.get_or_null(p_obstacle);
1123
ERR_FAIL_NULL_V(obstacle, 0);
1124
1125
return obstacle->get_radius();
1126
}
1127
1128
COMMAND_2(obstacle_set_velocity, RID, p_obstacle, Vector2, p_velocity) {
1129
NavObstacle2D *obstacle = obstacle_owner.get_or_null(p_obstacle);
1130
ERR_FAIL_NULL(obstacle);
1131
1132
obstacle->set_velocity(p_velocity);
1133
}
1134
1135
Vector2 GodotNavigationServer2D::obstacle_get_velocity(RID p_obstacle) const {
1136
NavObstacle2D *obstacle = obstacle_owner.get_or_null(p_obstacle);
1137
ERR_FAIL_NULL_V(obstacle, Vector2());
1138
1139
return obstacle->get_velocity();
1140
}
1141
1142
COMMAND_2(obstacle_set_position, RID, p_obstacle, Vector2, p_position) {
1143
NavObstacle2D *obstacle = obstacle_owner.get_or_null(p_obstacle);
1144
ERR_FAIL_NULL(obstacle);
1145
obstacle->set_position(p_position);
1146
}
1147
1148
Vector2 GodotNavigationServer2D::obstacle_get_position(RID p_obstacle) const {
1149
NavObstacle2D *obstacle = obstacle_owner.get_or_null(p_obstacle);
1150
ERR_FAIL_NULL_V(obstacle, Vector2());
1151
1152
return obstacle->get_position();
1153
}
1154
1155
COMMAND_2(obstacle_set_avoidance_layers, RID, p_obstacle, uint32_t, p_layers) {
1156
NavObstacle2D *obstacle = obstacle_owner.get_or_null(p_obstacle);
1157
ERR_FAIL_NULL(obstacle);
1158
obstacle->set_avoidance_layers(p_layers);
1159
}
1160
1161
uint32_t GodotNavigationServer2D::obstacle_get_avoidance_layers(RID p_obstacle) const {
1162
NavObstacle2D *obstacle = obstacle_owner.get_or_null(p_obstacle);
1163
ERR_FAIL_NULL_V(obstacle, 0);
1164
1165
return obstacle->get_avoidance_layers();
1166
}
1167
1168
void GodotNavigationServer2D::obstacle_set_vertices(RID p_obstacle, const Vector<Vector2> &p_vertices) {
1169
NavObstacle2D *obstacle = obstacle_owner.get_or_null(p_obstacle);
1170
ERR_FAIL_NULL(obstacle);
1171
obstacle->set_vertices(p_vertices);
1172
}
1173
1174
Vector<Vector2> GodotNavigationServer2D::obstacle_get_vertices(RID p_obstacle) const {
1175
NavObstacle2D *obstacle = obstacle_owner.get_or_null(p_obstacle);
1176
ERR_FAIL_NULL_V(obstacle, Vector<Vector2>());
1177
1178
return obstacle->get_vertices();
1179
}
1180
1181
void GodotNavigationServer2D::flush_queries() {
1182
MutexLock lock(commands_mutex);
1183
MutexLock lock2(operations_mutex);
1184
1185
for (SetCommand2D *command : commands) {
1186
command->exec(this);
1187
memdelete(command);
1188
}
1189
commands.clear();
1190
}
1191
1192
COMMAND_1(free, RID, p_object) {
1193
if (geometry_parser_owner.owns(p_object)) {
1194
RWLockWrite write_lock(geometry_parser_rwlock);
1195
1196
NavMeshGeometryParser2D *parser = geometry_parser_owner.get_or_null(p_object);
1197
ERR_FAIL_NULL(parser);
1198
1199
generator_parsers.erase(parser);
1200
#ifdef CLIPPER2_ENABLED
1201
NavMeshGenerator2D::get_singleton()->set_generator_parsers(generator_parsers);
1202
#endif
1203
geometry_parser_owner.free(parser->self);
1204
return;
1205
}
1206
if (map_owner.owns(p_object)) {
1207
NavMap2D *map = map_owner.get_or_null(p_object);
1208
1209
// Removes any assigned region.
1210
for (NavRegion2D *region : map->get_regions()) {
1211
map->remove_region(region);
1212
region->set_map(nullptr);
1213
}
1214
1215
// Removes any assigned links.
1216
for (NavLink2D *link : map->get_links()) {
1217
map->remove_link(link);
1218
link->set_map(nullptr);
1219
}
1220
1221
// Remove any assigned agent.
1222
for (NavAgent2D *agent : map->get_agents()) {
1223
map->remove_agent(agent);
1224
agent->set_map(nullptr);
1225
}
1226
1227
// Remove any assigned obstacles.
1228
for (NavObstacle2D *obstacle : map->get_obstacles()) {
1229
map->remove_obstacle(obstacle);
1230
obstacle->set_map(nullptr);
1231
}
1232
1233
int map_index = active_maps.find(map);
1234
if (map_index >= 0) {
1235
active_maps.remove_at(map_index);
1236
}
1237
map_owner.free(p_object);
1238
1239
} else if (region_owner.owns(p_object)) {
1240
NavRegion2D *region = region_owner.get_or_null(p_object);
1241
1242
// Removes this region from the map if assigned.
1243
if (region->get_map() != nullptr) {
1244
region->get_map()->remove_region(region);
1245
region->set_map(nullptr);
1246
}
1247
1248
region_owner.free(p_object);
1249
1250
} else if (link_owner.owns(p_object)) {
1251
NavLink2D *link = link_owner.get_or_null(p_object);
1252
1253
// Removes this link from the map if assigned.
1254
if (link->get_map() != nullptr) {
1255
link->get_map()->remove_link(link);
1256
link->set_map(nullptr);
1257
}
1258
1259
link_owner.free(p_object);
1260
1261
} else if (agent_owner.owns(p_object)) {
1262
internal_free_agent(p_object);
1263
1264
} else if (obstacle_owner.owns(p_object)) {
1265
internal_free_obstacle(p_object);
1266
1267
} else {
1268
ERR_PRINT("Attempted to free a NavigationServer RID that did not exist (or was already freed).");
1269
}
1270
}
1271
1272
void GodotNavigationServer2D::internal_free_agent(RID p_object) {
1273
NavAgent2D *agent = agent_owner.get_or_null(p_object);
1274
if (agent) {
1275
if (agent->get_map() != nullptr) {
1276
agent->get_map()->remove_agent(agent);
1277
agent->set_map(nullptr);
1278
}
1279
agent_owner.free(p_object);
1280
}
1281
}
1282
1283
void GodotNavigationServer2D::internal_free_obstacle(RID p_object) {
1284
NavObstacle2D *obstacle = obstacle_owner.get_or_null(p_object);
1285
if (obstacle) {
1286
NavAgent2D *obstacle_agent = obstacle->get_agent();
1287
if (obstacle_agent) {
1288
RID _agent_rid = obstacle_agent->get_self();
1289
internal_free_agent(_agent_rid);
1290
obstacle->set_agent(nullptr);
1291
}
1292
if (obstacle->get_map() != nullptr) {
1293
obstacle->get_map()->remove_obstacle(obstacle);
1294
obstacle->set_map(nullptr);
1295
}
1296
obstacle_owner.free(p_object);
1297
}
1298
}
1299
1300
void GodotNavigationServer2D::process(double p_delta_time) {
1301
// Called for each main loop iteration AFTER node and user script process() and BEFORE RenderingServer sync.
1302
// Will run reliably every rendered frame independent of the physics tick rate.
1303
// Use for things that (only) need to update once per main loop iteration and rendered frame or is visible to the user.
1304
// E.g. (final) sync of objects for this main loop iteration, updating rendered debug visuals, updating debug statistics, ...
1305
1306
sync();
1307
}
1308
1309
void GodotNavigationServer2D::physics_process(double p_delta_time) {
1310
// Called for each physics process step AFTER node and user script physics_process() and BEFORE PhysicsServer sync.
1311
// Will NOT run reliably every rendered frame. If there is no physics step this function will not run.
1312
// Use for physics or step depending calculations and updates where the result affects the next step calculation.
1313
// E.g. anything physics sync related, avoidance simulations, physics space state queries, ...
1314
// If physics process needs to play catchup this function will be called multiple times per frame so it should not hold
1315
// costly updates that are not important outside the stepped calculations to avoid causing a physics performance death spiral.
1316
1317
flush_queries();
1318
1319
if (!active) {
1320
return;
1321
}
1322
1323
int _new_pm_region_count = 0;
1324
int _new_pm_agent_count = 0;
1325
int _new_pm_link_count = 0;
1326
int _new_pm_polygon_count = 0;
1327
int _new_pm_edge_count = 0;
1328
int _new_pm_edge_merge_count = 0;
1329
int _new_pm_edge_connection_count = 0;
1330
int _new_pm_edge_free_count = 0;
1331
int _new_pm_obstacle_count = 0;
1332
1333
MutexLock lock(operations_mutex);
1334
for (uint32_t i(0); i < active_maps.size(); i++) {
1335
active_maps[i]->sync();
1336
active_maps[i]->step(p_delta_time);
1337
active_maps[i]->dispatch_callbacks();
1338
1339
_new_pm_region_count += active_maps[i]->get_pm_region_count();
1340
_new_pm_agent_count += active_maps[i]->get_pm_agent_count();
1341
_new_pm_link_count += active_maps[i]->get_pm_link_count();
1342
_new_pm_polygon_count += active_maps[i]->get_pm_polygon_count();
1343
_new_pm_edge_count += active_maps[i]->get_pm_edge_count();
1344
_new_pm_edge_merge_count += active_maps[i]->get_pm_edge_merge_count();
1345
_new_pm_edge_connection_count += active_maps[i]->get_pm_edge_connection_count();
1346
_new_pm_edge_free_count += active_maps[i]->get_pm_edge_free_count();
1347
_new_pm_obstacle_count += active_maps[i]->get_pm_obstacle_count();
1348
}
1349
1350
pm_region_count = _new_pm_region_count;
1351
pm_agent_count = _new_pm_agent_count;
1352
pm_link_count = _new_pm_link_count;
1353
pm_polygon_count = _new_pm_polygon_count;
1354
pm_edge_count = _new_pm_edge_count;
1355
pm_edge_merge_count = _new_pm_edge_merge_count;
1356
pm_edge_connection_count = _new_pm_edge_connection_count;
1357
pm_edge_free_count = _new_pm_edge_free_count;
1358
pm_obstacle_count = _new_pm_obstacle_count;
1359
}
1360
1361
void GodotNavigationServer2D::set_active(bool p_active) {
1362
MutexLock lock(operations_mutex);
1363
1364
active = p_active;
1365
}
1366
1367
void GodotNavigationServer2D::query_path(const Ref<NavigationPathQueryParameters2D> &p_query_parameters, Ref<NavigationPathQueryResult2D> p_query_result, const Callable &p_callback) {
1368
ERR_FAIL_COND(p_query_parameters.is_null());
1369
ERR_FAIL_COND(p_query_result.is_null());
1370
1371
NavMap2D *map = map_owner.get_or_null(p_query_parameters->get_map());
1372
ERR_FAIL_NULL(map);
1373
1374
NavMeshQueries2D::map_query_path(map, p_query_parameters, p_query_result, p_callback);
1375
}
1376
1377
RID GodotNavigationServer2D::source_geometry_parser_create() {
1378
RWLockWrite write_lock(geometry_parser_rwlock);
1379
1380
RID rid = geometry_parser_owner.make_rid();
1381
1382
NavMeshGeometryParser2D *parser = geometry_parser_owner.get_or_null(rid);
1383
parser->self = rid;
1384
1385
generator_parsers.push_back(parser);
1386
#ifdef CLIPPER2_ENABLED
1387
NavMeshGenerator2D::get_singleton()->set_generator_parsers(generator_parsers);
1388
#endif
1389
return rid;
1390
}
1391
1392
void GodotNavigationServer2D::source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) {
1393
RWLockWrite write_lock(geometry_parser_rwlock);
1394
1395
NavMeshGeometryParser2D *parser = geometry_parser_owner.get_or_null(p_parser);
1396
ERR_FAIL_NULL(parser);
1397
1398
parser->callback = p_callback;
1399
}
1400
1401
int GodotNavigationServer2D::get_process_info(ProcessInfo p_info) const {
1402
switch (p_info) {
1403
case INFO_ACTIVE_MAPS: {
1404
return active_maps.size();
1405
} break;
1406
case INFO_REGION_COUNT: {
1407
return pm_region_count;
1408
} break;
1409
case INFO_AGENT_COUNT: {
1410
return pm_agent_count;
1411
} break;
1412
case INFO_LINK_COUNT: {
1413
return pm_link_count;
1414
} break;
1415
case INFO_POLYGON_COUNT: {
1416
return pm_polygon_count;
1417
} break;
1418
case INFO_EDGE_COUNT: {
1419
return pm_edge_count;
1420
} break;
1421
case INFO_EDGE_MERGE_COUNT: {
1422
return pm_edge_merge_count;
1423
} break;
1424
case INFO_EDGE_CONNECTION_COUNT: {
1425
return pm_edge_connection_count;
1426
} break;
1427
case INFO_EDGE_FREE_COUNT: {
1428
return pm_edge_free_count;
1429
} break;
1430
case INFO_OBSTACLE_COUNT: {
1431
return pm_obstacle_count;
1432
} break;
1433
}
1434
1435
return 0;
1436
}
1437
1438
#undef COMMAND_1
1439
#undef COMMAND_2
1440
1441