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