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.
297 lines
6.1 KiB
Go
297 lines
6.1 KiB
Go
package windows
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
|
|
"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/shmem"
|
|
"git.kirsle.net/go/render"
|
|
"git.kirsle.net/go/ui"
|
|
)
|
|
|
|
// Layers shows the layers when editing a doodad file.
|
|
type Layers struct {
|
|
Supervisor *ui.Supervisor
|
|
Engine render.Engine
|
|
|
|
// Pointer to the currently edited level.
|
|
EditDoodad *doodads.Doodad
|
|
ActiveLayer int // pointer to selected layer
|
|
activeLayer string // cached string for radio button
|
|
|
|
// Callback functions.
|
|
OnChange func(*doodads.Doodad) // Doodad data was modified, reload the Canvas etc.
|
|
OnAddLayer func() // "Add Layer" button was clicked
|
|
OnCancel func() // Close button was clicked.
|
|
|
|
// Editor should change the active layer
|
|
OnChangeLayer func(index int)
|
|
}
|
|
|
|
// NewLayerWindow initializes the window.
|
|
func NewLayerWindow(config Layers) *ui.Window {
|
|
// Default options.
|
|
var (
|
|
title = "Layers"
|
|
rows = []*ui.Frame{}
|
|
|
|
// size of the popup window
|
|
width = 320
|
|
height = 300
|
|
|
|
// Column sizes of the palette table.
|
|
col1 = 40 // Index
|
|
col3 = 120 // Name
|
|
col4 = 60 // Edit button
|
|
// col5 = 150 // Delete
|
|
|
|
// pagination values
|
|
page = 1
|
|
perPage = 5
|
|
)
|
|
|
|
config.activeLayer = fmt.Sprintf("%d", config.ActiveLayer)
|
|
log.Warn("config.activeLayer=%s", config.activeLayer)
|
|
|
|
window := ui.NewWindow(title)
|
|
window.SetButtons(ui.CloseButton)
|
|
window.Configure(ui.Config{
|
|
Width: width,
|
|
Height: height,
|
|
Background: render.Grey,
|
|
})
|
|
|
|
frame := ui.NewFrame("Window Body Frame")
|
|
window.Pack(frame, ui.Pack{
|
|
Side: ui.N,
|
|
Fill: true,
|
|
Expand: true,
|
|
})
|
|
|
|
log.Info("SETUP PALETTE WINDOW")
|
|
|
|
// Draw the header row.
|
|
headers := []struct {
|
|
Name string
|
|
Size int
|
|
}{
|
|
{"Index", col1},
|
|
{"Name", col3},
|
|
{"Edit", col4},
|
|
}
|
|
header := ui.NewFrame("Header")
|
|
for _, col := range headers {
|
|
labelFrame := ui.NewFrame(col.Name)
|
|
labelFrame.Configure(ui.Config{
|
|
Width: col.Size,
|
|
Height: 24,
|
|
})
|
|
|
|
label := ui.NewLabel(ui.Label{
|
|
Text: col.Name,
|
|
Font: balance.MenuFontBold,
|
|
})
|
|
labelFrame.Pack(label, ui.Pack{
|
|
Side: ui.N,
|
|
})
|
|
|
|
header.Pack(labelFrame, ui.Pack{
|
|
Side: ui.W,
|
|
Padding: 2,
|
|
})
|
|
}
|
|
|
|
header.Compute(config.Engine)
|
|
frame.Pack(header, ui.Pack{
|
|
Side: ui.N,
|
|
})
|
|
|
|
// Draw the rows for each Layer in the given doodad.
|
|
if doodad := config.EditDoodad; doodad != nil {
|
|
for i, _ := range doodad.Layers {
|
|
i := i // rescope
|
|
var idStr = fmt.Sprintf("%d", i)
|
|
|
|
row := ui.NewFrame("Layer " + idStr)
|
|
rows = append(rows, row)
|
|
|
|
// Off the end of the first page?
|
|
if i >= perPage {
|
|
row.Hide()
|
|
}
|
|
|
|
// ID label.
|
|
idLabel := ui.NewLabel(ui.Label{
|
|
Text: idStr + ".",
|
|
Font: balance.MenuFont,
|
|
})
|
|
idLabel.Configure(ui.Config{
|
|
Width: col1,
|
|
Height: 24,
|
|
})
|
|
|
|
// Name button (click to rename the swatch)
|
|
btnName := ui.NewButton("Name", ui.NewLabel(ui.Label{
|
|
TextVariable: &doodad.Layers[i].Name,
|
|
}))
|
|
btnName.Configure(ui.Config{
|
|
Width: col3,
|
|
Height: 24,
|
|
})
|
|
btnName.Handle(ui.Click, func(ed ui.EventData) error {
|
|
shmem.Prompt("New layer name ["+doodad.Layers[i].Name+"]: ", func(answer string) {
|
|
log.Warn("Answer: %s", answer)
|
|
if answer != "" {
|
|
doodad.Layers[i].Name = answer
|
|
if config.OnChange != nil {
|
|
config.OnChange(config.EditDoodad)
|
|
}
|
|
}
|
|
})
|
|
return nil
|
|
})
|
|
config.Supervisor.Add(btnName)
|
|
|
|
// Edit button (open layer for editing)
|
|
// btnEdit := ui.NewButton("Edit", ui.NewLabel(ui.Label{
|
|
// Text: "Edit",
|
|
// }))
|
|
btnEdit := ui.NewRadioButton("Edit",
|
|
&config.activeLayer, idStr, ui.NewLabel(ui.Label{
|
|
Text: "Edit",
|
|
}))
|
|
btnEdit.Configure(ui.Config{
|
|
Width: col4,
|
|
Height: 24,
|
|
})
|
|
btnEdit.Handle(ui.Click, func(ed ui.EventData) error {
|
|
if config.OnChangeLayer != nil {
|
|
config.OnChangeLayer(i)
|
|
}
|
|
return nil
|
|
})
|
|
config.Supervisor.Add(btnEdit)
|
|
|
|
// Pack all the widgets.
|
|
row.Pack(idLabel, ui.Pack{
|
|
Side: ui.W,
|
|
PadX: 2,
|
|
})
|
|
row.Pack(btnName, ui.Pack{
|
|
Side: ui.W,
|
|
PadX: 2,
|
|
})
|
|
row.Pack(btnEdit, ui.Pack{
|
|
Side: ui.W,
|
|
PadX: 2,
|
|
})
|
|
|
|
row.Compute(config.Engine)
|
|
frame.Pack(row, ui.Pack{
|
|
Side: ui.N,
|
|
PadY: 2,
|
|
})
|
|
}
|
|
}
|
|
|
|
{
|
|
/******************
|
|
* Confirm/cancel buttons.
|
|
******************/
|
|
|
|
bottomFrame := ui.NewFrame("Button Frame")
|
|
frame.Pack(bottomFrame, ui.Pack{
|
|
Side: ui.S,
|
|
FillX: true,
|
|
})
|
|
|
|
// Pager for the doodads.
|
|
pager := ui.NewPager(ui.Pager{
|
|
Name: "Layers Window Pager",
|
|
Page: page,
|
|
Pages: int(math.Ceil(
|
|
float64(len(rows)) / float64(perPage),
|
|
)),
|
|
PerPage: perPage,
|
|
MaxPageButtons: 10,
|
|
Font: balance.MenuFont,
|
|
OnChange: func(newPage, perPage int) {
|
|
page = newPage
|
|
log.Info("Page: %d, %d", page, perPage)
|
|
|
|
// Re-evaluate which rows are shown/hidden for this page.
|
|
var (
|
|
minRow = (page - 1) * perPage
|
|
visible = 0
|
|
)
|
|
for i, row := range rows {
|
|
if visible >= perPage {
|
|
row.Hide()
|
|
continue
|
|
}
|
|
|
|
if i < minRow {
|
|
row.Hide()
|
|
} else {
|
|
row.Show()
|
|
visible++
|
|
}
|
|
}
|
|
},
|
|
})
|
|
pager.Compute(config.Engine)
|
|
pager.Supervise(config.Supervisor)
|
|
bottomFrame.Place(pager, ui.Place{
|
|
Top: 20,
|
|
Left: 20,
|
|
})
|
|
|
|
btnFrame := ui.NewFrame("Window Buttons")
|
|
var buttons = []struct {
|
|
Label string
|
|
F func(ui.EventData) error
|
|
}{
|
|
{"Add Layer", func(ed ui.EventData) error {
|
|
if config.OnAddLayer != nil {
|
|
config.OnAddLayer()
|
|
}
|
|
|
|
if config.OnChange != nil {
|
|
config.OnChange(config.EditDoodad)
|
|
}
|
|
return nil
|
|
}},
|
|
{"Close", func(ed ui.EventData) error {
|
|
if config.OnCancel != nil {
|
|
config.OnCancel()
|
|
}
|
|
return nil
|
|
}},
|
|
}
|
|
for _, t := range buttons {
|
|
btn := ui.NewButton(t.Label, ui.NewLabel(ui.Label{
|
|
Text: t.Label,
|
|
Font: balance.MenuFont,
|
|
}))
|
|
btn.Handle(ui.Click, t.F)
|
|
btn.Compute(config.Engine)
|
|
config.Supervisor.Add(btn)
|
|
|
|
btnFrame.Pack(btn, ui.Pack{
|
|
Side: ui.W,
|
|
PadX: 4,
|
|
})
|
|
}
|
|
bottomFrame.Place(btnFrame, ui.Place{
|
|
Top: 60,
|
|
Center: true,
|
|
})
|
|
}
|
|
|
|
window.Hide()
|
|
return window
|
|
}
|