Skip to content

Commit adfb0d8

Browse files
committed
Optimize TileMapLayer
1 parent c2202d3 commit adfb0d8

File tree

2 files changed

+52
-19
lines changed

2 files changed

+52
-19
lines changed

scene/2d/tile_map_layer.cpp

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ void TileMapLayer::_debug_update(bool p_force_cleanup) {
6464

6565
// Check if we should cleanup everything.
6666
bool forced_cleanup = p_force_cleanup || !enabled || tile_set.is_null() || !is_visible_in_tree();
67+
if (forced_cleanup && _debug_was_cleaned_up) {
68+
return;
69+
}
6770

6871
if (forced_cleanup) {
6972
for (KeyValue<Vector2i, Ref<DebugQuadrant>> &kv : debug_quadrant_map) {
@@ -203,6 +206,9 @@ void TileMapLayer::_rendering_update(bool p_force_cleanup) {
203206

204207
// Check if we should cleanup everything.
205208
bool forced_cleanup = p_force_cleanup || !enabled || tile_set.is_null() || !is_visible_in_tree();
209+
if (forced_cleanup && _rendering_was_cleaned_up) {
210+
return;
211+
}
206212

207213
// ----------- Layer level processing -----------
208214
if (!forced_cleanup) {
@@ -231,7 +237,7 @@ void TileMapLayer::_rendering_update(bool p_force_cleanup) {
231237
(!is_y_sort_enabled() && dirty.flags[DIRTY_FLAGS_LAYER_RENDERING_QUADRANT_SIZE]);
232238

233239
// Free all quadrants.
234-
if (forced_cleanup || quadrant_shape_changed) {
240+
if (!_rendering_was_cleaned_up && (forced_cleanup || quadrant_shape_changed)) {
235241
for (const KeyValue<Vector2i, Ref<RenderingQuadrant>> &kv : rendering_quadrant_map) {
236242
for (const RID &ci : kv.value->canvas_items) {
237243
if (ci.is_valid()) {
@@ -395,15 +401,23 @@ void TileMapLayer::_rendering_update(bool p_force_cleanup) {
395401
int index = -(int64_t)0x80000000; // Always must be drawn below children.
396402

397403
// Sort the quadrants coords per local coordinates.
398-
RBMap<Vector2, Ref<RenderingQuadrant>, RenderingQuadrant::CoordsWorldComparator> local_to_map;
404+
LocalVector<Pair<Vector2, Ref<RenderingQuadrant>>> sortable_quadrant_keys;
405+
sortable_quadrant_keys.reserve(rendering_quadrant_map.size());
399406
for (KeyValue<Vector2i, Ref<RenderingQuadrant>> &kv : rendering_quadrant_map) {
400-
Ref<RenderingQuadrant> &rendering_quadrant = kv.value;
401-
local_to_map[tile_set->map_to_local(rendering_quadrant->quadrant_coords)] = rendering_quadrant;
407+
Vector2 local_coords = tile_set->map_to_local(kv.value->quadrant_coords);
408+
sortable_quadrant_keys.push_back(Pair<Vector2, Ref<RenderingQuadrant>>(local_coords, kv.value));
402409
}
410+
struct PairedQuadrantSorter {
411+
RenderingQuadrant::CoordsWorldComparator comparator;
412+
_ALWAYS_INLINE_ bool operator()(const Pair<Vector2, Ref<RenderingQuadrant>> &p_a, const Pair<Vector2, Ref<RenderingQuadrant>> &p_b) const {
413+
return comparator(p_a.first, p_b.first);
414+
}
415+
};
416+
sortable_quadrant_keys.sort_custom<PairedQuadrantSorter>();
403417

404-
// Sort the quadrants.
405-
for (const KeyValue<Vector2, Ref<RenderingQuadrant>> &E : local_to_map) {
406-
for (const RID &ci : E.value->canvas_items) {
418+
// Set the draw indices.
419+
for (const Pair<Vector2, Ref<RenderingQuadrant>> &E : sortable_quadrant_keys) {
420+
for (const RID &ci : E.second->canvas_items) {
407421
RS::get_singleton()->canvas_item_set_draw_index(ci, index++);
408422
}
409423
}
@@ -426,14 +440,23 @@ void TileMapLayer::_rendering_update(bool p_force_cleanup) {
426440
}
427441
}
428442

443+
// -----------
444+
// Mark the rendering state as up to date.
445+
_rendering_was_cleaned_up = forced_cleanup;
446+
429447
// ----------- Occluders processing -----------
430-
if (forced_cleanup || !occlusion_enabled) {
448+
bool cleanup_occlusion = forced_cleanup || !occlusion_enabled;
449+
if (cleanup_occlusion && _occlusion_was_cleaned_up) {
450+
return;
451+
}
452+
453+
if (cleanup_occlusion) {
431454
// Clean everything.
432455
for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
433456
_rendering_occluders_clear_cell(kv.value);
434457
}
435458
} else {
436-
if (_rendering_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_SET]) {
459+
if (_occlusion_was_cleaned_up || dirty.flags[DIRTY_FLAGS_TILE_SET]) {
437460
// Update all cells.
438461
for (KeyValue<Vector2i, CellData> &kv : tile_map_layer_data) {
439462
_rendering_occluders_update_cell(kv.value);
@@ -448,8 +471,8 @@ void TileMapLayer::_rendering_update(bool p_force_cleanup) {
448471
}
449472

450473
// -----------
451-
// Mark the rendering state as up to date.
452-
_rendering_was_cleaned_up = forced_cleanup || !occlusion_enabled;
474+
// Mark the occlusion state as up to date.
475+
_occlusion_was_cleaned_up = cleanup_occlusion;
453476
}
454477

455478
void TileMapLayer::_rendering_notification(int p_what) {
@@ -718,6 +741,9 @@ void TileMapLayer::_physics_update(bool p_force_cleanup) {
718741

719742
// Check if we should cleanup everything.
720743
bool forced_cleanup = p_force_cleanup || !enabled || !collision_enabled || !is_inside_tree() || tile_set.is_null();
744+
if (forced_cleanup && _physics_was_cleaned_up) {
745+
return;
746+
}
721747

722748
// ----------- Quadrants processing -----------
723749

@@ -729,7 +755,7 @@ void TileMapLayer::_physics_update(bool p_force_cleanup) {
729755
bool quadrant_shape_changed = dirty.flags[DIRTY_FLAGS_TILE_SET] || dirty.flags[DIRTY_FLAGS_LAYER_PHYSICS_QUADRANT_SIZE];
730756

731757
// Free all quadrants.
732-
if (forced_cleanup || quadrant_shape_changed) {
758+
if (!_physics_was_cleaned_up && (forced_cleanup || quadrant_shape_changed)) {
733759
for (const KeyValue<Vector2i, Ref<PhysicsQuadrant>> &kv : physics_quadrant_map) {
734760
// Clear bodies.
735761
for (KeyValue<PhysicsQuadrant::PhysicsBodyKey, PhysicsQuadrant::PhysicsBodyValue> &kvbody : kv.value->bodies) {
@@ -936,7 +962,7 @@ void TileMapLayer::_physics_update(bool p_force_cleanup) {
936962

937963
// -----------
938964
// Mark the physics state as up to date.
939-
_physics_was_cleaned_up = forced_cleanup || !occlusion_enabled;
965+
_physics_was_cleaned_up = forced_cleanup;
940966
}
941967

942968
void TileMapLayer::_physics_quadrants_update_cell(CellData &r_cell_data, SelfList<PhysicsQuadrant>::List &r_dirty_physics_quadrant_list) {
@@ -1256,6 +1282,9 @@ void TileMapLayer::_navigation_update(bool p_force_cleanup) {
12561282

12571283
// Check if we should cleanup everything.
12581284
bool forced_cleanup = p_force_cleanup || !enabled || !navigation_enabled || !is_inside_tree() || tile_set.is_null();
1285+
if (forced_cleanup && _navigation_was_cleaned_up) {
1286+
return;
1287+
}
12591288

12601289
// ----------- Layer level processing -----------
12611290
// All this processing is kept for compatibility with the TileMap node.
@@ -1527,6 +1556,9 @@ void TileMapLayer::_navigation_draw_cell_debug(const RID &p_canvas_item, const V
15271556
void TileMapLayer::_scenes_update(bool p_force_cleanup) {
15281557
// Check if we should cleanup everything.
15291558
bool forced_cleanup = p_force_cleanup || !enabled || !is_inside_tree() || tile_set.is_null();
1559+
if (forced_cleanup && _scenes_was_cleaned_up) {
1560+
return;
1561+
}
15301562

15311563
if (forced_cleanup) {
15321564
// Clean everything.
@@ -1682,7 +1714,7 @@ void TileMapLayer::_build_runtime_update_tile_data(bool p_force_cleanup) {
16821714
}
16831715

16841716
// -----------
1685-
// Mark the navigation state as up to date.
1717+
// Mark the tile data state as up to date.
16861718
_runtime_update_tile_data_was_cleaned_up = forced_cleanup;
16871719
}
16881720

scene/2d/tile_map_layer.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -430,14 +430,15 @@ class TileMapLayer : public Node2D {
430430
// Per-system methods.
431431
#ifdef DEBUG_ENABLED
432432
HashMap<Vector2i, Ref<DebugQuadrant>> debug_quadrant_map;
433-
bool _debug_was_cleaned_up = false;
433+
bool _debug_was_cleaned_up = true;
434434
void _debug_update(bool p_force_cleanup);
435435
void _debug_quadrants_update_cell(CellData &r_cell_data);
436436
void _get_debug_quadrant_for_cell(const Vector2i &p_coords);
437437
#endif // DEBUG_ENABLED
438438

439439
HashMap<Vector2i, Ref<RenderingQuadrant>> rendering_quadrant_map;
440-
bool _rendering_was_cleaned_up = false;
440+
bool _rendering_was_cleaned_up = true;
441+
bool _occlusion_was_cleaned_up = true;
441442
void _rendering_update(bool p_force_cleanup);
442443
void _rendering_notification(int p_what);
443444
void _rendering_quadrants_update_cell(CellData &r_cell_data, SelfList<RenderingQuadrant>::List &r_dirty_rendering_quadrant_list);
@@ -450,7 +451,7 @@ class TileMapLayer : public Node2D {
450451
#ifndef PHYSICS_2D_DISABLED
451452
HashMap<Vector2i, Ref<PhysicsQuadrant>> physics_quadrant_map;
452453
HashMap<RID, Vector2i> bodies_coords; // Mapping for RID to coords.
453-
bool _physics_was_cleaned_up = false;
454+
bool _physics_was_cleaned_up = true;
454455
void _physics_update(bool p_force_cleanup);
455456
void _physics_notification(int p_what);
456457
void _physics_quadrants_update_cell(CellData &r_cell_data, SelfList<PhysicsQuadrant>::List &r_dirty_physics_quadrant_list);
@@ -462,7 +463,7 @@ class TileMapLayer : public Node2D {
462463
#endif // PHYSICS_2D_DISABLED
463464

464465
#ifndef NAVIGATION_2D_DISABLED
465-
bool _navigation_was_cleaned_up = false;
466+
bool _navigation_was_cleaned_up = true;
466467
void _navigation_update(bool p_force_cleanup);
467468
void _navigation_notification(int p_what);
468469
void _navigation_clear_cell(CellData &r_cell_data);
@@ -472,7 +473,7 @@ class TileMapLayer : public Node2D {
472473
#endif // DEBUG_ENABLED
473474
#endif // NAVIGATION_2D_DISABLED
474475

475-
bool _scenes_was_cleaned_up = false;
476+
bool _scenes_was_cleaned_up = true;
476477
void _scenes_update(bool p_force_cleanup);
477478
void _scenes_clear_cell(CellData &r_cell_data);
478479
void _scenes_update_cell(CellData &r_cell_data);

0 commit comments

Comments
 (0)