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

View File

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