From 787c784aca28f19841b2eb79b702e517007d9901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gilles=20Roudi=C3=A8re?= Date: Wed, 28 Feb 2024 17:17:46 +0100 Subject: [PATCH] Remove almost all remaining dependencies of TileMapLayer on TileMap --- scene/2d/tile_map.cpp | 60 ++---- scene/2d/tile_map.h | 6 +- scene/2d/tile_map_layer.cpp | 338 +++++++++++++++++++----------- scene/2d/tile_map_layer.h | 64 ++++-- scene/2d/tile_map_layer_group.cpp | 8 +- 5 files changed, 294 insertions(+), 182 deletions(-) diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 48fe2afccce..f8737730ba9 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -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 &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); } diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index c9844f29af7..edea90fa95f 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -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 &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; diff --git a/scene/2d/tile_map_layer.cpp b/scene/2d/tile_map_layer.cpp index c9431f53d8e..c7aa4c2be44 100644 --- a/scene/2d/tile_map_layer.cpp +++ b/scene/2d/tile_map_layer.cpp @@ -40,10 +40,6 @@ #include "servers/navigation_server_3d.h" #endif // DEBUG_ENABLED -TileMap *TileMapLayer::_fetch_tilemap() const { - return TileMap::cast_to(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 &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 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(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(get_parent()); + if (tile_map_layer_group) { + const Vector 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(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> &kv : rendering_quadrant_map) { Ref &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::List &r_dirty_rendering_quadrant_list) { - const TileMap *tile_map_node = _fetch_tilemap(); const Ref &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 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 &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 &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 &tile_set = get_effective_tile_set(); NavigationServer2D *ns = NavigationServer2D::get_singleton(); + const Ref &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 &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 &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 &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 &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 &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 &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 *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 &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(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(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 & 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 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 = get_effective_tile_set(); ERR_FAIL_COND_MSG(tileset.is_null(), "Cannot call fix_invalid_tiles() on a TileMap without a valid TileSet."); diff --git a/scene/2d/tile_map_layer.h b/scene/2d/tile_map_layer.h index 5a0c51d7e5f..c58c72949c2 100644 --- a/scene/2d/tile_map_layer.h +++ b/scene/2d/tile_map_layer.h @@ -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 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 &p_data); Vector 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 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(); diff --git a/scene/2d/tile_map_layer_group.cpp b/scene/2d/tile_map_layer_group.cpp index c5965344745..132b4bbba54 100644 --- a/scene/2d/tile_map_layer_group.cpp +++ b/scene/2d/tile_map_layer_group.cpp @@ -53,7 +53,7 @@ void TileMapLayerGroup::_tile_set_changed() { for (int i = 0; i < get_child_count(); i++) { TileMapLayer *layer = Object::cast_to(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 p_layer_names) { for (int i = 0; i < get_child_count(); i++) { TileMapLayer *layer = Object::cast_to(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(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 &p_tileset) { for (int i = 0; i < get_child_count(); i++) { TileMapLayer *layer = Object::cast_to(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); } } }