1
0
forked from noxious/client

Most comprehensive undo/redo so far

This commit is contained in:
Andrei 2025-02-13 13:27:15 -06:00
parent 5e243e5201
commit 8b0bf6534e
2 changed files with 17 additions and 7 deletions

View File

@ -1,6 +1,6 @@
<template>
<MapTiles ref="mapTiles" @createCommand="addCommand" v-if="tileMap && tileMapLayer" :tileMap :tileMapLayer />
<PlacedMapObjects ref="mapObjects" @update="updateMapObjects" @updateAndCommit="updateAndCommit" v-if="tileMap && tileMapLayer" :tileMap :tileMapLayer />
<PlacedMapObjects ref="mapObjects" @update="updateMapObjects" @updateAndCommit="updateAndCommit" @pauseObjectTracking="pause" @resumeObjectTracking="resume" v-if="tileMap && tileMapLayer" :tileMap :tileMapLayer />
<MapEventTiles ref="eventTiles" @createCommand="addCommand" v-if="tileMap" :tileMap />
</template>
@ -36,7 +36,7 @@ let originTiles: string[][] = []
let originEventTiles: MapEventTile[] = []
let originObjects = ref<PlacedMapObjectT[]>(mapEditor.currentMap.value.placedMapObjects)
const {undo, redo, commit, reset, history, canUndo, canRedo} = useRefHistory(originObjects, {clone:true, deep:true, capacity:9})
const {undo, redo, commit, pause, resume, canUndo, canRedo} = useRefHistory(originObjects, {deep:true, capacity:9})
//Command Pattern basic interface, extended to store what elements have been changed by each edit
export interface EditorCommand {
@ -101,6 +101,7 @@ function update(commands: (EditorCommand | number)[]) {
mapEditor.currentMap.value.tiles = modifiedTiles
mapEditor.currentMap.value.mapEventTiles = eventTiles
mapEditor.currentMap.value.placedMapObjects = originObjects.value
}
function updateMapObjects(map: MapT) {
@ -125,7 +126,6 @@ function undoEdit() {
if (commandIndex.value > 0) {
if (typeof(commandStack[--commandIndex.value]) === 'number' && canUndo) {
undo()
mapEditor.currentMap.value.placedMapObjects = originObjects.value
}
update(commandStack.slice(0, commandIndex.value))
}
@ -135,7 +135,6 @@ function redoEdit() {
if (commandIndex.value <= 9 && commandIndex.value < commandStack.length) {
if (typeof(commandStack[commandIndex.value++]) === 'number' && canRedo) {
redo()
mapEditor.currentMap.value.placedMapObjects = originObjects.value
}
update(commandStack.slice(0, commandIndex.value))
}
@ -191,7 +190,10 @@ function handlePointerUp(pointer: Phaser.Input.Pointer) {
mapTiles.value!.finalizeCommand()
break
case 'map_object':
updateAndCommit()
if (mapEditor.tool.value === 'pencil' || mapEditor.tool.value === 'eraser') {
resume()
updateAndCommit()
}
break
case 'teleport':
eventTiles.value!.finalizeCommand()

View File

@ -27,7 +27,7 @@ const scene = useScene()
const mapEditor = useMapEditorComposable()
const map = computed(() => mapEditor.currentMap.value!)
const emit = defineEmits<{(e: 'update', map: MapT): void, (e: 'updateAndCommit', map: MapT): void}>()
const emit = defineEmits<{(e: 'update', map: MapT): void, (e: 'updateAndCommit', map: MapT): void, (e:'pauseObjectTracking'), (e:'resumeObjectTracking')}>()
defineExpose({ handlePointer })
@ -54,6 +54,8 @@ function updatePreviewPosition(pointer: Phaser.Input.Pointer) {
}
function pencil(pointer: Phaser.Input.Pointer, map: MapT) {
emit('pauseObjectTracking')
const tile = getTile(props.tileMap, pointer.worldX, pointer.worldY)
if (!tile) return
@ -79,6 +81,8 @@ function pencil(pointer: Phaser.Input.Pointer, map: MapT) {
}
function eraser(pointer: Phaser.Input.Pointer, map: MapT) {
emit('pauseObjectTracking')
// Check if object already exists on position
const existingPlacedMapObject = findObjectByPointer(pointer, map)
if (!existingPlacedMapObject) return
@ -108,6 +112,8 @@ function objectPicker(pointer: Phaser.Input.Pointer, map: MapT) {
function moveMapObject(id: string, map: MapT) {
mapEditor.movingPlacedObject.value = map.placedMapObjects.find((object) => object.id === id) as PlacedMapObjectT
emit('pauseObjectTracking')
function handlePointerMove(pointer: Phaser.Input.Pointer) {
if (!mapEditor.movingPlacedObject.value) return
const tile = getTile(props.tileMap, pointer.worldX, pointer.worldY)
@ -133,8 +139,10 @@ function moveMapObject(id: string, map: MapT) {
}})
mapEditor.movingPlacedObject.value = null
emit('updateAndCommit', map)
scene.input.off(Phaser.Input.Events.POINTER_UP, handlePointerUp)
emit('resumeObjectTracking')
emit('updateAndCommit', map)
}
}