Window Icon, UI Polish
* SDL2 builds of the game now set their app window icon. * Create/Edit Level window is updated to show a tabbed UI to create a new Level or a new Doodad. The dedicated main menu button to create a new doodad (which immediately prompted for its size) is replaced by this new tab's UI. * Edit Drawing/Play Level window is more responsive to smaller screen sizes by drawing fewer columns of filenames. * Bugfix: the Alert and Confirm modals always re-center themselves on screen, especially to adapt between Portrait or Landscape mode on a mobile device.
BIN
assets/icons/1024.png
Normal file
After Width: | Height: | Size: 89 KiB |
BIN
assets/icons/128.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
assets/icons/16.png
Normal file
After Width: | Height: | Size: 785 B |
BIN
assets/icons/256.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
assets/icons/32.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/icons/512.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
assets/icons/64.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
assets/icons/96.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
|
@ -19,6 +19,7 @@ import (
|
||||||
"git.kirsle.net/apps/doodle/pkg/log"
|
"git.kirsle.net/apps/doodle/pkg/log"
|
||||||
"git.kirsle.net/apps/doodle/pkg/shmem"
|
"git.kirsle.net/apps/doodle/pkg/shmem"
|
||||||
"git.kirsle.net/apps/doodle/pkg/sound"
|
"git.kirsle.net/apps/doodle/pkg/sound"
|
||||||
|
"git.kirsle.net/apps/doodle/pkg/sprites"
|
||||||
"git.kirsle.net/apps/doodle/pkg/usercfg"
|
"git.kirsle.net/apps/doodle/pkg/usercfg"
|
||||||
"git.kirsle.net/go/render"
|
"git.kirsle.net/go/render"
|
||||||
"git.kirsle.net/go/render/sdl"
|
"git.kirsle.net/go/render/sdl"
|
||||||
|
@ -166,6 +167,16 @@ func main() {
|
||||||
|
|
||||||
game := doodle.New(c.Bool("debug"), engine)
|
game := doodle.New(c.Bool("debug"), engine)
|
||||||
game.SetupEngine()
|
game.SetupEngine()
|
||||||
|
|
||||||
|
// Set the app window icon.
|
||||||
|
if engine, ok := game.Engine.(*sdl.Renderer); ok {
|
||||||
|
if icon, err := sprites.LoadImage(game.Engine, balance.WindowIcon); err == nil {
|
||||||
|
engine.SetWindowIcon(icon.Image)
|
||||||
|
} else {
|
||||||
|
log.Error("Couldn't load WindowIcon (%s): %s", balance.WindowIcon, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if c.Bool("guitest") {
|
if c.Bool("guitest") {
|
||||||
game.Goto(&doodle.GUITestScene{})
|
game.Goto(&doodle.GUITestScene{})
|
||||||
} else if filename != "" {
|
} else if filename != "" {
|
||||||
|
|
|
@ -8,6 +8,8 @@ import (
|
||||||
|
|
||||||
// Theme and appearance variables.
|
// Theme and appearance variables.
|
||||||
var (
|
var (
|
||||||
|
WindowIcon = "assets/icons/96.png"
|
||||||
|
|
||||||
// Title Screen Font
|
// Title Screen Font
|
||||||
TitleScreenFont = render.Text{
|
TitleScreenFont = render.Text{
|
||||||
Size: 46,
|
Size: 46,
|
||||||
|
|
|
@ -78,7 +78,7 @@ func (u *EditorUI) SetupMenuBar(d *Doodle) *ui.MenuBar {
|
||||||
|
|
||||||
fileMenu.AddItemAccel("Open...", "Ctrl-O", u.Scene.MenuOpen)
|
fileMenu.AddItemAccel("Open...", "Ctrl-O", u.Scene.MenuOpen)
|
||||||
fileMenu.AddSeparator()
|
fileMenu.AddSeparator()
|
||||||
fileMenu.AddItem("Close "+drawingType, func() {
|
fileMenu.AddItem("Quit to menu", func() {
|
||||||
u.Scene.ConfirmUnload(func() {
|
u.Scene.ConfirmUnload(func() {
|
||||||
d.Goto(&MainScene{})
|
d.Goto(&MainScene{})
|
||||||
})
|
})
|
||||||
|
|
|
@ -17,3 +17,11 @@ const (
|
||||||
DoodadExt = ".doodad"
|
DoodadExt = ".doodad"
|
||||||
LevelPackExt = ".levelpack"
|
LevelPackExt = ".levelpack"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Responsive breakpoints for mobile friendly UIs.
|
||||||
|
const (
|
||||||
|
ScreenWidthXSmall = 400
|
||||||
|
ScreenWidthSmall = 600
|
||||||
|
ScreenWidthMedium = 800
|
||||||
|
ScreenWidthLarge = 1000
|
||||||
|
)
|
||||||
|
|
|
@ -36,7 +36,6 @@ type MainScene struct {
|
||||||
labelVersion *ui.Label
|
labelVersion *ui.Label
|
||||||
labelHint *ui.Label
|
labelHint *ui.Label
|
||||||
frame *ui.Frame // Main button frame
|
frame *ui.Frame // Main button frame
|
||||||
btnRegister *ui.Button
|
|
||||||
winRegister *ui.Window
|
winRegister *ui.Window
|
||||||
winSettings *ui.Window
|
winSettings *ui.Window
|
||||||
winLevelPacks *ui.Window
|
winLevelPacks *ui.Window
|
||||||
|
@ -125,13 +124,72 @@ func (s *MainScene) Setup(d *Doodle) error {
|
||||||
s.updateButton.Hide()
|
s.updateButton.Hide()
|
||||||
s.Supervisor.Add(s.updateButton)
|
s.Supervisor.Add(s.updateButton)
|
||||||
|
|
||||||
// Register button.
|
// Main UI button frame.
|
||||||
s.btnRegister = ui.NewButton("Register", ui.NewLabel(ui.Label{
|
frame := ui.NewFrame("frame")
|
||||||
Text: "Register Game",
|
s.frame = frame
|
||||||
Font: balance.LabelFont,
|
|
||||||
}))
|
var buttons = []struct {
|
||||||
s.btnRegister.SetStyle(&balance.ButtonPrimary)
|
Name string
|
||||||
s.btnRegister.Handle(ui.Click, func(ed ui.EventData) error {
|
If func() bool
|
||||||
|
Func func()
|
||||||
|
Style *style.Button
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Name: "Story Mode",
|
||||||
|
Func: func() {
|
||||||
|
if s.winLevelPacks == nil {
|
||||||
|
s.winLevelPacks = windows.NewLevelPackWindow(windows.LevelPack{
|
||||||
|
Supervisor: s.Supervisor,
|
||||||
|
Engine: d.Engine,
|
||||||
|
|
||||||
|
OnPlayLevel: func(lp levelpack.LevelPack, which levelpack.Level) {
|
||||||
|
if err := d.PlayFromLevelpack(lp, which); err != nil {
|
||||||
|
shmem.FlashError(err.Error())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
OnCloseWindow: func() {
|
||||||
|
s.winLevelPacks.Hide()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
s.winLevelPacks.MoveTo(render.Point{
|
||||||
|
X: (d.width / 2) - (s.winLevelPacks.Size().W / 2),
|
||||||
|
Y: (d.height / 2) - (s.winLevelPacks.Size().H / 2),
|
||||||
|
})
|
||||||
|
s.winLevelPacks.Show()
|
||||||
|
},
|
||||||
|
Style: &balance.ButtonBabyBlue,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Play a Level",
|
||||||
|
Func: d.GotoPlayMenu,
|
||||||
|
Style: &balance.ButtonBabyBlue,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "New Drawing",
|
||||||
|
Func: d.GotoNewMenu,
|
||||||
|
Style: &balance.ButtonPink,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Edit Drawing",
|
||||||
|
Func: d.GotoLoadMenu,
|
||||||
|
Style: &balance.ButtonPink,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Settings",
|
||||||
|
Func: func() {
|
||||||
|
if s.winSettings == nil {
|
||||||
|
s.winSettings = d.MakeSettingsWindow(s.Supervisor)
|
||||||
|
}
|
||||||
|
s.winSettings.Show()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Register",
|
||||||
|
If: func() bool {
|
||||||
|
return !license.IsRegistered()
|
||||||
|
},
|
||||||
|
Func: func() {
|
||||||
if s.winRegister == nil {
|
if s.winRegister == nil {
|
||||||
cfg := windows.License{
|
cfg := windows.License{
|
||||||
Supervisor: s.Supervisor,
|
Supervisor: s.Supervisor,
|
||||||
|
@ -151,78 +209,9 @@ func (s *MainScene) Setup(d *Doodle) error {
|
||||||
cfg.OnLicensed()
|
cfg.OnLicensed()
|
||||||
}
|
}
|
||||||
s.winRegister.Show()
|
s.winRegister.Show()
|
||||||
return nil
|
|
||||||
})
|
|
||||||
s.btnRegister.Compute(d.Engine)
|
|
||||||
s.Supervisor.Add(s.btnRegister)
|
|
||||||
|
|
||||||
if license.IsRegistered() {
|
|
||||||
s.btnRegister.Hide()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Main UI button frame.
|
|
||||||
frame := ui.NewFrame("frame")
|
|
||||||
s.frame = frame
|
|
||||||
|
|
||||||
var buttons = []struct {
|
|
||||||
Name string
|
|
||||||
Func func()
|
|
||||||
Style *style.Button
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
Name: "Story Mode",
|
|
||||||
Func: func() {
|
|
||||||
if s.winLevelPacks == nil {
|
|
||||||
s.winLevelPacks = windows.NewLevelPackWindow(windows.LevelPack{
|
|
||||||
Supervisor: s.Supervisor,
|
|
||||||
Engine: d.Engine,
|
|
||||||
|
|
||||||
OnPlayLevel: func(lp levelpack.LevelPack, which levelpack.Level) {
|
|
||||||
if err := d.PlayFromLevelpack(lp, which); err != nil {
|
|
||||||
shmem.FlashError(err.Error())
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
})
|
|
||||||
}
|
|
||||||
s.winLevelPacks.MoveTo(render.Point{
|
|
||||||
X: (d.width / 2) - (s.winLevelPacks.Size().W / 2),
|
|
||||||
Y: (d.height / 2) - (s.winLevelPacks.Size().H / 2),
|
|
||||||
})
|
|
||||||
s.winLevelPacks.Show()
|
|
||||||
},
|
|
||||||
Style: &balance.ButtonBabyBlue,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Play a Level",
|
|
||||||
Func: d.GotoPlayMenu,
|
|
||||||
Style: &balance.ButtonBabyBlue,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Create a Level",
|
|
||||||
Func: d.GotoNewMenu,
|
|
||||||
Style: &balance.ButtonPink,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Create a Doodad",
|
|
||||||
Func: func() {
|
|
||||||
d.NewDoodad(0)
|
|
||||||
},
|
|
||||||
Style: &balance.ButtonPink,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "Edit a Drawing",
|
|
||||||
Func: d.GotoLoadMenu,
|
|
||||||
Style: &balance.ButtonPrimary,
|
Style: &balance.ButtonPrimary,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Name: "Settings",
|
|
||||||
Func: func() {
|
|
||||||
if s.winSettings == nil {
|
|
||||||
s.winSettings = d.MakeSettingsWindow(s.Supervisor)
|
|
||||||
}
|
|
||||||
s.winSettings.Show()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
for _, button := range buttons {
|
for _, button := range buttons {
|
||||||
button := button
|
button := button
|
||||||
|
@ -406,12 +395,6 @@ func (s *MainScene) positionMenuPortrait(d *Doodle) {
|
||||||
X: (d.width / 2) - (s.frame.Size().W / 2),
|
X: (d.width / 2) - (s.frame.Size().W / 2),
|
||||||
Y: 260,
|
Y: 260,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Register button.
|
|
||||||
s.btnRegister.MoveTo(render.Point{
|
|
||||||
X: d.width - s.btnRegister.Size().W - 24,
|
|
||||||
Y: d.height - s.btnRegister.Size().H - 24,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MainScene) positionMenuLandscape(d *Doodle) {
|
func (s *MainScene) positionMenuLandscape(d *Doodle) {
|
||||||
|
@ -447,13 +430,6 @@ func (s *MainScene) positionMenuLandscape(d *Doodle) {
|
||||||
X: (col2.X+col2.W)/2 - (s.frame.Size().W / 2),
|
X: (col2.X+col2.W)/2 - (s.frame.Size().W / 2),
|
||||||
Y: (d.height / 2) - (s.frame.Size().H / 2),
|
Y: (d.height / 2) - (s.frame.Size().H / 2),
|
||||||
})
|
})
|
||||||
|
|
||||||
// Register button to the top left.
|
|
||||||
// TODO: not ideal, move into main button list?
|
|
||||||
s.btnRegister.MoveTo(render.Point{
|
|
||||||
X: 20,
|
|
||||||
Y: 20,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoopLazyScroll gently scrolls the title screen demo level, called each Loop.
|
// LoopLazyScroll gently scrolls the title screen demo level, called each Loop.
|
||||||
|
@ -560,9 +536,6 @@ func (s *MainScene) Draw(d *Doodle) error {
|
||||||
s.frame.Compute(d.Engine)
|
s.frame.Compute(d.Engine)
|
||||||
s.frame.Present(d.Engine, s.frame.Point())
|
s.frame.Present(d.Engine, s.frame.Point())
|
||||||
|
|
||||||
// Register button.
|
|
||||||
s.btnRegister.Present(d.Engine, s.btnRegister.Point())
|
|
||||||
|
|
||||||
// Present supervised windows.
|
// Present supervised windows.
|
||||||
s.Supervisor.Present(d.Engine)
|
s.Supervisor.Present(d.Engine)
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,9 @@ MenuScene holds the main dialog menu UIs for:
|
||||||
* New Level
|
* New Level
|
||||||
* Open Level
|
* Open Level
|
||||||
* Settings
|
* Settings
|
||||||
|
|
||||||
|
DEPRECATED: migrate these prompts into popup windows to appear
|
||||||
|
on the MainScene or elsewhere as wanted.
|
||||||
*/
|
*/
|
||||||
type MenuScene struct {
|
type MenuScene struct {
|
||||||
// Configuration.
|
// Configuration.
|
||||||
|
@ -159,6 +162,9 @@ func (s *MenuScene) setupNewWindow(d *Doodle) error {
|
||||||
Level: lvl,
|
Level: lvl,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
OnCreateNewDoodad: func(size int) {
|
||||||
|
d.NewDoodad(size)
|
||||||
|
},
|
||||||
OnCancel: func() {
|
OnCancel: func() {
|
||||||
d.Goto(&MainScene{})
|
d.Goto(&MainScene{})
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||||
"git.kirsle.net/apps/doodle/pkg/keybind"
|
"git.kirsle.net/apps/doodle/pkg/keybind"
|
||||||
"git.kirsle.net/apps/doodle/pkg/modal/loadscreen"
|
"git.kirsle.net/apps/doodle/pkg/modal/loadscreen"
|
||||||
|
"git.kirsle.net/apps/doodle/pkg/shmem"
|
||||||
"git.kirsle.net/go/render"
|
"git.kirsle.net/go/render"
|
||||||
"git.kirsle.net/go/render/event"
|
"git.kirsle.net/go/render/event"
|
||||||
"git.kirsle.net/go/ui"
|
"git.kirsle.net/go/ui"
|
||||||
|
@ -87,10 +88,13 @@ func Draw() {
|
||||||
|
|
||||||
// Center the window on screen.
|
// Center the window on screen.
|
||||||
func center(win *ui.Window) {
|
func center(win *ui.Window) {
|
||||||
var modSize = win.Size()
|
var (
|
||||||
|
modSize = win.Size()
|
||||||
|
width, height = shmem.CurrentRenderEngine.WindowSize()
|
||||||
|
)
|
||||||
var moveTo = render.Point{
|
var moveTo = render.Point{
|
||||||
X: (window.W / 2) - (modSize.W / 2),
|
X: (width / 2) - (modSize.W / 2),
|
||||||
Y: (window.H / 4) - (modSize.H / 2),
|
Y: (height / 4) - (modSize.H / 2),
|
||||||
}
|
}
|
||||||
win.MoveTo(moveTo)
|
win.MoveTo(moveTo)
|
||||||
|
|
||||||
|
|
|
@ -24,19 +24,60 @@ type AddEditLevel struct {
|
||||||
// Callback functions.
|
// Callback functions.
|
||||||
OnChangePageTypeAndWallpaper func(pageType level.PageType, wallpaper string)
|
OnChangePageTypeAndWallpaper func(pageType level.PageType, wallpaper string)
|
||||||
OnCreateNewLevel func(*level.Level)
|
OnCreateNewLevel func(*level.Level)
|
||||||
|
OnCreateNewDoodad func(size int)
|
||||||
OnReload func()
|
OnReload func()
|
||||||
OnCancel func()
|
OnCancel func()
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAddEditLevel initializes the window.
|
// NewAddEditLevel initializes the window.
|
||||||
func NewAddEditLevel(config AddEditLevel) *ui.Window {
|
func NewAddEditLevel(config AddEditLevel) *ui.Window {
|
||||||
|
// Default options.
|
||||||
|
var (
|
||||||
|
title = "New Drawing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Given a level to edit?
|
||||||
|
if config.EditLevel != nil {
|
||||||
|
title = "Level Properties"
|
||||||
|
}
|
||||||
|
|
||||||
|
window := ui.NewWindow(title)
|
||||||
|
window.SetButtons(ui.CloseButton)
|
||||||
|
window.Configure(ui.Config{
|
||||||
|
Width: 400,
|
||||||
|
Height: 280,
|
||||||
|
Background: render.Grey,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Tabbed UI for New Level or New Doodad.
|
||||||
|
tabframe := ui.NewTabFrame("Level Tabs")
|
||||||
|
if config.EditLevel != nil {
|
||||||
|
tabframe.SetTabsHidden(true)
|
||||||
|
}
|
||||||
|
window.Pack(tabframe, ui.Pack{
|
||||||
|
Side: ui.N,
|
||||||
|
Fill: true,
|
||||||
|
Expand: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Add the tabs.
|
||||||
|
config.setupLevelFrame(tabframe)
|
||||||
|
config.setupDoodadFrame(tabframe)
|
||||||
|
|
||||||
|
tabframe.Supervise(config.Supervisor)
|
||||||
|
|
||||||
|
window.Hide()
|
||||||
|
return window
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates the Create/Edit Level tab ("index").
|
||||||
|
func (config AddEditLevel) setupLevelFrame(tf *ui.TabFrame) {
|
||||||
// Default options.
|
// Default options.
|
||||||
var (
|
var (
|
||||||
newPageType = level.Bounded.String()
|
newPageType = level.Bounded.String()
|
||||||
newWallpaper = "notebook.png"
|
newWallpaper = "notebook.png"
|
||||||
paletteName = level.DefaultPaletteNames[0]
|
paletteName = level.DefaultPaletteNames[0]
|
||||||
isNewLevel = config.EditLevel == nil
|
isNewLevel = config.EditLevel == nil
|
||||||
title = "New Drawing"
|
|
||||||
|
|
||||||
// Default text for the Palette drop-down for already-existing levels.
|
// Default text for the Palette drop-down for already-existing levels.
|
||||||
// (needs --experimental feature flag to enable the UI).
|
// (needs --experimental feature flag to enable the UI).
|
||||||
|
@ -53,24 +94,12 @@ func NewAddEditLevel(config AddEditLevel) *ui.Window {
|
||||||
newPageType = config.EditLevel.PageType.String()
|
newPageType = config.EditLevel.PageType.String()
|
||||||
newWallpaper = config.EditLevel.Wallpaper
|
newWallpaper = config.EditLevel.Wallpaper
|
||||||
paletteName = textCurrentPalette
|
paletteName = textCurrentPalette
|
||||||
title = "Level Properties"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
window := ui.NewWindow(title)
|
frame := tf.AddTab("index", ui.NewLabel(ui.Label{
|
||||||
window.SetButtons(ui.CloseButton)
|
Text: "New Level",
|
||||||
window.Configure(ui.Config{
|
Font: balance.TabFont,
|
||||||
Width: 400,
|
}))
|
||||||
Height: 280,
|
|
||||||
Background: render.Grey,
|
|
||||||
})
|
|
||||||
|
|
||||||
{
|
|
||||||
frame := ui.NewFrame("New Level Frame")
|
|
||||||
window.Pack(frame, ui.Pack{
|
|
||||||
Side: ui.N,
|
|
||||||
Fill: true,
|
|
||||||
Expand: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
/******************
|
/******************
|
||||||
* Frame for selecting Page Type
|
* Frame for selecting Page Type
|
||||||
|
@ -468,7 +497,11 @@ func NewAddEditLevel(config AddEditLevel) *ui.Window {
|
||||||
lvl.SetFile(balance.CustomWallpaperEmbedPath, []byte(newWallpaperB64))
|
lvl.SetFile(balance.CustomWallpaperEmbedPath, []byte(newWallpaperB64))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.OnCreateNewLevel != nil {
|
||||||
config.OnCreateNewLevel(lvl)
|
config.OnCreateNewLevel(lvl)
|
||||||
|
} else {
|
||||||
|
shmem.FlashError("OnCreateNewLevel not attached")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}},
|
}},
|
||||||
|
|
||||||
|
@ -517,8 +550,126 @@ func NewAddEditLevel(config AddEditLevel) *ui.Window {
|
||||||
PadY: 8,
|
PadY: 8,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates the "New Doodad" frame.
|
||||||
|
func (config AddEditLevel) setupDoodadFrame(tf *ui.TabFrame) {
|
||||||
|
// Default options.
|
||||||
|
var (
|
||||||
|
doodadSize = 64
|
||||||
|
)
|
||||||
|
|
||||||
|
frame := tf.AddTab("doodad", ui.NewLabel(ui.Label{
|
||||||
|
Text: "New Doodad",
|
||||||
|
Font: balance.TabFont,
|
||||||
|
}))
|
||||||
|
|
||||||
|
/******************
|
||||||
|
* Frame for selecting Page Type
|
||||||
|
******************/
|
||||||
|
|
||||||
|
typeFrame := ui.NewFrame("Doodad Options Frame")
|
||||||
|
frame.Pack(typeFrame, ui.Pack{
|
||||||
|
Side: ui.N,
|
||||||
|
FillX: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
label1 := ui.NewLabel(ui.Label{
|
||||||
|
Text: "Doodad sprite size (square):",
|
||||||
|
Font: balance.LabelFont,
|
||||||
|
})
|
||||||
|
typeFrame.Pack(label1, ui.Pack{
|
||||||
|
Side: ui.W,
|
||||||
|
})
|
||||||
|
|
||||||
|
// A selectbox to suggest some sizes or let the user enter a custom.
|
||||||
|
sizeBtn := ui.NewSelectBox("Size Select", ui.Label{
|
||||||
|
Font: ui.MenuFont,
|
||||||
|
})
|
||||||
|
typeFrame.Pack(sizeBtn, ui.Pack{
|
||||||
|
Side: ui.W,
|
||||||
|
Expand: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, row := range []struct {
|
||||||
|
Name string
|
||||||
|
Value int
|
||||||
|
}{
|
||||||
|
{"32", 32},
|
||||||
|
{"64", 64},
|
||||||
|
{"96", 96},
|
||||||
|
{"128", 128},
|
||||||
|
{"200", 200},
|
||||||
|
{"256", 256},
|
||||||
|
{"Custom...", 0},
|
||||||
|
} {
|
||||||
|
row := row
|
||||||
|
sizeBtn.AddItem(row.Name, row.Value, func() {})
|
||||||
}
|
}
|
||||||
|
|
||||||
window.Hide()
|
sizeBtn.SetValue(doodadSize)
|
||||||
return window
|
sizeBtn.Handle(ui.Change, func(ed ui.EventData) error {
|
||||||
|
if selection, ok := sizeBtn.GetValue(); ok {
|
||||||
|
if size, ok := selection.Value.(int); ok {
|
||||||
|
if size == 0 {
|
||||||
|
shmem.Prompt("Enter a custom size for the doodad width and height: ", func(answer string) {
|
||||||
|
if a, err := strconv.Atoi(answer); err == nil && a > 0 {
|
||||||
|
doodadSize = a
|
||||||
|
} else {
|
||||||
|
shmem.FlashError("Doodad size should be a number greater than zero.")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
doodadSize = size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
sizeBtn.Supervise(config.Supervisor)
|
||||||
|
config.Supervisor.Add(sizeBtn)
|
||||||
|
|
||||||
|
/******************
|
||||||
|
* Confirm/cancel buttons.
|
||||||
|
******************/
|
||||||
|
|
||||||
|
bottomFrame := ui.NewFrame("Button Frame")
|
||||||
|
frame.Pack(bottomFrame, ui.Pack{
|
||||||
|
Side: ui.N,
|
||||||
|
FillX: true,
|
||||||
|
PadY: 8,
|
||||||
|
})
|
||||||
|
|
||||||
|
var buttons = []struct {
|
||||||
|
Label string
|
||||||
|
F func(ui.EventData) error
|
||||||
|
}{
|
||||||
|
{"Continue", func(ed ui.EventData) error {
|
||||||
|
if config.OnCreateNewDoodad != nil {
|
||||||
|
config.OnCreateNewDoodad(doodadSize)
|
||||||
|
} else {
|
||||||
|
shmem.FlashError("OnCreateNewDoodad not attached")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}},
|
||||||
|
|
||||||
|
{"Cancel", func(ed ui.EventData) error {
|
||||||
|
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)
|
||||||
|
config.Supervisor.Add(btn)
|
||||||
|
bottomFrame.Pack(btn, ui.Pack{
|
||||||
|
Side: ui.W,
|
||||||
|
PadX: 4,
|
||||||
|
PadY: 8,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ type LevelPack struct {
|
||||||
|
|
||||||
// Callback functions.
|
// Callback functions.
|
||||||
OnPlayLevel func(pack levelpack.LevelPack, level levelpack.Level)
|
OnPlayLevel func(pack levelpack.LevelPack, level levelpack.Level)
|
||||||
|
OnCloseWindow func()
|
||||||
|
|
||||||
// Internal variables
|
// Internal variables
|
||||||
window *ui.Window
|
window *ui.Window
|
||||||
|
@ -65,6 +66,7 @@ func NewLevelPackWindow(config LevelPack) *ui.Window {
|
||||||
// And each LevelPack's screen is a pager for its Levels.
|
// And each LevelPack's screen is a pager for its Levels.
|
||||||
tabFrame := ui.NewTabFrame("Screens Manager")
|
tabFrame := ui.NewTabFrame("Screens Manager")
|
||||||
tabFrame.SetTabsHidden(true)
|
tabFrame.SetTabsHidden(true)
|
||||||
|
tabFrame.Supervise(config.Supervisor)
|
||||||
window.Pack(tabFrame, ui.Pack{
|
window.Pack(tabFrame, ui.Pack{
|
||||||
Side: ui.N,
|
Side: ui.N,
|
||||||
FillX: true,
|
FillX: true,
|
||||||
|
@ -90,12 +92,23 @@ func NewLevelPackWindow(config LevelPack) *ui.Window {
|
||||||
config.makeDetailScreen(tab, width, height, packmap[filename])
|
config.makeDetailScreen(tab, width, height, packmap[filename])
|
||||||
}
|
}
|
||||||
|
|
||||||
// indexTab.Resize(render.Rect{
|
// Close button.
|
||||||
// W: width-4,
|
if config.OnCloseWindow != nil {
|
||||||
// H: height-4,
|
closeBtn := ui.NewButton("Close Window", ui.NewLabel(ui.Label{
|
||||||
// })
|
Text: "Close",
|
||||||
|
Font: balance.MenuFont,
|
||||||
|
}))
|
||||||
|
closeBtn.Handle(ui.Click, func(ed ui.EventData) error {
|
||||||
|
config.OnCloseWindow()
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
config.Supervisor.Add(closeBtn)
|
||||||
|
window.Place(closeBtn, ui.Place{
|
||||||
|
Bottom: 15,
|
||||||
|
Center: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
tabFrame.Supervise(config.Supervisor)
|
|
||||||
window.Supervise(config.Supervisor)
|
window.Supervise(config.Supervisor)
|
||||||
window.Hide()
|
window.Hide()
|
||||||
return window
|
return window
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||||
|
"git.kirsle.net/apps/doodle/pkg/enum"
|
||||||
"git.kirsle.net/apps/doodle/pkg/level"
|
"git.kirsle.net/apps/doodle/pkg/level"
|
||||||
"git.kirsle.net/apps/doodle/pkg/log"
|
"git.kirsle.net/apps/doodle/pkg/log"
|
||||||
"git.kirsle.net/apps/doodle/pkg/native"
|
"git.kirsle.net/apps/doodle/pkg/native"
|
||||||
|
@ -32,8 +33,18 @@ type OpenLevelEditor struct {
|
||||||
func NewOpenLevelEditor(config OpenLevelEditor) *ui.Window {
|
func NewOpenLevelEditor(config OpenLevelEditor) *ui.Window {
|
||||||
var (
|
var (
|
||||||
width, height = config.Engine.WindowSize()
|
width, height = config.Engine.WindowSize()
|
||||||
|
columns = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Show fewer columns on smaller devices.
|
||||||
|
if width <= enum.ScreenWidthXSmall {
|
||||||
|
columns = 1
|
||||||
|
} else if width <= enum.ScreenWidthSmall {
|
||||||
|
columns = 2
|
||||||
|
} else if width <= enum.ScreenWidthMedium {
|
||||||
|
columns = 3
|
||||||
|
}
|
||||||
|
|
||||||
window := ui.NewWindow("Open Drawing")
|
window := ui.NewWindow("Open Drawing")
|
||||||
window.Configure(ui.Config{
|
window.Configure(ui.Config{
|
||||||
Width: int(float64(width) * 0.75),
|
Width: int(float64(width) * 0.75),
|
||||||
|
@ -86,7 +97,9 @@ func NewOpenLevelEditor(config OpenLevelEditor) *ui.Window {
|
||||||
func(i int, lvl string) {
|
func(i int, lvl string) {
|
||||||
btn := ui.NewButton("Level Btn", ui.NewLabel(ui.Label{
|
btn := ui.NewButton("Level Btn", ui.NewLabel(ui.Label{
|
||||||
Text: lvl,
|
Text: lvl,
|
||||||
Font: balance.MenuFont,
|
Font: balance.MenuFont.Update(render.Text{
|
||||||
|
PadY: 2,
|
||||||
|
}),
|
||||||
}))
|
}))
|
||||||
btn.Handle(ui.Click, func(ed ui.EventData) error {
|
btn.Handle(ui.Click, func(ed ui.EventData) error {
|
||||||
if config.LoadForPlay {
|
if config.LoadForPlay {
|
||||||
|
@ -103,7 +116,7 @@ func NewOpenLevelEditor(config OpenLevelEditor) *ui.Window {
|
||||||
Fill: true,
|
Fill: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
if i > 0 && (i+1)%4 == 0 {
|
if columns == 1 || i > 0 && (i+1)%columns == 0 {
|
||||||
lvlRow = ui.NewFrame(fmt.Sprintf("Level Row %d", i))
|
lvlRow = ui.NewFrame(fmt.Sprintf("Level Row %d", i))
|
||||||
frame.Pack(lvlRow, ui.Pack{
|
frame.Pack(lvlRow, ui.Pack{
|
||||||
Side: ui.N,
|
Side: ui.N,
|
||||||
|
|