Painting over identical tiles no longer adds an empty undo step (#212)
A rectangle drawn over cells that already hold exactly that tile
pushed a command that changed nothing. Undo then seemed to do nothing
and the project was marked as modified. PaintTilesCommand.changes()
was meant to prevent that, but nothing called it since #128.
- New paintTiles() in tilemapCommands.ts returns the command for a
finished stroke or fill, or null when no cell changes. It is the
first caller of PaintTilesCommand.changes().
- All three paint paths in the Scene View go through it: brush and
eraser, rectangle (both in endStroke) and flood fill (fillFrom).
- Flood fill was not affected, because floodFill already returns []
for the same tile. The guard is there anyway, as the issue asked.
- A rectangle that changes even one cell stays a normal undo step.
Tests:
- ./check.sh: 145 files, 2190 tests, CHECK EXIT 0 (before 2187).
- 3 new unit tests in tests/core/tilemap.test.ts: same rectangle
twice gives no command, a wider rectangle still does, a fill that
finds nothing gives no command.
- 1 new e2e check in 40d: the same rectangle again, then one undo
must take 9 cells to 0. A redo restores them for later blocks.
- GM_STEPS=39,40 on the final build: ALL PASSED, 81 checks.
- Counter-probe with changes(...) || true: exactly the two unit
tests fail, and in the browser exactly the new check fails with
{"afterUndo":9}. Original restored via cmp (IDENTICAL), rebuilt.
- Editor suite check total: CI measured 1312 at 0e85856, new total
1313 (calculated) in README and wiki.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0e8585665a
commit
487b3aa5b4
5 files changed
+80
-20
No files matched your search
@@ -10,6 +10,7 @@ import {
|
||||
DuplicateTilemapLayerCommand,
|
||||
MoveTilemapLayerCommand,
|
||||
PaintTilesCommand,
|
||||
paintTiles,
|
||||
RemoveTilemapLayerCommand,
|
||||
RenameTilemapLayerCommand,
|
||||
SetTilemapLayerHiddenCommand,
|
||||
@@ -26,6 +27,7 @@ import {
|
||||
cellOrigin,
|
||||
cellsAlong,
|
||||
cellsInRect,
|
||||
floodFill,
|
||||
inGrid,
|
||||
layerTiles,
|
||||
neighboursOf,
|
||||
@@ -151,6 +153,41 @@ describe('painting a tilemap', () => {
|
||||
expect(PaintTilesCommand.changes(layer, [{ x: 5, y: 5, tileId: f.tileId }])).toBe(true);
|
||||
});
|
||||
|
||||
it('makes no undo step for a rectangle over cells that already hold its tile', () => {
|
||||
const f = makeTilemap();
|
||||
const box = cellsInRect(f.assetOf().props, { x: 0, y: 0 }, { x: 2, y: 2 });
|
||||
f.paint(box);
|
||||
const again = box.map((at) => ({ ...at, tileId: f.tileId }));
|
||||
expect(paintTiles(f.assetOf().layers[0]!, f.tilemapId, again)).toBeNull();
|
||||
// The one undo left takes back the first rectangle, not an empty second one.
|
||||
f.stack.undo();
|
||||
expect(cellsOf(f.project, f.tilemapId)).toEqual({});
|
||||
});
|
||||
|
||||
it('still makes one when a single cell of the rectangle changes', () => {
|
||||
const f = makeTilemap();
|
||||
f.paint(cellsInRect(f.assetOf().props, { x: 0, y: 0 }, { x: 1, y: 1 }));
|
||||
const wider = cellsInRect(f.assetOf().props, { x: 0, y: 0 }, { x: 2, y: 1 });
|
||||
const command = paintTiles(
|
||||
f.assetOf().layers[0]!,
|
||||
f.tilemapId,
|
||||
wider.map((at) => ({ ...at, tileId: f.tileId })),
|
||||
);
|
||||
expect(command).not.toBeNull();
|
||||
f.stack.execute(command!);
|
||||
expect(Object.keys(cellsOf(f.project, f.tilemapId))).toHaveLength(6);
|
||||
f.stack.undo();
|
||||
expect(Object.keys(cellsOf(f.project, f.tilemapId)).sort()).toEqual(['0,0', '0,1', '1,0', '1,1']);
|
||||
});
|
||||
|
||||
it('makes no undo step for a fill that finds nothing to fill', () => {
|
||||
const f = makeTilemap();
|
||||
f.paint([{ x: 0, y: 0 }]);
|
||||
const layer = f.assetOf().layers[0]!;
|
||||
expect(floodFill(f.assetOf().props, layer, { x: 0, y: 0 }, f.tileId)).toEqual([]);
|
||||
expect(paintTiles(layer, f.tilemapId, [])).toBeNull();
|
||||
});
|
||||
|
||||
it('covers the cells between two pointer events', () => {
|
||||
expect(cellsAlong({ x: 0, y: 0 }, { x: 3, y: 0 })).toEqual([
|
||||
{ x: 1, y: 0 },
|
||||
|
||||
Reference in new issue
Block a user