Bugfix: Undo/Redo works for the Doodad Editor

Changed dependencies around so the undo/redo feature works on doodads as
well as levels.
This commit is contained in:
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 ( import (
"git.kirsle.net/apps/doodle/pkg/balance" "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/level"
"git.kirsle.net/apps/doodle/pkg/log" "git.kirsle.net/apps/doodle/pkg/log"
"git.kirsle.net/go/render" "git.kirsle.net/go/render"
@ -17,6 +18,9 @@ type Doodad struct {
Hitbox render.Rect `json:"hitbox"` Hitbox render.Rect `json:"hitbox"`
Layers []Layer `json:"layers"` Layers []Layer `json:"layers"`
Tags map[string]string `json:"data"` // arbitrary key/value data storage 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. // Layer holds a layer of drawing data for a Doodad.
@ -43,7 +47,8 @@ func New(size int) *Doodad {
Chunker: level.NewChunker(size), 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. // Underlying chunk data for the drawing.
level *level.Level level *level.Level
chunks *level.Chunker chunks *level.Chunker
doodad *doodads.Doodad
modified bool // set to True when the drawing has been modified, like in Editor Mode. modified bool // set to True when the drawing has been modified, like in Editor Mode.
// Actors to superimpose on top of the drawing. // 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. // LoadDoodad initializes a Canvas from a Doodad object.
func (w *Canvas) LoadDoodad(d *doodads.Doodad) { func (w *Canvas) LoadDoodad(d *doodads.Doodad) {
// TODO more safe // TODO more safe
w.doodad = d
w.Load(d.Palette, d.Layers[0].Chunker) 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. // Add the stroke to level history.
if w.level != nil && addHistory { if w.level != nil && addHistory {
w.level.UndoHistory.AddStroke(w.currentStroke) w.level.UndoHistory.AddStroke(w.currentStroke)
} else if w.doodad != nil && addHistory {
w.doodad.UndoHistory.AddStroke(w.currentStroke)
} }
w.RemoveStroke(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 // added to the level. Returns false and emits a warning to the log if the
// canvas has no level loaded properly. // canvas has no level loaded properly.
func (w *Canvas) UndoStroke() bool { func (w *Canvas) UndoStroke() bool {
if w.level == nil { var undoer *drawtool.History
log.Error("Canvas.UndoStroke: no Level currently available to the canvas") 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 return false
} }
latest := w.level.UndoHistory.Latest() latest := undoer.Latest()
if latest != nil { if latest != nil {
// TODO: only single-thickness lines will restore the original color; // TODO: only single-thickness lines will restore the original color;
// thick lines just delete their pixels from the world due to performance. // 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 // RedoStroke rolls the level's UndoHistory forwards again and replays the
// recently undone changes. // recently undone changes.
func (w *Canvas) RedoStroke() bool { func (w *Canvas) RedoStroke() bool {
if w.level == nil { var undoer *drawtool.History
log.Error("Canvas.UndoStroke: no Level currently available to the canvas") 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 return false
} }
ok := w.level.UndoHistory.Redo() ok := undoer.Redo()
if !ok { if !ok {
return false return false
} }
latest := w.level.UndoHistory.Latest() latest := undoer.Latest()
// We stored the ActiveSwatch on this stroke as we drew it. Recover it // We stored the ActiveSwatch on this stroke as we drew it. Recover it
// and place the pixels back down. // and place the pixels back down.