Skip to content

Commit 7ae2c0a

Browse files
committed
Add MultiNodeEdit support for NavigationRegion3D
Adds MultiNodeEdit support for NavigationRegion3D.
1 parent cc9761c commit 7ae2c0a

8 files changed

+297
-72
lines changed

modules/navigation_3d/3d/godot_navigation_server_3d.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,6 +1219,14 @@ bool GodotNavigationServer3D::is_baking_navigation_mesh(Ref<NavigationMesh> p_na
12191219
return NavMeshGenerator3D::get_singleton()->is_baking(p_navigation_mesh);
12201220
}
12211221

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+
12221230
COMMAND_1(free, RID, p_object) {
12231231
if (map_owner.owns(p_object)) {
12241232
NavMap3D *map = map_owner.get_or_null(p_object);

modules/navigation_3d/3d/godot_navigation_server_3d.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ class GodotNavigationServer3D : public NavigationServer3D {
272272
virtual void bake_from_source_geometry_data(const Ref<NavigationMesh> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data, const Callable &p_callback = Callable()) override;
273273
virtual void bake_from_source_geometry_data_async(const Ref<NavigationMesh> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data, const Callable &p_callback = Callable()) override;
274274
virtual bool is_baking_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh) const override;
275+
virtual String get_baking_navigation_mesh_state_msg(Ref<NavigationMesh> p_navigation_mesh) const override;
275276

276277
virtual RID source_geometry_parser_create() override;
277278
virtual void source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) override;

modules/navigation_3d/3d/nav_mesh_generator_3d.cpp

Lines changed: 55 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,26 @@ RWLock NavMeshGenerator3D::generator_parsers_rwlock;
4545
bool NavMeshGenerator3D::use_threads = true;
4646
bool NavMeshGenerator3D::baking_use_multiple_threads = true;
4747
bool NavMeshGenerator3D::baking_use_high_priority_threads = true;
48-
HashSet<Ref<NavigationMesh>> NavMeshGenerator3D::baking_navmeshes;
48+
HashMap<Ref<NavigationMesh>, NavMeshGenerator3D::NavMeshGeneratorTask3D *> NavMeshGenerator3D::baking_navmeshes;
4949
HashMap<WorkerThreadPool::TaskID, NavMeshGenerator3D::NavMeshGeneratorTask3D *> NavMeshGenerator3D::generator_tasks;
5050
LocalVector<NavMeshGeometryParser3D *> NavMeshGenerator3D::generator_parsers;
5151

52+
static const char *_navmesh_bake_state_msgs[(size_t)NavMeshGenerator3D::NavMeshBakeState::BAKE_STATE_MAX] = {
53+
"",
54+
"Setting up configuration...",
55+
"Calculating grid size...",
56+
"Creating heightfield...",
57+
"Marking walkable triangles...",
58+
"Constructing compact heightfield...", // step 5
59+
"Eroding walkable area...",
60+
"Sample partitioning...",
61+
"Creating contours...",
62+
"Creating polymesh...",
63+
"Converting to native navigation mesh...", // step 10
64+
"Baking cleanup...",
65+
"Baking finished.",
66+
};
67+
5268
NavMeshGenerator3D *NavMeshGenerator3D::get_singleton() {
5369
return singleton;
5470
}
@@ -158,10 +174,15 @@ void NavMeshGenerator3D::bake_from_source_geometry_data(Ref<NavigationMesh> p_na
158174
ERR_FAIL_MSG("NavigationMesh is already baking. Wait for current bake to finish.");
159175
}
160176
baking_navmesh_mutex.lock();
161-
baking_navmeshes.insert(p_navigation_mesh);
177+
NavMeshGeneratorTask3D generator_task;
178+
baking_navmeshes.insert(p_navigation_mesh, &generator_task);
162179
baking_navmesh_mutex.unlock();
163180

164-
generator_bake_from_source_geometry_data(p_navigation_mesh, p_source_geometry_data);
181+
generator_task.navigation_mesh = p_navigation_mesh;
182+
generator_task.source_geometry_data = p_source_geometry_data;
183+
generator_task.status = NavMeshGeneratorTask3D::TaskStatus::BAKING_STARTED;
184+
185+
generator_bake_from_source_geometry_data(&generator_task);
165186

166187
baking_navmesh_mutex.lock();
167188
baking_navmeshes.erase(p_navigation_mesh);
@@ -197,16 +218,16 @@ void NavMeshGenerator3D::bake_from_source_geometry_data_async(Ref<NavigationMesh
197218
return;
198219
}
199220
baking_navmesh_mutex.lock();
200-
baking_navmeshes.insert(p_navigation_mesh);
221+
NavMeshGeneratorTask3D *generator_task = memnew(NavMeshGeneratorTask3D);
222+
baking_navmeshes.insert(p_navigation_mesh, generator_task);
201223
baking_navmesh_mutex.unlock();
202224

203-
MutexLock generator_task_lock(generator_task_mutex);
204-
NavMeshGeneratorTask3D *generator_task = memnew(NavMeshGeneratorTask3D);
205225
generator_task->navigation_mesh = p_navigation_mesh;
206226
generator_task->source_geometry_data = p_source_geometry_data;
207227
generator_task->callback = p_callback;
208228
generator_task->status = NavMeshGeneratorTask3D::TaskStatus::BAKING_STARTED;
209229
generator_task->thread_task_id = WorkerThreadPool::get_singleton()->add_native_task(&NavMeshGenerator3D::generator_thread_bake, generator_task, NavMeshGenerator3D::baking_use_high_priority_threads, SNAME("NavMeshGeneratorBake3D"));
230+
MutexLock generator_task_lock(generator_task_mutex);
210231
generator_tasks.insert(generator_task->thread_task_id, generator_task);
211232
}
212233

