/** * Columns and Rows of a placed tilemap in the inspector (#136): the grid grows at the right or bottom * edge while the painted cells stay where they are, already while the value is previewed. The * preview counts from where the edit started, so dragging back and forth leaves no drift, and the * commit is one undo step. */ import { describe, expect, it } from 'vitest'; import { CreateAssetCommand } from '../../src/core/commands/assetCommands'; import { PlaceAssetCommand, SetOverrideCommand } from '../../src/core/commands/sceneObjectCommands'; import { findObject } from '../../src/core/model/hierarchy'; import { resolvedHolder } from '../../src/core/model/instance'; import { createEmptyProject, findScene } from '../../src/core/model/Project'; import { TILEMAP_COLUMNS_KEY } from '../../src/core/model/tilemap'; import { previewingHandlers } from '../../src/editor/inspector/previewHandlers'; import { tilemapSizeValue } from '../../src/editor/inspector/valueSpecs'; import { EditorState } from '../../src/editor/state'; function setup() { const state = new EditorState(); state.loadProject(createEmptyProject('p', 'P'), 1); const scene = new CreateAssetCommand('scene', 'Main'); const map = new CreateAssetCommand('tilemap', 'Ground'); state.execute(scene); state.execute(map); const placed = new PlaceAssetCommand(scene.asset.id, map.asset.id, { x: 10, y: 20 }); state.execute(placed); state.execute(new SetOverrideCommand(scene.asset.id, placed.objectId, 'rotation', 90)); const object = () => findObject(resolvedHolder(state.project, findScene(state.project, scene.asset.id)!), placed.objectId)!; const field = previewingHandlers( { state }, tilemapSizeValue(state, scene.asset.id, placed.objectId, TILEMAP_COLUMNS_KEY), ); return { state, object, field }; } describe('the Columns field of a placed tilemap', () => { it('moves the origin along while previewing, from where the edit started', () => { const { object, field } = setup(); // 20 columns of 48 px by default; turned by 90°, the map's own x axis points down the screen. field.onInput(23); expect(object().position.x).toBeCloseTo(10, 9); expect(object().position.y).toBeCloseTo(20 + 72, 9); field.onInput(17); field.onInput(21); expect(object().position.y).toBeCloseTo(20 + 24, 9); }); it('commits one undo step that holds the content, and undo returns exactly to the start', () => { const { state, object, field } = setup(); const start = structuredClone(object()); for (const value of [31, 5, 26]) field.onInput(value); field.onChange(26); expect(object().overrides[TILEMAP_COLUMNS_KEY]).toBe(26); expect(object().position.y).toBeCloseTo(20 + 144, 9); state.undo(); expect(object()).toEqual(start); }); it('takes a value typed in without a preview as well', () => { const { object, field } = setup(); field.onChange(19); expect(object().overrides[TILEMAP_COLUMNS_KEY]).toBe(19); expect(object().position.y).toBeCloseTo(20 - 24, 9); }); });