Bugfix: Undo/Redo works for the Doodad Editor

Changed dependencies around so the undo/redo feature works on doodads as
well as levels.
pull/84/head
Noah 2021-10-11 16:10:04 -07:00
parent 0ec259b171
commit 3a9cc83e78
4 changed files with 28 additions and 9 deletions

View File

@ -2,6 +2,7 @@ package doodads
import (
"git.kirsle.net/apps/doodle/pkg/balance"
"git.kirsle.net/apps/doodle/pkg/drawtool"
"git.kirsle.net/apps/doodle/pkg/level"
"git.kirsle.net/apps/doodle/pkg/log"
"git.kirsle.net/go/render"
@ -17,6 +18,9 @@ type Doodad struct {
Hitbox render.Rect `json:"hitbox"`
Layers []Layer `json:"layers"`
Tags map[string]string `json:"data"` // arbitrary key/value data storage
// Undo history, temporary live data not persisted to the level file.
UndoHistory *drawtool.History `json:"-" msgpack:"-"`
}
// Layer holds a layer of drawing data for a Doodad.
@ -43,7 +47,8 @@ func New(size int) *Doodad {
Chunker: level.NewChunker(size),
},
},
Tags: map[string]string{},
Tags: map[string]string{},
UndoHistory: drawtool.NewHistory(balance.UndoHistory),
}
}

View File

@ -54,6 +54,7 @@ type Canvas struct {
// Underlying chunk data for the drawing.
level *level.Level
chunks *level.Chunker
doodad *doodads.Doodad
modified bool // set to True when the drawing has been modified, like in Editor Mode.
// Actors to superimpose on top of the drawing.
@ -179,6 +180,7 @@ func (w *Canvas) LoadLevel(level *level.Level) {
// LoadDoodad initializes a Canvas from a Doodad object.
func (w *Canvas) LoadDoodad(d *doodads.Doodad) {
// TODO more safe
w.doodad = d
w.Load(d.Palette, d.Layers[0].Chunker)
}

View File

@ -106,6 +106,8 @@ func (w *Canvas) commitStroke(tool drawtool.Tool, addHistory bool) {
// Add the stroke to level history.
if w.level != nil && addHistory {
w.level.UndoHistory.AddStroke(w.currentStroke)
} else if w.doodad != nil && addHistory {
w.doodad.UndoHistory.AddStroke(w.currentStroke)
}
w.RemoveStroke(w.currentStroke)

View File

@ -42,12 +42,17 @@ func (w *Canvas) RemoveStroke(stroke *drawtool.Stroke) bool {
// added to the level. Returns false and emits a warning to the log if the
// canvas has no level loaded properly.
func (w *Canvas) UndoStroke() bool {
if w.level == nil {
log.Error("Canvas.UndoStroke: no Level currently available to the canvas")
var undoer *drawtool.History
if w.level != nil {
undoer = w.level.UndoHistory
} else if w.doodad != nil {
undoer = w.doodad.UndoHistory
} else {
log.Error("Canvas.UndoStroke: no Level or Doodad currently available to the canvas")
return false
}
latest := w.level.UndoHistory.Latest()
latest := undoer.Latest()
if latest != nil {
// TODO: only single-thickness lines will restore the original color;
// thick lines just delete their pixels from the world due to performance.
@ -93,23 +98,28 @@ func (w *Canvas) UndoStroke() bool {
}
}
return w.level.UndoHistory.Undo()
return undoer.Undo()
}
// RedoStroke rolls the level's UndoHistory forwards again and replays the
// recently undone changes.
func (w *Canvas) RedoStroke() bool {
if w.level == nil {
log.Error("Canvas.UndoStroke: no Level currently available to the canvas")
var undoer *drawtool.History
if w.level != nil {
undoer = w.level.UndoHistory
} else if w.doodad != nil {
undoer = w.doodad.UndoHistory
} else {
log.Error("Canvas.UndoStroke: no Level or Doodad currently available to the canvas")
return false
}
ok := w.level.UndoHistory.Redo()
ok := undoer.Redo()
if !ok {
return false
}
latest := w.level.UndoHistory.Latest()
latest := undoer.Latest()
// We stored the ActiveSwatch on this stroke as we drew it. Recover it
// and place the pixels back down.