@@ -215,10 +236,21 @@ bool NavMeshGenerator3D::is_baking(Ref<NavigationMesh> p_navigation_mesh) {
215236
return baking_navmeshes.has(p_navigation_mesh);
216237
}
217238

239+
String NavMeshGenerator3D::get_baking_state_msg(Ref<NavigationMesh> p_navigation_mesh) {
240+
String bake_state_msg;
241+
MutexLock baking_navmesh_lock(baking_navmesh_mutex);
242+
if (baking_navmeshes.has(p_navigation_mesh)) {
243+
bake_state_msg = _navmesh_bake_state_msgs[baking_navmeshes[p_navigation_mesh]->bake_state];
244+
} else {
245+
bake_state_msg = _navmesh_bake_state_msgs[NavMeshBakeState::BAKE_STATE_NONE];
246+
}
247+
return bake_state_msg;
248+
}
249+
218250
void NavMeshGenerator3D::generator_thread_bake(void *p_arg) {
219251
NavMeshGeneratorTask3D *generator_task = static_cast<NavMeshGeneratorTask3D *>(p_arg);
220252

221-
generator_bake_from_source_geometry_data(generator_task->navigation_mesh, generator_task->source_geometry_data);
253+
generator_bake_from_source_geometry_data(generator_task);
222254

223255
generator_task->status = NavMeshGeneratorTask3D::TaskStatus::BAKING_FINISHED;
224256
}
@@ -269,7 +301,10 @@ void NavMeshGenerator3D::generator_parse_source_geometry_data(const Ref<Navigati
269301
}
270302
}
271303

272-
void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref<NavigationMesh> p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data) {
304+
void NavMeshGenerator3D::generator_bake_from_source_geometry_data(NavMeshGeneratorTask3D *p_generator_task) {
305+
Ref<NavigationMesh> p_navigation_mesh = p_generator_task->navigation_mesh;
306+
const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data = p_generator_task->source_geometry_data;
307+
273308
if (p_navigation_mesh.is_null() || p_source_geometry_data.is_null()) {
274309
return;
275310
}
@@ -294,10 +329,7 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref<Navigation
294329
rcPolyMeshDetail *detail_mesh = nullptr;
295330
rcContext ctx;
296331

297-
// added to keep track of steps, no functionality right now
298-
String bake_state = "";
299-
300-
bake_state = "Setting up Configuration..."; // step #1
332+
p_generator_task->bake_state = NavMeshBakeState::BAKE_STATE_CONFIGURATION; // step #1
301333

302334
const float *verts = source_geometry_vertices.ptr();
303335
const int nverts = source_geometry_vertices.size() / 3;
@@ -373,7 +405,7 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref<Navigation
373405
cfg.bmax[2] = cfg.bmin[2] + baking_aabb.size[2];
374406
}
375407

376-
bake_state = "Calculating grid size..."; // step #2
408+
p_generator_task->bake_state = NavMeshBakeState::BAKE_STATE_CALC_GRID_SIZE; // step #2
377409
rcCalcGridSize(cfg.bmin, cfg.bmax, cfg.cs, &cfg.width, &cfg.height);
378410

379411
// ~30000000 seems to be around sweetspot where Editor baking breaks
@@ -387,13 +419,13 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref<Navigation
387419
return;
388420
}
389421

