Merge pull request #88966 from groud/remove_tilemap_layer_dependencies_to_tilemap

Remove almost all remaining dependencies of TileMapLayer on TileMap
This commit is contained in:
Rémi Verschelde 2024-02-29 13:54:49 +01:00
commit 8328d9a647
No known key found for this signature in database
GPG key ID: C3336907360768E1
5 changed files with 294 additions and 182 deletions

View file

@ -105,7 +105,7 @@ void TileMap::set_rendering_quadrant_size(int p_size) {
rendering_quadrant_size = p_size;
for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_QUADRANT_SIZE);
layer->set_rendering_quadrant_size(p_size);
}
_emit_changed();
}
@ -214,11 +214,10 @@ void TileMap::add_layer(int p_to_pos) {
TileMapLayer *new_layer = memnew(TileMapLayer);
layers.insert(p_to_pos, new_layer);
add_child(new_layer, false, INTERNAL_MODE_FRONT);
new_layer->force_parent_owned();
new_layer->set_name(vformat("Layer%d", p_to_pos));
move_child(new_layer, p_to_pos);
for (uint32_t i = 0; i < layers.size(); i++) {
layers[i]->set_layer_index_in_tile_map_node(i);
layers[i]->set_as_tile_map_internal_node(i);
}
new_layer->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TileMap::_emit_changed));
@ -239,7 +238,7 @@ void TileMap::move_layer(int p_layer, int p_to_pos) {
layers.remove_at(p_to_pos < p_layer ? p_layer + 1 : p_layer);
for (uint32_t i = 0; i < layers.size(); i++) {
move_child(layers[i], i);
layers[i]->set_layer_index_in_tile_map_node(i);
layers[i]->set_as_tile_map_internal_node(i);
}
notify_property_list_changed();
@ -255,7 +254,7 @@ void TileMap::remove_layer(int p_layer) {
layers[p_layer]->queue_free();
layers.remove_at(p_layer);
for (uint32_t i = 0; i < layers.size(); i++) {
layers[i]->set_layer_index_in_tile_map_node(i);
layers[i]->set_as_tile_map_internal_node(i);
}
notify_property_list_changed();
@ -350,7 +349,7 @@ void TileMap::set_collision_visibility_mode(TileMap::VisibilityMode p_show_colli
}
collision_visibility_mode = p_show_collision;
for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_COLLISION_VISIBILITY_MODE);
layer->set_collision_visibility_mode(TileMapLayer::VisibilityMode(p_show_collision));
}
_emit_changed();
}
@ -365,7 +364,7 @@ void TileMap::set_navigation_visibility_mode(TileMap::VisibilityMode p_show_navi
}
navigation_visibility_mode = p_show_navigation;
for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_NAVIGATION_VISIBILITY_MODE);
layer->set_navigation_visibility_mode(TileMapLayer::VisibilityMode(p_show_navigation));
}
_emit_changed();
}
@ -380,7 +379,7 @@ void TileMap::set_y_sort_enabled(bool p_enable) {
}
Node2D::set_y_sort_enabled(p_enable);
for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_Y_SORT_ENABLED);
layer->set_y_sort_enabled(p_enable);
}
_emit_changed();
update_configuration_warnings();
@ -497,10 +496,10 @@ void TileMap::update_internals() {
void TileMap::notify_runtime_tile_data_update(int p_layer) {
if (p_layer >= 0) {
TILEMAP_CALL_FOR_LAYER(p_layer, notify_tile_map_change, TileMapLayer::DIRTY_FLAGS_TILE_MAP_RUNTIME_UPDATE);
TILEMAP_CALL_FOR_LAYER(p_layer, notify_runtime_tile_data_update);
} else {
for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_RUNTIME_UPDATE);
layer->notify_runtime_tile_data_update();
}
}
}
@ -539,9 +538,8 @@ bool TileMap::_set(const StringName &p_name, const Variant &p_value) {
if (layers.size() == 0) {
TileMapLayer *new_layer = memnew(TileMapLayer);
add_child(new_layer, false, INTERNAL_MODE_FRONT);
new_layer->force_parent_owned();
new_layer->set_as_tile_map_internal_node(0);
new_layer->set_name("Layer0");
new_layer->set_layer_index_in_tile_map_node(0);
new_layer->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TileMap::_emit_changed));
layers.push_back(new_layer);
}
@ -565,9 +563,8 @@ bool TileMap::_set(const StringName &p_name, const Variant &p_value) {
while (index >= (int)layers.size()) {
TileMapLayer *new_layer = memnew(TileMapLayer);
add_child(new_layer, false, INTERNAL_MODE_FRONT);
new_layer->force_parent_owned();
new_layer->set_as_tile_map_internal_node(index);
new_layer->set_name(vformat("Layer%d", index));
new_layer->set_layer_index_in_tile_map_node(index);
new_layer->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TileMap::_emit_changed));
layers.push_back(new_layer);
}
@ -795,46 +792,34 @@ Rect2i TileMap::get_used_rect() const {
// --- Override some methods of the CanvasItem class to pass the changes to the quadrants CanvasItems ---
void TileMap::set_light_mask(int p_light_mask) {
// Occlusion: set light mask.
// Set light mask for occlusion and applies it to all layers too.
CanvasItem::set_light_mask(p_light_mask);
for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_LIGHT_MASK);
layer->set_light_mask(p_light_mask);
}
}
void TileMap::set_material(const Ref<Material> &p_material) {
// Set material for the whole tilemap.
CanvasItem::set_material(p_material);
// Update material for the whole tilemap.
void TileMap::set_self_modulate(const Color &p_self_modulate) {
// Set self_modulation and applies it to all layers too.
CanvasItem::set_self_modulate(p_self_modulate);
for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_MATERIAL);
}
}
void TileMap::set_use_parent_material(bool p_use_parent_material) {
// Set use_parent_material for the whole tilemap.
CanvasItem::set_use_parent_material(p_use_parent_material);
// Update use_parent_material for the whole tilemap.
for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_USE_PARENT_MATERIAL);
layer->set_self_modulate(p_self_modulate);
}
}
void TileMap::set_texture_filter(TextureFilter p_texture_filter) {
// Set a default texture filter for the whole tilemap.
// Set a default texture filter and applies it to all layers too.
CanvasItem::set_texture_filter(p_texture_filter);
for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_TEXTURE_FILTER);
layer->set_texture_filter(p_texture_filter);
}
}
void TileMap::set_texture_repeat(CanvasItem::TextureRepeat p_texture_repeat) {
// Set a default texture repeat for the whole tilemap.
// Set a default texture repeat and applies it to all layers too.
CanvasItem::set_texture_repeat(p_texture_repeat);
for (TileMapLayer *layer : layers) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_TILE_MAP_TEXTURE_REPEAT);
layer->set_texture_repeat(p_texture_repeat);
}
}
@ -1003,11 +988,10 @@ void TileMap::_bind_methods() {
TileMap::TileMap() {
TileMapLayer *new_layer = memnew(TileMapLayer);
add_child(new_layer, false, INTERNAL_MODE_FRONT);
new_layer->set_as_tile_map_internal_node(0);
new_layer->set_name("Layer0");
new_layer->set_layer_index_in_tile_map_node(0);
new_layer->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &TileMap::_emit_changed));
layers.push_back(new_layer);
default_layer = memnew(TileMapLayer);
}

