You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-04 12:00:25 +00:00
Fix TileMapLayer navmesh baking
This commit is contained in:
@@ -243,7 +243,7 @@ void NavMeshGenerator2D::generator_parse_geometry_node(Ref<NavigationPolygon> p_
|
|||||||
generator_parse_multimeshinstance2d_node(p_navigation_mesh, p_source_geometry_data, p_node);
|
generator_parse_multimeshinstance2d_node(p_navigation_mesh, p_source_geometry_data, p_node);
|
||||||
generator_parse_polygon2d_node(p_navigation_mesh, p_source_geometry_data, p_node);
|
generator_parse_polygon2d_node(p_navigation_mesh, p_source_geometry_data, p_node);
|
||||||
generator_parse_staticbody2d_node(p_navigation_mesh, p_source_geometry_data, p_node);
|
generator_parse_staticbody2d_node(p_navigation_mesh, p_source_geometry_data, p_node);
|
||||||
generator_parse_tilemap_node(p_navigation_mesh, p_source_geometry_data, p_node);
|
generator_parse_tile_map_layer_node(p_navigation_mesh, p_source_geometry_data, p_node);
|
||||||
generator_parse_navigationobstacle_node(p_navigation_mesh, p_source_geometry_data, p_node);
|
generator_parse_navigationobstacle_node(p_navigation_mesh, p_source_geometry_data, p_node);
|
||||||
|
|
||||||
generator_rid_rwlock.read_lock();
|
generator_rid_rwlock.read_lock();
|
||||||
@@ -259,6 +259,14 @@ void NavMeshGenerator2D::generator_parse_geometry_node(Ref<NavigationPolygon> p_
|
|||||||
for (int i = 0; i < p_node->get_child_count(); i++) {
|
for (int i = 0; i < p_node->get_child_count(); i++) {
|
||||||
generator_parse_geometry_node(p_navigation_mesh, p_source_geometry_data, p_node->get_child(i), p_recurse_children);
|
generator_parse_geometry_node(p_navigation_mesh, p_source_geometry_data, p_node->get_child(i), p_recurse_children);
|
||||||
}
|
}
|
||||||
|
} else if (Object::cast_to<TileMap>(p_node)) {
|
||||||
|
// Special case for TileMap, so that internal layer get parsed even if p_recurse_children is false.
|
||||||
|
for (int i = 0; i < p_node->get_child_count(); i++) {
|
||||||
|
TileMapLayer *tile_map_layer = Object::cast_to<TileMapLayer>(p_node->get_child(i));
|
||||||
|
if (tile_map_layer->get_index_in_tile_map() >= 0) {
|
||||||
|
generator_parse_tile_map_layer_node(p_navigation_mesh, p_source_geometry_data, tile_map_layer);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -580,80 +588,55 @@ void NavMeshGenerator2D::generator_parse_staticbody2d_node(const Ref<NavigationP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NavMeshGenerator2D::generator_parse_tilemap_node(const Ref<NavigationPolygon> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, Node *p_node) {
|
void NavMeshGenerator2D::generator_parse_tile_map_layer_node(const Ref<NavigationPolygon> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, Node *p_node) {
|
||||||
TileMap *tilemap = Object::cast_to<TileMap>(p_node);
|
TileMapLayer *tile_map_layer = Object::cast_to<TileMapLayer>(p_node);
|
||||||
|
if (tile_map_layer == nullptr) {
|
||||||
if (tilemap == nullptr) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NavigationPolygon::ParsedGeometryType parsed_geometry_type = p_navigation_mesh->get_parsed_geometry_type();
|
Ref<TileSet> tile_set = tile_map_layer->get_tile_set();
|
||||||
uint32_t parsed_collision_mask = p_navigation_mesh->get_parsed_collision_mask();
|
|
||||||
|
|
||||||
if (tilemap->get_layers_count() <= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<TileSet> tile_set = tilemap->get_tileset();
|
|
||||||
if (!tile_set.is_valid()) {
|
if (!tile_set.is_valid()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int physics_layers_count = tile_set->get_physics_layers_count();
|
int physics_layers_count = tile_set->get_physics_layers_count();
|
||||||
int navigation_layers_count = tile_set->get_navigation_layers_count();
|
int navigation_layers_count = tile_set->get_navigation_layers_count();
|
||||||
|
|
||||||
if (physics_layers_count <= 0 && navigation_layers_count <= 0) {
|
if (physics_layers_count <= 0 && navigation_layers_count <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HashSet<Vector2i> cells_with_navigation_polygon;
|
NavigationPolygon::ParsedGeometryType parsed_geometry_type = p_navigation_mesh->get_parsed_geometry_type();
|
||||||
HashSet<Vector2i> cells_with_collision_polygon;
|
uint32_t parsed_collision_mask = p_navigation_mesh->get_parsed_collision_mask();
|
||||||
|
|
||||||
const Transform2D tilemap_xform = p_source_geometry_data->root_node_transform * tilemap->get_global_transform();
|
const Transform2D tilemap_xform = p_source_geometry_data->root_node_transform * tile_map_layer->get_global_transform();
|
||||||
|
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
int error_print_counter = 0;
|
|
||||||
int error_print_max = 10;
|
|
||||||
#endif // DEBUG_ENABLED
|
|
||||||
|
|
||||||
for (int tilemap_layer = 0; tilemap_layer < tilemap->get_layers_count(); tilemap_layer++) {
|
|
||||||
TypedArray<Vector2i> used_cells = tilemap->get_used_cells(tilemap_layer);
|
|
||||||
|
|
||||||
|
TypedArray<Vector2i> used_cells = tile_map_layer->get_used_cells();
|
||||||
for (int used_cell_index = 0; used_cell_index < used_cells.size(); used_cell_index++) {
|
for (int used_cell_index = 0; used_cell_index < used_cells.size(); used_cell_index++) {
|
||||||
const Vector2i &cell = used_cells[used_cell_index];
|
const Vector2i &cell = used_cells[used_cell_index];
|
||||||
|
|
||||||
const TileData *tile_data = tilemap->get_cell_tile_data(tilemap_layer, cell, false);
|
const TileData *tile_data = tile_map_layer->get_cell_tile_data(cell);
|
||||||
if (tile_data == nullptr) {
|
if (tile_data == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform flags.
|
// Transform flags.
|
||||||
const int alternative_id = tilemap->get_cell_alternative_tile(tilemap_layer, cell, false);
|
const int alternative_id = tile_map_layer->get_cell_alternative_tile(cell);
|
||||||
bool flip_h = (alternative_id & TileSetAtlasSource::TRANSFORM_FLIP_H);
|
bool flip_h = (alternative_id & TileSetAtlasSource::TRANSFORM_FLIP_H);
|
||||||
bool flip_v = (alternative_id & TileSetAtlasSource::TRANSFORM_FLIP_V);
|
bool flip_v = (alternative_id & TileSetAtlasSource::TRANSFORM_FLIP_V);
|
||||||
bool transpose = (alternative_id & TileSetAtlasSource::TRANSFORM_TRANSPOSE);
|
bool transpose = (alternative_id & TileSetAtlasSource::TRANSFORM_TRANSPOSE);
|
||||||
|
|
||||||
Transform2D tile_transform;
|
Transform2D tile_transform;
|
||||||
tile_transform.set_origin(tilemap->map_to_local(cell));
|
tile_transform.set_origin(tile_map_layer->map_to_local(cell));
|
||||||
|
|
||||||
const Transform2D tile_transform_offset = tilemap_xform * tile_transform;
|
const Transform2D tile_transform_offset = tilemap_xform * tile_transform;
|
||||||
|
|
||||||
if (navigation_layers_count > 0) {
|
// Parse traversable polygons.
|
||||||
Ref<NavigationPolygon> navigation_polygon = tile_data->get_navigation_polygon(tilemap_layer, flip_h, flip_v, transpose);
|
for (int navigation_layer = 0; navigation_layer < navigation_layers_count; navigation_layer++) {
|
||||||
|
Ref<NavigationPolygon> navigation_polygon = tile_data->get_navigation_polygon(navigation_layer, flip_h, flip_v, transpose);
|
||||||
if (navigation_polygon.is_valid()) {
|
if (navigation_polygon.is_valid()) {
|
||||||
if (cells_with_navigation_polygon.has(cell)) {
|
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
error_print_counter++;
|
|
||||||
if (error_print_counter <= error_print_max) {
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
#endif // DEBUG_ENABLED
|
|
||||||
} else {
|
|
||||||
cells_with_navigation_polygon.insert(cell);
|
|
||||||
|
|
||||||
for (int outline_index = 0; outline_index < navigation_polygon->get_outline_count(); outline_index++) {
|
for (int outline_index = 0; outline_index < navigation_polygon->get_outline_count(); outline_index++) {
|
||||||
const Vector<Vector2> &navigation_polygon_outline = navigation_polygon->get_outline(outline_index);
|
const Vector<Vector2> &navigation_polygon_outline = navigation_polygon->get_outline(outline_index);
|
||||||
if (navigation_polygon_outline.size() == 0) {
|
if (navigation_polygon_outline.is_empty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -671,22 +654,14 @@ void NavMeshGenerator2D::generator_parse_tilemap_node(const Ref<NavigationPolygo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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)) {
|
// Parse obstacles.
|
||||||
if (cells_with_collision_polygon.has(cell)) {
|
for (int physics_layer = 0; physics_layer < physics_layers_count; physics_layer++) {
|
||||||
#ifdef DEBUG_ENABLED
|
if ((parsed_geometry_type == NavigationPolygon::PARSED_GEOMETRY_STATIC_COLLIDERS || parsed_geometry_type == NavigationPolygon::PARSED_GEOMETRY_BOTH) &&
|
||||||
error_print_counter++;
|
(tile_set->get_physics_layer_collision_layer(physics_layer) & parsed_collision_mask)) {
|
||||||
if (error_print_counter <= error_print_max) {
|
for (int collision_polygon_index = 0; collision_polygon_index < tile_data->get_collision_polygons_count(physics_layer); collision_polygon_index++) {
|
||||||
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));
|
PackedVector2Array collision_polygon_points = tile_data->get_collision_polygon_points(physics_layer, collision_polygon_index);
|
||||||
}
|
if (collision_polygon_points.is_empty()) {
|
||||||
#endif // DEBUG_ENABLED
|
|
||||||
} else {
|
|
||||||
cells_with_collision_polygon.insert(cell);
|
|
||||||
|
|
||||||
for (int collision_polygon_index = 0; collision_polygon_index < tile_data->get_collision_polygons_count(tilemap_layer); collision_polygon_index++) {
|
|
||||||
PackedVector2Array collision_polygon_points = tile_data->get_collision_polygon_points(tilemap_layer, collision_polygon_index);
|
|
||||||
if (collision_polygon_points.size() == 0) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -710,12 +685,6 @@ void NavMeshGenerator2D::generator_parse_tilemap_node(const Ref<NavigationPolygo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
if (error_print_counter > error_print_max) {
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
#endif // DEBUG_ENABLED
|
|
||||||
}
|
|
||||||
|
|
||||||
void NavMeshGenerator2D::generator_parse_navigationobstacle_node(const Ref<NavigationPolygon> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, Node *p_node) {
|
void NavMeshGenerator2D::generator_parse_navigationobstacle_node(const Ref<NavigationPolygon> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, Node *p_node) {
|
||||||
NavigationObstacle2D *obstacle = Object::cast_to<NavigationObstacle2D>(p_node);
|
NavigationObstacle2D *obstacle = Object::cast_to<NavigationObstacle2D>(p_node);
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ class NavMeshGenerator2D : public Object {
|
|||||||
static void generator_parse_multimeshinstance2d_node(const Ref<NavigationPolygon> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, Node *p_node);
|
static void generator_parse_multimeshinstance2d_node(const Ref<NavigationPolygon> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, Node *p_node);
|
||||||
static void generator_parse_polygon2d_node(const Ref<NavigationPolygon> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, Node *p_node);
|
static void generator_parse_polygon2d_node(const Ref<NavigationPolygon> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, Node *p_node);
|
||||||
static void generator_parse_staticbody2d_node(const Ref<NavigationPolygon> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, Node *p_node);
|
static void generator_parse_staticbody2d_node(const Ref<NavigationPolygon> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, Node *p_node);
|
||||||
static void generator_parse_tilemap_node(const Ref<NavigationPolygon> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, Node *p_node);
|
static void generator_parse_tile_map_layer_node(const Ref<NavigationPolygon> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, Node *p_node);
|
||||||
static void generator_parse_navigationobstacle_node(const Ref<NavigationPolygon> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, Node *p_node);
|
static void generator_parse_navigationobstacle_node(const Ref<NavigationPolygon> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, Node *p_node);
|
||||||
|
|
||||||
static bool generator_emit_callback(const Callable &p_callback);
|
static bool generator_emit_callback(const Callable &p_callback);
|
||||||
|
|||||||
Reference in New Issue
Block a user