390-
bake_state = "Creating heightfield..."; // step #3
422+
p_generator_task->bake_state = NavMeshBakeState::BAKE_STATE_CREATE_HEIGHTFIELD; // step #3
391423
hf = rcAllocHeightfield();
392424

393425
ERR_FAIL_NULL(hf);
394426
ERR_FAIL_COND(!rcCreateHeightfield(&ctx, *hf, cfg.width, cfg.height, cfg.bmin, cfg.bmax, cfg.cs, cfg.ch));
395427

396-
bake_state = "Marking walkable triangles..."; // step #4
428+
p_generator_task->bake_state = NavMeshBakeState::BAKE_STATE_MARK_WALKABLE_TRIANGLES; // step #4
397429
{
398430
Vector<unsigned char> tri_areas;
399431
tri_areas.resize(ntris);
@@ -416,7 +448,7 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref<Navigation
416448
rcFilterWalkableLowHeightSpans(&ctx, cfg.walkableHeight, *hf);
417449
}
418450

419-
bake_state = "Constructing compact heightfield..."; // step #5
451+
p_generator_task->bake_state = NavMeshBakeState::BAKE_STATE_CONSTRUCT_COMPACT_HEIGHTFIELD; // step #5
420452

421453
chf = rcAllocCompactHeightfield();
422454

@@ -443,7 +475,7 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref<Navigation
443475
}
444476
}
445477

446-
bake_state = "Eroding walkable area..."; // step #6
478+
p_generator_task->bake_state = NavMeshBakeState::BAKE_STATE_ERODE_WALKABLE_AREA; // step #6
447479

448480
ERR_FAIL_COND(!rcErodeWalkableArea(&ctx, cfg.walkableRadius, *chf));
449481

@@ -464,7 +496,7 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref<Navigation
464496
}
465497
}
466498

467-
bake_state = "Partitioning..."; // step #7
499+
p_generator_task->bake_state = NavMeshBakeState::BAKE_STATE_SAMPLE_PARTITIONING; // step #7
468500

469501
if (p_navigation_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_WATERSHED) {
470502
ERR_FAIL_COND(!rcBuildDistanceField(&ctx, *chf));
@@ -475,14 +507,14 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref<Navigation
475507
ERR_FAIL_COND(!rcBuildLayerRegions(&ctx, *chf, cfg.borderSize, cfg.minRegionArea));
476508
}
477509

478-
bake_state = "Creating contours..."; // step #8
510+
p_generator_task->bake_state = NavMeshBakeState::BAKE_STATE_CREATING_CONTOURS; // step #8
479511

480512
cset = rcAllocContourSet();
481513

482514
ERR_FAIL_NULL(cset);
483515
ERR_FAIL_COND(!rcBuildContours(&ctx, *chf, cfg.maxSimplificationError, cfg.maxEdgeLen, *cset));
484516

485-
bake_state = "Creating polymesh..."; // step #9
517+
p_generator_task->bake_state = NavMeshBakeState::BAKE_STATE_CREATING_POLYMESH; // step #9
486518

487519
poly_mesh = rcAllocPolyMesh();
488520
ERR_FAIL_NULL(poly_mesh);
@@ -497,7 +529,7 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref<Navigation
497529
rcFreeContourSet(cset);
498530
cset = nullptr;
499531

500-
bake_state = "Converting to native navigation mesh..."; // step #10
532+
p_generator_task->bake_state = NavMeshBakeState::BAKE_STATE_CONVERTING_NATIVE_NAVMESH; // step #10
501533

502534
Vector<Vector3> nav_vertices;
503535
Vector<Vector<int>> nav_polygons;
@@ -544,14 +576,14 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref<Navigation
544576