View file

@ -46,9 +46,10 @@ enum TileMapDataFormat {
};
class TileMap : public TileMapLayerGroup {
GDCLASS(TileMap, TileMapLayerGroup);
GDCLASS(TileMap, TileMapLayerGroup)
public:
// Kept for compatibility, but should use TileMapLayer::VisibilityMode instead.
enum VisibilityMode {
VISIBILITY_MODE_DEFAULT,
VISIBILITY_MODE_FORCE_SHOW,
@ -187,8 +188,7 @@ public:
// Override some methods of the CanvasItem class to pass the changes to the quadrants CanvasItems.
virtual void set_light_mask(int p_light_mask) override;
virtual void set_material(const Ref<Material> &p_material) override;
virtual void set_use_parent_material(bool p_use_parent_material) override;
virtual void set_self_modulate(const Color &p_self_modulate) override;
virtual void set_texture_filter(CanvasItem::TextureFilter p_texture_filter) override;
virtual void set_texture_repeat(CanvasItem::TextureRepeat p_texture_repeat) override;

View file

@ -40,10 +40,6 @@
#include "servers/navigation_server_3d.h"
#endif // DEBUG_ENABLED
TileMap *TileMapLayer::_fetch_tilemap() const {
return TileMap::cast_to<TileMap>(get_parent());
}
#ifdef DEBUG_ENABLED
/////////////////////////////// Debug //////////////////////////////////////////
constexpr int TILE_MAP_DEBUG_QUADRANT_SIZE = 16;
@ -183,7 +179,6 @@ void TileMapLayer::_debug_quadrants_update_cell(CellData &r_cell_data, SelfList<
/////////////////////////////// Rendering //////////////////////////////////////
void TileMapLayer::_rendering_update() {
const TileMap *tile_map_node = _fetch_tilemap();
const Ref<TileSet> &tile_set = get_effective_tile_set();
RenderingServer *rs = RenderingServer::get_singleton();
@ -192,24 +187,23 @@ void TileMapLayer::_rendering_update() {
// ----------- Layer level processing -----------
if (!forced_cleanup) {
// Update the layer's CanvasItem.
set_use_parent_material(true);
set_light_mask(tile_map_node->get_light_mask());
// Modulate the layer.
Color layer_modulate = get_modulate();
#ifdef TOOLS_ENABLED
const Vector<StringName> selected_layers = tile_map_node->get_selected_layers();
if (tile_map_node->is_highlighting_selected_layer() && selected_layers.size() == 1 && get_name() != selected_layers[0]) {
TileMapLayer *selected_layer = Object::cast_to<TileMapLayer>(tile_map_node->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;
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;
}
}
}
}
@ -224,8 +218,8 @@ 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_TILE_MAP_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_TILE_MAP_Y_SORT_ENABLED] || dirty.flags[DIRTY_FLAGS_LAYER_LOCAL_TRANSFORM] || dirty.flags[DIRTY_FLAGS_LAYER_GROUP_TILE_SET]));
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]));
// Free all quadrants.
if (forced_cleanup || quandrant_shape_changed) {
@ -330,7 +324,7 @@ void TileMapLayer::_rendering_update() {
Transform2D xform(0, rendering_quadrant->canvas_items_position);
rs->canvas_item_set_transform(ci, xform);
rs->canvas_item_set_light_mask(ci, tile_map_node->get_light_mask());
rs->canvas_item_set_light_mask(ci, get_light_mask());
rs->canvas_item_set_z_as_relative_to_parent(ci, true);
rs->canvas_item_set_z_index(ci, tile_z_index);
@ -398,17 +392,15 @@ void TileMapLayer::_rendering_update() {
}
}
// Updates on TileMap changes.
if (dirty.flags[DIRTY_FLAGS_TILE_MAP_LIGHT_MASK] ||
dirty.flags[DIRTY_FLAGS_TILE_MAP_USE_PARENT_MATERIAL] ||
dirty.flags[DIRTY_FLAGS_TILE_MAP_MATERIAL] ||
dirty.flags[DIRTY_FLAGS_TILE_MAP_TEXTURE_FILTER] ||
dirty.flags[DIRTY_FLAGS_TILE_MAP_TEXTURE_REPEAT] ||
// Updates on rendering changes.
if (dirty.flags[DIRTY_FLAGS_LAYER_LIGHT_MASK] ||
dirty.flags[DIRTY_FLAGS_LAYER_TEXTURE_FILTER] ||
dirty.flags[DIRTY_FLAGS_LAYER_TEXTURE_REPEAT] ||
dirty.flags[DIRTY_FLAGS_LAYER_SELF_MODULATE]) {
for (KeyValue<Vector2i, Ref<RenderingQuadrant>> &kv : rendering_quadrant_map) {
Ref<RenderingQuadrant> &rendering_quadrant = kv.value;
for (const RID &ci : rendering_quadrant->canvas_items) {
rs->canvas_item_set_light_mask(ci, tile_map_node->get_light_mask());
rs->canvas_item_set_light_mask(ci, get_light_mask());
rs->canvas_item_set_default_texture_filter(ci, RS::CanvasItemTextureFilter(get_texture_filter_in_tree()));
rs->canvas_item_set_default_texture_repeat(ci, RS::CanvasItemTextureRepeat(get_texture_repeat_in_tree()));
rs->canvas_item_set_self_modulate(ci, get_self_modulate());
@ -465,7 +457,6 @@ void TileMapLayer::_rendering_notification(int p_what) {
}
void TileMapLayer::_rendering_quadrants_update_cell(CellData &r_cell_data, SelfList<RenderingQuadrant>::List &r_dirty_rendering_quadrant_list) {
const TileMap *tile_map_node = _fetch_tilemap();
const Ref<TileSet> &tile_set = get_effective_tile_set();
// Check if the cell is valid and retrieve its y_sort_origin.
@ -495,14 +486,13 @@ void TileMapLayer::_rendering_quadrants_update_cell(CellData &r_cell_data, SelfL
canvas_items_position = Vector2(0, tile_set->map_to_local(r_cell_data.coords).y + tile_y_sort_origin + y_sort_origin);
quadrant_coords = canvas_items_position * 100;
} else {
int quad_size = tile_map_node->get_rendering_quadrant_size();
const Vector2i &coords = r_cell_data.coords;
// Rounding down, instead of simply rounding towards zero (truncating).
quadrant_coords = Vector2i(
coords.x > 0 ? coords.x / quad_size : (coords.x - (quad_size - 1)) / quad_size,
coords.y > 0 ? coords.y / quad_size : (coords.y - (quad_size - 1)) / quad_size);
canvas_items_position = tile_set->map_to_local(quad_size * quadrant_coords);
coords.x > 0 ? coords.x / rendering_quadrant_size : (coords.x - (rendering_quadrant_size - 1)) / rendering_quadrant_size,
coords.y > 0 ? coords.y / rendering_quadrant_size : (coords.y - (rendering_quadrant_size - 1)) / rendering_quadrant_size);
canvas_items_position = tile_set->map_to_local(rendering_quadrant_size * quadrant_coords);
}
Ref<RenderingQuadrant> rendering_quadrant;
@ -767,7 +757,6 @@ void TileMapLayer::_physics_clear_cell(CellData &r_cell_data) {
}
void TileMapLayer::_physics_update_cell(CellData &r_cell_data) {
const TileMap *tile_map_node = _fetch_tilemap();
const Ref<TileSet> &tile_set = get_effective_tile_set();
Transform2D gl_transform = get_global_transform();
RID space = get_world_2d()->get_space();
@ -825,7 +814,7 @@ void TileMapLayer::_physics_update_cell(CellData &r_cell_data) {
body = ps->body_create();
}
bodies_coords[body] = r_cell_data.coords;
ps->body_set_mode(body, tile_map_node->is_collision_animatable() ? PhysicsServer2D::BODY_MODE_KINEMATIC : PhysicsServer2D::BODY_MODE_STATIC);
ps->body_set_mode(body, use_kinematic_bodies ? PhysicsServer2D::BODY_MODE_KINEMATIC : PhysicsServer2D::BODY_MODE_STATIC);
ps->body_set_space(body, space);
Transform2D xform;
@ -833,7 +822,7 @@ void TileMapLayer::_physics_update_cell(CellData &r_cell_data) {
xform = gl_transform * xform;
ps->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform);
ps->body_attach_object_instance_id(body, tile_map_node->get_instance_id());
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_pickable(body, false);
@ -885,7 +874,6 @@ 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.
TileMap *tile_map_node = _fetch_tilemap();
const Ref<TileSet> &tile_set = get_effective_tile_set();
ERR_FAIL_COND(!tile_set.is_valid());
@ -894,14 +882,14 @@ void TileMapLayer::_physics_draw_cell_debug(const RID &p_canvas_item, const Vect
}
bool show_collision = false;
switch (tile_map_node->get_collision_visibility_mode()) {
case TileMap::VISIBILITY_MODE_DEFAULT:
switch (collision_visibility_mode) {
case TileMapLayer::VISIBILITY_MODE_DEFAULT:
show_collision = !Engine::get_singleton()->is_editor_hint() && get_tree()->is_debugging_collisions_hint();
break;
case TileMap::VISIBILITY_MODE_FORCE_HIDE:
case TileMapLayer::VISIBILITY_MODE_FORCE_HIDE:
show_collision = false;
break;
case TileMap::VISIBILITY_MODE_FORCE_SHOW:
case TileMapLayer::VISIBILITY_MODE_FORCE_SHOW:
show_collision = true;
break;
}
@ -942,32 +930,32 @@ void TileMapLayer::_physics_draw_cell_debug(const RID &p_canvas_item, const Vect
void TileMapLayer::_navigation_update() {
ERR_FAIL_NULL(NavigationServer2D::get_singleton());
const Ref<TileSet> &tile_set = get_effective_tile_set();
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();
// ----------- Layer level processing -----------
if (forced_cleanup) {
if (navigation_map.is_valid() && !uses_world_navigation_map) {
ns->free(navigation_map);
navigation_map = RID();
}
} else {
// Update navigation maps.
if (!navigation_map.is_valid()) {
if (layer_index_in_tile_map_node == 0) {
// Use the default World2D navigation map for the first layer when empty.
navigation_map = get_world_2d()->get_navigation_map();
uses_world_navigation_map = true;
} else {
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_active(new_layer_map, true);
navigation_map = new_layer_map;
uses_world_navigation_map = false;
// All this processing is kept for compatibility with the TileMap node.
// Otherwise, layers shall use the World2D navigation map or define a custom one with set_navigation_map(...).
if (tile_map_node) {
if (forced_cleanup) {
if (navigation_map_override.is_valid()) {
ns->free(navigation_map_override);
navigation_map_override = RID();
}
} else {
// Update navigation maps.
if (!navigation_map_override.is_valid()) {
if (layer_index_in_tile_map_node > 0) {
// 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_active(new_layer_map, true);
navigation_map_override = new_layer_map;
}
}
}
}
@ -979,7 +967,7 @@ void TileMapLayer::_navigation_update() {
_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]) {
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]) {
// Update all cells.
for (KeyValue<Vector2i, CellData> &kv : tile_map) {
_navigation_update_cell(kv.value);
@ -1033,10 +1021,11 @@ void TileMapLayer::_navigation_clear_cell(CellData &r_cell_data) {
}
void TileMapLayer::_navigation_update_cell(CellData &r_cell_data) {
const TileMap *tile_map_node = _fetch_tilemap();
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();
ERR_FAIL_COND(navigation_map.is_null());
// Get the navigation polygons and create regions.
TileMapCell &c = r_cell_data.cell;
@ -1084,7 +1073,7 @@ void TileMapLayer::_navigation_update_cell(CellData &r_cell_data) {
if (!region.is_valid()) {
region = ns->region_create();
}
ns->region_set_owner_id(region, tile_map_node->get_instance_id());
ns->region_set_owner_id(region, tile_map_node ? tile_map_node->get_instance_id() : get_instance_id());
ns->region_set_map(region, navigation_map);
ns->region_set_transform(region, gl_xform * tile_transform);
ns->region_set_navigation_layers(region, tile_set->get_navigation_layer_layers(navigation_layer_index));
@ -1111,16 +1100,15 @@ void TileMapLayer::_navigation_update_cell(CellData &r_cell_data) {
#ifdef DEBUG_ENABLED
void TileMapLayer::_navigation_draw_cell_debug(const RID &p_canvas_item, const Vector2 &p_quadrant_pos, const CellData &r_cell_data) {
// Draw the debug collision shapes.
const TileMap *tile_map_node = _fetch_tilemap();
bool show_navigation = false;
switch (tile_map_node->get_navigation_visibility_mode()) {
case TileMap::VISIBILITY_MODE_DEFAULT:
switch (navigation_visibility_mode) {
case TileMapLayer::VISIBILITY_MODE_DEFAULT:
show_navigation = !Engine::get_singleton()->is_editor_hint() && get_tree()->is_debugging_navigation_hint();
break;
case TileMap::VISIBILITY_MODE_FORCE_HIDE:
case TileMapLayer::VISIBILITY_MODE_FORCE_HIDE:
show_navigation = false;
break;
case TileMap::VISIBILITY_MODE_FORCE_SHOW:
case TileMapLayer::VISIBILITY_MODE_FORCE_SHOW:
show_navigation = true;
break;
}
@ -1250,13 +1238,14 @@ void TileMapLayer::_scenes_update() {
}
void TileMapLayer::_scenes_clear_cell(CellData &r_cell_data) {
const TileMap *tile_map_node = _fetch_tilemap();
if (!tile_map_node) {
return;
}
// Cleanup existing scene.
Node *node = tile_map_node->get_node_or_null(r_cell_data.scene);
Node *node = nullptr;
if (tile_map_node) {
// Compatibility with TileMap.
node = tile_map_node->get_node_or_null(r_cell_data.scene);
} else {
node = get_node_or_null(r_cell_data.scene);
}
if (node) {
node->queue_free();
}
@ -1264,7 +1253,6 @@ void TileMapLayer::_scenes_clear_cell(CellData &r_cell_data) {
}
void TileMapLayer::_scenes_update_cell(CellData &r_cell_data) {
TileMap *tile_map_node = _fetch_tilemap();
const Ref<TileSet> &tile_set = get_effective_tile_set();
// Clear the scene in any case.
@ -1292,7 +1280,12 @@ void TileMapLayer::_scenes_update_cell(CellData &r_cell_data) {
xform.set_origin(tile_set->map_to_local(r_cell_data.coords));
scene_as_node2d->set_transform(xform * scene_as_node2d->get_transform());
}
tile_map_node->add_child(scene);
if (tile_map_node) {
// Compatibility with TileMap.
tile_map_node->add_child(scene);
} else {
add_child(scene);
}
r_cell_data.scene = scene->get_name();
}
}
@ -1352,26 +1345,28 @@ void TileMapLayer::_scenes_draw_cell_debug(const RID &p_canvas_item, const Vecto
/////////////////////////////////////////////////////////////////////
void TileMapLayer::_build_runtime_update_tile_data() {
const TileMap *tile_map_node = _fetch_tilemap();
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();
if (!forced_cleanup) {
if (tile_map_node->GDVIRTUAL_IS_OVERRIDDEN(_use_tile_data_runtime_update) && tile_map_node->GDVIRTUAL_IS_OVERRIDDEN(_tile_data_runtime_update)) {
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]) {
_runtime_update_needs_all_cells_cleaned_up = true;
for (KeyValue<Vector2i, CellData> &E : tile_map) {
_build_runtime_update_tile_data_for_cell(E.value);
_build_runtime_update_tile_data_for_cell(E.value, use_tilemap_for_runtime);
}
} else if (dirty.flags[DIRTY_FLAGS_TILE_MAP_RUNTIME_UPDATE]) {
} else if (dirty.flags[DIRTY_FLAGS_LAYER_RUNTIME_UPDATE]) {
for (KeyValue<Vector2i, CellData> &E : tile_map) {
_build_runtime_update_tile_data_for_cell(E.value, true);
_build_runtime_update_tile_data_for_cell(E.value, use_tilemap_for_runtime, true);
}
} else {
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();
_build_runtime_update_tile_data_for_cell(cell_data);
_build_runtime_update_tile_data_for_cell(cell_data, use_tilemap_for_runtime);
}
}
}
@ -1382,8 +1377,7 @@ void TileMapLayer::_build_runtime_update_tile_data() {
_runtime_update_tile_data_was_cleaned_up = forced_cleanup;
}
void TileMapLayer::_build_runtime_update_tile_data_for_cell(CellData &r_cell_data, bool p_auto_add_to_dirty_list) {
TileMap *tile_map_node = _fetch_tilemap();
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;
@ -1395,18 +1389,37 @@ void TileMapLayer::_build_runtime_update_tile_data_for_cell(CellData &r_cell_dat
TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source);
if (atlas_source) {
bool ret = false;
if (tile_map_node->GDVIRTUAL_CALL(_use_tile_data_runtime_update, layer_index_in_tile_map_node, r_cell_data.coords, ret) && ret) {
TileData *tile_data = atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile);
// Create the runtime TileData.
TileData *tile_data_runtime_use = tile_data->duplicate();
tile_data_runtime_use->set_allow_transform(true);
r_cell_data.runtime_tile_data_cache = tile_data_runtime_use;
if (p_use_tilemap_for_runtime) {
// Compatibility with TileMap.
if (tile_map_node->GDVIRTUAL_CALL(_use_tile_data_runtime_update, layer_index_in_tile_map_node, r_cell_data.coords, ret) && ret) {
TileData *tile_data = atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile);
tile_map_node->GDVIRTUAL_CALL(_tile_data_runtime_update, layer_index_in_tile_map_node, r_cell_data.coords, tile_data_runtime_use);
// Create the runtime TileData.
TileData *tile_data_runtime_use = tile_data->duplicate();
tile_data_runtime_use->set_allow_transform(true);
r_cell_data.runtime_tile_data_cache = tile_data_runtime_use;
if (p_auto_add_to_dirty_list) {
dirty.cell_list.add(&r_cell_data.dirty_list_element);
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) {
dirty.cell_list.add(&r_cell_data.dirty_list_element);
}
}
} else {
if (GDVIRTUAL_CALL(_use_tile_data_runtime_update, r_cell_data.coords, ret) && ret) {
TileData *tile_data = atlas_source->get_tile_data(c.get_atlas_coords(), c.alternative_tile);
// Create the runtime TileData.
TileData *tile_data_runtime_use = tile_data->duplicate();
tile_data_runtime_use->set_allow_transform(true);
r_cell_data.runtime_tile_data_cache = tile_data_runtime_use;
GDVIRTUAL_CALL(_tile_data_runtime_update, r_cell_data.coords, tile_data_runtime_use);
if (p_auto_add_to_dirty_list) {
dirty.cell_list.add(&r_cell_data.dirty_list_element);
}
}
}
}
@ -1611,8 +1624,7 @@ void TileMapLayer::_renamed() {
}
void TileMapLayer::_update_notify_local_transform() {
TileMap *tile_map_node = _fetch_tilemap();
bool notify = tile_map_node->is_collision_animatable() || is_y_sort_enabled();
bool notify = is_using_kinematic_bodies() || is_y_sort_enabled();
if (!notify) {
if (is_y_sort_enabled()) {
notify = true;
@ -1727,16 +1739,23 @@ void TileMapLayer::_notification(int p_what) {
void TileMapLayer::_bind_methods() {
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));
GDVIRTUAL_BIND(_use_tile_data_runtime_update, "coords");
GDVIRTUAL_BIND(_tile_data_runtime_update, "coords", "tile_data");
ADD_SIGNAL(MethodInfo(CoreStringNames::get_singleton()->changed));
}
void TileMapLayer::set_layer_index_in_tile_map_node(int p_index) {
if (p_index == layer_index_in_tile_map_node) {
return;
void TileMapLayer::set_as_tile_map_internal_node(int p_index) {
// Compatibility with TileMap.
ERR_FAIL_NULL(get_parent());
tile_map_node = Object::cast_to<TileMap>(get_parent());
set_use_parent_material(true);
force_parent_owned();
if (layer_index_in_tile_map_node != p_index) {
layer_index_in_tile_map_node = p_index;
dirty.flags[DIRTY_FLAGS_LAYER_INDEX_IN_TILE_MAP_NODE] = true;
_queue_internal_update();
}
layer_index_in_tile_map_node = p_index;
dirty.flags[DIRTY_FLAGS_LAYER_INDEX_IN_TILE_MAP_NODE] = true;
_queue_internal_update();
}
Rect2 TileMapLayer::get_rect(bool &r_changed) const {
@ -2085,7 +2104,7 @@ void TileMapLayer::set_tile_data(TileMapDataFormat p_format, const Vector<int> &
clear();
#ifdef DISABLE_DEPRECATED
ERR_FAIL_COND_MSG(p_format != TileMapDataFormat::FORMAT_3, vformat("Cannot handle deprecated TileMap data format version %d. This Godot version was compiled with no support for deprecated data.", p_format));
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) {
@ -2176,7 +2195,7 @@ Vector<int> TileMapLayer::get_tile_data() const {
return tile_data;
}
void TileMapLayer::notify_tile_map_change(DirtyFlags p_what) {
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) {
@ -2192,6 +2211,12 @@ void TileMapLayer::update_internals() {
_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) {
// Set the current cell tile (using integer position).
Vector2i pk(p_coords);
@ -2532,8 +2557,9 @@ void TileMapLayer::set_enabled(bool p_enabled) {
_queue_internal_update();
emit_signal(CoreStringNames::get_singleton()->changed);
TileMap *tile_map_node = _fetch_tilemap();
tile_map_node->update_configuration_warnings();
if (tile_map_node) {
tile_map_node->update_configuration_warnings();
}
}
bool TileMapLayer::is_enabled() const {
@ -2559,8 +2585,9 @@ void TileMapLayer::set_y_sort_enabled(bool p_y_sort_enabled) {
_queue_internal_update();
emit_signal(CoreStringNames::get_singleton()->changed);
TileMap *tile_map_node = _fetch_tilemap();
tile_map_node->update_configuration_warnings();
if (tile_map_node) {
tile_map_node->update_configuration_warnings();
}
_update_notify_local_transform();
}
@ -2587,8 +2614,51 @@ void TileMapLayer::set_z_index(int p_z_index) {
_queue_internal_update();
emit_signal(CoreStringNames::get_singleton()->changed);
TileMap *tile_map_node = _fetch_tilemap();
tile_map_node->update_configuration_warnings();
if (tile_map_node) {
tile_map_node->update_configuration_warnings();
}
}
void TileMapLayer::set_light_mask(int p_light_mask) {
if (get_light_mask() == p_light_mask) {
return;
}
CanvasItem::set_light_mask(p_light_mask);
dirty.flags[DIRTY_FLAGS_LAYER_LIGHT_MASK] = true;
_queue_internal_update();
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;
}
dirty.flags[DIRTY_FLAGS_LAYER_RENDERING_QUADRANT_SIZE] = true;
ERR_FAIL_COND_MSG(p_size < 1, "TileMapQuadrant size cannot be smaller than 1.");
rendering_quadrant_size = p_size;
_queue_internal_update();
emit_signal(CoreStringNames::get_singleton()->changed);
}
int TileMapLayer::get_rendering_quadrant_size() const {
return rendering_quadrant_size;
}
void TileMapLayer::set_use_kinematic_bodies(bool p_use_kinematic_bodies) {
@ -2602,6 +2672,20 @@ bool TileMapLayer::is_using_kinematic_bodies() const {
return use_kinematic_bodies;
}
void TileMapLayer::set_collision_visibility_mode(TileMapLayer::VisibilityMode p_show_collision) {
if (collision_visibility_mode == p_show_collision) {
return;
}
collision_visibility_mode = p_show_collision;
dirty.flags[DIRTY_FLAGS_LAYER_COLLISION_VISIBILITY_MODE] = true;
_queue_internal_update();
emit_signal(CoreStringNames::get_singleton()->changed);
}
TileMapLayer::VisibilityMode TileMapLayer::get_collision_visibility_mode() const {
return collision_visibility_mode;
}
void TileMapLayer::set_navigation_enabled(bool p_enabled) {
if (navigation_enabled == p_enabled) {
return;
@ -2617,18 +2701,38 @@ bool TileMapLayer::is_navigation_enabled() const {
}
void TileMapLayer::set_navigation_map(RID p_map) {
ERR_FAIL_COND_MSG(!is_inside_tree(), "A TileMap navigation map can only be changed while inside the SceneTree.");
navigation_map = p_map;
uses_world_navigation_map = p_map == get_world_2d()->get_navigation_map();
if (navigation_map_override == p_map) {
return;
}
navigation_map_override = p_map;
dirty.flags[DIRTY_FLAGS_LAYER_NAVIGATION_MAP] = true;
_queue_internal_update();
emit_signal(CoreStringNames::get_singleton()->changed);
}
RID TileMapLayer::get_navigation_map() const {
if (navigation_map.is_valid()) {
return navigation_map;
if (navigation_map_override.is_valid()) {
return navigation_map_override;
} else if (is_inside_tree()) {
return get_world_2d()->get_navigation_map();
}
return RID();
}
void TileMapLayer::set_navigation_visibility_mode(TileMapLayer::VisibilityMode p_show_navigation) {
if (navigation_visibility_mode == p_show_navigation) {
return;
}
navigation_visibility_mode = p_show_navigation;
dirty.flags[DIRTY_FLAGS_LAYER_NAVIGATION_VISIBILITY_MODE] = true;
_queue_internal_update();
emit_signal(CoreStringNames::get_singleton()->changed);
}
TileMapLayer::VisibilityMode 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.");

View file

@ -218,6 +218,12 @@ class TileMapLayer : public Node2D {
GDCLASS(TileMapLayer, Node2D);
public:
enum VisibilityMode {
VISIBILITY_MODE_DEFAULT,
VISIBILITY_MODE_FORCE_SHOW,
VISIBILITY_MODE_FORCE_HIDE,
};
enum DirtyFlags {
DIRTY_FLAGS_LAYER_ENABLED = 0,
DIRTY_FLAGS_LAYER_IN_TREE,
@ -228,24 +234,23 @@ public:
DIRTY_FLAGS_LAYER_Y_SORT_ENABLED,
DIRTY_FLAGS_LAYER_Y_SORT_ORIGIN,
DIRTY_FLAGS_LAYER_Z_INDEX,
DIRTY_FLAGS_LAYER_LIGHT_MASK,
DIRTY_FLAGS_LAYER_TEXTURE_FILTER,
DIRTY_FLAGS_LAYER_TEXTURE_REPEAT,
DIRTY_FLAGS_LAYER_RENDERING_QUADRANT_SIZE,
DIRTY_FLAGS_LAYER_USE_KINEMATIC_BODIES,
DIRTY_FLAGS_LAYER_COLLISION_VISIBILITY_MODE,
DIRTY_FLAGS_LAYER_NAVIGATION_ENABLED,
DIRTY_FLAGS_LAYER_INDEX_IN_TILE_MAP_NODE,
DIRTY_FLAGS_LAYER_NAVIGATION_MAP,
DIRTY_FLAGS_LAYER_NAVIGATION_VISIBILITY_MODE,
DIRTY_FLAGS_LAYER_RUNTIME_UPDATE,
DIRTY_FLAGS_LAYER_INDEX_IN_TILE_MAP_NODE, // For compatibility.
DIRTY_FLAGS_LAYER_GROUP_SELECTED_LAYERS,
DIRTY_FLAGS_LAYER_GROUP_HIGHLIGHT_SELECTED,
DIRTY_FLAGS_LAYER_GROUP_TILE_SET,
DIRTY_FLAGS_TILE_MAP_LIGHT_MASK,
DIRTY_FLAGS_TILE_MAP_MATERIAL,
DIRTY_FLAGS_TILE_MAP_USE_PARENT_MATERIAL,
DIRTY_FLAGS_TILE_MAP_TEXTURE_FILTER,
DIRTY_FLAGS_TILE_MAP_TEXTURE_REPEAT,
DIRTY_FLAGS_TILE_MAP_QUADRANT_SIZE,
DIRTY_FLAGS_TILE_MAP_COLLISION_VISIBILITY_MODE,
DIRTY_FLAGS_TILE_MAP_NAVIGATION_VISIBILITY_MODE,
DIRTY_FLAGS_TILE_MAP_Y_SORT_ENABLED,
DIRTY_FLAGS_TILE_MAP_RUNTIME_UPDATE,
DIRTY_FLAGS_MAX,
};
@ -253,16 +258,23 @@ private:
// Exposed properties.
bool enabled = true;
int y_sort_origin = 0;
int rendering_quadrant_size = 16;
bool use_kinematic_bodies = false;
VisibilityMode collision_visibility_mode = VISIBILITY_MODE_DEFAULT;
bool navigation_enabled = true;
RID navigation_map;
bool uses_world_navigation_map = false;
RID navigation_map_override;
VisibilityMode navigation_visibility_mode = VISIBILITY_MODE_DEFAULT;
// Internal.
int layer_index_in_tile_map_node = -1;
HashMap<Vector2i, CellData> tile_map;
bool pending_update = false;
// For keeping compatibility with TileMap.
TileMap *tile_map_node = nullptr;
int layer_index_in_tile_map_node = -1;
// Dirty flag. Allows knowing what was modified since the last update.
struct {
bool flags[DIRTY_FLAGS_MAX] = { false };
@ -276,13 +288,10 @@ private:
mutable Rect2i used_rect_cache;
mutable bool used_rect_cache_dirty = true;
// Method to fetch the TileSet to use
TileMap *_fetch_tilemap() const;
// Runtime tile data.
bool _runtime_update_tile_data_was_cleaned_up = false;
void _build_runtime_update_tile_data();
void _build_runtime_update_tile_data_for_cell(CellData &r_cell_data, bool p_auto_add_to_dirty_list = false);
void _build_runtime_update_tile_data_for_cell(CellData &r_cell_data, bool p_use_tilemap_for_runtime, bool p_auto_add_to_dirty_list = false);
bool _runtime_update_needs_all_cells_cleaned_up = false;
void _clear_runtime_update_tile_data();
void _clear_runtime_update_tile_data_for_cell(CellData &r_cell_data);
@ -353,7 +362,7 @@ protected:
public:
// TileMap node.
void set_layer_index_in_tile_map_node(int p_index);
void set_as_tile_map_internal_node(int p_index);
// Rect caching.
Rect2 get_rect(bool &r_changed) const;
@ -370,9 +379,10 @@ public:
// For TileMap node's use.
void set_tile_data(TileMapDataFormat p_format, const Vector<int> &p_data);
Vector<int> get_tile_data() const;
void notify_tile_map_change(DirtyFlags p_what);
void notify_tile_map_layer_group_change(DirtyFlags p_what);
void update_internals();
void notify_runtime_tile_data_update();
// --- Exposed in TileMap ---
// Cells manipulation.
@ -406,12 +416,23 @@ public:
void set_y_sort_origin(int p_y_sort_origin);
int get_y_sort_origin() const;
virtual void set_z_index(int p_z_index) override;
virtual void set_light_mask(int p_light_mask) override;
virtual void set_texture_filter(CanvasItem::TextureFilter p_texture_filter) override;
virtual void set_texture_repeat(CanvasItem::TextureRepeat p_texture_repeat) override;
void set_rendering_quadrant_size(int p_size);
int get_rendering_quadrant_size() const;
void set_use_kinematic_bodies(bool p_use_kinematic_bodies);
bool is_using_kinematic_bodies() const;
void set_collision_visibility_mode(VisibilityMode p_show_collision);
VisibilityMode get_collision_visibility_mode() const;
void set_navigation_enabled(bool p_enabled);
bool is_navigation_enabled() const;
void set_navigation_map(RID p_map);
RID get_navigation_map() const;
void set_navigation_visibility_mode(VisibilityMode p_show_navigation);
VisibilityMode get_navigation_visibility_mode() const;
// Fixing and clearing methods.
void fix_invalid_tiles();
@ -423,6 +444,9 @@ public:
// Helper.
Ref<TileSet> get_effective_tile_set() const;
// Virtual function to modify the TileData at runtime.
GDVIRTUAL1R(bool, _use_tile_data_runtime_update, Vector2i);
GDVIRTUAL2(_tile_data_runtime_update, Vector2i, TileData *);
// ---
TileMapLayer();

View file

@ -53,7 +53,7 @@ void TileMapLayerGroup::_tile_set_changed() {
for (int i = 0; i < get_child_count(); i++) {
TileMapLayer *layer = Object::cast_to<TileMapLayer>(get_child(i));
if (layer) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_LAYER_GROUP_TILE_SET);
layer->notify_tile_map_layer_group_change(TileMapLayer::DIRTY_FLAGS_LAYER_GROUP_TILE_SET);
}
}
@ -70,7 +70,7 @@ void TileMapLayerGroup::set_selected_layers(Vector<StringName> p_layer_names) {
for (int i = 0; i < get_child_count(); i++) {
TileMapLayer *layer = Object::cast_to<TileMapLayer>(get_child(i));
if (layer) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_LAYER_GROUP_SELECTED_LAYERS);
layer->notify_tile_map_layer_group_change(TileMapLayer::DIRTY_FLAGS_LAYER_GROUP_SELECTED_LAYERS);
}
}
}
@ -89,7 +89,7 @@ void TileMapLayerGroup::set_highlight_selected_layer(bool p_highlight_selected_l
for (int i = 0; i < get_child_count(); i++) {
TileMapLayer *layer = Object::cast_to<TileMapLayer>(get_child(i));
if (layer) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_LAYER_GROUP_HIGHLIGHT_SELECTED);
layer->notify_tile_map_layer_group_change(TileMapLayer::DIRTY_FLAGS_LAYER_GROUP_HIGHLIGHT_SELECTED);
}
}
}
@ -132,7 +132,7 @@ void TileMapLayerGroup::set_tileset(const Ref<TileSet> &p_tileset) {
for (int i = 0; i < get_child_count(); i++) {
TileMapLayer *layer = Object::cast_to<TileMapLayer>(get_child(i));
if (layer) {
layer->notify_tile_map_change(TileMapLayer::DIRTY_FLAGS_LAYER_GROUP_TILE_SET);
layer->notify_tile_map_layer_group_change(TileMapLayer::DIRTY_FLAGS_LAYER_GROUP_TILE_SET);
}
}
}