113 lines
3.1 KiB
Go
113 lines
3.1 KiB
Go
|
package uix
|
||
|
|
||
|
import (
|
||
|
"git.kirsle.net/apps/doodle/lib/render"
|
||
|
"git.kirsle.net/apps/doodle/lib/ui"
|
||
|
"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"
|
||
|
)
|
||
|
|
||
|
// canvas_strokes.go: functions related to drawtool.Stroke and the Canvas.
|
||
|
|
||
|
// AddStroke installs a new Stroke to be superimposed over drawing data
|
||
|
// in the canvas.
|
||
|
//
|
||
|
// The stroke is added to the canvas's map by its ID so it can be removed later.
|
||
|
// The stroke must have a non-zero ID value set or this function will panic.
|
||
|
// drawtool.NewStroke() creates an initialized Stroke object to use here.
|
||
|
func (w *Canvas) AddStroke(stroke *drawtool.Stroke) {
|
||
|
if stroke.ID == 0 {
|
||
|
panic("Canvas.AddStroke: the Stroke is missing an ID; was it initialized properly?")
|
||
|
}
|
||
|
|
||
|
w.strokes[stroke.ID] = stroke
|
||
|
}
|
||
|
|
||
|
// RemoveStroke uninstalls a Stroke from the canvas using its ID.
|
||
|
//
|
||
|
// Returns true if the stroke existed to begin with, false if not.
|
||
|
func (w *Canvas) RemoveStroke(stroke *drawtool.Stroke) bool {
|
||
|
if _, ok := w.strokes[stroke.ID]; ok {
|
||
|
delete(w.strokes, stroke.ID)
|
||
|
return true
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// UndoStroke rolls back the level's UndoHistory and deletes the pixels last
|
||
|
// 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")
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
latest := w.level.UndoHistory.Latest()
|
||
|
if latest != nil {
|
||
|
for point := range latest.IterPoints() {
|
||
|
w.chunks.Delete(point)
|
||
|
}
|
||
|
}
|
||
|
return w.level.UndoHistory.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")
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
ok := w.level.UndoHistory.Redo()
|
||
|
if !ok {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
latest := w.level.UndoHistory.Latest()
|
||
|
|
||
|
// We stored the ActiveSwatch on this stroke as we drew it. Recover it
|
||
|
// and place the pixels back down.
|
||
|
if swatch, ok := latest.ExtraData.(*level.Swatch); ok {
|
||
|
for point := range latest.IterPoints() {
|
||
|
w.chunks.Set(point, swatch)
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
log.Error("Canvas.UndoStroke: undo was successful but no Swatch was stored on the Stroke.ExtraData!")
|
||
|
|
||
|
return ok
|
||
|
}
|
||
|
|
||
|
// presentStrokes is called as part of Present() and draws the strokes whose
|
||
|
// pixels are currently visible within the viewport.
|
||
|
func (w *Canvas) presentStrokes(e render.Engine) {
|
||
|
var (
|
||
|
P = ui.AbsolutePosition(w) // w.Point() // Canvas point in UI
|
||
|
VP = w.ViewportRelative() // Canvas scroll viewport
|
||
|
)
|
||
|
|
||
|
for _, stroke := range w.strokes {
|
||
|
for point := range stroke.IterPoints() {
|
||
|
if !point.Inside(VP) {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
dest := render.Point{
|
||
|
X: P.X + w.Scroll.X + w.BoxThickness(1) + point.X,
|
||
|
Y: P.Y + w.Scroll.Y + w.BoxThickness(1) + point.Y,
|
||
|
}
|
||
|
|
||
|
if balance.DebugCanvasStrokeColor != render.Invisible {
|
||
|
e.DrawPoint(balance.DebugCanvasStrokeColor, dest)
|
||
|
} else {
|
||
|
e.DrawPoint(stroke.Color, dest)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|