545577
p_navigation_mesh->set_data(nav_vertices, nav_polygons);
546578

547-
bake_state = "Cleanup..."; // step #11
579+
p_generator_task->bake_state = NavMeshBakeState::BAKE_STATE_BAKE_CLEANUP; // step #11
548580

549581
rcFreePolyMesh(poly_mesh);
550582
poly_mesh = nullptr;
551583
rcFreePolyMeshDetail(detail_mesh);
552584
detail_mesh = nullptr;
553585

554-
bake_state = "Baking finished."; // step #12
586+
p_generator_task->bake_state = NavMeshBakeState::BAKE_STATE_BAKE_FINISHED; // step #12
555587
}
556588

557589
bool NavMeshGenerator3D::generator_emit_callback(const Callable &p_callback) {

modules/navigation_3d/3d/nav_mesh_generator_3d.h

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,25 @@ class NavMeshGenerator3D : public Object {
5252
static bool baking_use_multiple_threads;
5353
static bool baking_use_high_priority_threads;
5454

55+
public:
56+
enum NavMeshBakeState {
57+
BAKE_STATE_NONE,
58+
BAKE_STATE_CONFIGURATION,
59+
BAKE_STATE_CALC_GRID_SIZE,
60+
BAKE_STATE_CREATE_HEIGHTFIELD,
61+
BAKE_STATE_MARK_WALKABLE_TRIANGLES,
62+
BAKE_STATE_CONSTRUCT_COMPACT_HEIGHTFIELD,
63+
BAKE_STATE_ERODE_WALKABLE_AREA,
64+
BAKE_STATE_SAMPLE_PARTITIONING,
65+
BAKE_STATE_CREATING_CONTOURS,
66+
BAKE_STATE_CREATING_POLYMESH,
67+
BAKE_STATE_CONVERTING_NATIVE_NAVMESH,
68+
BAKE_STATE_BAKE_CLEANUP,
69+
BAKE_STATE_BAKE_FINISHED,
70+
BAKE_STATE_MAX,
71+
};
72+
73+
private:
5574
struct NavMeshGeneratorTask3D {
5675
enum TaskStatus {
5776
BAKING_STARTED,
@@ -66,17 +85,19 @@ class NavMeshGenerator3D : public Object {
6685
Callable callback;
6786
WorkerThreadPool::TaskID thread_task_id = WorkerThreadPool::INVALID_TASK_ID;
6887
NavMeshGeneratorTask3D::TaskStatus status = NavMeshGeneratorTask3D::TaskStatus::BAKING_STARTED;
88+
89+
NavMeshBakeState bake_state = NavMeshBakeState::BAKE_STATE_NONE;
6990
};
7091

7192
static HashMap<WorkerThreadPool::TaskID, NavMeshGeneratorTask3D *> generator_tasks;
7293

7394
static void generator_thread_bake(void *p_arg);
7495

75-
static HashSet<Ref<NavigationMesh>> baking_navmeshes;
96+
static HashMap<Ref<NavigationMesh>, NavMeshGeneratorTask3D *> baking_navmeshes;
7697

7798
static void generator_parse_geometry_node(const Ref<NavigationMesh> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, Node *p_node, bool p_recurse_children);
7899
static void generator_parse_source_geometry_data(const Ref<NavigationMesh> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, Node *p_root_node);
79-
static void generator_bake_from_source_geometry_data(Ref<NavigationMesh> p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data);
100+
static void generator_bake_from_source_geometry_data(NavMeshGeneratorTask3D *p_generator_task);
80101

81102
static bool generator_emit_callback(const Callable &p_callback);
82103

@@ -93,6 +114,7 @@ class NavMeshGenerator3D : public Object {
93114
static void bake_from_source_geometry_data(Ref<NavigationMesh> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, const Callable &p_callback = Callable());
94115
static void bake_from_source_geometry_data_async(Ref<NavigationMesh> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, const Callable &p_callback = Callable());
95116
static bool is_baking(Ref<NavigationMesh> p_navigation_mesh);
117+
static String get_baking_state_msg(Ref<NavigationMesh> p_navigation_mesh);
96118

97119
NavMeshGenerator3D();
98120
~NavMeshGenerator3D();

0 commit comments

Comments
 (0)