feat: updated engine version to 4.4-rc1

This commit is contained in:
Sara 2025-02-23 14:38:14 +01:00
parent ee00efde1f
commit 21ba8e33af
5459 changed files with 1128836 additions and 198305 deletions

View file

@ -33,12 +33,12 @@
#include "core/io/marshalls.h"
#include "scene/2d/tile_map.h"
#include "scene/gui/control.h"
#include "scene/resources/2d/navigation_mesh_source_geometry_data_2d.h"
#include "scene/resources/world_2d.h"
#include "servers/navigation_server_2d.h"
#ifdef DEBUG_ENABLED
#include "servers/navigation_server_3d.h"
#endif // DEBUG_ENABLED
Callable TileMapLayer::_navmesh_source_geometry_parsing_callback;
RID TileMapLayer::_navmesh_source_geometry_parser;
#ifdef DEBUG_ENABLED
/////////////////////////////// Debug //////////////////////////////////////////
@ -313,7 +313,7 @@ void TileMapLayer::_rendering_update(bool p_force_cleanup) {
rs->canvas_item_set_material(ci, mat->get_rid());
}
rs->canvas_item_set_parent(ci, get_canvas_item());
rs->canvas_item_set_use_parent_material(ci, !mat.is_valid());
rs->canvas_item_set_use_parent_material(ci, mat.is_null());
Transform2D xform(0, rendering_quadrant->canvas_items_position);
rs->canvas_item_set_transform(ci, xform);
@ -411,7 +411,7 @@ void TileMapLayer::_rendering_update(bool p_force_cleanup) {
}
// ----------- Occluders processing -----------
if (forced_cleanup) {
if (forced_cleanup || !occlusion_enabled) {
// Clean everything.
for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
_rendering_occluders_clear_cell(kv.value);
@ -433,7 +433,7 @@ void TileMapLayer::_rendering_update(bool p_force_cleanup) {
// -----------
// Mark the rendering state as up to date.
_rendering_was_cleaned_up = forced_cleanup;
_rendering_was_cleaned_up = forced_cleanup || !occlusion_enabled;
}
void TileMapLayer::_rendering_notification(int p_what) {
@ -443,13 +443,15 @@ void TileMapLayer::_rendering_notification(int p_what) {
Transform2D tilemap_xform = get_global_transform();
for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
const CellData &cell_data = kv.value;
for (const RID &occluder : cell_data.occluders) {
if (occluder.is_null()) {
continue;
for (const LocalVector<RID> &polygons : cell_data.occluders) {
for (const RID &rid : polygons) {
if (rid.is_null()) {
continue;
}
Transform2D xform(0, tile_set->map_to_local(kv.key));
rs->canvas_light_occluder_attach_to_canvas(rid, get_canvas());
rs->canvas_light_occluder_set_transform(rid, tilemap_xform * xform);
}
Transform2D xform(0, tile_set->map_to_local(kv.key));
rs->canvas_light_occluder_attach_to_canvas(occluder, get_canvas());
rs->canvas_light_occluder_set_transform(occluder, tilemap_xform * xform);
}
}
}
@ -557,8 +559,10 @@ void TileMapLayer::_rendering_occluders_clear_cell(CellData &r_cell_data) {
RenderingServer *rs = RenderingServer::get_singleton();
// Free the occluders.
for (const RID &rid : r_cell_data.occluders) {
rs->free(rid);
for (const LocalVector<RID> &polygons : r_cell_data.occluders) {
for (const RID &rid : polygons) {
rs->free(rid);
}
}
r_cell_data.occluders.clear();
}
@ -566,11 +570,12 @@ void TileMapLayer::_rendering_occluders_clear_cell(CellData &r_cell_data) {
void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) {
RenderingServer *rs = RenderingServer::get_singleton();
// Free unused occluders then resize the occluders array.
// Free unused occluders then resize the occluder array.
for (uint32_t i = tile_set->get_occlusion_layers_count(); i < r_cell_data.occluders.size(); i++) {
RID occluder_id = r_cell_data.occluders[i];
if (occluder_id.is_valid()) {
rs->free(occluder_id);
for (const RID &occluder_id : r_cell_data.occluders[i]) {
if (occluder_id.is_valid()) {
rs->free(occluder_id);
}
}
}
r_cell_data.occluders.resize(tile_set->get_occlusion_layers_count());
@ -598,30 +603,42 @@ void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) {
// Create, update or clear occluders.
bool needs_set_not_interpolated = is_inside_tree() && get_tree()->is_physics_interpolation_enabled() && !is_physics_interpolated();
for (uint32_t occlusion_layer_index = 0; occlusion_layer_index < r_cell_data.occluders.size(); occlusion_layer_index++) {
Ref<OccluderPolygon2D> occluder_polygon = tile_data->get_occluder(occlusion_layer_index);
LocalVector<RID> &occluders = r_cell_data.occluders[occlusion_layer_index];
RID &occluder = r_cell_data.occluders[occlusion_layer_index];
if (occluder_polygon.is_valid()) {
// Create or update occluder.
Transform2D xform;
xform.set_origin(tile_set->map_to_local(r_cell_data.coords));
if (!occluder.is_valid()) {
occluder = rs->canvas_light_occluder_create();
if (needs_set_not_interpolated) {
rs->canvas_light_occluder_set_interpolated(occluder, false);
}
// Free unused occluders then resize the occluders array.
for (uint32_t i = tile_data->get_occluder_polygons_count(occlusion_layer_index); i < r_cell_data.occluders[occlusion_layer_index].size(); i++) {
RID occluder_id = occluders[i];
if (occluder_id.is_valid()) {
rs->free(occluder_id);
}
rs->canvas_light_occluder_set_transform(occluder, get_global_transform() * xform);
rs->canvas_light_occluder_set_polygon(occluder, tile_data->get_occluder(occlusion_layer_index, flip_h, flip_v, transpose)->get_rid());
rs->canvas_light_occluder_attach_to_canvas(occluder, get_canvas());
rs->canvas_light_occluder_set_light_mask(occluder, tile_set->get_occlusion_layer_light_mask(occlusion_layer_index));
rs->canvas_light_occluder_set_as_sdf_collision(occluder, tile_set->get_occlusion_layer_sdf_collision(occlusion_layer_index));
} else {
// Clear occluder.
if (occluder.is_valid()) {
rs->free(occluder);
occluder = RID();
}
occluders.resize(tile_data->get_occluder_polygons_count(occlusion_layer_index));
for (uint32_t occlusion_polygon_index = 0; occlusion_polygon_index < occluders.size(); occlusion_polygon_index++) {
RID &occluder = occluders[occlusion_polygon_index];
Ref<OccluderPolygon2D> occluder_polygon = tile_data->get_occluder_polygon(occlusion_layer_index, occlusion_polygon_index);
if (occluder_polygon.is_valid()) {
// Create or update occluder.
Transform2D xform;
xform.set_origin(tile_set->map_to_local(r_cell_data.coords));
if (!occluder.is_valid()) {
occluder = rs->canvas_light_occluder_create();
if (needs_set_not_interpolated) {
rs->canvas_light_occluder_set_interpolated(occluder, false);
}
}
rs->canvas_light_occluder_set_transform(occluder, get_global_transform() * xform);
rs->canvas_light_occluder_set_polygon(occluder, tile_data->get_occluder_polygon(occlusion_layer_index, occlusion_polygon_index, flip_h, flip_v, transpose)->get_rid());
rs->canvas_light_occluder_attach_to_canvas(occluder, get_canvas());
rs->canvas_light_occluder_set_light_mask(occluder, tile_set->get_occlusion_layer_light_mask(occlusion_layer_index));
rs->canvas_light_occluder_set_as_sdf_collision(occluder, tile_set->get_occlusion_layer_sdf_collision(occlusion_layer_index));
} else {
// Clear occluder.
if (occluder.is_valid()) {
rs->free(occluder);
occluder = RID();
}
}
}
}
@ -655,7 +672,7 @@ void TileMapLayer::_rendering_draw_cell_debug(const RID &p_canvas_item, const Ve
TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
if (atlas_source) {
Vector2i grid_size = atlas_source->get_atlas_grid_size();
if (!atlas_source->get_runtime_texture().is_valid() || c.get_atlas_coords().x >= grid_size.x || c.get_atlas_coords().y >= grid_size.y) {
if (atlas_source->get_runtime_texture().is_null() || c.get_atlas_coords().x >= grid_size.x || c.get_atlas_coords().y >= grid_size.y) {
// Generate a random color from the hashed values of the tiles.
Array to_hash;
to_hash.push_back(c.source_id);
@ -806,6 +823,7 @@ void TileMapLayer::_physics_update_cell(CellData &r_cell_data) {
Ref<PhysicsMaterial> physics_material = tile_set->get_physics_layer_physics_material(tile_set_physics_layer);
uint32_t physics_layer = tile_set->get_physics_layer_collision_layer(tile_set_physics_layer);
uint32_t physics_mask = tile_set->get_physics_layer_collision_mask(tile_set_physics_layer);
real_t physics_priority = tile_set->get_physics_layer_collision_priority(tile_set_physics_layer);
RID body = r_cell_data.bodies[tile_set_physics_layer];
if (tile_data->get_collision_polygons_count(tile_set_physics_layer) == 0) {
@ -832,11 +850,12 @@ void TileMapLayer::_physics_update_cell(CellData &r_cell_data) {
ps->body_attach_object_instance_id(body, tile_map_node ? tile_map_node->get_instance_id() : get_instance_id());
ps->body_set_collision_layer(body, physics_layer);
ps->body_set_collision_mask(body, physics_mask);
ps->body_set_collision_priority(body, physics_priority);
ps->body_set_pickable(body, false);
ps->body_set_state(body, PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, tile_data->get_constant_linear_velocity(tile_set_physics_layer));
ps->body_set_state(body, PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, tile_data->get_constant_angular_velocity(tile_set_physics_layer));
if (!physics_material.is_valid()) {
if (physics_material.is_null()) {
ps->body_set_param(body, PhysicsServer2D::BODY_PARAM_BOUNCE, 0);
ps->body_set_param(body, PhysicsServer2D::BODY_PARAM_FRICTION, 1);
} else {
@ -929,7 +948,7 @@ void TileMapLayer::_physics_draw_cell_debug(const RID &p_canvas_item, const Vect
rs->canvas_item_add_set_transform(p_canvas_item, Transform2D());
}
}
};
}
#endif // DEBUG_ENABLED
/////////////////////////////// Navigation //////////////////////////////////////
@ -957,7 +976,7 @@ void TileMapLayer::_navigation_update(bool p_force_cleanup) {
// Create a dedicated map for each layer.
RID new_layer_map = ns->map_create();
// Set the default NavigationPolygon cell_size on the new map as a mismatch causes an error.
ns->map_set_cell_size(new_layer_map, 1.0);
ns->map_set_cell_size(new_layer_map, NavigationDefaults2D::navmesh_cell_size);
ns->map_set_active(new_layer_map, true);
navigation_map_override = new_layer_map;
}
@ -1313,7 +1332,7 @@ void TileMapLayer::_scenes_draw_cell_debug(const RID &p_canvas_item, const Vecto
TileSetScenesCollectionSource *scenes_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source);
if (scenes_collection_source) {
if (!scenes_collection_source->get_scene_tile_scene(c.alternative_tile).is_valid() || scenes_collection_source->get_scene_tile_display_placeholder(c.alternative_tile)) {
if (scenes_collection_source->get_scene_tile_scene(c.alternative_tile).is_null() || scenes_collection_source->get_scene_tile_display_placeholder(c.alternative_tile)) {
// Generate a random color from the hashed values of the tiles.
Array to_hash;
to_hash.push_back(c.source_id);
@ -1394,7 +1413,7 @@ void TileMapLayer::_build_runtime_update_tile_data_for_cell(CellData &r_cell_dat
tile_map_node->GDVIRTUAL_CALL(_tile_data_runtime_update, layer_index_in_tile_map_node, r_cell_data.coords, tile_data_runtime_use);
if (p_auto_add_to_dirty_list) {
if (p_auto_add_to_dirty_list && !r_cell_data.dirty_list_element.in_list()) {
dirty.cell_list.add(&r_cell_data.dirty_list_element);
}
}
@ -1409,7 +1428,7 @@ void TileMapLayer::_build_runtime_update_tile_data_for_cell(CellData &r_cell_dat
GDVIRTUAL_CALL(_tile_data_runtime_update, r_cell_data.coords, tile_data_runtime_use);
if (p_auto_add_to_dirty_list) {
if (p_auto_add_to_dirty_list && !r_cell_data.dirty_list_element.in_list()) {
dirty.cell_list.add(&r_cell_data.dirty_list_element);
}
}
@ -1441,6 +1460,24 @@ void TileMapLayer::_clear_runtime_update_tile_data_for_cell(CellData &r_cell_dat
}
}
void TileMapLayer::_update_cells_callback(bool p_force_cleanup) {
if (!GDVIRTUAL_IS_OVERRIDDEN(_update_cells)) {
return;
}
// Check if we should cleanup everything.
bool forced_cleanup = p_force_cleanup || !enabled || tile_set.is_null() || !is_visible_in_tree();
// List all the dirty cell's positions to notify script of cell updates.
TypedArray<Vector2i> dirty_cell_positions;
for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) {
CellData &cell_data = *cell_data_list_element->self();
dirty_cell_positions.push_back(cell_data.coords);
}
GDVIRTUAL_CALL(_update_cells, dirty_cell_positions, forced_cleanup);
}
TileSet::TerrainsPattern TileMapLayer::_get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, const RBSet<TerrainConstraint> &p_constraints, TileSet::TerrainsPattern p_current_pattern) const {
if (tile_set.is_null()) {
return TileSet::TerrainsPattern();
@ -1654,6 +1691,10 @@ void TileMapLayer::_internal_update(bool p_force_cleanup) {
// This may add cells to the dirty list if a runtime modification has been notified.
_build_runtime_update_tile_data(p_force_cleanup);
// Callback for implementing custom subsystems.
// This may add to the dirty list if some cells are changed inside _update_cells.
_update_cells_callback(p_force_cleanup);
// Update all subsystems.
_rendering_update(p_force_cleanup);
_physics_update(p_force_cleanup);
@ -1709,11 +1750,13 @@ void TileMapLayer::_physics_interpolated_changed() {
}
for (const KeyValue<Vector2i, CellData> &E : tile_map_layer_data) {
for (const RID &occluder : E.value.occluders) {
if (occluder.is_valid()) {
rs->canvas_light_occluder_set_interpolated(occluder, interpolated);
if (needs_reset) {
rs->canvas_light_occluder_reset_physics_interpolation(occluder);
for (const LocalVector<RID> &polygons : E.value.occluders) {
for (const RID &occluder_id : polygons) {
if (occluder_id.is_valid()) {
rs->canvas_light_occluder_set_interpolated(occluder_id, interpolated);
if (needs_reset) {
rs->canvas_light_occluder_reset_physics_interpolation(occluder_id);
}
}
}
}
@ -1773,6 +1816,10 @@ void TileMapLayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_cell_alternative_tile", "coords"), &TileMapLayer::get_cell_alternative_tile);
ClassDB::bind_method(D_METHOD("get_cell_tile_data", "coords"), &TileMapLayer::get_cell_tile_data);
ClassDB::bind_method(D_METHOD("is_cell_flipped_h", "coords"), &TileMapLayer::is_cell_flipped_h);
ClassDB::bind_method(D_METHOD("is_cell_flipped_v", "coords"), &TileMapLayer::is_cell_flipped_v);
ClassDB::bind_method(D_METHOD("is_cell_transposed", "coords"), &TileMapLayer::is_cell_transposed);
ClassDB::bind_method(D_METHOD("get_used_cells"), &TileMapLayer::get_used_cells);
ClassDB::bind_method(D_METHOD("get_used_cells_by_id", "source_id", "atlas_coords", "alternative_tile"), &TileMapLayer::get_used_cells_by_id, DEFVAL(TileSet::INVALID_SOURCE), DEFVAL(TileSetSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetSource::INVALID_TILE_ALTERNATIVE));
ClassDB::bind_method(D_METHOD("get_used_rect"), &TileMapLayer::get_used_rect);
@ -1791,7 +1838,7 @@ void TileMapLayer::_bind_methods() {
// --- Runtime ---
ClassDB::bind_method(D_METHOD("update_internals"), &TileMapLayer::update_internals);
ClassDB::bind_method(D_METHOD("notify_runtime_tile_data_update"), &TileMapLayer::notify_runtime_tile_data_update, DEFVAL(-1));
ClassDB::bind_method(D_METHOD("notify_runtime_tile_data_update"), &TileMapLayer::notify_runtime_tile_data_update);
// --- Shortcuts to methods defined in TileSet ---
ClassDB::bind_method(D_METHOD("map_pattern", "position_in_tilemap", "coords_in_pattern", "pattern"), &TileMapLayer::map_pattern);
@ -1824,6 +1871,9 @@ void TileMapLayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_collision_visibility_mode", "visibility_mode"), &TileMapLayer::set_collision_visibility_mode);
ClassDB::bind_method(D_METHOD("get_collision_visibility_mode"), &TileMapLayer::get_collision_visibility_mode);
ClassDB::bind_method(D_METHOD("set_occlusion_enabled", "enabled"), &TileMapLayer::set_occlusion_enabled);
ClassDB::bind_method(D_METHOD("is_occlusion_enabled"), &TileMapLayer::is_occlusion_enabled);
ClassDB::bind_method(D_METHOD("set_navigation_enabled", "enabled"), &TileMapLayer::set_navigation_enabled);
ClassDB::bind_method(D_METHOD("is_navigation_enabled"), &TileMapLayer::is_navigation_enabled);
ClassDB::bind_method(D_METHOD("set_navigation_map", "map"), &TileMapLayer::set_navigation_map);
@ -1833,12 +1883,14 @@ void TileMapLayer::_bind_methods() {
GDVIRTUAL_BIND(_use_tile_data_runtime_update, "coords");
GDVIRTUAL_BIND(_tile_data_runtime_update, "coords", "tile_data");
GDVIRTUAL_BIND(_update_cells, "coords", "forced_cleanup");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "tile_map_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_tile_map_data_from_array", "get_tile_map_data_as_array");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "tile_set", PROPERTY_HINT_RESOURCE_TYPE, "TileSet"), "set_tile_set", "get_tile_set");
ADD_GROUP("Rendering", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "occlusion_enabled"), "set_occlusion_enabled", "is_occlusion_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "y_sort_origin"), "set_y_sort_origin", "get_y_sort_origin");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "x_draw_order_reversed"), "set_x_draw_order_reversed", "is_x_draw_order_reversed");
ADD_PROPERTY(PropertyInfo(Variant::INT, "rendering_quadrant_size"), "set_rendering_quadrant_size", "get_rendering_quadrant_size");
@ -2490,6 +2542,18 @@ Rect2i TileMapLayer::get_used_rect() const {
return used_rect_cache;
}
bool TileMapLayer::is_cell_flipped_h(const Vector2i &p_coords) const {
return get_cell_alternative_tile(p_coords) & TileSetAtlasSource::TRANSFORM_FLIP_H;
}
bool TileMapLayer::is_cell_flipped_v(const Vector2i &p_coords) const {
return get_cell_alternative_tile(p_coords) & TileSetAtlasSource::TRANSFORM_FLIP_V;
}
bool TileMapLayer::is_cell_transposed(const Vector2i &p_coords) const {
return get_cell_alternative_tile(p_coords) & TileSetAtlasSource::TRANSFORM_TRANSPOSE;
}
Ref<TileMapPattern> TileMapLayer::get_pattern(TypedArray<Vector2i> p_coords_array) {
ERR_FAIL_COND_V(tile_set.is_null(), nullptr);
@ -2944,6 +3008,20 @@ TileMapLayer::DebugVisibilityMode TileMapLayer::get_collision_visibility_mode()
return collision_visibility_mode;
}
void TileMapLayer::set_occlusion_enabled(bool p_enabled) {
if (occlusion_enabled == p_enabled) {
return;
}
occlusion_enabled = p_enabled;
dirty.flags[DIRTY_FLAGS_LAYER_OCCLUSION_ENABLED] = true;
_queue_internal_update();
emit_signal(CoreStringName(changed));
}
bool TileMapLayer::is_occlusion_enabled() const {
return occlusion_enabled;
}
void TileMapLayer::set_navigation_enabled(bool p_enabled) {
if (navigation_enabled == p_enabled) {
return;
@ -2991,6 +3069,114 @@ TileMapLayer::DebugVisibilityMode TileMapLayer::get_navigation_visibility_mode()
return navigation_visibility_mode;
}
void TileMapLayer::navmesh_parse_init() {
ERR_FAIL_NULL(NavigationServer2D::get_singleton());
if (!_navmesh_source_geometry_parser.is_valid()) {
_navmesh_source_geometry_parsing_callback = callable_mp_static(&TileMapLayer::navmesh_parse_source_geometry);
_navmesh_source_geometry_parser = NavigationServer2D::get_singleton()->source_geometry_parser_create();
NavigationServer2D::get_singleton()->source_geometry_parser_set_callback(_navmesh_source_geometry_parser, _navmesh_source_geometry_parsing_callback);
}
}
void TileMapLayer::navmesh_parse_source_geometry(const Ref<NavigationPolygon> &p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, Node *p_node) {
TileMapLayer *tile_map_layer = Object::cast_to<TileMapLayer>(p_node);
if (tile_map_layer == nullptr) {
return;
}
Ref<TileSet> tile_set = tile_map_layer->get_tile_set();
if (tile_set.is_null()) {
return;
}
int physics_layers_count = tile_set->get_physics_layers_count();
int navigation_layers_count = tile_set->get_navigation_layers_count();
if (physics_layers_count <= 0 && navigation_layers_count <= 0) {
return;
}
NavigationPolygon::ParsedGeometryType parsed_geometry_type = p_navigation_mesh->get_parsed_geometry_type();
uint32_t parsed_collision_mask = p_navigation_mesh->get_parsed_collision_mask();
const Transform2D tilemap_xform = p_source_geometry_data->root_node_transform * tile_map_layer->get_global_transform();
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++) {
const Vector2i &cell = used_cells[used_cell_index];
const TileData *tile_data = tile_map_layer->get_cell_tile_data(cell);
if (tile_data == nullptr) {
continue;
}
// Transform flags.
const int alternative_id = tile_map_layer->get_cell_alternative_tile(cell);
bool flip_h = (alternative_id & TileSetAtlasSource::TRANSFORM_FLIP_H);
bool flip_v = (alternative_id & TileSetAtlasSource::TRANSFORM_FLIP_V);
bool transpose = (alternative_id & TileSetAtlasSource::TRANSFORM_TRANSPOSE);
Transform2D tile_transform;
tile_transform.set_origin(tile_map_layer->map_to_local(cell));
const Transform2D tile_transform_offset = tilemap_xform * tile_transform;
// Parse traversable polygons.
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()) {
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);
if (navigation_polygon_outline.is_empty()) {
continue;
}
Vector<Vector2> traversable_outline;
traversable_outline.resize(navigation_polygon_outline.size());
const Vector2 *navigation_polygon_outline_ptr = navigation_polygon_outline.ptr();
Vector2 *traversable_outline_ptrw = traversable_outline.ptrw();
for (int traversable_outline_index = 0; traversable_outline_index < traversable_outline.size(); traversable_outline_index++) {
traversable_outline_ptrw[traversable_outline_index] = tile_transform_offset.xform(navigation_polygon_outline_ptr[traversable_outline_index]);
}
p_source_geometry_data->_add_traversable_outline(traversable_outline);
}
}
}
// Parse obstacles.
for (int physics_layer = 0; physics_layer < physics_layers_count; physics_layer++) {
if ((parsed_geometry_type == NavigationPolygon::PARSED_GEOMETRY_STATIC_COLLIDERS || parsed_geometry_type == NavigationPolygon::PARSED_GEOMETRY_BOTH) &&
(tile_set->get_physics_layer_collision_layer(physics_layer) & parsed_collision_mask)) {
for (int collision_polygon_index = 0; collision_polygon_index < tile_data->get_collision_polygons_count(physics_layer); collision_polygon_index++) {
PackedVector2Array collision_polygon_points = tile_data->get_collision_polygon_points(physics_layer, collision_polygon_index);
if (collision_polygon_points.is_empty()) {
continue;
}
if (flip_h || flip_v || transpose) {
collision_polygon_points = TileData::get_transformed_vertices(collision_polygon_points, flip_h, flip_v, transpose);
}
Vector<Vector2> obstruction_outline;
obstruction_outline.resize(collision_polygon_points.size());
const Vector2 *collision_polygon_points_ptr = collision_polygon_points.ptr();
Vector2 *obstruction_outline_ptrw = obstruction_outline.ptrw();
for (int obstruction_outline_index = 0; obstruction_outline_index < obstruction_outline.size(); obstruction_outline_index++) {
obstruction_outline_ptrw[obstruction_outline_index] = tile_transform_offset.xform(collision_polygon_points_ptr[obstruction_outline_index]);
}
p_source_geometry_data->_add_obstruction_outline(obstruction_outline);
}
}
}
}
}
TileMapLayer::TileMapLayer() {
set_notify_transform(true);
}
@ -3004,7 +3190,7 @@ HashMap<Vector2i, TileSet::CellNeighbor> TerrainConstraint::get_overlapping_coor
HashMap<Vector2i, TileSet::CellNeighbor> output;
ERR_FAIL_COND_V(is_center_bit(), output);
ERR_FAIL_COND_V(!tile_set.is_valid(), output);
ERR_FAIL_COND_V(tile_set.is_null(), output);
TileSet::TileShape shape = tile_set->get_tile_shape();
if (shape == TileSet::TILE_SHAPE_SQUARE) {
@ -3108,7 +3294,7 @@ HashMap<Vector2i, TileSet::CellNeighbor> TerrainConstraint::get_overlapping_coor
}
TerrainConstraint::TerrainConstraint(Ref<TileSet> p_tile_set, const Vector2i &p_position, int p_terrain) {
ERR_FAIL_COND(!p_tile_set.is_valid());
ERR_FAIL_COND(p_tile_set.is_null());
tile_set = p_tile_set;
bit = 0;
base_cell_coords = p_position;
@ -3117,7 +3303,7 @@ TerrainConstraint::TerrainConstraint(Ref<TileSet> p_tile_set, const Vector2i &p_
TerrainConstraint::TerrainConstraint(Ref<TileSet> p_tile_set, const Vector2i &p_position, const TileSet::CellNeighbor &p_bit, int p_terrain) {
// The way we build the constraint make it easy to detect conflicting constraints.
ERR_FAIL_COND(!p_tile_set.is_valid());
ERR_FAIL_COND(p_tile_set.is_null());
tile_set = p_tile_set;
TileSet::TileShape shape = tile_set->get_tile_shape();