@@ -362,6 +362,134 @@ bool GridMap::get_center_z() const {
362362 return center_z;
363363}
364364
365+ void GridMap::set_debug_octant_color (const Color &p_color) {
366+ #ifdef DEBUG_ENABLED
367+ if (debug_octant_color == p_color) {
368+ return ;
369+ }
370+
371+ debug_octant_color = p_color;
372+
373+ if (debug_octant_line_material.is_valid ()) {
374+ debug_octant_line_material->set_albedo (debug_octant_color);
375+ }
376+ #endif
377+ }
378+
379+ Color GridMap::get_debug_octant_color () const {
380+ return debug_octant_color;
381+ }
382+
383+ #ifdef DEBUG_ENABLED
384+ void GridMap::_debug_update () {
385+ if (debug_dirty || !is_inside_tree ()) {
386+ return ;
387+ }
388+ debug_dirty = true ;
389+
390+ callable_mp (this , &GridMap::_debug_update_octants).call_deferred ();
391+ }
392+
393+ void GridMap::_debug_update_octants () {
394+ debug_dirty = false ;
395+
396+ if (!debug_show_octants) {
397+ _debug_clear_octants ();
398+ return ;
399+ }
400+
401+ if (debug_octant_line_material.is_null ()) {
402+ debug_octant_line_material.instantiate ();
403+ debug_octant_line_material->set_shading_mode (StandardMaterial3D::SHADING_MODE_UNSHADED );
404+ debug_octant_line_material->set_transparency (StandardMaterial3D::TRANSPARENCY_ALPHA );
405+ debug_octant_line_material->set_flag (StandardMaterial3D::FLAG_DISABLE_FOG , true );
406+ debug_octant_line_material->set_albedo (debug_octant_color);
407+ }
408+
409+ Array debug_mesh_arrays = _build_octant_line_mesh_arrays ();
410+
411+ if (debug_octant_line_mesh_rid.is_null ()) {
412+ debug_octant_line_mesh_rid = RS::get_singleton ()->mesh_create ();
413+ }
414+ RS::get_singleton ()->mesh_clear (debug_octant_line_mesh_rid);
415+ RS::get_singleton ()->mesh_add_surface_from_arrays (debug_octant_line_mesh_rid, RSE ::PRIMITIVE_LINES , debug_mesh_arrays);
416+ RS::get_singleton ()->mesh_surface_set_material (debug_octant_line_mesh_rid, 0 , debug_octant_line_material->get_rid ());
417+
418+ RID debug_scenario = get_world_3d ()->get_scenario ();
419+ const Transform3D &gridmap_xform = get_global_transform ();
420+
421+ for (const KeyValue<OctantKey, Octant *> &ele : octant_map) {
422+ OctantKey octant_key = ele.key ;
423+ HashMap<OctantKey, OctantDebug *, OctantKey>::Iterator E = debug_octant_map.find (octant_key);
424+ if (!E) {
425+ OctantDebug *octant_debug = memnew (OctantDebug);
426+
427+ RID debug_octant_line_instance_rid = RS::get_singleton ()->instance_create ();
428+
429+ RS::get_singleton ()->instance_set_base (debug_octant_line_instance_rid, debug_octant_line_mesh_rid);
430+ RS::get_singleton ()->instance_set_scenario (debug_octant_line_instance_rid, debug_scenario);
431+
432+ octant_debug->debug_line_instance_rid = debug_octant_line_instance_rid;
433+
434+ E = debug_octant_map.insert (octant_key, octant_debug);
435+ }
436+
437+ OctantDebug &octant_debug = *E->value ;
438+ const Transform3D octant_transform = gridmap_xform * (Transform3D (Basis (), Vector3 (octant_key.x , octant_key.y , octant_key.z ) * octant_size * cell_size));
439+
440+ RS::get_singleton ()->instance_set_scenario (octant_debug.debug_line_instance_rid , debug_scenario);
441+ RS::get_singleton ()->instance_set_transform (octant_debug.debug_line_instance_rid , octant_transform);
442+ RS::get_singleton ()->instance_set_visible (octant_debug.debug_line_instance_rid , is_visible_in_tree ());
443+ }
444+ }
445+
446+ void GridMap::_debug_clear_octants () {
447+ for (const KeyValue<OctantKey, Octant *> &ele : octant_map) {
448+ OctantKey octant_key = ele.key ;
449+ HashMap<OctantKey, OctantDebug *, OctantKey>::Iterator E = debug_octant_map.find (octant_key);
450+ if (E) {
451+ OctantDebug &octant_debug = *E->value ;
452+
453+ if (octant_debug.debug_line_mesh_rid .is_valid ()) {
454+ RS::get_singleton ()->free_rid (octant_debug.debug_line_mesh_rid );
455+ octant_debug.debug_line_mesh_rid = RID ();
456+ }
457+ if (octant_debug.debug_line_instance_rid .is_valid ()) {
458+ RS::get_singleton ()->free_rid (octant_debug.debug_line_instance_rid );
459+ octant_debug.debug_line_instance_rid = RID ();
460+ }
461+
462+ memdelete (&octant_debug);
463+ }
464+ }
465+
466+ debug_octant_map.clear ();
467+ }
468+
469+ Array GridMap::_build_octant_line_mesh_arrays () const {
470+ AABB aabb;
471+ aabb.size = octant_size * cell_size;
472+
473+ Vector<Vector3> vertex_array;
474+ vertex_array.resize (24 );
475+ Vector3 *vertex_array_ptrw = vertex_array.ptrw ();
476+ int vertex_index = 0 ;
477+
478+ for (int i = 0 ; i < 12 ; i++) {
479+ Vector3 a, b;
480+ aabb.get_edge (i, a, b);
481+ vertex_array_ptrw[vertex_index++] = a;
482+ vertex_array_ptrw[vertex_index++] = b;
483+ }
484+
485+ Array mesh_arrays;
486+ mesh_arrays.resize (Mesh::ARRAY_MAX );
487+ mesh_arrays[Mesh::ARRAY_VERTEX ] = vertex_array;
488+
489+ return mesh_arrays;
490+ }
491+ #endif // DEBUG_ENABLED
492+
365493void GridMap::set_cell_item (const Vector3i &p_position, int p_item, int p_rot) {
366494 if (baked_meshes.size () && !recreating_octants) {
367495 // if you set a cell item, baked meshes go good bye
@@ -991,6 +1119,8 @@ void GridMap::_octant_exit_world(const OctantKey &p_key) {
9911119 g.navigation_debug_edge_connections_mesh .unref ();
9921120 }
9931121 }
1122+
1123+ _debug_clear_octants ();
9941124#endif // DEBUG_ENABLED
9951125}
9961126
@@ -1040,9 +1170,11 @@ void GridMap::_octant_clean_up(const OctantKey &p_key) {
10401170 g.navigation_debug_edge_connections_mesh .unref ();
10411171 }
10421172 }
1173+
1174+ _debug_clear_octants ();
10431175#endif // DEBUG_ENABLED
10441176
1045- // erase multimeshes
1177+ // Erase multimeshes.
10461178
10471179 for (int i = 0 ; i < g.multimesh_instances .size (); i++) {
10481180 RS::get_singleton ()->free_rid (g.multimesh_instances [i].instance );
@@ -1072,15 +1204,23 @@ void GridMap::_notification(int p_what) {
10721204 _update_navigation_debug_edge_connections ();
10731205 }
10741206#endif // defined(DEBUG_ENABLED) && !defined(NAVIGATION_3D_DISABLED)
1207+
10751208 _update_visibility ();
1209+ _debug_update ();
1210+ } break ;
1211+
1212+ #ifdef DEBUG_ENABLED
1213+ case NOTIFICATION_EXIT_TREE : {
1214+ _debug_clear_octants ();
10761215 } break ;
1216+ #endif
10771217
10781218 case NOTIFICATION_TRANSFORM_CHANGED : {
10791219 Transform3D new_xform = get_global_transform ();
10801220 if (new_xform == last_transform) {
10811221 break ;
10821222 }
1083- // update run
1223+
10841224 for (const KeyValue<OctantKey, Octant *> &E : octant_map) {
10851225 _octant_transform (E.key );
10861226 }
@@ -1090,16 +1230,24 @@ void GridMap::_notification(int p_what) {
10901230 for (int i = 0 ; i < baked_meshes.size (); i++) {
10911231 RS::get_singleton ()->instance_set_transform (baked_meshes[i].instance , get_global_transform ());
10921232 }
1233+
1234+ #ifdef DEBUG_ENABLED
1235+ for (const KeyValue<OctantKey, OctantDebug *> &E : debug_octant_map) {
1236+ OctantKey octant_key = E.key ;
1237+ OctantDebug &octant_debug = *E.value ;
1238+ if (octant_debug.debug_line_instance_rid .is_valid ()) {
1239+ const Transform3D octant_transform = new_xform * (Transform3D (Basis (), Vector3 (octant_key.x , octant_key.y , octant_key.z ) * octant_size * cell_size));
1240+ RS::get_singleton ()->instance_set_transform (octant_debug.debug_line_instance_rid , octant_transform);
1241+ }
1242+ }
1243+ #endif
10931244 } break ;
10941245
10951246 case NOTIFICATION_EXIT_WORLD : {
10961247 for (const KeyValue<OctantKey, Octant *> &E : octant_map) {
10971248 _octant_exit_world (E.key );
10981249 }
10991250
1100- // _queue_octants_dirty(MAP_DIRTY_INSTANCES|MAP_DIRTY_TRANSFORMS);
1101- // _update_octants_callback();
1102- // _update_area_instances();
11031251 for (int i = 0 ; i < baked_meshes.size (); i++) {
11041252 RS::get_singleton ()->instance_set_scenario (baked_meshes[i].instance , RID ());
11051253 }
@@ -1127,6 +1275,15 @@ void GridMap::_update_visibility() {
11271275 for (int i = 0 ; i < baked_meshes.size (); i++) {
11281276 RS::get_singleton ()->instance_set_visible (baked_meshes[i].instance , is_visible_in_tree ());
11291277 }
1278+
1279+ #ifdef DEBUG_ENABLED
1280+ for (const KeyValue<OctantKey, OctantDebug *> &E : debug_octant_map) {
1281+ OctantDebug &octant_debug = *E.value ;
1282+ if (octant_debug.debug_line_instance_rid .is_valid ()) {
1283+ RS::get_singleton ()->instance_set_visible (octant_debug.debug_line_instance_rid , is_visible_in_tree ());
1284+ }
1285+ }
1286+ #endif
11301287}
11311288
11321289void GridMap::_queue_octants_dirty () {
@@ -1140,12 +1297,15 @@ void GridMap::_queue_octants_dirty() {
11401297
11411298void GridMap::_recreate_octant_data () {
11421299 recreating_octants = true ;
1300+
11431301 HashMap<IndexKey, Cell, IndexKey> cell_copy (cell_map);
11441302 _clear_internal ();
11451303 for (const KeyValue<IndexKey, Cell> &E : cell_copy) {
11461304 set_cell_item (Vector3i (E.key ), E.value .item , E.value .rot );
11471305 }
1306+
11481307 recreating_octants = false ;
1308+ _debug_update ();
11491309}
11501310
11511311void GridMap::_clear_internal () {
@@ -1160,6 +1320,10 @@ void GridMap::_clear_internal() {
11601320
11611321 octant_map.clear ();
11621322 cell_map.clear ();
1323+ #ifdef DEBUG_ENABLED
1324+ _debug_clear_octants ();
1325+ _debug_update ();
1326+ #endif
11631327}
11641328
11651329void GridMap::clear () {
@@ -1194,6 +1358,8 @@ void GridMap::_update_octants_callback() {
11941358
11951359 _update_visibility ();
11961360 awaiting_update = false ;
1361+
1362+ _debug_update_octants ();
11971363}
11981364
11991365void GridMap::_bind_methods () {
@@ -1284,6 +1450,12 @@ void GridMap::_bind_methods() {
12841450 ClassDB::bind_method (D_METHOD (" clear_baked_meshes" ), &GridMap::clear_baked_meshes);
12851451 ClassDB::bind_method (D_METHOD (" make_baked_meshes" , " gen_lightmap_uv" , " lightmap_uv_texel_size" ), &GridMap::make_baked_meshes, DEFVAL (false ), DEFVAL (0.1 ));
12861452
1453+ ClassDB::bind_method (D_METHOD (" set_debug_show_octants" , " enable" ), &GridMap::set_debug_show_octants);
1454+ ClassDB::bind_method (D_METHOD (" get_debug_show_octants" ), &GridMap::get_debug_show_octants);
1455+
1456+ ClassDB::bind_method (D_METHOD (" set_debug_octant_color" , " color" ), &GridMap::set_debug_octant_color);
1457+ ClassDB::bind_method (D_METHOD (" get_debug_octant_color" ), &GridMap::get_debug_octant_color);
1458+
12871459 ADD_PROPERTY (PropertyInfo (Variant::OBJECT , " mesh_library" , PROPERTY_HINT_RESOURCE_TYPE , MeshLibrary::get_class_static ()), " set_mesh_library" , " get_mesh_library" );
12881460#ifndef PHYSICS_3D_DISABLED
12891461 ADD_PROPERTY (PropertyInfo (Variant::OBJECT , " physics_material" , PROPERTY_HINT_RESOURCE_TYPE , PhysicsMaterial::get_class_static ()), " set_physics_material" , " get_physics_material" );
@@ -1304,6 +1476,9 @@ void GridMap::_bind_methods() {
13041476#endif // PHYSICS_3D_DISABLED
13051477 ADD_GROUP (" Navigation" , " " );
13061478 ADD_PROPERTY (PropertyInfo (Variant::BOOL , " bake_navigation" ), " set_bake_navigation" , " is_baking_navigation" );
1479+ ADD_GROUP (" Debug" , " " );
1480+ ADD_PROPERTY (PropertyInfo (Variant::BOOL , " debug_show_octants" ), " set_debug_show_octants" , " get_debug_show_octants" );
1481+ ADD_PROPERTY (PropertyInfo (Variant::COLOR , " debug_octant_color" ), " set_debug_octant_color" , " get_debug_octant_color" );
13071482
13081483 BIND_CONSTANT (INVALID_CELL_ITEM );
13091484
@@ -1689,6 +1864,21 @@ RID GridMap::get_bake_mesh_instance(int p_idx) {
16891864 return baked_meshes[p_idx].instance ;
16901865}
16911866
1867+ void GridMap::set_debug_show_octants (bool p_enable) {
1868+ #ifdef DEBUG_ENABLED
1869+ if (debug_show_octants == p_enable) {
1870+ return ;
1871+ }
1872+
1873+ debug_show_octants = p_enable;
1874+ _debug_update ();
1875+ #endif
1876+ }
1877+
1878+ bool GridMap::get_debug_show_octants () const {
1879+ return debug_show_octants;
1880+ }
1881+
16921882GridMap::GridMap () {
16931883 set_notify_transform (true );
16941884#if defined(DEBUG_ENABLED) && !defined(NAVIGATION_3D_DISABLED)
@@ -1857,10 +2047,16 @@ void GridMap::_navigation_map_changed(RID p_map) {
18572047
18582048GridMap::~GridMap () {
18592049 clear ();
1860- #if defined(DEBUG_ENABLED) && !defined(NAVIGATION_3D_DISABLED)
2050+
2051+ #ifdef DEBUG_ENABLED
2052+ _debug_clear_octants ();
2053+
2054+ #ifndef NAVIGATION_3D_DISABLED
18612055 NavigationServer3D::get_singleton ()->disconnect (" map_changed" , callable_mp (this , &GridMap::_navigation_map_changed));
18622056 NavigationServer3D::get_singleton ()->disconnect (" navigation_debug_changed" , callable_mp (this , &GridMap::_update_navigation_debug_edge_connections));
1863- #endif // defined(DEBUG_ENABLED) && !defined(NAVIGATION_3D_DISABLED)
2057+ #endif // NAVIGATION_3D_DISABLED
2058+
2059+ #endif // DEBUG_ENABLED
18642060}
18652061
18662062#if defined(DEBUG_ENABLED) && !defined(NAVIGATION_3D_DISABLED)
0 commit comments