Noah Petherbridge
190d4be1b6
* When editing a doodad in the Editor Mode, the toolbar has a "Lyr." button that opens the Layers window. * The Layers window allows switching the active doodad layer that you are drawing on, as well as create and rename layers. * With this feature, Doodads may be fully drawn in-game, including adding alternate named layers for animations and multiple-state doodads. * Update the Pager component to have a configurable MaxPageButtons. Controls that have more pages than this limit will stop having buttons drawn after the limit. The "Forward" and "Next" buttons can still navigate into the extra pages. * Refactored and centralized the various popup windows in Editor Mode into editor_ui_popups.go; the SetupPopups() and various methods such as ShowPaletteWindow() and ShowDoodadDropper() make management of popups simple for the editor_ui! * The Menu Bar in Editor Mode now has context-specific tools in the Tools menu: the Doodad Dropper for levels and Layers for doodads. * Bugfix the Palette Editor window to work equally between Levels and Doodads, by only having it care about the Palette and not the Level that owns it.
285 lines
6.4 KiB
Go
285 lines
6.4 KiB
Go
package doodle
|
|
|
|
import (
|
|
"git.kirsle.net/apps/doodle/pkg/balance"
|
|
"git.kirsle.net/apps/doodle/pkg/drawtool"
|
|
"git.kirsle.net/apps/doodle/pkg/enum"
|
|
"git.kirsle.net/apps/doodle/pkg/sprites"
|
|
"git.kirsle.net/go/render"
|
|
"git.kirsle.net/go/ui"
|
|
)
|
|
|
|
// Width of the toolbar frame.
|
|
var toolbarWidth = 44 // 38px button (32px sprite + borders) + padding
|
|
var toolbarSpriteSize = 32 // 32x32 sprites.
|
|
|
|
// SetupToolbar configures the UI for the Tools panel.
|
|
func (u *EditorUI) SetupToolbar(d *Doodle) *ui.Frame {
|
|
frame := ui.NewFrame("Tool Bar")
|
|
frame.Resize(render.NewRect(toolbarWidth, 100))
|
|
frame.Configure(ui.Config{
|
|
BorderSize: 2,
|
|
BorderStyle: ui.BorderRaised,
|
|
Background: render.Grey,
|
|
})
|
|
|
|
btnFrame := ui.NewFrame("Tool Buttons")
|
|
frame.Pack(btnFrame, ui.Pack{
|
|
Side: ui.N,
|
|
})
|
|
|
|
// Buttons.
|
|
var buttons = []struct {
|
|
Value string
|
|
Icon string
|
|
Tooltip string
|
|
Click func()
|
|
|
|
// Optional fields.
|
|
NoDoodad bool // tool not available for Doodad editing (Levels only)
|
|
}{
|
|
{
|
|
Value: drawtool.PencilTool.String(),
|
|
Icon: "assets/sprites/pencil-tool.png",
|
|
Tooltip: "Pencil Tool",
|
|
Click: func() {
|
|
u.Canvas.Tool = drawtool.PencilTool
|
|
d.Flash("Pencil Tool selected.")
|
|
},
|
|
},
|
|
|
|
{
|
|
Value: drawtool.LineTool.String(),
|
|
Icon: "assets/sprites/line-tool.png",
|
|
Tooltip: "Line Tool",
|
|
Click: func() {
|
|
u.Canvas.Tool = drawtool.LineTool
|
|
d.Flash("Line Tool selected.")
|
|
},
|
|
},
|
|
|
|
{
|
|
Value: drawtool.RectTool.String(),
|
|
Icon: "assets/sprites/rect-tool.png",
|
|
Tooltip: "Rectangle Tool",
|
|
Click: func() {
|
|
u.Canvas.Tool = drawtool.RectTool
|
|
d.Flash("Rectangle Tool selected.")
|
|
},
|
|
},
|
|
|
|
{
|
|
Value: drawtool.EllipseTool.String(),
|
|
Icon: "assets/sprites/ellipse-tool.png",
|
|
Tooltip: "Ellipse Tool",
|
|
Click: func() {
|
|
u.Canvas.Tool = drawtool.EllipseTool
|
|
d.Flash("Ellipse Tool selected.")
|
|
},
|
|
},
|
|
|
|
{
|
|
Value: drawtool.ActorTool.String(),
|
|
Icon: "assets/sprites/actor-tool.png",
|
|
Tooltip: "Doodad Tool\nDrag-and-drop objects into your map",
|
|
NoDoodad: true,
|
|
Click: func() {
|
|
u.Canvas.Tool = drawtool.ActorTool
|
|
u.doodadWindow.Show()
|
|
d.Flash("Actor Tool selected. Drag a Doodad from the drawer into your level.")
|
|
},
|
|
},
|
|
|
|
{
|
|
Value: drawtool.LinkTool.String(),
|
|
Icon: "assets/sprites/link-tool.png",
|
|
Tooltip: "Link Tool\nConnect doodads to each other",
|
|
NoDoodad: true,
|
|
Click: func() {
|
|
u.Canvas.Tool = drawtool.LinkTool
|
|
u.doodadWindow.Show()
|
|
d.Flash("Link Tool selected. Click a doodad in your level to link it to another.")
|
|
},
|
|
},
|
|
|
|
{
|
|
Value: drawtool.EraserTool.String(),
|
|
Icon: "assets/sprites/eraser-tool.png",
|
|
Tooltip: "Eraser Tool",
|
|
Click: func() {
|
|
u.Canvas.Tool = drawtool.EraserTool
|
|
|
|
// Set the brush size within range for the eraser.
|
|
if u.Canvas.BrushSize < balance.DefaultEraserBrushSize {
|
|
u.Canvas.BrushSize = balance.DefaultEraserBrushSize
|
|
} else if u.Canvas.BrushSize > balance.MaxEraserBrushSize {
|
|
u.Canvas.BrushSize = balance.MaxEraserBrushSize
|
|
}
|
|
|
|
d.Flash("Eraser Tool selected.")
|
|
},
|
|
},
|
|
}
|
|
for _, button := range buttons {
|
|
button := button
|
|
if button.NoDoodad && u.Scene.DrawingType == enum.DoodadDrawing {
|
|
continue
|
|
}
|
|
|
|
image, err := sprites.LoadImage(d.Engine, button.Icon)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
btn := ui.NewRadioButton(
|
|
button.Value,
|
|
&u.activeTool,
|
|
button.Value,
|
|
image,
|
|
)
|
|
|
|
var btnSize = btn.BoxThickness(2) + toolbarSpriteSize
|
|
btn.Resize(render.NewRect(btnSize, btnSize))
|
|
|
|
btn.Handle(ui.Click, func(ed ui.EventData) error {
|
|
button.Click()
|
|
return nil
|
|
})
|
|
u.Supervisor.Add(btn)
|
|
|
|
ui.NewTooltip(btn, ui.Tooltip{
|
|
Text: button.Tooltip,
|
|
Edge: ui.Right,
|
|
})
|
|
|
|
btnFrame.Pack(btn, ui.Pack{
|
|
Side: ui.N,
|
|
PadY: 2,
|
|
})
|
|
}
|
|
|
|
// Doodad Editor: show the Layers button.
|
|
if u.Scene.DrawingType == enum.DoodadDrawing {
|
|
btn := ui.NewButton("Layers Button", ui.NewLabel(ui.Label{
|
|
Text: "Lyr.",
|
|
Font: balance.MenuFont,
|
|
}))
|
|
btn.Handle(ui.Click, func(ed ui.EventData) error {
|
|
u.OpenLayersWindow()
|
|
return nil
|
|
})
|
|
u.Supervisor.Add(btn)
|
|
btnFrame.Pack(btn, ui.Pack{
|
|
Side: ui.N,
|
|
PadY: 2,
|
|
})
|
|
}
|
|
|
|
// Spacer frame.
|
|
frame.Pack(ui.NewFrame("spacer"), ui.Pack{
|
|
Side: ui.N,
|
|
PadY: 8,
|
|
})
|
|
|
|
// "Brush Size" label
|
|
bsLabel := ui.NewLabel(ui.Label{
|
|
Text: "Size:",
|
|
Font: balance.LabelFont,
|
|
})
|
|
frame.Pack(bsLabel, ui.Pack{
|
|
Side: ui.N,
|
|
})
|
|
|
|
ui.NewTooltip(bsLabel, ui.Tooltip{
|
|
Text: "Set the line thickness for drawing",
|
|
Edge: ui.Right,
|
|
})
|
|
u.Supervisor.Add(bsLabel)
|
|
|
|
// Brush Size widget
|
|
{
|
|
sizeFrame := ui.NewFrame("Brush Size Frame")
|
|
frame.Pack(sizeFrame, ui.Pack{
|
|
Side: ui.N,
|
|
PadY: 0,
|
|
})
|
|
|
|
sizeLabel := ui.NewLabel(ui.Label{
|
|
IntVariable: &u.Canvas.BrushSize,
|
|
Font: balance.SmallMonoFont,
|
|
})
|
|
sizeLabel.Configure(ui.Config{
|
|
BorderSize: 1,
|
|
BorderStyle: ui.BorderSunken,
|
|
Background: render.Grey,
|
|
})
|
|
sizeFrame.Pack(sizeLabel, ui.Pack{
|
|
Side: ui.N,
|
|
FillX: true,
|
|
PadY: 2,
|
|
})
|
|
|
|
sizeBtnFrame := ui.NewFrame("Size Increment Button Frame")
|
|
sizeFrame.Pack(sizeBtnFrame, ui.Pack{
|
|
Side: ui.N,
|
|
FillX: true,
|
|
})
|
|
|
|
var incButtons = []struct {
|
|
Label string
|
|
F func()
|
|
}{
|
|
{
|
|
Label: "-",
|
|
F: func() {
|
|
// Select next smaller brush size.
|
|
for i := len(balance.BrushSizeOptions) - 1; i >= 0; i-- {
|
|
if balance.BrushSizeOptions[i] < u.Canvas.BrushSize {
|
|
u.Canvas.BrushSize = balance.BrushSizeOptions[i]
|
|
break
|
|
}
|
|
}
|
|
},
|
|
},
|
|
{
|
|
Label: "+",
|
|
F: func() {
|
|
// Select next bigger brush size.
|
|
for _, size := range balance.BrushSizeOptions {
|
|
if size > u.Canvas.BrushSize {
|
|
u.Canvas.BrushSize = size
|
|
break
|
|
}
|
|
}
|
|
|
|
// Limit the eraser brush size, too big and it's slow because
|
|
// the eraser has to scan and remember pixels to be able to
|
|
// Undo the erase and restore them.
|
|
if u.Canvas.Tool == drawtool.EraserTool && u.Canvas.BrushSize > balance.MaxEraserBrushSize {
|
|
u.Canvas.BrushSize = balance.MaxEraserBrushSize
|
|
}
|
|
},
|
|
},
|
|
}
|
|
for _, button := range incButtons {
|
|
button := button
|
|
btn := ui.NewButton("BrushSize"+button.Label, ui.NewLabel(ui.Label{
|
|
Text: button.Label,
|
|
Font: balance.SmallMonoFont,
|
|
}))
|
|
btn.Handle(ui.Click, func(ed ui.EventData) error {
|
|
button.F()
|
|
return nil
|
|
})
|
|
u.Supervisor.Add(btn)
|
|
sizeBtnFrame.Pack(btn, ui.Pack{
|
|
Side: ui.W,
|
|
})
|
|
}
|
|
}
|
|
|
|
frame.Compute(d.Engine)
|
|
|
|
return frame
|
|
}
|