doodle/pkg/editor_ui_doodad.go

189 lines
4.9 KiB
Go
Raw Normal View History

package doodle
// XXX REFACTOR XXX
// This function only uses EditorUI and not Doodle and is a candidate for
// refactor into a subpackage if EditorUI itself can ever be decoupled.
import (
"fmt"
"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/doodads"
"git.kirsle.net/apps/doodle/pkg/log"
"git.kirsle.net/apps/doodle/pkg/uix"
)
// DraggableActor is a Doodad being dragged from the Doodad palette.
type DraggableActor struct {
canvas *uix.Canvas
doodad *doodads.Doodad
}
// startDragActor begins the drag event for a Doodad onto a level.
func (u *EditorUI) startDragActor(doodad *doodads.Doodad) {
u.Supervisor.DragStart()
// Create the canvas to render on the mouse cursor.
drawing := uix.NewCanvas(doodad.Layers[0].Chunker.Size, false)
drawing.LoadDoodad(doodad)
drawing.Resize(doodad.Rect())
drawing.SetBackground(render.RGBA(0, 0, 1, 0)) // TODO: invisible becomes white
drawing.MaskColor = balance.DragColor // blueprint effect
u.DraggableActor = &DraggableActor{
canvas: drawing,
doodad: doodad,
}
}
// setupDoodadFrame configures the Doodad Palette tab for Edit Mode.
// This is a subroutine of editor_ui.go#SetupPalette()
//
// Can return an error if userdir.ListDoodads() returns an error (like directory
// not found), but it will *ALWAYS* return a valid ui.Frame -- it will just be
// empty and uninitialized.
func (u *EditorUI) setupDoodadFrame(e render.Engine, window *ui.Window) (*ui.Frame, error) {
var (
frame = ui.NewFrame("Doodad Tab")
perRow = balance.UIDoodadsPerRow
)
2019-06-09 00:02:28 +00:00
frame.SetBackground(render.RGBA(0, 153, 255, 153))
// Toolbar on top of the Doodad panel.
toolbar := ui.NewFrame("Doodad Palette Toolbar")
toolbar.Configure(ui.Config{
Background: render.Grey,
BorderSize: 2,
BorderStyle: ui.BorderRaised,
Height: 24,
2019-06-09 00:02:28 +00:00
})
{
// Link button.
linkButton := ui.NewButton("Link", ui.NewLabel(ui.Label{
Text: "Link Doodads",
}))
linkButton.Handle(ui.Click, func(p render.Point) {
u.Canvas.LinkStart()
u.d.Flash("Click on the first Doodad to link to another one.")
2019-06-09 00:02:28 +00:00
})
u.Supervisor.Add(linkButton)
toolbar.Pack(linkButton, ui.Pack{
Anchor: ui.N,
FillX: true,
})
}
frame.Pack(toolbar, ui.Pack{
Anchor: ui.N,
Fill: true,
})
// Pager buttons on top of the doodad list.
pager := ui.NewFrame("Doodad Pager")
pager.SetBackground(render.RGBA(255, 0, 0, 20)) // TODO: if I don't set a background color,
// this frame will light up the same color as the Link button on mouse
// over. somewhere some memory might be shared between the recent widgets
2019-06-09 00:02:28 +00:00
{
leftBtn := ui.NewButton("Prev Page", ui.NewLabel(ui.Label{
Text: "<",
}))
u.Supervisor.Add(leftBtn)
pager.Pack(leftBtn, ui.Pack{
Anchor: ui.W,
})
pageLabel := ui.NewLabel(ui.Label{
Text: " Page 1 of 20",
})
pager.Pack(pageLabel, ui.Pack{
Anchor: ui.W,
Expand: true,
})
rightBtn := ui.NewButton("Next Page", ui.NewLabel(ui.Label{
Text: ">",
}))
u.Supervisor.Add(rightBtn)
pager.Pack(rightBtn, ui.Pack{
Anchor: ui.W,
})
}
frame.Pack(pager, ui.Pack{
Anchor: ui.N,
Fill: true,
PadY: 5,
2019-06-09 00:02:28 +00:00
})
doodadsAvailable, err := doodads.ListDoodads()
if err != nil {
return frame, fmt.Errorf(
"setupDoodadFrame: doodads.ListDoodads: %s",
err,
)
}
var buttonSize = (paletteWidth - window.BoxThickness(2)) / int32(perRow)
// Draw the doodad buttons in a grid `perRow` buttons wide.
var (
row *ui.Frame
rowCount int // for labeling the ui.Frame for each row
)
for i, filename := range doodadsAvailable {
if row == nil || i%perRow == 0 {
rowCount++
row = ui.NewFrame(fmt.Sprintf("Doodad Row %d", rowCount))
row.SetBackground(balance.WindowBackground)
frame.Pack(row, ui.Pack{
Anchor: ui.N,
Fill: true,
})
}
func(filename string) {
doodad, err := doodads.LoadFile(filename)
if err != nil {
log.Error(err.Error())
doodad = doodads.New(balance.DoodadSize)
}
can := uix.NewCanvas(int(buttonSize), true)
can.Name = filename
can.SetBackground(render.White)
can.LoadDoodad(doodad)
btn := ui.NewButton(filename, can)
btn.Resize(render.NewRect(
buttonSize-2, // TODO: without the -2 the button border
buttonSize-2, // rests on top of the window border.
))
row.Pack(btn, ui.Pack{
Anchor: ui.W,
})
// Begin the drag event to grab this Doodad.
// NOTE: The drag target is the EditorUI.Canvas in
// editor_ui.go#SetupCanvas()
btn.Handle(ui.MouseDown, func(e render.Point) {
Bindata: Embedding Doodads and Levels (for WASM) * Use `go-bindata` to embed built-in doodads and levels directly into the Doodle binary. `make bindata` produces the bindata source file. * Add `FromJSON()` method to Levels and Doodads to load objects from JSON strings in memory (for bindata built-ins or WASM ajax requests) * Update file loading functions to check the embedded bindata files. * pkg/config.go#EditFile: * Supports editing a level from bindata (TODO: remove this support) * If the "assets/levels/%(simple-name.level)" exists in bindata, edits that drawing. * No such support for editing built-in doodads. * WASM has no filesystem access to edit files except built-in levels (yet) * pkg/doodads#ListDoodads: * Prepends built-in doodads from bindata to the returned list. * WASM: no filesystem access so gets only the built-ins. * pkg/doodads#LoadFile: * Checks built-in bindata store first for doodad files. * WASM: tries an HTTP request if not found in bindata but can go no further if not found (no filesystem access) * pkg/filesystem#FindFile: * This function finds a level/doodad by checking all the places. * If the level or doodad exists in bindata built-in, always returns its system path like "assets/doodads/test.doodad" * WASM: always returns the built-in candidate path even if not found in bindata so that ajax GET can be attempted. * pkg/level#ListSystemLevels: * New function that lists the system level files, similar to the equivalent doodads function. * Prepends the bindata built-in level files. * WASM: only returns the built-ins (no filesystem support) * Desktop: also lists and returns the assets/levels/ directory. * pkg/level#LoadFile: * Like the doodads.LoadFile, tries from built-in bindata first, then ajax request (WASM) before accessing the filesystem (desktop) * Menu Scene: TODO, list the built-in levels in the Load Level menu. This feature will soon go away when WASM gets its own storage for user levels (localStorage instead of filesystem)
2019-06-27 22:07:34 +00:00
log.Warn("MouseDown on doodad %s (%s)", doodad.Filename, doodad.Title)
u.startDragActor(doodad)
})
u.Supervisor.Add(btn)
// Resize the canvas to fill the button interior.
btnSize := btn.Size()
can.Resize(render.NewRect(
btnSize.W-btn.BoxThickness(2),
btnSize.H-btn.BoxThickness(2),
),
)
btn.Compute(e)
}(filename)
}
return frame, nil
}