Files
feuerwerk/tests/viewport/tilemap-fill.test.ts
T
adminandClaude Opus 5.5 f4cc681df4
game-maker / gate (push) Successful in 2m57s
game-maker / suite (push) Failing after 9m24s
Fill texture and tilemap collision only where it is being edited
The faint fill on every frame outline and on every tilemap made the
scene and the texture editor look green all over. Like the collider
before, the fill now shows only on what is selected, and a bit
stronger, so it marks the thing being worked on.

- Texture collision: all frame outlines stay visible. Only the
  outlines of the selected frame are filled, at alpha 0.3 instead of
  0.15 on every frame.
- Tilemap: the outline still shows where the whole map blocks. The
  fill appears only while the tilemap alone is selected, and only for
  the part the layer chosen in the panel adds. Solid is 0.3 and
  one-way 0.15, before 0.12 and 0.06 on every map.
- New query layerSolids(layerId) in items.ts. It builds the same
  solids for one layer and runs only for the selected map.
- The small landing wedge on one-way edges stays filled. It belongs
  to the edge marker, not to the area.

Not covered by tests: the texture canvas and the scene view wiring
that picks the map and the layer. Neither was looked at in a browser.

Tests:
- ./check.sh: 159 files, 2337 tests, CHECK EXIT 0 (before 2334)
- e2e 1-17,39-43: ALL PASSED, 668 checks
- 3 new unit tests in tests/viewport/tilemap-fill.test.ts
- Counter-check: with layerSolids ignoring the layer, exactly the
  layer test fails. Original restored, checked with cmp.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 12:23:13 +02:00

79 lines
3.4 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { Container, type Graphics } from 'pixi.js';
import { CreateAssetCommand, SetAssetPropertyCommand } from '../../src/core/commands/assetCommands';
import { AddTilemapLayerCommand, PaintTilesCommand } from '../../src/core/commands/tilemapCommands';
import type { TilemapAsset } from '../../src/core/model/Asset';
import { findAsset } from '../../src/core/model/Project';
import { TILE_SOLID_KEY } from '../../src/core/model/tile';
import { TilemapSolidOutlines } from '../../src/editor/viewport/tilemapSolids';
import { collectHolderItems, type DrawItem } from '../../src/viewport/items';
import { COLLIDER_FILL_ALPHA } from '../../src/viewport/symbols';
import { makeSpriteScene, place } from '../helpers';
/** A map of two layers with a solid wall tile: two cells on "Ground", one on "Roofs". */
function setup() {
const f = makeSpriteScene();
const wall = new CreateAssetCommand('tile', 'Wall');
const map = new CreateAssetCommand('tilemap', 'Village');
f.stack.execute(wall);
f.stack.execute(map);
f.stack.execute(new SetAssetPropertyCommand(wall.asset.id, TILE_SOLID_KEY, true));
const ground = (findAsset(f.project, map.asset.id) as TilemapAsset).layers[0]!.id;
const roofs = new AddTilemapLayerCommand(map.asset.id);
f.stack.execute(roofs);
const paint = (layerId: string, cells: [number, number][]) =>
f.stack.execute(
new PaintTilesCommand(
map.asset.id,
layerId,
cells.map(([x, y]) => ({ x, y, tileId: wall.asset.id })),
),
);
paint(ground, [
[0, 0],
[1, 0],
]);
paint(roofs.layerId, [[4, 4]]);
const mapObject = place(f, map.asset.id, { x: 0, y: 0 });
const item = collectHolderItems(f.project, f.sceneOf(), 0).items.find((i) => i.id === mapObject)!;
return { item, ground, roofs: roofs.layerId };
}
/** What the outline node of a map draws: each fill with its alpha, and how many strokes. */
function drawn(item: DrawItem, filled: Parameters<TilemapSolidOutlines['sync']>[3]) {
const layer = new Container();
new TilemapSolidOutlines(layer).sync(item, true, 1, filled);
const node = layer.children[0] as Graphics;
const instructions = node.context.instructions;
return {
fills: instructions
.filter((i) => i.action === 'fill')
.map((i) => (i.data.style as { alpha: number }).alpha),
strokes: instructions.filter((i) => i.action === 'stroke').length,
};
}
describe('the tint on where a tilemap blocks in the scene view', () => {
it('knows where one layer alone blocks', () => {
const { item, ground, roofs } = setup();
expect(item.tilemap!.solids).toEqual([
{ x: 0, y: 0, w: 2, h: 1 },
{ x: 4, y: 4, w: 1, h: 1 },
]);
expect(item.tilemap!.layerSolids(ground).solids).toEqual([{ x: 0, y: 0, w: 2, h: 1 }]);
expect(item.tilemap!.layerSolids(roofs).solids).toEqual([{ x: 4, y: 4, w: 1, h: 1 }]);
expect(item.tilemap!.layerSolids('gone').solids).toEqual([]);
});
it('is only an outline while nothing asks for a fill', () => {
const { item } = setup();
expect(drawn(item, null)).toEqual({ fills: [], strokes: 1 });
});
it('fills the painted layer at the collider alpha and still outlines the whole map', () => {
const { item, roofs } = setup();
const layerSolids = item.tilemap!.layerSolids(roofs);
expect(drawn(item, layerSolids)).toEqual({ fills: [COLLIDER_FILL_ALPHA], strokes: 1 });
});
});