Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a way to know when a TileMapLayer's cell is modified #96188

Merged
merged 1 commit into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions doc/classes/TileMapLayer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,21 @@
[b]Note:[/b] If the properties of [param tile_data] object should change over time, use [method notify_runtime_tile_data_update] to notify the [TileMapLayer] it needs an update.
</description>
</method>
<method name="_update_cells" qualifiers="virtual">
<return type="void" />
<param index="0" name="coords" type="Vector2i[]" />
<param index="1" name="forced_cleanup" type="bool" />
<description>
Called when this [TileMapLayer]'s cells need an internal update. This update may be caused from individual cells being modified or by a change in the [member tile_set] (causing all cells to be queued for an update). The first call to this function is always for initializing all the [TileMapLayer]'s cells. [param coords] contains the coordinates of all modified cells, roughly in the order they were modified. [param forced_cleanup] is [code]true[/code] when the [TileMapLayer]'s internals should be fully cleaned up. This is the case when:
- The layer is disabled;
- The layer is not visible;
- [member tile_set] is set to [code]null[/code];
- The node is removed from the tree;
- The node is freed.
Note that any internal update happening while one of these conditions is verified is considered to be a "cleanup". See also [method update_internals].
[b]Warning:[/b] Implementing this method may degrade the [TileMapLayer]'s performance.
</description>
</method>
<method name="_use_tile_data_runtime_update" qualifiers="virtual">
<return type="bool" />
<param index="0" name="coords" type="Vector2i" />
Expand Down
23 changes: 23 additions & 0 deletions scene/2d/tile_map_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1460,6 +1460,24 @@ void TileMapLayer::_clear_runtime_update_tile_data_for_cell(CellData &r_cell_dat
}
}

void TileMapLayer::_update_cells_callback(bool p_force_cleanup) {
if (!GDVIRTUAL_IS_OVERRIDDEN(_update_cells)) {
return;
}

// Check if we should cleanup everything.
bool forced_cleanup = p_force_cleanup || !enabled || tile_set.is_null() || !is_visible_in_tree();

// List all the dirty cell's positions to notify script of cell updates.
TypedArray<Vector2i> dirty_cell_positions;
for (SelfList<CellData> *cell_data_list_element = dirty.cell_list.first(); cell_data_list_element; cell_data_list_element = cell_data_list_element->next()) {
CellData &cell_data = *cell_data_list_element->self();
dirty_cell_positions.push_back(cell_data.coords);
}

GDVIRTUAL_CALL(_update_cells, dirty_cell_positions, forced_cleanup);
}

TileSet::TerrainsPattern TileMapLayer::_get_best_terrain_pattern_for_constraints(int p_terrain_set, const Vector2i &p_position, const RBSet<TerrainConstraint> &p_constraints, TileSet::TerrainsPattern p_current_pattern) const {
if (tile_set.is_null()) {
return TileSet::TerrainsPattern();
Expand Down Expand Up @@ -1673,6 +1691,10 @@ void TileMapLayer::_internal_update(bool p_force_cleanup) {
// This may add cells to the dirty list if a runtime modification has been notified.
_build_runtime_update_tile_data(p_force_cleanup);

// Callback for implementing custom subsystems.
// This may add to the dirty list if some cells are changed inside _update_cells.
_update_cells_callback(p_force_cleanup);

// Update all subsystems.
_rendering_update(p_force_cleanup);
_physics_update(p_force_cleanup);
Expand Down Expand Up @@ -1861,6 +1883,7 @@ void TileMapLayer::_bind_methods() {

GDVIRTUAL_BIND(_use_tile_data_runtime_update, "coords");
GDVIRTUAL_BIND(_tile_data_runtime_update, "coords", "tile_data");
GDVIRTUAL_BIND(_update_cells, "coords", "forced_cleanup");

ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "tile_map_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_tile_map_data_from_array", "get_tile_map_data_as_array");

Expand Down
2 changes: 2 additions & 0 deletions scene/2d/tile_map_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ class TileMapLayer : public Node2D {
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);
void _update_cells_callback(bool p_force_cleanup);

// Per-system methods.
#ifdef DEBUG_ENABLED
Expand Down Expand Up @@ -462,6 +463,7 @@ class TileMapLayer : public Node2D {
void notify_runtime_tile_data_update();
GDVIRTUAL1R(bool, _use_tile_data_runtime_update, Vector2i);
GDVIRTUAL2(_tile_data_runtime_update, Vector2i, TileData *);
GDVIRTUAL2(_update_cells, TypedArray<Vector2i>, bool);

// --- Shortcuts to methods defined in TileSet ---
Vector2i map_pattern(const Vector2i &p_position_in_tilemap, const Vector2i &p_coords_in_pattern, Ref<TileMapPattern> p_pattern);
Expand Down