@@ -243,7 +243,7 @@ void NavMeshGenerator2D::generator_parse_geometry_node(Ref<NavigationPolygon> p_
243243 generator_parse_multimeshinstance2d_node (p_navigation_mesh, p_source_geometry_data, p_node);
244244 generator_parse_polygon2d_node (p_navigation_mesh, p_source_geometry_data, p_node);
245245 generator_parse_staticbody2d_node (p_navigation_mesh, p_source_geometry_data, p_node);
246- generator_parse_tilemap_node (p_navigation_mesh, p_source_geometry_data, p_node);
246+ generator_parse_tile_map_layer_node (p_navigation_mesh, p_source_geometry_data, p_node);
247247 generator_parse_navigationobstacle_node (p_navigation_mesh, p_source_geometry_data, p_node);
248248
249249 generator_rid_rwlock.read_lock ();
@@ -259,6 +259,14 @@ void NavMeshGenerator2D::generator_parse_geometry_node(Ref<NavigationPolygon> p_
259259 for (int i = 0 ; i < p_node->get_child_count (); i++) {
260260 generator_parse_geometry_node (p_navigation_mesh, p_source_geometry_data, p_node->get_child (i), p_recurse_children);
261261 }
262+ } else if (Object::cast_to<TileMap>(p_node)) {
263+ // Special case for TileMap, so that internal layer get parsed even if p_recurse_children is false.
264+ for (int i = 0 ; i < p_node->get_child_count (); i++) {
265+ TileMapLayer *tile_map_layer = Object::cast_to<TileMapLayer>(p_node->get_child (i));
266+ if (tile_map_layer->get_index_in_tile_map () >= 0 ) {
267+ generator_parse_tile_map_layer_node (p_navigation_mesh, p_source_geometry_data, tile_map_layer);
268+ }
269+ }
262270 }
263271}
264272
@@ -580,141 +588,102 @@ void NavMeshGenerator2D::generator_parse_staticbody2d_node(const Ref<NavigationP
580588 }
581589}
582590
583- void NavMeshGenerator2D::generator_parse_tilemap_node (const Ref<NavigationPolygon> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, Node *p_node) {
584- TileMap *tilemap = Object::cast_to<TileMap>(p_node);
585-
586- if (tilemap == nullptr ) {
591+ void NavMeshGenerator2D::generator_parse_tile_map_layer_node (const Ref<NavigationPolygon> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, Node *p_node) {
592+ TileMapLayer *tile_map_layer = Object::cast_to<TileMapLayer>(p_node);
593+ if (tile_map_layer == nullptr ) {
587594 return ;
588595 }
589596
590- NavigationPolygon::ParsedGeometryType parsed_geometry_type = p_navigation_mesh->get_parsed_geometry_type ();
591- uint32_t parsed_collision_mask = p_navigation_mesh->get_parsed_collision_mask ();
592-
593- if (tilemap->get_layers_count () <= 0 ) {
594- return ;
595- }
596-
597- Ref<TileSet> tile_set = tilemap->get_tileset ();
597+ Ref<TileSet> tile_set = tile_map_layer->get_tile_set ();
598598 if (!tile_set.is_valid ()) {
599599 return ;
600600 }
601601
602602 int physics_layers_count = tile_set->get_physics_layers_count ();
603603 int navigation_layers_count = tile_set->get_navigation_layers_count ();
604-
605604 if (physics_layers_count <= 0 && navigation_layers_count <= 0 ) {
606605 return ;
607606 }
608607
609- HashSet<Vector2i> cells_with_navigation_polygon;
610- HashSet<Vector2i> cells_with_collision_polygon;
608+ NavigationPolygon::ParsedGeometryType parsed_geometry_type = p_navigation_mesh->get_parsed_geometry_type ();
609+ uint32_t parsed_collision_mask = p_navigation_mesh->get_parsed_collision_mask ();
610+
611+ const Transform2D tilemap_xform = p_source_geometry_data->root_node_transform * tile_map_layer->get_global_transform ();
611612
612- const Transform2D tilemap_xform = p_source_geometry_data->root_node_transform * tilemap->get_global_transform ();
613+ TypedArray<Vector2i> used_cells = tile_map_layer->get_used_cells ();
614+ for (int used_cell_index = 0 ; used_cell_index < used_cells.size (); used_cell_index++) {
615+ const Vector2i &cell = used_cells[used_cell_index];
613616
614- # ifdef DEBUG_ENABLED
615- int error_print_counter = 0 ;
616- int error_print_max = 10 ;
617- # endif // DEBUG_ENABLED
617+ const TileData *tile_data = tile_map_layer-> get_cell_tile_data (cell);
618+ if (tile_data == nullptr ) {
619+ continue ;
620+ }
618621
619- for (int tilemap_layer = 0 ; tilemap_layer < tilemap->get_layers_count (); tilemap_layer++) {
620- TypedArray<Vector2i> used_cells = tilemap->get_used_cells (tilemap_layer);
622+ // Transform flags.
623+ const int alternative_id = tile_map_layer->get_cell_alternative_tile (cell);
624+ bool flip_h = (alternative_id & TileSetAtlasSource::TRANSFORM_FLIP_H);
625+ bool flip_v = (alternative_id & TileSetAtlasSource::TRANSFORM_FLIP_V);
626+ bool transpose = (alternative_id & TileSetAtlasSource::TRANSFORM_TRANSPOSE);
627+
628+ Transform2D tile_transform;
629+ tile_transform.set_origin (tile_map_layer->map_to_local (cell));
630+
631+ const Transform2D tile_transform_offset = tilemap_xform * tile_transform;
632+
633+ // Parse traversable polygons.
634+ for (int navigation_layer = 0 ; navigation_layer < navigation_layers_count; navigation_layer++) {
635+ Ref<NavigationPolygon> navigation_polygon = tile_data->get_navigation_polygon (navigation_layer, flip_h, flip_v, transpose);
636+ if (navigation_polygon.is_valid ()) {
637+ for (int outline_index = 0 ; outline_index < navigation_polygon->get_outline_count (); outline_index++) {
638+ const Vector<Vector2> &navigation_polygon_outline = navigation_polygon->get_outline (outline_index);
639+ if (navigation_polygon_outline.is_empty ()) {
640+ continue ;
641+ }
621642
622- for ( int used_cell_index = 0 ; used_cell_index < used_cells. size (); used_cell_index++) {
623- const Vector2i &cell = used_cells[used_cell_index] ;
643+ Vector<Vector2> traversable_outline;
644+ traversable_outline. resize (navigation_polygon_outline. size ()) ;
624645
625- const TileData *tile_data = tilemap->get_cell_tile_data (tilemap_layer, cell, false );
626- if (tile_data == nullptr ) {
627- continue ;
628- }
646+ const Vector2 *navigation_polygon_outline_ptr = navigation_polygon_outline.ptr ();
647+ Vector2 *traversable_outline_ptrw = traversable_outline.ptrw ();
629648
630- // Transform flags.
631- const int alternative_id = tilemap->get_cell_alternative_tile (tilemap_layer, cell, false );
632- bool flip_h = (alternative_id & TileSetAtlasSource::TRANSFORM_FLIP_H);
633- bool flip_v = (alternative_id & TileSetAtlasSource::TRANSFORM_FLIP_V);
634- bool transpose = (alternative_id & TileSetAtlasSource::TRANSFORM_TRANSPOSE);
635-
636- Transform2D tile_transform;
637- tile_transform.set_origin (tilemap->map_to_local (cell));
638-
639- const Transform2D tile_transform_offset = tilemap_xform * tile_transform;
640-
641- if (navigation_layers_count > 0 ) {
642- Ref<NavigationPolygon> navigation_polygon = tile_data->get_navigation_polygon (tilemap_layer, flip_h, flip_v, transpose);
643- if (navigation_polygon.is_valid ()) {
644- if (cells_with_navigation_polygon.has (cell)) {
645- #ifdef DEBUG_ENABLED
646- error_print_counter++;
647- if (error_print_counter <= error_print_max) {
648- WARN_PRINT (vformat (" TileMap navigation mesh baking error. The TileMap cell key Vector2i(%s, %s) has navigation mesh from 2 or more different TileMap layers assigned. This can cause unexpected navigation mesh baking results. The duplicated cell data was ignored." , cell.x , cell.y ));
649- }
650- #endif // DEBUG_ENABLED
651- } else {
652- cells_with_navigation_polygon.insert (cell);
653-
654- for (int outline_index = 0 ; outline_index < navigation_polygon->get_outline_count (); outline_index++) {
655- const Vector<Vector2> &navigation_polygon_outline = navigation_polygon->get_outline (outline_index);
656- if (navigation_polygon_outline.size () == 0 ) {
657- continue ;
658- }
659-
660- Vector<Vector2> traversable_outline;
661- traversable_outline.resize (navigation_polygon_outline.size ());
662-
663- const Vector2 *navigation_polygon_outline_ptr = navigation_polygon_outline.ptr ();
664- Vector2 *traversable_outline_ptrw = traversable_outline.ptrw ();
665-
666- for (int traversable_outline_index = 0 ; traversable_outline_index < traversable_outline.size (); traversable_outline_index++) {
667- traversable_outline_ptrw[traversable_outline_index] = tile_transform_offset.xform (navigation_polygon_outline_ptr[traversable_outline_index]);
668- }
669-
670- p_source_geometry_data->_add_traversable_outline (traversable_outline);
671- }
649+ for (int traversable_outline_index = 0 ; traversable_outline_index < traversable_outline.size (); traversable_outline_index++) {
650+ traversable_outline_ptrw[traversable_outline_index] = tile_transform_offset.xform (navigation_polygon_outline_ptr[traversable_outline_index]);
672651 }
652+
653+ p_source_geometry_data->_add_traversable_outline (traversable_outline);
673654 }
674655 }
656+ }
675657
676- if (physics_layers_count > 0 && (parsed_geometry_type == NavigationPolygon::PARSED_GEOMETRY_STATIC_COLLIDERS || parsed_geometry_type == NavigationPolygon::PARSED_GEOMETRY_BOTH) && (tile_set->get_physics_layer_collision_layer (tilemap_layer) & parsed_collision_mask)) {
677- if (cells_with_collision_polygon.has (cell)) {
678- #ifdef DEBUG_ENABLED
679- error_print_counter++;
680- if (error_print_counter <= error_print_max) {
681- WARN_PRINT (vformat (" TileMap navigation mesh baking error. The cell key Vector2i(%s, %s) has collision polygons from 2 or more different TileMap layers assigned that all match the parsed collision mask. This can cause unexpected navigation mesh baking results. The duplicated cell data was ignored." , cell.x , cell.y ));
658+ // Parse obstacles.
659+ for (int physics_layer = 0 ; physics_layer < physics_layers_count; physics_layer++) {
660+ if ((parsed_geometry_type == NavigationPolygon::PARSED_GEOMETRY_STATIC_COLLIDERS || parsed_geometry_type == NavigationPolygon::PARSED_GEOMETRY_BOTH) &&
661+ (tile_set->get_physics_layer_collision_layer (physics_layer) & parsed_collision_mask)) {
662+ for (int collision_polygon_index = 0 ; collision_polygon_index < tile_data->get_collision_polygons_count (physics_layer); collision_polygon_index++) {
663+ PackedVector2Array collision_polygon_points = tile_data->get_collision_polygon_points (physics_layer, collision_polygon_index);
664+ if (collision_polygon_points.is_empty ()) {
665+ continue ;
682666 }
683- #endif // DEBUG_ENABLED
684- } else {
685- cells_with_collision_polygon.insert (cell);
686-
687- for (int collision_polygon_index = 0 ; collision_polygon_index < tile_data->get_collision_polygons_count (tilemap_layer); collision_polygon_index++) {
688- PackedVector2Array collision_polygon_points = tile_data->get_collision_polygon_points (tilemap_layer, collision_polygon_index);
689- if (collision_polygon_points.size () == 0 ) {
690- continue ;
691- }
692-
693- if (flip_h || flip_v || transpose) {
694- collision_polygon_points = TileData::get_transformed_vertices (collision_polygon_points, flip_h, flip_v, transpose);
695- }
696667
697- Vector<Vector2> obstruction_outline;
698- obstruction_outline.resize (collision_polygon_points.size ());
668+ if (flip_h || flip_v || transpose) {
669+ collision_polygon_points = TileData::get_transformed_vertices (collision_polygon_points, flip_h, flip_v, transpose);
670+ }
699671
700- const Vector2 *collision_polygon_points_ptr = collision_polygon_points. ptr () ;
701- Vector2 *obstruction_outline_ptrw = obstruction_outline.ptrw ( );
672+ Vector< Vector2> obstruction_outline ;
673+ obstruction_outline.resize (collision_polygon_points. size () );
702674
703- for (int obstruction_outline_index = 0 ; obstruction_outline_index < obstruction_outline.size (); obstruction_outline_index++) {
704- obstruction_outline_ptrw[obstruction_outline_index] = tile_transform_offset.xform (collision_polygon_points_ptr[obstruction_outline_index]);
705- }
675+ const Vector2 *collision_polygon_points_ptr = collision_polygon_points.ptr ();
676+ Vector2 *obstruction_outline_ptrw = obstruction_outline.ptrw ();
706677
707- p_source_geometry_data->_add_obstruction_outline (obstruction_outline);
678+ for (int obstruction_outline_index = 0 ; obstruction_outline_index < obstruction_outline.size (); obstruction_outline_index++) {
679+ obstruction_outline_ptrw[obstruction_outline_index] = tile_transform_offset.xform (collision_polygon_points_ptr[obstruction_outline_index]);
708680 }
681+
682+ p_source_geometry_data->_add_obstruction_outline (obstruction_outline);
709683 }
710684 }
711685 }
712686 }
713- #ifdef DEBUG_ENABLED
714- if (error_print_counter > error_print_max) {
715- ERR_PRINT (vformat (" TileMap navigation mesh baking error. A total of %s cells with navigation or collision polygons from 2 or more different TileMap layers overlap. This can cause unexpected navigation mesh baking results. The duplicated cell data was ignored." , error_print_counter));
716- }
717- #endif // DEBUG_ENABLED
718687}
719688
720689void NavMeshGenerator2D::generator_parse_navigationobstacle_node (const Ref<NavigationPolygon> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, Node *p_node) {
0 commit comments