summaryrefslogtreecommitdiffstats
path: root/scene/2d/tile_map_layer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/2d/tile_map_layer.cpp')
-rw-r--r--scene/2d/tile_map_layer.cpp842
1 files changed, 448 insertions, 394 deletions
diff --git a/scene/2d/tile_map_layer.cpp b/scene/2d/tile_map_layer.cpp
index c7aa4c2be4..3f10eb7661 100644
--- a/scene/2d/tile_map_layer.cpp
+++ b/scene/2d/tile_map_layer.cpp
@@ -32,6 +32,7 @@
#include "core/core_string_names.h"
#include "core/io/marshalls.h"
+#include "scene/2d/tile_map.h"
#include "scene/gui/control.h"
#include "scene/resources/world_2d.h"
#include "servers/navigation_server_2d.h"
@@ -51,11 +52,10 @@ Vector2i TileMapLayer::_coords_to_debug_quadrant_coords(const Vector2i &p_coords
}
void TileMapLayer::_debug_update() {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
RenderingServer *rs = RenderingServer::get_singleton();
// Check if we should cleanup everything.
- bool forced_cleanup = in_destructor || !enabled || !tile_set.is_valid() || !is_visible_in_tree();
+ bool forced_cleanup = in_destructor || !enabled || tile_set.is_null() || !is_visible_in_tree();
if (forced_cleanup) {
for (KeyValue<Vector2i, Ref<DebugQuadrant>> &kv : debug_quadrant_map) {
@@ -84,7 +84,7 @@ void TileMapLayer::_debug_update() {
if (_debug_was_cleaned_up || anything_changed) {
// Update all cells.
- for (KeyValue<Vector2i, CellData> &kv : tile_map) {
+ for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
CellData &cell_data = kv.value;
_debug_quadrants_update_cell(cell_data, dirty_debug_quadrant_list);
}
@@ -179,33 +179,21 @@ void TileMapLayer::_debug_quadrants_update_cell(CellData &r_cell_data, SelfList<
/////////////////////////////// Rendering //////////////////////////////////////
void TileMapLayer::_rendering_update() {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
RenderingServer *rs = RenderingServer::get_singleton();
// Check if we should cleanup everything.
- bool forced_cleanup = in_destructor || !enabled || !tile_set.is_valid() || !is_visible_in_tree();
+ bool forced_cleanup = in_destructor || !enabled || tile_set.is_null() || !is_visible_in_tree();
// ----------- Layer level processing -----------
if (!forced_cleanup) {
// Modulate the layer.
Color layer_modulate = get_modulate();
#ifdef TOOLS_ENABLED
- const TileMapLayerGroup *tile_map_layer_group = Object::cast_to<TileMapLayerGroup>(get_parent());
- if (tile_map_layer_group) {
- const Vector<StringName> selected_layers = tile_map_layer_group->get_selected_layers();
- if (tile_map_layer_group->is_highlighting_selected_layer() && selected_layers.size() == 1 && get_name() != selected_layers[0]) {
- TileMapLayer *selected_layer = Object::cast_to<TileMapLayer>(tile_map_layer_group->get_node_or_null(String(selected_layers[0])));
- if (selected_layer) {
- int z_selected = selected_layer->get_z_index();
- int layer_z_index = get_z_index();
- if (layer_z_index < z_selected || (layer_z_index == z_selected && get_index() < selected_layer->get_index())) {
- layer_modulate = layer_modulate.darkened(0.5);
- } else if (layer_z_index > z_selected || (layer_z_index == z_selected && get_index() > selected_layer->get_index())) {
- layer_modulate = layer_modulate.darkened(0.5);
- layer_modulate.a *= 0.3;
- }
- }
- }
+ if (highlight_mode == HIGHLIGHT_MODE_BELOW) {
+ layer_modulate = layer_modulate.darkened(0.5);
+ } else if (highlight_mode == HIGHLIGHT_MODE_ABOVE) {
+ layer_modulate = layer_modulate.darkened(0.5);
+ layer_modulate.a *= 0.3;
}
#endif // TOOLS_ENABLED
rs->canvas_item_set_modulate(get_canvas_item(), layer_modulate);
@@ -219,7 +207,7 @@ void TileMapLayer::_rendering_update() {
// Check if anything changed that might change the quadrant shape.
// If so, recreate everything.
bool quandrant_shape_changed = dirty.flags[DIRTY_FLAGS_LAYER_RENDERING_QUADRANT_SIZE] ||
- (is_y_sort_enabled() && (dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ENABLED] || dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN] || dirty.flags[DIRTY_FLAGS_LAYER_LOCAL_TRANSFORM] || dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET]));
+ (is_y_sort_enabled() && (dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ENABLED] || dirty.flags[DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN] || dirty.flags[DIRTY_FLAGS_LAYER_LOCAL_TRANSFORM] || dirty.flags[DIRTY_FLAGS_TILE_SET]));
// Free all quadrants.
if (forced_cleanup || quandrant_shape_changed) {
@@ -238,9 +226,9 @@ void TileMapLayer::_rendering_update() {
if (!forced_cleanup) {
// List all quadrants to update, recreating them if needed.
- if (dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE] || _rendering_was_cleaned_up) {
+ if (dirty.flags[DIRTY_FLAGS_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE] || _rendering_was_cleaned_up) {
// Update all cells.
- for (KeyValue<Vector2i, CellData> &kv : tile_map) {
+ for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
CellData &cell_data = kv.value;
_rendering_quadrants_update_cell(cell_data, dirty_rendering_quadrant_list);
}
@@ -356,6 +344,14 @@ void TileMapLayer::_rendering_update() {
// Drawing the tile in the canvas item.
TileMap::draw_tile(ci, local_tile_pos - rendering_quadrant->canvas_items_position, tile_set, cell_data.cell.source_id, cell_data.cell.get_atlas_coords(), cell_data.cell.alternative_tile, -1, get_self_modulate(), tile_data, random_animation_offset);
}
+
+ // Reset physics interpolation for any recreated canvas items.
+ if (is_physics_interpolated_and_enabled() && is_visible_in_tree()) {
+ for (const RID &ci : rendering_quadrant->canvas_items) {
+ rs->canvas_item_reset_physics_interpolation(ci);
+ }
+ }
+
} else {
// Free the quadrant.
for (int i = 0; i < rendering_quadrant->canvas_items.size(); i++) {
@@ -412,13 +408,13 @@ void TileMapLayer::_rendering_update() {
// ----------- Occluders processing -----------
if (forced_cleanup) {
// Clean everything.
- for (KeyValue<Vector2i, CellData> &kv : tile_map) {
+ for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
_rendering_occluders_clear_cell(kv.value);
}
} else {
- if (_rendering_was_cleaned_up || dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET]) {
+ if (_rendering_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_SET]) {
// Update all cells.
- for (KeyValue<Vector2i, CellData> &kv : tile_map) {
+ for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
_rendering_occluders_update_cell(kv.value);
}
} else {
@@ -437,11 +433,10 @@ void TileMapLayer::_rendering_update() {
void TileMapLayer::_rendering_notification(int p_what) {
RenderingServer *rs = RenderingServer::get_singleton();
- const Ref<TileSet> &tile_set = get_effective_tile_set();
if (p_what == NOTIFICATION_TRANSFORM_CHANGED || p_what == NOTIFICATION_ENTER_CANVAS || p_what == NOTIFICATION_VISIBILITY_CHANGED) {
if (tile_set.is_valid()) {
Transform2D tilemap_xform = get_global_transform();
- for (KeyValue<Vector2i, CellData> &kv : tile_map) {
+ 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()) {
@@ -453,12 +448,19 @@ void TileMapLayer::_rendering_notification(int p_what) {
}
}
}
+ } else if (p_what == NOTIFICATION_RESET_PHYSICS_INTERPOLATION) {
+ for (const KeyValue<Vector2i, Ref<RenderingQuadrant>> &kv : rendering_quadrant_map) {
+ for (const RID &ci : kv.value->canvas_items) {
+ if (ci.is_null()) {
+ continue;
+ }
+ rs->canvas_item_reset_physics_interpolation(ci);
+ }
+ }
}
}
void TileMapLayer::_rendering_quadrants_update_cell(CellData &r_cell_data, SelfList<RenderingQuadrant>::List &r_dirty_rendering_quadrant_list) {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
-
// Check if the cell is valid and retrieve its y_sort_origin.
bool is_valid = false;
int tile_y_sort_origin = 0;
@@ -556,7 +558,6 @@ void TileMapLayer::_rendering_occluders_clear_cell(CellData &r_cell_data) {
}
void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
RenderingServer *rs = RenderingServer::get_singleton();
// Free unused occluders then resize the occluders array.
@@ -625,8 +626,7 @@ void TileMapLayer::_rendering_occluders_update_cell(CellData &r_cell_data) {
#ifdef DEBUG_ENABLED
void TileMapLayer::_rendering_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data) {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
- ERR_FAIL_COND(!tile_set.is_valid());
+ ERR_FAIL_COND(tile_set.is_null());
if (!Engine::get_singleton()->is_editor_hint()) {
return;
@@ -674,19 +674,17 @@ void TileMapLayer::_rendering_draw_cell_debug(const RID &p_canvas_item, const Ve
/////////////////////////////// Physics //////////////////////////////////////
void TileMapLayer::_physics_update() {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
-
// Check if we should cleanup everything.
- bool forced_cleanup = in_destructor || !enabled || !is_inside_tree() || !tile_set.is_valid();
+ bool forced_cleanup = in_destructor || !enabled || !collision_enabled || !is_inside_tree() || tile_set.is_null();
if (forced_cleanup) {
// Clean everything.
- for (KeyValue<Vector2i, CellData> &kv : tile_map) {
+ for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
_physics_clear_cell(kv.value);
}
} else {
- if (_physics_was_cleaned_up || dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_USE_KINEMATIC_BODIES] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) {
+ if (_physics_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_USE_KINEMATIC_BODIES] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) {
// Update all cells.
- for (KeyValue<Vector2i, CellData> &kv : tile_map) {
+ for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
_physics_update_cell(kv.value);
}
} else {
@@ -704,7 +702,6 @@ void TileMapLayer::_physics_update() {
}
void TileMapLayer::_physics_notification(int p_what) {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
Transform2D gl_transform = get_global_transform();
PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
@@ -712,7 +709,7 @@ void TileMapLayer::_physics_notification(int p_what) {
case NOTIFICATION_TRANSFORM_CHANGED:
// Move the collisison shapes along with the TileMap.
if (is_inside_tree() && tile_set.is_valid()) {
- for (KeyValue<Vector2i, CellData> &kv : tile_map) {
+ for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
const CellData &cell_data = kv.value;
for (RID body : cell_data.bodies) {
@@ -730,7 +727,7 @@ void TileMapLayer::_physics_notification(int p_what) {
if (is_inside_tree()) {
RID space = get_world_2d()->get_space();
- for (KeyValue<Vector2i, CellData> &kv : tile_map) {
+ for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
const CellData &cell_data = kv.value;
for (RID body : cell_data.bodies) {
@@ -757,7 +754,6 @@ void TileMapLayer::_physics_clear_cell(CellData &r_cell_data) {
}
void TileMapLayer::_physics_update_cell(CellData &r_cell_data) {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
Transform2D gl_transform = get_global_transform();
RID space = get_world_2d()->get_space();
PhysicsServer2D *ps = PhysicsServer2D::get_singleton();
@@ -874,8 +870,7 @@ void TileMapLayer::_physics_update_cell(CellData &r_cell_data) {
#ifdef DEBUG_ENABLED
void TileMapLayer::_physics_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data) {
// Draw the debug collision shapes.
- const Ref<TileSet> &tile_set = get_effective_tile_set();
- ERR_FAIL_COND(!tile_set.is_valid());
+ ERR_FAIL_COND(tile_set.is_null());
if (!get_tree()) {
return;
@@ -883,13 +878,13 @@ void TileMapLayer::_physics_draw_cell_debug(const RID &p_canvas_item, const Vect
bool show_collision = false;
switch (collision_visibility_mode) {
- case TileMapLayer::VISIBILITY_MODE_DEFAULT:
+ case TileMapLayer::DEBUG_VISIBILITY_MODE_DEFAULT:
show_collision = !Engine::get_singleton()->is_editor_hint() && get_tree()->is_debugging_collisions_hint();
break;
- case TileMapLayer::VISIBILITY_MODE_FORCE_HIDE:
+ case TileMapLayer::DEBUG_VISIBILITY_MODE_FORCE_HIDE:
show_collision = false;
break;
- case TileMapLayer::VISIBILITY_MODE_FORCE_SHOW:
+ case TileMapLayer::DEBUG_VISIBILITY_MODE_FORCE_SHOW:
show_collision = true;
break;
}
@@ -931,10 +926,9 @@ void TileMapLayer::_physics_draw_cell_debug(const RID &p_canvas_item, const Vect
void TileMapLayer::_navigation_update() {
ERR_FAIL_NULL(NavigationServer2D::get_singleton());
NavigationServer2D *ns = NavigationServer2D::get_singleton();
- const Ref<TileSet> &tile_set = get_effective_tile_set();
// Check if we should cleanup everything.
- bool forced_cleanup = in_destructor || !enabled || !navigation_enabled || !is_inside_tree() || !tile_set.is_valid();
+ bool forced_cleanup = in_destructor || !enabled || !navigation_enabled || !is_inside_tree() || tile_set.is_null();
// ----------- Layer level processing -----------
// All this processing is kept for compatibility with the TileMap node.
@@ -963,13 +957,13 @@ void TileMapLayer::_navigation_update() {
// ----------- Navigation regions processing -----------
if (forced_cleanup) {
// Clean everything.
- for (KeyValue<Vector2i, CellData> &kv : tile_map) {
+ for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
_navigation_clear_cell(kv.value);
}
} else {
- if (_navigation_was_cleaned_up || dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE] || dirty.flags[DIRTY_FLAGS_LAYER_NAVIGATION_MAP]) {
+ if (_navigation_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE] || dirty.flags[DIRTY_FLAGS_LAYER_NAVIGATION_MAP]) {
// Update all cells.
- for (KeyValue<Vector2i, CellData> &kv : tile_map) {
+ for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
_navigation_update_cell(kv.value);
}
} else {
@@ -987,11 +981,10 @@ void TileMapLayer::_navigation_update() {
}
void TileMapLayer::_navigation_notification(int p_what) {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
if (tile_set.is_valid()) {
Transform2D tilemap_xform = get_global_transform();
- for (KeyValue<Vector2i, CellData> &kv : tile_map) {
+ for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
const CellData &cell_data = kv.value;
// Update navigation regions transform.
for (const RID &region : cell_data.navigation_regions) {
@@ -1021,7 +1014,6 @@ void TileMapLayer::_navigation_clear_cell(CellData &r_cell_data) {
}
void TileMapLayer::_navigation_update_cell(CellData &r_cell_data) {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
NavigationServer2D *ns = NavigationServer2D::get_singleton();
Transform2D gl_xform = get_global_transform();
RID navigation_map = navigation_map_override.is_valid() ? navigation_map_override : get_world_2d()->get_navigation_map();
@@ -1102,13 +1094,13 @@ void TileMapLayer::_navigation_draw_cell_debug(const RID &p_canvas_item, const V
// Draw the debug collision shapes.
bool show_navigation = false;
switch (navigation_visibility_mode) {
- case TileMapLayer::VISIBILITY_MODE_DEFAULT:
+ case TileMapLayer::DEBUG_VISIBILITY_MODE_DEFAULT:
show_navigation = !Engine::get_singleton()->is_editor_hint() && get_tree()->is_debugging_navigation_hint();
break;
- case TileMapLayer::VISIBILITY_MODE_FORCE_HIDE:
+ case TileMapLayer::DEBUG_VISIBILITY_MODE_FORCE_HIDE:
show_navigation = false;
break;
- case TileMapLayer::VISIBILITY_MODE_FORCE_SHOW:
+ case TileMapLayer::DEBUG_VISIBILITY_MODE_FORCE_SHOW:
show_navigation = true;
break;
}
@@ -1121,8 +1113,6 @@ void TileMapLayer::_navigation_draw_cell_debug(const RID &p_canvas_item, const V
return;
}
- const Ref<TileSet> &tile_set = get_effective_tile_set();
-
RenderingServer *rs = RenderingServer::get_singleton();
const NavigationServer2D *ns2d = NavigationServer2D::get_singleton();
@@ -1207,20 +1197,18 @@ void TileMapLayer::_navigation_draw_cell_debug(const RID &p_canvas_item, const V
/////////////////////////////// Scenes //////////////////////////////////////
void TileMapLayer::_scenes_update() {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
-
// Check if we should cleanup everything.
- bool forced_cleanup = in_destructor || !enabled || !is_inside_tree() || !tile_set.is_valid();
+ bool forced_cleanup = in_destructor || !enabled || !is_inside_tree() || tile_set.is_null();
if (forced_cleanup) {
// Clean everything.
- for (KeyValue<Vector2i, CellData> &kv : tile_map) {
+ for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
_scenes_clear_cell(kv.value);
}
} else {
- if (_scenes_was_cleaned_up || dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) {
+ if (_scenes_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_IN_TREE]) {
// Update all cells.
- for (KeyValue<Vector2i, CellData> &kv : tile_map) {
+ for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
_scenes_update_cell(kv.value);
}
} else {
@@ -1253,8 +1241,6 @@ void TileMapLayer::_scenes_clear_cell(CellData &r_cell_data) {
}
void TileMapLayer::_scenes_update_cell(CellData &r_cell_data) {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
-
// Clear the scene in any case.
_scenes_clear_cell(r_cell_data);
@@ -1295,8 +1281,7 @@ void TileMapLayer::_scenes_update_cell(CellData &r_cell_data) {
#ifdef DEBUG_ENABLED
void TileMapLayer::_scenes_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data) {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
- ERR_FAIL_COND(!tile_set.is_valid());
+ ERR_FAIL_COND(tile_set.is_null());
if (!Engine::get_singleton()->is_editor_hint()) {
return;
@@ -1345,22 +1330,20 @@ void TileMapLayer::_scenes_draw_cell_debug(const RID &p_canvas_item, const Vecto
/////////////////////////////////////////////////////////////////////
void TileMapLayer::_build_runtime_update_tile_data() {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
-
// Check if we should cleanup everything.
- bool forced_cleanup = in_destructor || !enabled || !tile_set.is_valid() || !is_visible_in_tree();
+ bool forced_cleanup = in_destructor || !enabled || tile_set.is_null() || !is_visible_in_tree();
if (!forced_cleanup) {
bool valid_runtime_update = GDVIRTUAL_IS_OVERRIDDEN(_use_tile_data_runtime_update) && GDVIRTUAL_IS_OVERRIDDEN(_tile_data_runtime_update);
bool valid_runtime_update_for_tilemap = tile_map_node && tile_map_node->GDVIRTUAL_IS_OVERRIDDEN(_use_tile_data_runtime_update) && tile_map_node->GDVIRTUAL_IS_OVERRIDDEN(_tile_data_runtime_update); // For keeping compatibility.
if (valid_runtime_update || valid_runtime_update_for_tilemap) {
bool use_tilemap_for_runtime = valid_runtime_update_for_tilemap && !valid_runtime_update;
- if (_runtime_update_tile_data_was_cleaned_up || dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET]) {
+ if (_runtime_update_tile_data_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_SET]) {
_runtime_update_needs_all_cells_cleaned_up = true;
- for (KeyValue<Vector2i, CellData> &E : tile_map) {
+ for (KeyValue<Vector2i, CellData> &E : tile_map_layer_data) {
_build_runtime_update_tile_data_for_cell(E.value, use_tilemap_for_runtime);
}
} else if (dirty.flags[DIRTY_FLAGS_LAYER_RUNTIME_UPDATE]) {
- for (KeyValue<Vector2i, CellData> &E : tile_map) {
+ for (KeyValue<Vector2i, CellData> &E : tile_map_layer_data) {
_build_runtime_update_tile_data_for_cell(E.value, use_tilemap_for_runtime, true);
}
} else {
@@ -1378,8 +1361,6 @@ void TileMapLayer::_build_runtime_update_tile_data() {
}
void TileMapLayer::_build_runtime_update_tile_data_for_cell(CellData &r_cell_data, bool p_use_tilemap_for_runtime, bool p_auto_add_to_dirty_list) {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
-
TileMapCell &c = r_cell_data.cell;
TileSetSource *source;
if (tile_set->has_source(c.source_id)) {
@@ -1429,7 +1410,7 @@ void TileMapLayer::_build_runtime_update_tile_data_for_cell(CellData &r_cell_dat
void TileMapLayer::_clear_runtime_update_tile_data() {
if (_runtime_update_needs_all_cells_cleaned_up) {
- for (KeyValue<Vector2i, CellData> &E : tile_map) {
+ for (KeyValue<Vector2i, CellData> &E : tile_map_layer_data) {
_clear_runtime_update_tile_data_for_cell(E.value);
}
_runtime_update_needs_all_cells_cleaned_up = false;
@@ -1450,8 +1431,7 @@ void TileMapLayer::_clear_runtime_update_tile_data_for_cell(CellData &r_cell_dat
}
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 {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
- if (!tile_set.is_valid()) {
+ if (tile_set.is_null()) {
return TileSet::TerrainsPattern();
}
// Returns all tiles compatible with the given constraints.
@@ -1511,8 +1491,7 @@ TileSet::TerrainsPattern TileMapLayer::_get_best_terrain_pattern_for_constraints
}
RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_added_pattern(const Vector2i &p_position, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern) const {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
- if (!tile_set.is_valid()) {
+ if (tile_set.is_null()) {
return RBSet<TerrainConstraint>();
}
@@ -1532,8 +1511,7 @@ RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_added_patte
}
RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_painted_cells_list(const RBSet<Vector2i> &p_painted, int p_terrain_set, bool p_ignore_empty_terrains) const {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
- if (!tile_set.is_valid()) {
+ if (tile_set.is_null()) {
return RBSet<TerrainConstraint>();
}
@@ -1619,6 +1597,12 @@ RBSet<TerrainConstraint> TileMapLayer::_get_terrain_constraints_from_painted_cel
return constraints;
}
+void TileMapLayer::_tile_set_changed() {
+ dirty.flags[DIRTY_FLAGS_TILE_SET] = true;
+ _queue_internal_update();
+ emit_signal(CoreStringNames::get_singleton()->changed);
+}
+
void TileMapLayer::_renamed() {
emit_signal(CoreStringNames::get_singleton()->changed);
}
@@ -1689,7 +1673,7 @@ void TileMapLayer::_internal_update() {
// Remove cells that are empty after the cleanup.
for (const Vector2i &coords : to_delete) {
- tile_map.erase(coords);
+ tile_map_layer_data.erase(coords);
}
// Clear the dirty cells list.
@@ -1737,12 +1721,115 @@ void TileMapLayer::_notification(int p_what) {
}
void TileMapLayer::_bind_methods() {
+ // --- Cells manipulation ---
+ // Generic cells manipulations and access.
ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMapLayer::set_cell, DEFVAL(TileSet::INVALID_SOURCE), DEFVAL(TileSetSource::INVALID_ATLAS_COORDS), DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("erase_cell", "coords"), &TileMapLayer::erase_cell);
+ ClassDB::bind_method(D_METHOD("fix_invalid_tiles"), &TileMapLayer::fix_invalid_tiles);
+ ClassDB::bind_method(D_METHOD("clear"), &TileMapLayer::clear);
+
+ ClassDB::bind_method(D_METHOD("get_cell_source_id", "coords"), &TileMapLayer::get_cell_source_id);
+ ClassDB::bind_method(D_METHOD("get_cell_atlas_coords", "coords"), &TileMapLayer::get_cell_atlas_coords);
+ 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("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);
+
+ // Patterns.
+ ClassDB::bind_method(D_METHOD("get_pattern", "coords_array"), &TileMapLayer::get_pattern);
+ ClassDB::bind_method(D_METHOD("set_pattern", "position", "pattern"), &TileMapLayer::set_pattern);
+
+ // Terrains.
+ ClassDB::bind_method(D_METHOD("set_cells_terrain_connect", "cells", "terrain_set", "terrain", "ignore_empty_terrains"), &TileMapLayer::set_cells_terrain_connect, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("set_cells_terrain_path", "path", "terrain_set", "terrain", "ignore_empty_terrains"), &TileMapLayer::set_cells_terrain_path, DEFVAL(true));
+
+ // --- Physics helpers ---
+ ClassDB::bind_method(D_METHOD("has_body_rid", "body"), &TileMapLayer::has_body_rid);
+ ClassDB::bind_method(D_METHOD("get_coords_for_body_rid", "body"), &TileMapLayer::get_coords_for_body_rid);
+
+ // --- 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));
+
+ // --- Shortcuts to methods defined in TileSet ---
+ ClassDB::bind_method(D_METHOD("map_pattern", "position_in_tilemap", "coords_in_pattern", "pattern"), &TileMapLayer::map_pattern);
+ ClassDB::bind_method(D_METHOD("get_surrounding_cells", "coords"), &TileMapLayer::get_surrounding_cells);
+ ClassDB::bind_method(D_METHOD("get_neighbor_cell", "coords", "neighbor"), &TileMapLayer::get_neighbor_cell);
+ ClassDB::bind_method(D_METHOD("map_to_local", "map_position"), &TileMapLayer::map_to_local);
+ ClassDB::bind_method(D_METHOD("local_to_map", "local_position"), &TileMapLayer::local_to_map);
+
+ // --- Accessors ---
+ ClassDB::bind_method(D_METHOD("set_tile_map_data_from_array", "tile_map_layer_data"), &TileMapLayer::set_tile_map_data_from_array);
+ ClassDB::bind_method(D_METHOD("get_tile_map_data_as_array"), &TileMapLayer::get_tile_map_data_as_array);
+
+ ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &TileMapLayer::set_enabled);
+ ClassDB::bind_method(D_METHOD("is_enabled"), &TileMapLayer::is_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_tile_set", "tile_set"), &TileMapLayer::set_tile_set);
+ ClassDB::bind_method(D_METHOD("get_tile_set"), &TileMapLayer::get_tile_set);
+
+ ClassDB::bind_method(D_METHOD("set_y_sort_origin", "y_sort_origin"), &TileMapLayer::set_y_sort_origin);
+ ClassDB::bind_method(D_METHOD("get_y_sort_origin"), &TileMapLayer::get_y_sort_origin);
+ ClassDB::bind_method(D_METHOD("set_rendering_quadrant_size", "size"), &TileMapLayer::set_rendering_quadrant_size);
+ ClassDB::bind_method(D_METHOD("get_rendering_quadrant_size"), &TileMapLayer::get_rendering_quadrant_size);
+
+ ClassDB::bind_method(D_METHOD("set_collision_enabled", "enabled"), &TileMapLayer::set_collision_enabled);
+ ClassDB::bind_method(D_METHOD("is_collision_enabled"), &TileMapLayer::is_collision_enabled);
+ ClassDB::bind_method(D_METHOD("set_use_kinematic_bodies", "use_kinematic_bodies"), &TileMapLayer::set_use_kinematic_bodies);
+ ClassDB::bind_method(D_METHOD("is_using_kinematic_bodies"), &TileMapLayer::is_using_kinematic_bodies);
+ 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_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);
+ ClassDB::bind_method(D_METHOD("get_navigation_map"), &TileMapLayer::get_navigation_map);
+ ClassDB::bind_method(D_METHOD("set_navigation_visibility_mode", "show_navigation"), &TileMapLayer::set_navigation_visibility_mode);
+ ClassDB::bind_method(D_METHOD("get_navigation_visibility_mode"), &TileMapLayer::get_navigation_visibility_mode);
GDVIRTUAL_BIND(_use_tile_data_runtime_update, "coords");
GDVIRTUAL_BIND(_tile_data_runtime_update, "coords", "tile_data");
+ 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::INT, "y_sort_origin"), "set_y_sort_origin", "get_y_sort_origin");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "rendering_quadrant_size"), "set_rendering_quadrant_size", "get_rendering_quadrant_size");
+ ADD_GROUP("Physics", "");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collision_enabled"), "set_collision_enabled", "is_collision_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_kinematic_bodies"), "set_use_kinematic_bodies", "is_using_kinematic_bodies");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_visibility_mode", PROPERTY_HINT_ENUM, "Default,Force Show,Force Hide"), "set_collision_visibility_mode", "get_collision_visibility_mode");
+ ADD_GROUP("Navigation", "");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "navigation_enabled"), "set_navigation_enabled", "is_navigation_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_visibility_mode", PROPERTY_HINT_ENUM, "Default,Force Show,Force Hide"), "set_navigation_visibility_mode", "get_navigation_visibility_mode");
+
ADD_SIGNAL(MethodInfo(CoreStringNames::get_singleton()->changed));
+
+ ADD_PROPERTY_DEFAULT("tile_map_data_format", TileMapDataFormat::TILE_MAP_DATA_FORMAT_1);
+
+ BIND_ENUM_CONSTANT(DEBUG_VISIBILITY_MODE_DEFAULT);
+ BIND_ENUM_CONSTANT(DEBUG_VISIBILITY_MODE_FORCE_HIDE);
+ BIND_ENUM_CONSTANT(DEBUG_VISIBILITY_MODE_FORCE_SHOW);
+}
+
+void TileMapLayer::_update_self_texture_filter(RS::CanvasItemTextureFilter p_texture_filter) {
+ // Set a default texture filter for the whole tilemap.
+ CanvasItem::_update_self_texture_filter(p_texture_filter);
+ dirty.flags[DIRTY_FLAGS_LAYER_TEXTURE_FILTER] = true;
+ _queue_internal_update();
+ emit_signal(CoreStringNames::get_singleton()->changed);
+}
+
+void TileMapLayer::_update_self_texture_repeat(RS::CanvasItemTextureRepeat p_texture_repeat) {
+ // Set a default texture repeat for the whole tilemap.
+ CanvasItem::_update_self_texture_repeat(p_texture_repeat);
+ dirty.flags[DIRTY_FLAGS_LAYER_TEXTURE_REPEAT] = true;
+ _queue_internal_update();
+ emit_signal(CoreStringNames::get_singleton()->changed);
}
void TileMapLayer::set_as_tile_map_internal_node(int p_index) {
@@ -1759,7 +1846,6 @@ void TileMapLayer::set_as_tile_map_internal_node(int p_index) {
}
Rect2 TileMapLayer::get_rect(bool &r_changed) const {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
if (tile_set.is_null()) {
r_changed = rect_cache != Rect2();
return Rect2();
@@ -1772,7 +1858,7 @@ Rect2 TileMapLayer::get_rect(bool &r_changed) const {
if (rect_cache_dirty) {
Rect2 r_total;
bool first = true;
- for (const KeyValue<Vector2i, CellData> &E : tile_map) {
+ for (const KeyValue<Vector2i, CellData> &E : tile_map_layer_data) {
Rect2 r;
r.position = tile_set->map_to_local(E.key);
r.size = Size2();
@@ -1794,8 +1880,7 @@ Rect2 TileMapLayer::get_rect(bool &r_changed) const {
}
HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_constraints(const Vector<Vector2i> &p_to_replace, int p_terrain_set, const RBSet<TerrainConstraint> &p_constraints) const {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
- if (!tile_set.is_valid()) {
+ if (tile_set.is_null()) {
return HashMap<Vector2i, TileSet::TerrainsPattern>();
}
@@ -1843,8 +1928,7 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_constrain
HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_connect(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) const {
HashMap<Vector2i, TileSet::TerrainsPattern> output;
- const Ref<TileSet> &tile_set = get_effective_tile_set();
- ERR_FAIL_COND_V(!tile_set.is_valid(), output);
+ ERR_FAIL_COND_V(tile_set.is_null(), output);
ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output);
// Build list and set of tiles that can be modified (painted and their surroundings).
@@ -1949,8 +2033,7 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_connect(c
HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_path(const Vector<Vector2i> &p_coords_array, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) const {
HashMap<Vector2i, TileSet::TerrainsPattern> output;
- const Ref<TileSet> &tile_set = get_effective_tile_set();
- ERR_FAIL_COND_V(!tile_set.is_valid(), output);
+ ERR_FAIL_COND_V(tile_set.is_null(), output);
ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output);
// Make sure the path is correct and build the peering bit list while doing it.
@@ -2023,8 +2106,7 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_path(cons
HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_pattern(const Vector<Vector2i> &p_coords_array, int p_terrain_set, TileSet::TerrainsPattern p_terrains_pattern, bool p_ignore_empty_terrains) const {
HashMap<Vector2i, TileSet::TerrainsPattern> output;
- const Ref<TileSet> &tile_set = get_effective_tile_set();
- ERR_FAIL_COND_V(!tile_set.is_valid(), output);
+ ERR_FAIL_COND_V(tile_set.is_null(), output);
ERR_FAIL_INDEX_V(p_terrain_set, tile_set->get_terrain_sets_count(), output);
// Build list and set of tiles that can be modified (painted and their surroundings).
@@ -2074,153 +2156,18 @@ HashMap<Vector2i, TileSet::TerrainsPattern> TileMapLayer::terrain_fill_pattern(c
return output;
}
-TileMapCell TileMapLayer::get_cell(const Vector2i &p_coords, bool p_use_proxies) const {
- if (!tile_map.has(p_coords)) {
+TileMapCell TileMapLayer::get_cell(const Vector2i &p_coords) const {
+ if (!tile_map_layer_data.has(p_coords)) {
return TileMapCell();
} else {
- TileMapCell c = tile_map.find(p_coords)->value.cell;
- const Ref<TileSet> &tile_set = get_effective_tile_set();
- if (p_use_proxies && tile_set.is_valid()) {
- Array proxyed = tile_set->map_tile_proxy(c.source_id, c.get_atlas_coords(), c.alternative_tile);
- c.source_id = proxyed[0];
- c.set_atlas_coords(proxyed[1]);
- c.alternative_tile = proxyed[2];
- }
- return c;
+ return tile_map_layer_data.find(p_coords)->value.cell;
}
}
-void TileMapLayer::set_tile_data(TileMapDataFormat p_format, const Vector<int> &p_data) {
- ERR_FAIL_COND(p_format > TileMapDataFormat::FORMAT_3);
-
- // Set data for a given tile from raw data.
-
- int c = p_data.size();
- const int *r = p_data.ptr();
-
- int offset = (p_format >= TileMapDataFormat::FORMAT_2) ? 3 : 2;
- ERR_FAIL_COND_MSG(c % offset != 0, vformat("Corrupted tile data. Got size: %s. Expected modulo: %s", offset));
-
- clear();
-
-#ifdef DISABLE_DEPRECATED
- ERR_FAIL_COND_MSG(p_format != TileMapDataFormat::FORMAT_3, vformat("Cannot handle deprecated TileMapLayer data format version %d. This Godot version was compiled with no support for deprecated data.", p_format));
-#endif
-
- for (int i = 0; i < c; i += offset) {
- const uint8_t *ptr = (const uint8_t *)&r[i];
- uint8_t local[12];
- for (int j = 0; j < ((p_format >= TileMapDataFormat::FORMAT_2) ? 12 : 8); j++) {
- local[j] = ptr[j];
- }
-
-#ifdef BIG_ENDIAN_ENABLED
-
- SWAP(local[0], local[3]);
- SWAP(local[1], local[2]);
- SWAP(local[4], local[7]);
- SWAP(local[5], local[6]);
- //TODO: ask someone to check this...
- if (FORMAT >= FORMAT_2) {
- SWAP(local[8], local[11]);
- SWAP(local[9], local[10]);
- }
-#endif
- // Extracts position in TileMap.
- int16_t x = decode_uint16(&local[0]);
- int16_t y = decode_uint16(&local[2]);
-
- if (p_format == TileMapDataFormat::FORMAT_3) {
- uint16_t source_id = decode_uint16(&local[4]);
- uint16_t atlas_coords_x = decode_uint16(&local[6]);
- uint16_t atlas_coords_y = decode_uint16(&local[8]);
- uint16_t alternative_tile = decode_uint16(&local[10]);
- set_cell(Vector2i(x, y), source_id, Vector2i(atlas_coords_x, atlas_coords_y), alternative_tile);
- } else {
-#ifndef DISABLE_DEPRECATED
- // Previous decated format.
-
- uint32_t v = decode_uint32(&local[4]);
- // Extract the transform flags that used to be in the tilemap.
- bool flip_h = v & (1UL << 29);
- bool flip_v = v & (1UL << 30);
- bool transpose = v & (1UL << 31);
- v &= (1UL << 29) - 1;
-
- // Extract autotile/atlas coords.
- int16_t coord_x = 0;
- int16_t coord_y = 0;
- if (p_format == TileMapDataFormat::FORMAT_2) {
- coord_x = decode_uint16(&local[8]);
- coord_y = decode_uint16(&local[10]);
- }
-
- const Ref<TileSet> &tile_set = get_effective_tile_set();
- if (tile_set.is_valid()) {
- Array a = tile_set->compatibility_tilemap_map(v, Vector2i(coord_x, coord_y), flip_h, flip_v, transpose);
- if (a.size() == 3) {
- set_cell(Vector2i(x, y), a[0], a[1], a[2]);
- } else {
- ERR_PRINT(vformat("No valid tile in Tileset for: tile:%s coords:%s flip_h:%s flip_v:%s transpose:%s", v, Vector2i(coord_x, coord_y), flip_h, flip_v, transpose));
- }
- } else {
- int compatibility_alternative_tile = ((int)flip_h) + ((int)flip_v << 1) + ((int)transpose << 2);
- set_cell(Vector2i(x, y), v, Vector2i(coord_x, coord_y), compatibility_alternative_tile);
- }
-#endif
- }
- }
-}
-
-Vector<int> TileMapLayer::get_tile_data() const {
- // Export tile data to raw format.
- Vector<int> tile_data;
- tile_data.resize(tile_map.size() * 3);
- int *w = tile_data.ptrw();
-
- // Save in highest format.
-
- int idx = 0;
- for (const KeyValue<Vector2i, CellData> &E : tile_map) {
- uint8_t *ptr = (uint8_t *)&w[idx];
- encode_uint16((int16_t)(E.key.x), &ptr[0]);
- encode_uint16((int16_t)(E.key.y), &ptr[2]);
- encode_uint16(E.value.cell.source_id, &ptr[4]);
- encode_uint16(E.value.cell.coord_x, &ptr[6]);
- encode_uint16(E.value.cell.coord_y, &ptr[8]);
- encode_uint16(E.value.cell.alternative_tile, &ptr[10]);
- idx += 3;
- }
-
- return tile_data;
-}
-
-void TileMapLayer::notify_tile_map_layer_group_change(DirtyFlags p_what) {
- if (p_what == DIRTY_FLAGS_LAYER_GROUP_SELECTED_LAYERS ||
- p_what == DIRTY_FLAGS_LAYER_GROUP_HIGHLIGHT_SELECTED ||
- p_what == DIRTY_FLAGS_LAYER_GROUP_TILE_SET) {
- emit_signal(CoreStringNames::get_singleton()->changed);
- }
-
- dirty.flags[p_what] = true;
- _queue_internal_update();
-}
-
-void TileMapLayer::update_internals() {
- pending_update = true;
- _deferred_internal_update();
-}
-
-void TileMapLayer::notify_runtime_tile_data_update() {
- dirty.flags[TileMapLayer::DIRTY_FLAGS_LAYER_RUNTIME_UPDATE] = true;
- _queue_internal_update();
- emit_signal(CoreStringNames::get_singleton()->changed);
-}
-
-void TileMapLayer::set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i p_atlas_coords, int p_alternative_tile) {
+void TileMapLayer::set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i &p_atlas_coords, int p_alternative_tile) {
// Set the current cell tile (using integer position).
Vector2i pk(p_coords);
- HashMap<Vector2i, CellData>::Iterator E = tile_map.find(pk);
+ HashMap<Vector2i, CellData>::Iterator E = tile_map_layer_data.find(pk);
int source_id = p_source_id;
Vector2i atlas_coords = p_atlas_coords;
@@ -2241,7 +2188,7 @@ void TileMapLayer::set_cell(const Vector2i &p_coords, int p_source_id, const Vec
// Insert a new cell in the tile map.
CellData new_cell_data;
new_cell_data.coords = pk;
- E = tile_map.insert(pk, new_cell_data);
+ E = tile_map_layer_data.insert(pk, new_cell_data);
} else {
if (E->value.cell.source_id == source_id && E->value.cell.get_atlas_coords() == atlas_coords && E->value.cell.alternative_tile == alternative_tile) {
return; // Nothing changed.
@@ -2266,83 +2213,139 @@ void TileMapLayer::erase_cell(const Vector2i &p_coords) {
set_cell(p_coords, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
}
-int TileMapLayer::get_cell_source_id(const Vector2i &p_coords, bool p_use_proxies) const {
+void TileMapLayer::fix_invalid_tiles() {
+ ERR_FAIL_COND_MSG(tile_set.is_null(), "Cannot call fix_invalid_tiles() on a TileMap without a valid TileSet.");
+
+ RBSet<Vector2i> coords;
+ for (const KeyValue<Vector2i, CellData> &E : tile_map_layer_data) {
+ TileSetSource *source = *tile_set->get_source(E.value.cell.source_id);
+ if (!source || !source->has_tile(E.value.cell.get_atlas_coords()) || !source->has_alternative_tile(E.value.cell.get_atlas_coords(), E.value.cell.alternative_tile)) {
+ coords.insert(E.key);
+ }
+ }
+ for (const Vector2i &E : coords) {
+ set_cell(E, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
+ }
+}
+
+void TileMapLayer::clear() {
+ // Remove all tiles.
+ for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
+ erase_cell(kv.key);
+ }
+ used_rect_cache_dirty = true;
+}
+
+int TileMapLayer::get_cell_source_id(const Vector2i &p_coords) const {
// Get a cell source id from position.
- HashMap<Vector2i, CellData>::ConstIterator E = tile_map.find(p_coords);
+ HashMap<Vector2i, CellData>::ConstIterator E = tile_map_layer_data.find(p_coords);
if (!E) {
return TileSet::INVALID_SOURCE;
}
- const Ref<TileSet> &tile_set = get_effective_tile_set();
- if (p_use_proxies && tile_set.is_valid()) {
- Array proxyed = tile_set->map_tile_proxy(E->value.cell.source_id, E->value.cell.get_atlas_coords(), E->value.cell.alternative_tile);
- return proxyed[0];
- }
-
return E->value.cell.source_id;
}
-Vector2i TileMapLayer::get_cell_atlas_coords(const Vector2i &p_coords, bool p_use_proxies) const {
+Vector2i TileMapLayer::get_cell_atlas_coords(const Vector2i &p_coords) const {
// Get a cell source id from position.
- HashMap<Vector2i, CellData>::ConstIterator E = tile_map.find(p_coords);
+ HashMap<Vector2i, CellData>::ConstIterator E = tile_map_layer_data.find(p_coords);
if (!E) {
return TileSetSource::INVALID_ATLAS_COORDS;
}
- const Ref<TileSet> &tile_set = get_effective_tile_set();
- if (p_use_proxies && tile_set.is_valid()) {
- Array proxyed = tile_set->map_tile_proxy(E->value.cell.source_id, E->value.cell.get_atlas_coords(), E->value.cell.alternative_tile);
- return proxyed[1];
- }
-
return E->value.cell.get_atlas_coords();
}
-int TileMapLayer::get_cell_alternative_tile(const Vector2i &p_coords, bool p_use_proxies) const {
+int TileMapLayer::get_cell_alternative_tile(const Vector2i &p_coords) const {
// Get a cell source id from position.
- HashMap<Vector2i, CellData>::ConstIterator E = tile_map.find(p_coords);
+ HashMap<Vector2i, CellData>::ConstIterator E = tile_map_layer_data.find(p_coords);
if (!E) {
return TileSetSource::INVALID_TILE_ALTERNATIVE;
}
- const Ref<TileSet> &tile_set = get_effective_tile_set();
- if (p_use_proxies && tile_set.is_valid()) {
- Array proxyed = tile_set->map_tile_proxy(E->value.cell.source_id, E->value.cell.get_atlas_coords(), E->value.cell.alternative_tile);
- return proxyed[2];
- }
-
return E->value.cell.alternative_tile;
}
-TileData *TileMapLayer::get_cell_tile_data(const Vector2i &p_coords, bool p_use_proxies) const {
- int source_id = get_cell_source_id(p_coords, p_use_proxies);
+TileData *TileMapLayer::get_cell_tile_data(const Vector2i &p_coords) const {
+ int source_id = get_cell_source_id(p_coords);
if (source_id == TileSet::INVALID_SOURCE) {
return nullptr;
}
- const Ref<TileSet> &tile_set = get_effective_tile_set();
Ref<TileSetAtlasSource> source = tile_set->get_source(source_id);
if (source.is_valid()) {
- return source->get_tile_data(get_cell_atlas_coords(p_coords, p_use_proxies), get_cell_alternative_tile(p_coords, p_use_proxies));
+ return source->get_tile_data(get_cell_atlas_coords(p_coords), get_cell_alternative_tile(p_coords));
}
return nullptr;
}
-void TileMapLayer::clear() {
- // Remove all tiles.
- for (KeyValue<Vector2i, CellData> &kv : tile_map) {
- erase_cell(kv.key);
+TypedArray<Vector2i> TileMapLayer::get_used_cells() const {
+ // Returns the cells used in the tilemap.
+ TypedArray<Vector2i> a;
+ for (const KeyValue<Vector2i, CellData> &E : tile_map_layer_data) {
+ const TileMapCell &c = E.value.cell;
+ if (c.source_id == TileSet::INVALID_SOURCE) {
+ continue;
+ }
+ a.push_back(E.key);
}
- used_rect_cache_dirty = true;
+
+ return a;
+}
+
+TypedArray<Vector2i> TileMapLayer::get_used_cells_by_id(int p_source_id, const Vector2i &p_atlas_coords, int p_alternative_tile) const {
+ // Returns the cells used in the tilemap.
+ TypedArray<Vector2i> a;
+ for (const KeyValue<Vector2i, CellData> &E : tile_map_layer_data) {
+ const TileMapCell &c = E.value.cell;
+ if (c.source_id == TileSet::INVALID_SOURCE) {
+ continue;
+ }
+ if ((p_source_id == TileSet::INVALID_SOURCE || p_source_id == c.source_id) &&
+ (p_atlas_coords == TileSetSource::INVALID_ATLAS_COORDS || p_atlas_coords == c.get_atlas_coords()) &&
+ (p_alternative_tile == TileSetSource::INVALID_TILE_ALTERNATIVE || p_alternative_tile == c.alternative_tile)) {
+ a.push_back(E.key);
+ }
+ }
+
+ return a;
+}
+
+Rect2i TileMapLayer::get_used_rect() const {
+ // Return the rect of the currently used area.
+ if (used_rect_cache_dirty) {
+ used_rect_cache = Rect2i();
+
+ bool first = true;
+ for (const KeyValue<Vector2i, CellData> &E : tile_map_layer_data) {
+ const TileMapCell &c = E.value.cell;
+ if (c.source_id == TileSet::INVALID_SOURCE) {
+ continue;
+ }
+ if (first) {
+ used_rect_cache = Rect2i(E.key, Size2i());
+ first = false;
+ } else {
+ used_rect_cache.expand_to(E.key);
+ }
+ }
+ if (!first) {
+ // Only if we have at least one cell.
+ // The cache expands to top-left coordinate, so we add one full tile.
+ used_rect_cache.size += Vector2i(1, 1);
+ }
+ used_rect_cache_dirty = false;
+ }
+
+ return used_rect_cache;
}
Ref<TileMapPattern> TileMapLayer::get_pattern(TypedArray<Vector2i> p_coords_array) {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
- ERR_FAIL_COND_V(!tile_set.is_valid(), nullptr);
+ ERR_FAIL_COND_V(tile_set.is_null(), nullptr);
Ref<TileMapPattern> output;
output.instantiate();
@@ -2395,7 +2398,6 @@ Ref<TileMapPattern> TileMapLayer::get_pattern(TypedArray<Vector2i> p_coords_arra
}
void TileMapLayer::set_pattern(const Vector2i &p_position, const Ref<TileMapPattern> p_pattern) {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
ERR_FAIL_COND(tile_set.is_null());
ERR_FAIL_COND(p_pattern.is_null());
@@ -2407,8 +2409,7 @@ void TileMapLayer::set_pattern(const Vector2i &p_position, const Ref<TileMapPatt
}
void TileMapLayer::set_cells_terrain_connect(TypedArray<Vector2i> p_cells, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
- ERR_FAIL_COND(!tile_set.is_valid());
+ ERR_FAIL_COND(tile_set.is_null());
ERR_FAIL_INDEX(p_terrain_set, tile_set->get_terrain_sets_count());
Vector<Vector2i> cells_vector;
@@ -2447,8 +2448,7 @@ void TileMapLayer::set_cells_terrain_connect(TypedArray<Vector2i> p_cells, int p
}
void TileMapLayer::set_cells_terrain_path(TypedArray<Vector2i> p_path, int p_terrain_set, int p_terrain, bool p_ignore_empty_terrains) {
- const Ref<TileSet> &tile_set = get_effective_tile_set();
- ERR_FAIL_COND(!tile_set.is_valid());
+ ERR_FAIL_COND(tile_set.is_null());
ERR_FAIL_INDEX(p_terrain_set, tile_set->get_terrain_sets_count());
Vector<Vector2i> vector_path;
@@ -2487,65 +2487,50 @@ void TileMapLayer::set_cells_terrain_path(TypedArray<Vector2i> p_path, int p_ter
}
}
-TypedArray<Vector2i> TileMapLayer::get_used_cells() const {
- // Returns the cells used in the tilemap.
- TypedArray<Vector2i> a;
- for (const KeyValue<Vector2i, CellData> &E : tile_map) {
- const TileMapCell &c = E.value.cell;
- if (c.source_id == TileSet::INVALID_SOURCE) {
- continue;
- }
- a.push_back(E.key);
- }
+bool TileMapLayer::has_body_rid(RID p_physics_body) const {
+ return bodies_coords.has(p_physics_body);
+}
- return a;
+Vector2i TileMapLayer::get_coords_for_body_rid(RID p_physics_body) const {
+ const Vector2i *found = bodies_coords.getptr(p_physics_body);
+ ERR_FAIL_NULL_V(found, Vector2i());
+ return *found;
}
-TypedArray<Vector2i> TileMapLayer::get_used_cells_by_id(int p_source_id, const Vector2i p_atlas_coords, int p_alternative_tile) const {
- // Returns the cells used in the tilemap.
- TypedArray<Vector2i> a;
- for (const KeyValue<Vector2i, CellData> &E : tile_map) {
- const TileMapCell &c = E.value.cell;
- if (c.source_id == TileSet::INVALID_SOURCE) {
- continue;
- }
- if ((p_source_id == TileSet::INVALID_SOURCE || p_source_id == c.source_id) &&
- (p_atlas_coords == TileSetSource::INVALID_ATLAS_COORDS || p_atlas_coords == c.get_atlas_coords()) &&
- (p_alternative_tile == TileSetSource::INVALID_TILE_ALTERNATIVE || p_alternative_tile == c.alternative_tile)) {
- a.push_back(E.key);
- }
- }
+void TileMapLayer::update_internals() {
+ pending_update = true;
+ _deferred_internal_update();
+}
- return a;
+void TileMapLayer::notify_runtime_tile_data_update() {
+ dirty.flags[TileMapLayer::DIRTY_FLAGS_LAYER_RUNTIME_UPDATE] = true;
+ _queue_internal_update();
+ emit_signal(CoreStringNames::get_singleton()->changed);
}
-Rect2i TileMapLayer::get_used_rect() const {
- // Return the rect of the currently used area.
- if (used_rect_cache_dirty) {
- used_rect_cache = Rect2i();
+Vector2i TileMapLayer::map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern) {
+ ERR_FAIL_COND_V(tile_set.is_null(), Vector2i());
+ return tile_set->map_pattern(p_position_in_tilemap, p_coords_in_pattern, p_pattern);
+}
- bool first = true;
- for (const KeyValue<Vector2i, CellData> &E : tile_map) {
- const TileMapCell &c = E.value.cell;
- if (c.source_id == TileSet::INVALID_SOURCE) {
- continue;
- }
- if (first) {
- used_rect_cache = Rect2i(E.key.x, E.key.y, 0, 0);
- first = false;
- } else {
- used_rect_cache.expand_to(E.key);
- }
- }
- if (!first) {
- // Only if we have at least one cell.
- // The cache expands to top-left coordinate, so we add one full tile.
- used_rect_cache.size += Vector2i(1, 1);
- }
- used_rect_cache_dirty = false;
- }
+TypedArray<Vector2i> TileMapLayer::get_surrounding_cells(const Vector2i &p_coords) {
+ ERR_FAIL_COND_V(tile_set.is_null(), TypedArray<Vector2i>());
+ return tile_set->get_surrounding_cells(p_coords);
+}
- return used_rect_cache;
+Vector2i TileMapLayer::get_neighbor_cell(const Vector2i &p_coords, TileSet::CellNeighbor p_cell_neighbor) const {
+ ERR_FAIL_COND_V(tile_set.is_null(), Vector2i());
+ return tile_set->get_neighbor_cell(p_coords, p_cell_neighbor);
+}
+
+Vector2 TileMapLayer::map_to_local(const Vector2i &p_pos) const {
+ ERR_FAIL_COND_V(tile_set.is_null(), Vector2());
+ return tile_set->map_to_local(p_pos);
+}
+
+Vector2i TileMapLayer::local_to_map(const Vector2 &p_pos) const {
+ ERR_FAIL_COND_V(tile_set.is_null(), Vector2i());
+ return tile_set->local_to_map(p_pos);
}
void TileMapLayer::set_enabled(bool p_enabled) {
@@ -2556,16 +2541,127 @@ void TileMapLayer::set_enabled(bool p_enabled) {
dirty.flags[DIRTY_FLAGS_LAYER_ENABLED] = true;
_queue_internal_update();
emit_signal(CoreStringNames::get_singleton()->changed);
-
- if (tile_map_node) {
- tile_map_node->update_configuration_warnings();
- }
}
bool TileMapLayer::is_enabled() const {
return enabled;
}
+void TileMapLayer::set_tile_set(const Ref<TileSet> &p_tile_set) {
+ if (p_tile_set == tile_set) {
+ return;
+ }
+
+ dirty.flags[DIRTY_FLAGS_TILE_SET] = true;
+ _queue_internal_update();
+
+ // Set the TileSet, registering to its changes.
+ if (tile_set.is_valid()) {
+ tile_set->disconnect_changed(callable_mp(this, &TileMapLayer::_tile_set_changed));
+ }
+
+ tile_set = p_tile_set;
+
+ if (tile_set.is_valid()) {
+ tile_set->connect_changed(callable_mp(this, &TileMapLayer::_tile_set_changed));
+ }
+
+ emit_signal(CoreStringNames::get_singleton()->changed);
+
+ // Trigger updates for TileSet's read-only status.
+ notify_property_list_changed();
+}
+
+Ref<TileSet> TileMapLayer::get_tile_set() const {
+ return tile_set;
+}
+
+void TileMapLayer::set_highlight_mode(HighlightMode p_highlight_mode) {
+ if (p_highlight_mode == highlight_mode) {
+ return;
+ }
+ highlight_mode = p_highlight_mode;
+ _queue_internal_update();
+}
+
+TileMapLayer::HighlightMode TileMapLayer::get_highlight_mode() const {
+ return highlight_mode;
+}
+
+void TileMapLayer::set_tile_map_data_from_array(const Vector<uint8_t> &p_data) {
+ const int cell_data_struct_size = 12;
+
+ int size = p_data.size();
+ const uint8_t *ptr = p_data.ptr();
+
+ // Index in the array.
+ int index = 0;
+
+ // First extract the data version.
+ ERR_FAIL_COND_MSG(size < 2, "Corrupted tile map data: not enough bytes.");
+ uint16_t format = decode_uint16(&ptr[index]);
+ index += 2;
+ ERR_FAIL_COND_MSG(format >= TileMapLayerDataFormat::TILE_MAP_LAYER_DATA_FORMAT_MAX, vformat("Unsupported tile map data format: %s. Expected format ID lower or equal to: %s", format, TileMapLayerDataFormat::TILE_MAP_LAYER_DATA_FORMAT_MAX - 1));
+
+ // Clear the TileMap.
+ clear();
+
+ while (index < size) {
+ ERR_FAIL_COND_MSG(index + cell_data_struct_size > size, vformat("Corrupted tile map data: tiles might be missing."));
+
+ // Get a pointer at the start of the cell data.
+ const uint8_t *cell_data_ptr = &ptr[index];
+
+ // Extracts position in TileMap.
+ int16_t x = decode_uint16(&cell_data_ptr[0]);
+ int16_t y = decode_uint16(&cell_data_ptr[2]);
+
+ // Extracts the tile identifiers.
+ uint16_t source_id = decode_uint16(&cell_data_ptr[4]);
+ uint16_t atlas_coords_x = decode_uint16(&cell_data_ptr[6]);
+ uint16_t atlas_coords_y = decode_uint16(&cell_data_ptr[8]);
+ uint16_t alternative_tile = decode_uint16(&cell_data_ptr[10]);
+
+ set_cell(Vector2i(x, y), source_id, Vector2i(atlas_coords_x, atlas_coords_y), alternative_tile);
+ index += cell_data_struct_size;
+ }
+}
+
+Vector<uint8_t> TileMapLayer::get_tile_map_data_as_array() const {
+ const int cell_data_struct_size = 12;
+
+ Vector<uint8_t> tile_map_data_array;
+ tile_map_data_array.resize(2 + tile_map_layer_data.size() * cell_data_struct_size);
+ uint8_t *ptr = tile_map_data_array.ptrw();
+
+ // Index in the array.
+ int index = 0;
+
+ // Save the version.
+ encode_uint16(TileMapLayerDataFormat::TILE_MAP_LAYER_DATA_FORMAT_MAX - 1, &ptr[index]);
+ index += 2;
+
+ // Save in highest format.
+ for (const KeyValue<Vector2i, CellData> &E : tile_map_layer_data) {
+ // Get a pointer at the start of the cell data.
+ uint8_t *cell_data_ptr = (uint8_t *)&ptr[index];
+
+ // Store position in TileMap.
+ encode_uint16((int16_t)(E.key.x), &cell_data_ptr[0]);
+ encode_uint16((int16_t)(E.key.y), &cell_data_ptr[2]);
+
+ // Store the tile identifiers.
+ encode_uint16(E.value.cell.source_id, &cell_data_ptr[4]);
+ encode_uint16(E.value.cell.coord_x, &cell_data_ptr[6]);
+ encode_uint16(E.value.cell.coord_y, &cell_data_ptr[8]);
+ encode_uint16(E.value.cell.alternative_tile, &cell_data_ptr[10]);
+
+ index += cell_data_struct_size;
+ }
+
+ return tile_map_data_array;
+}
+
void TileMapLayer::set_self_modulate(const Color &p_self_modulate) {
if (get_self_modulate() == p_self_modulate) {
return;
@@ -2585,9 +2681,6 @@ void TileMapLayer::set_y_sort_enabled(bool p_y_sort_enabled) {
_queue_internal_update();
emit_signal(CoreStringNames::get_singleton()->changed);
- if (tile_map_node) {
- tile_map_node->update_configuration_warnings();
- }
_update_notify_local_transform();
}
@@ -2613,10 +2706,6 @@ void TileMapLayer::set_z_index(int p_z_index) {
dirty.flags[DIRTY_FLAGS_LAYER_Z_INDEX] = true;
_queue_internal_update();
emit_signal(CoreStringNames::get_singleton()->changed);
-
- if (tile_map_node) {
- tile_map_node->update_configuration_warnings();
- }
}
void TileMapLayer::set_light_mask(int p_light_mask) {
@@ -2629,22 +2718,6 @@ void TileMapLayer::set_light_mask(int p_light_mask) {
emit_signal(CoreStringNames::get_singleton()->changed);
}
-void TileMapLayer::set_texture_filter(TextureFilter p_texture_filter) {
- // Set a default texture filter for the whole tilemap.
- CanvasItem::set_texture_filter(p_texture_filter);
- dirty.flags[DIRTY_FLAGS_LAYER_TEXTURE_FILTER] = true;
- _queue_internal_update();
- emit_signal(CoreStringNames::get_singleton()->changed);
-}
-
-void TileMapLayer::set_texture_repeat(CanvasItem::TextureRepeat p_texture_repeat) {
- // Set a default texture repeat for the whole tilemap.
- CanvasItem::set_texture_repeat(p_texture_repeat);
- dirty.flags[DIRTY_FLAGS_LAYER_TEXTURE_REPEAT] = true;
- _queue_internal_update();
- emit_signal(CoreStringNames::get_singleton()->changed);
-}
-
void TileMapLayer::set_rendering_quadrant_size(int p_size) {
if (rendering_quadrant_size == p_size) {
return;
@@ -2661,6 +2734,20 @@ int TileMapLayer::get_rendering_quadrant_size() const {
return rendering_quadrant_size;
}
+void TileMapLayer::set_collision_enabled(bool p_enabled) {
+ if (collision_enabled == p_enabled) {
+ return;
+ }
+ collision_enabled = p_enabled;
+ dirty.flags[DIRTY_FLAGS_LAYER_COLLISION_ENABLED] = true;
+ _queue_internal_update();
+ emit_signal(CoreStringNames::get_singleton()->changed);
+}
+
+bool TileMapLayer::is_collision_enabled() const {
+ return collision_enabled;
+}
+
void TileMapLayer::set_use_kinematic_bodies(bool p_use_kinematic_bodies) {
use_kinematic_bodies = p_use_kinematic_bodies;
dirty.flags[DIRTY_FLAGS_LAYER_USE_KINEMATIC_BODIES] = p_use_kinematic_bodies;
@@ -2672,7 +2759,7 @@ bool TileMapLayer::is_using_kinematic_bodies() const {
return use_kinematic_bodies;
}
-void TileMapLayer::set_collision_visibility_mode(TileMapLayer::VisibilityMode p_show_collision) {
+void TileMapLayer::set_collision_visibility_mode(TileMapLayer::DebugVisibilityMode p_show_collision) {
if (collision_visibility_mode == p_show_collision) {
return;
}
@@ -2682,7 +2769,7 @@ void TileMapLayer::set_collision_visibility_mode(TileMapLayer::VisibilityMode p_
emit_signal(CoreStringNames::get_singleton()->changed);
}
-TileMapLayer::VisibilityMode TileMapLayer::get_collision_visibility_mode() const {
+TileMapLayer::DebugVisibilityMode TileMapLayer::get_collision_visibility_mode() const {
return collision_visibility_mode;
}
@@ -2719,7 +2806,7 @@ RID TileMapLayer::get_navigation_map() const {
return RID();
}
-void TileMapLayer::set_navigation_visibility_mode(TileMapLayer::VisibilityMode p_show_navigation) {
+void TileMapLayer::set_navigation_visibility_mode(TileMapLayer::DebugVisibilityMode p_show_navigation) {
if (navigation_visibility_mode == p_show_navigation) {
return;
}
@@ -2729,43 +2816,10 @@ void TileMapLayer::set_navigation_visibility_mode(TileMapLayer::VisibilityMode p
emit_signal(CoreStringNames::get_singleton()->changed);
}
-TileMapLayer::VisibilityMode TileMapLayer::get_navigation_visibility_mode() const {
+TileMapLayer::DebugVisibilityMode TileMapLayer::get_navigation_visibility_mode() const {
return navigation_visibility_mode;
}
-void TileMapLayer::fix_invalid_tiles() {
- Ref<TileSet> tileset = get_effective_tile_set();
- ERR_FAIL_COND_MSG(tileset.is_null(), "Cannot call fix_invalid_tiles() on a TileMap without a valid TileSet.");
-
- RBSet<Vector2i> coords;
- for (const KeyValue<Vector2i, CellData> &E : tile_map) {
- TileSetSource *source = *tileset->get_source(E.value.cell.source_id);
- if (!source || !source->has_tile(E.value.cell.get_atlas_coords()) || !source->has_alternative_tile(E.value.cell.get_atlas_coords(), E.value.cell.alternative_tile)) {
- coords.insert(E.key);
- }
- }
- for (const Vector2i &E : coords) {
- set_cell(E, TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE);
- }
-}
-
-bool TileMapLayer::has_body_rid(RID p_physics_body) const {
- return bodies_coords.has(p_physics_body);
-}
-
-Vector2i TileMapLayer::get_coords_for_body_rid(RID p_physics_body) const {
- return bodies_coords[p_physics_body];
-}
-
-Ref<TileSet> TileMapLayer::get_effective_tile_set() const {
- TileMapLayerGroup *tile_map_layer_group = Object::cast_to<TileMapLayerGroup>(get_parent());
- if (tile_map_layer_group) {
- return tile_map_layer_group->get_tileset();
- } else {
- return Ref<TileSet>();
- }
-}
-
TileMapLayer::TileMapLayer() {
set_notify_transform(true);
}