Recording a stack of editor tile changes with command pattern

This commit is contained in:
Andrei 2025-01-28 15:33:47 -06:00
parent 144a513cb6
commit e530f69311
2 changed files with 53 additions and 2 deletions

View File

@ -48,7 +48,9 @@ function handlePointerMove(pointer: Phaser.Input.Pointer) {
} }
function handlePointerUp(pointer: Phaser.Input.Pointer) { function handlePointerUp(pointer: Phaser.Input.Pointer) {
if (mapEditor.drawMode.value === 'tile') {
mapTiles.value?.finalizeCommand()
}
} }
onMounted(() => { onMounted(() => {

View File

@ -22,7 +22,27 @@ const tileStorage = new TileStorage()
const tileMap = shallowRef<Phaser.Tilemaps.Tilemap>() const tileMap = shallowRef<Phaser.Tilemaps.Tilemap>()
const tileLayer = shallowRef<Phaser.Tilemaps.TilemapLayer>() const tileLayer = shallowRef<Phaser.Tilemaps.TilemapLayer>()
defineExpose({ handlePointer }) defineExpose({ handlePointer, finalizeCommand })
//Record of commands
let commandStack: EditorCommand[] = []
let currentCommand: EditorCommand | null = null
type EditorCommand = {
operation: 'draw' | 'erase'
tileName?: string,
affectedTiles: TileChangeSet
}
//It must check if the position is in the set already. Otherwise it will duplicate positions
class TileChangeSet extends Set<{ x: number; y: number }> {
has(value: { x: number; y: number }): boolean {
for (const pos of this) {
if (pos.x === value.x && pos.y === value.y) return true
}
return false
}
}
function createTileMap() { function createTileMap() {
const mapData = new Phaser.Tilemaps.MapData({ const mapData = new Phaser.Tilemaps.MapData({
@ -73,6 +93,18 @@ function pencil(pointer: Phaser.Input.Pointer) {
// Place tile // Place tile
placeTile(tileMap.value, tileLayer.value, tile.x, tile.y, mapEditor.selectedTile.value) placeTile(tileMap.value, tileLayer.value, tile.x, tile.y, mapEditor.selectedTile.value)
if (!currentCommand) {
currentCommand = {
operation: 'draw',
tileName: mapEditor.selectedTile.value,
affectedTiles: new TileChangeSet()
}
}
if (!currentCommand.affectedTiles.has({ x: tile.x, y: tile.y })) {
currentCommand.affectedTiles.add({ x: tile.x, y: tile.y })
}
// Adjust mapEditorStore.map.tiles // Adjust mapEditorStore.map.tiles
map.tiles[tile.y][tile.x] = mapEditor.selectedTile.value map.tiles[tile.y][tile.x] = mapEditor.selectedTile.value
} }
@ -90,6 +122,18 @@ function eraser(pointer: Phaser.Input.Pointer) {
// Place tile // Place tile
placeTile(tileMap.value, tileLayer.value, tile.x, tile.y, 'blank_tile') placeTile(tileMap.value, tileLayer.value, tile.x, tile.y, 'blank_tile')
if (!currentCommand) {
currentCommand = {
operation: 'erase',
tileName: 'blank_tile',
affectedTiles: new TileChangeSet()
}
}
if (!currentCommand.affectedTiles.has({ x: tile.x, y: tile.y })) {
currentCommand.affectedTiles.add({ x: tile.x, y: tile.y })
}
// Adjust mapEditorStore.map.tiles // Adjust mapEditorStore.map.tiles
map.tiles[tile.y][tile.x] = 'blank_tile' map.tiles[tile.y][tile.x] = 'blank_tile'
} }
@ -121,6 +165,11 @@ function tilePicker(pointer: Phaser.Input.Pointer) {
mapEditor.setSelectedTile(map.tiles[tile.y][tile.x]) mapEditor.setSelectedTile(map.tiles[tile.y][tile.x])
} }
function finalizeCommand() {
commandStack.push(currentCommand!)
currentCommand = null
}
watch( watch(
() => mapEditor.shouldClearTiles, () => mapEditor.shouldClearTiles,
(shouldClear) => { (shouldClear) => {