Noah Petherbridge
c5e3fc297c
In the Level Editor, the "Level->Attached files" menu opens the FileSystem Window, which shows a paginated list of attached files and a "Delete" button to remove them. - Custom doodads which also exist locally can be deleted from the level's filesystem at any time. - If a custom doodad does NOT exist locally, and one of them is still placed somewhere within the level, you can not delete it. - You can't delete the custom wallpaper image IF the level is still using it. Change to a default wallpaper and then you can delete the custom wallpaper image.
297 lines
5.9 KiB
Go
297 lines
5.9 KiB
Go
package windows
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"strings"
|
|
|
|
"git.kirsle.net/apps/doodle/pkg/balance"
|
|
"git.kirsle.net/apps/doodle/pkg/level"
|
|
"git.kirsle.net/apps/doodle/pkg/level/publishing"
|
|
"git.kirsle.net/apps/doodle/pkg/log"
|
|
"git.kirsle.net/go/render"
|
|
"git.kirsle.net/go/ui"
|
|
)
|
|
|
|
// Publish window.
|
|
type Publish struct {
|
|
// Settings passed in by doodle
|
|
Supervisor *ui.Supervisor
|
|
Engine render.Engine
|
|
Level *level.Level
|
|
|
|
OnPublish func(builtinToo bool)
|
|
OnCancel func()
|
|
|
|
// Private vars.
|
|
includeBuiltins bool // show built-in doodads in checkbox-list.
|
|
}
|
|
|
|
// NewPublishWindow initializes the window.
|
|
func NewPublishWindow(cfg Publish) *ui.Window {
|
|
var (
|
|
windowWidth = 400
|
|
windowHeight = 300
|
|
page = 1
|
|
perPage = 4
|
|
pages = 1
|
|
maxPageButtons = 8
|
|
|
|
// columns and sizes to draw the doodad list
|
|
columns = 3
|
|
btnWidth = 120
|
|
btnHeight = 14
|
|
)
|
|
|
|
window := ui.NewWindow("Publish Level")
|
|
window.SetButtons(ui.CloseButton)
|
|
window.Configure(ui.Config{
|
|
Width: windowWidth,
|
|
Height: windowHeight,
|
|
Background: render.RGBA(200, 200, 255, 255),
|
|
})
|
|
|
|
/////////////
|
|
// Intro text
|
|
|
|
introFrame := ui.NewFrame("Intro Frame")
|
|
window.Pack(introFrame, ui.Pack{
|
|
Side: ui.N,
|
|
FillX: true,
|
|
})
|
|
|
|
lines := []struct {
|
|
Text string
|
|
Font render.Text
|
|
}{
|
|
{
|
|
Text: "About",
|
|
Font: balance.LabelFont,
|
|
},
|
|
{
|
|
Text: "Share your level easily! If you are using custom doodads in\n" +
|
|
"your level, you may attach them directly to your\n" +
|
|
"level file -- so it can easily run on another computer!",
|
|
Font: balance.UIFont,
|
|
},
|
|
{
|
|
Text: "List of Doodads in Your Level",
|
|
Font: balance.LabelFont,
|
|
},
|
|
}
|
|
for n, row := range lines {
|
|
frame := ui.NewFrame(fmt.Sprintf("Intro Line %d", n))
|
|
introFrame.Pack(frame, ui.Pack{
|
|
Side: ui.N,
|
|
FillX: true,
|
|
})
|
|
|
|
label := ui.NewLabel(ui.Label{
|
|
Text: row.Text,
|
|
Font: row.Font,
|
|
})
|
|
frame.Pack(label, ui.Pack{
|
|
Side: ui.W,
|
|
})
|
|
}
|
|
|
|
/////////////
|
|
// Custom Doodads checkbox-list.
|
|
doodadFrame := ui.NewFrame("Doodads Frame")
|
|
doodadFrame.Resize(render.Rect{
|
|
W: windowWidth,
|
|
H: btnHeight*perPage + 100,
|
|
})
|
|
window.Pack(doodadFrame, ui.Pack{
|
|
Side: ui.N,
|
|
FillX: true,
|
|
})
|
|
|
|
// First, the checkbox to show built-in doodads or not.
|
|
builtinRow := ui.NewFrame("Show Builtins Frame")
|
|
doodadFrame.Pack(builtinRow, ui.Pack{
|
|
Side: ui.N,
|
|
FillX: true,
|
|
})
|
|
builtinCB := ui.NewCheckbox("Show Builtins", &cfg.includeBuiltins, ui.NewLabel(ui.Label{
|
|
Text: "Attach built-in* doodads too",
|
|
Font: balance.UIFont,
|
|
}))
|
|
builtinCB.Supervise(cfg.Supervisor)
|
|
builtinRow.Pack(builtinCB, ui.Pack{
|
|
Side: ui.W,
|
|
PadX: 2,
|
|
})
|
|
|
|
// Collect the doodads named in this level.
|
|
usedBuiltins, usedCustom := publishing.GetUsedDoodadNames(cfg.Level)
|
|
|
|
// Helper function to draw the button rows for a set of doodads.
|
|
mkDoodadRows := func(filenames []string, builtin bool) []*ui.Frame {
|
|
var (
|
|
curRow *ui.Frame // = ui.NewFrame("mkDoodadRows 0")
|
|
frames = []*ui.Frame{}
|
|
)
|
|
|
|
for i, name := range filenames {
|
|
if i%columns == 0 {
|
|
curRow = ui.NewFrame(fmt.Sprintf("mkDoodadRows %d", i))
|
|
frames = append(frames, curRow)
|
|
}
|
|
|
|
font := balance.UIFont
|
|
if builtin {
|
|
font.Color = render.Blue
|
|
name += "*"
|
|
}
|
|
|
|
btn := ui.NewLabel(ui.Label{
|
|
Text: strings.Replace(name, ".doodad", "", 1),
|
|
Font: font,
|
|
})
|
|
btn.Configure(ui.Config{
|
|
Width: btnWidth,
|
|
Height: btnHeight,
|
|
})
|
|
curRow.Pack(btn, ui.Pack{
|
|
Side: ui.W,
|
|
PadX: 2,
|
|
PadY: 2,
|
|
})
|
|
}
|
|
|
|
return frames
|
|
}
|
|
|
|
// 1. Draw the built-in doodads in use.
|
|
var (
|
|
btnRows = []*ui.Frame{}
|
|
builtinRows = []*ui.Frame{}
|
|
customRows = []*ui.Frame{}
|
|
)
|
|
if len(usedCustom) > 0 {
|
|
customRows = mkDoodadRows(usedCustom, false)
|
|
btnRows = append(btnRows, customRows...)
|
|
}
|
|
if len(usedBuiltins) > 0 {
|
|
builtinRows = mkDoodadRows(usedBuiltins, true)
|
|
btnRows = append(btnRows, builtinRows...)
|
|
}
|
|
|
|
for i, row := range btnRows {
|
|
doodadFrame.Pack(row, ui.Pack{
|
|
Side: ui.N,
|
|
FillX: true,
|
|
})
|
|
|
|
// Hide if too long for 1st page.
|
|
if i >= perPage {
|
|
row.Hide()
|
|
}
|
|
}
|
|
|
|
/////////////
|
|
// Buttons at bottom of window
|
|
|
|
bottomFrame := ui.NewFrame("Button Frame")
|
|
window.Pack(bottomFrame, ui.Pack{
|
|
Side: ui.S,
|
|
FillX: true,
|
|
})
|
|
|
|
// Pager for the doodads.
|
|
pages = int(
|
|
math.Ceil(
|
|
float64(len(btnRows)) / float64(perPage),
|
|
),
|
|
)
|
|
pagerOnChange := func(newPage, perPage int) {
|
|
page = newPage
|
|
log.Info("Page: %d, %d", page, perPage)
|
|
|
|
// Re-evaluate which rows are shown/hidden for the page we're on.
|
|
var (
|
|
minRow = (page - 1) * perPage
|
|
visible = 0
|
|
)
|
|
for i, row := range btnRows {
|
|
if visible >= perPage {
|
|
row.Hide()
|
|
continue
|
|
}
|
|
|
|
if i < minRow {
|
|
row.Hide()
|
|
} else {
|
|
row.Show()
|
|
visible++
|
|
}
|
|
}
|
|
}
|
|
pager := ui.NewPager(ui.Pager{
|
|
Name: "Doodads List Pager",
|
|
Page: page,
|
|
Pages: pages,
|
|
PerPage: perPage,
|
|
MaxPageButtons: maxPageButtons,
|
|
Font: balance.MenuFont,
|
|
OnChange: pagerOnChange,
|
|
})
|
|
pager.Compute(cfg.Engine)
|
|
pager.Supervise(cfg.Supervisor)
|
|
bottomFrame.Place(pager, ui.Place{
|
|
Top: 20,
|
|
Left: 20,
|
|
})
|
|
|
|
frame := ui.NewFrame("Button frame")
|
|
buttons := []struct {
|
|
label string
|
|
primary bool
|
|
f func()
|
|
}{
|
|
{"Export Level", true, func() {
|
|
if cfg.OnPublish != nil {
|
|
cfg.OnPublish(cfg.includeBuiltins)
|
|
}
|
|
}},
|
|
{"Close", false, func() {
|
|
if cfg.OnCancel != nil {
|
|
cfg.OnCancel()
|
|
}
|
|
}},
|
|
}
|
|
for _, button := range buttons {
|
|
button := button
|
|
|
|
btn := ui.NewButton(button.label, ui.NewLabel(ui.Label{
|
|
Text: button.label,
|
|
Font: balance.MenuFont,
|
|
}))
|
|
if button.primary {
|
|
btn.SetStyle(&balance.ButtonPrimary)
|
|
}
|
|
|
|
btn.Handle(ui.Click, func(ed ui.EventData) error {
|
|
button.f()
|
|
return nil
|
|
})
|
|
|
|
btn.Compute(cfg.Engine)
|
|
cfg.Supervisor.Add(btn)
|
|
|
|
frame.Pack(btn, ui.Pack{
|
|
Side: ui.W,
|
|
PadX: 4,
|
|
Expand: true,
|
|
Fill: true,
|
|
})
|
|
}
|
|
bottomFrame.Pack(frame, ui.Pack{
|
|
Side: ui.E,
|
|
Padding: 8,
|
|
})
|
|
|
|
return window
|
|
}
|