Tilemaps: a painted cell works out only what is around it (#348)

- A fourth round on painting: the keys a writer changed, patching the
  changed cells and their neighbours, merging row by row, tiles sorted
  by id.
- The measurements on 60x60 and 120x120, and that the meshes of a
  layer still grow with the map.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
adminandClaude Opus 5.5 committed 2026-10-14 16:14:47 +02:00
1 parent 83f83f0e6e
commit ae9afcad81
1 file changed
+21 -2
+21 -2
@@ -374,8 +374,27 @@ Measured with a brush stroke on a copy of a project with a 60x60 map on three la
objects (Chrome, slow machine): 20 to 39 fps before, 47.5 after, against 55 to 57 fps without objects (Chrome, slow machine): 20 to 39 fps before, 47.5 after, against 55 to 57 fps without
painting. The stroke drew 2012 labels again before and none after, and the scene 1.32 times a painting. The stroke drew 2012 labels again before and none after, and the scene 1.32 times a
frame before and once after. One painted cell cost the scene view 28 ms headless before and 16 ms frame before and once after. One painted cell cost the scene view 28 ms headless before and 16 ms
after, on the same map doubled to 120x120 109 ms before and 49 ms after. That last part still grows after, on the same map doubled to 120x120 109 ms before and 49 ms after.
with the map: a painted cell works out the tiles and blocking cells of the whole map again.
A fourth round (#348) made a painted cell cost what is around it, not the whole map:
- `cellsChanged` takes the keys a writer changed (the brush, the paint command and its undo), and
each new version of the cells keeps them (`cellsChangedSince`, the last 16 versions). A writer
that names none costs one walk over the cells, and a replaced object starts afresh.
- The cell index, the tiles of a layer and the blocking cells patch only the changed cells and their
eight neighbours: nothing else can join or block otherwise. Both lists are in cell order now, so a
patch is one walk that keeps every other entry, the same object as before.
- The rectangles are merged row by row. A strip never spans two rows, so a patch joins again only
the rows around it and stacks the rest as they were. That is one row further than the patched
cells, since an autotile turning into a box cuts the box below it otherwise.
- The tiles a map names come sorted by id, so the same content gives the same order whichever way it
was painted. That is also the order of two trigger tiles on one cell.
Measured with the same map: one painted cell costs the scene's item list 3.5 ms on 60x60 and 4.0 ms
on 120x120, against 3.4 ms without painting (headless, before 16.8 and 54.6 ms). A brush stroke on
the map doubled to 120x120 runs at 42 fps instead of 28, p95 of a frame 52 instead of 92 ms. What
still grows with the map is the mesh: a painted cell builds the geometry of every tile on that layer
again, since the layer's tiles come as a new list and are grouped by tile afresh.
A frame still costs what it touches: an object standing **inside** many outlined cells is tested A frame still costs what it touches: an object standing **inside** many outlined cells is tested
against each of them, so an outline of a hundred corners around every cell of a lake is dearer than against each of them, so an outline of a hundred corners around every cell of a lake is dearer than