doodle/pkg/menu_scene.go

247 lines
5.6 KiB
Go
Raw Normal View History

package doodle
import (
"git.kirsle.net/apps/doodle/pkg/enum"
"git.kirsle.net/apps/doodle/pkg/level"
"git.kirsle.net/apps/doodle/pkg/log"
"git.kirsle.net/apps/doodle/pkg/uix"
"git.kirsle.net/apps/doodle/pkg/windows"
"git.kirsle.net/go/render"
"git.kirsle.net/go/render/event"
"git.kirsle.net/go/ui"
)
/*
MenuScene holds the main dialog menu UIs for:
* New Level
* Open Level
* Settings
DEPRECATED: migrate these prompts into popup windows to appear
on the MainScene or elsewhere as wanted.
*/
type MenuScene struct {
// Configuration.
StartupMenu string
Supervisor *ui.Supervisor
// Private widgets.
window *ui.Window
// Background wallpaper canvas.
canvas *uix.Canvas
// Values for the New menu
newPageType string
newWallpaper string
// Values for the Load/Play menu.
loadForPlay bool // false = load for edit
}
// Name of the scene.
func (s *MenuScene) Name() string {
return "Menu"
}
// DebugGetWindow surfaces the underlying private window.
func (s *MenuScene) DebugGetWindow() *ui.Window {
return s.window
}
// GotoNewMenu loads the MenuScene and shows the "New" window.
func (d *Doodle) GotoNewMenu() {
log.Info("Loading the MenuScene to the New window")
scene := &MenuScene{
StartupMenu: "new",
}
d.Goto(scene)
}
// GotoLoadMenu loads the MenuScene and shows the "Load" window.
func (d *Doodle) GotoLoadMenu() {
log.Info("Loading the MenuScene to the Load window for Edit Mode")
scene := &MenuScene{
StartupMenu: "load",
}
d.Goto(scene)
}
// GotoPlayMenu loads the MenuScene and shows the "Load" window for playing a
// level, not editing it.
func (d *Doodle) GotoPlayMenu() {
log.Info("Loading the MenuScene to the Load window for Play Mode")
scene := &MenuScene{
StartupMenu: "load",
loadForPlay: true,
}
d.Goto(scene)
}
// GotoSettingsMenu loads the settings screen.
func (d *Doodle) GotoSettingsMenu() {
log.Info("Loading the MenuScene to the Settings Menu")
scene := &MenuScene{
StartupMenu: "settings",
}
d.Goto(scene)
}
// Setup the scene.
func (s *MenuScene) Setup(d *Doodle) error {
s.Supervisor = ui.NewSupervisor()
// Set up the background wallpaper canvas.
s.canvas = uix.NewCanvas(100, false)
s.canvas.Resize(render.Rect{
W: d.width,
H: d.height,
})
s.canvas.LoadLevel(&level.Level{
Chunker: level.NewChunker(100),
Palette: level.NewPalette(),
PageType: level.Bounded,
Wallpaper: "notebook.png",
})
switch s.StartupMenu {
case "new":
if err := s.setupNewWindow(d); err != nil {
return err
}
case "load":
if err := s.setupLoadWindow(d); err != nil {
return err
}
case "settings":
if err := s.setupSettingsWindow(d); err != nil {
return err
}
default:
d.FlashError("No Valid StartupMenu Given to MenuScene")
}
// Whatever window we got, give it window manager controls under Supervisor.
s.window.Supervise(s.Supervisor)
s.window.Compute(d.Engine)
// Center the window.
s.window.MoveTo(render.Point{
X: (d.width / 2) - (s.window.Size().W / 2),
Y: 60,
})
return nil
}
// configureCanvas updates the settings of the background canvas, so a live
// preview of the wallpaper and wrapping type can be shown.
func (s *MenuScene) configureCanvas(pageType level.PageType, wallpaper string) {
s.canvas.LoadLevel(&level.Level{
Chunker: level.NewChunker(100),
Palette: level.NewPalette(),
PageType: pageType,
Wallpaper: wallpaper,
})
}
// setupNewWindow sets up the UI for the "New" window.
func (s *MenuScene) setupNewWindow(d *Doodle) error {
window := windows.NewAddEditLevel(windows.AddEditLevel{
Supervisor: s.Supervisor,
Engine: d.Engine,
OnChangePageTypeAndWallpaper: func(pageType level.PageType, wallpaper string) {
log.Info("OnChangePageTypeAndWallpaper called: %+v, %+v", pageType, wallpaper)
Optimize memory by freeing up SDL2 textures * Added to the F3 Debug Overlay is a "Texture:" label that counts the number of textures currently loaded by the (SDL2) render engine. * Added Teardown() functions to Level, Doodad and the Chunker they both use to free up SDL2 textures for all their cached graphics. * The Canvas.Destroy() function now cleans up all textures that the Canvas is responsible for: calling the Teardown() of the Level or Doodad, calling Destroy() on all level actors, and cleaning up Wallpaper textures. * The Destroy() method of the game's various Scenes will properly Destroy() their canvases to clean up when transitioning to another scene. The MainScene, MenuScene, EditorScene and PlayScene. * Fix the sprites package to actually cache the ui.Image widgets. The game has very few sprites so no need to free them just yet. Some tricky places that were leaking textures have been cleaned up: * Canvas.InstallActors() destroys the canvases of existing actors before it reinitializes the list and installs the replacements. * The DraggableActor when the user is dragging an actor around their level cleans up the blueprint masked drag/drop actor before nulling it out. Misc changes: * The player character cheats during Play Mode will immediately swap out the player character on the current level. * Properly call the Close() function instead of Hide() to dismiss popup windows. The Close() function itself calls Hide() but also triggers WindowClose event handlers. The Doodad Dropper subscribes to its close event to free textures for all its doodad canvases.
2022-04-09 21:41:24 +00:00
s.canvas.Destroy() // clean up old textures
s.configureCanvas(pageType, wallpaper)
},
OnCreateNewLevel: func(lvl *level.Level) {
d.Goto(&EditorScene{
DrawingType: enum.LevelDrawing,
Level: lvl,
})
},
OnCreateNewDoodad: func(size int) {
d.NewDoodad(size)
},
OnCancel: func() {
d.Goto(&MainScene{})
},
})
s.window = window
window.SetButtons(0)
window.Show()
return nil
}
// setupLoadWindow sets up the UI for the "New" window.
func (s *MenuScene) setupLoadWindow(d *Doodle) error {
window := windows.NewOpenLevelEditor(windows.OpenLevelEditor{
Supervisor: s.Supervisor,
Engine: d.Engine,
LoadForPlay: s.loadForPlay,
OnPlayLevel: func(filename string) {
d.PlayLevel(filename)
},
OnEditLevel: func(filename string) {
d.EditFile(filename)
},
OnCancel: func() {
d.Goto(&MainScene{})
},
})
s.window = window
return nil
}
// setupLoadWindow sets up the UI for the "New" window.
func (s *MenuScene) setupSettingsWindow(d *Doodle) error {
window := windows.NewSettingsWindow(windows.Settings{
Supervisor: s.Supervisor,
Engine: d.Engine,
})
window.SetButtons(0)
s.window = window
return nil
}
// Loop the editor scene.
func (s *MenuScene) Loop(d *Doodle, ev *event.State) error {
s.Supervisor.Loop(ev)
if ev.WindowResized {
log.Info("Resized to %dx%d", d.width, d.height)
s.canvas.Resize(render.Rect{
W: d.width,
H: d.height,
})
}
return nil
}
// Draw the pixels on this frame.
func (s *MenuScene) Draw(d *Doodle) error {
// Draw the background canvas.
s.canvas.Present(d.Engine, render.Origin)
// TODO: if I don't call Compute here, buttons in the Edit Window get all
// bunched up. Investigate why later.
s.window.Compute(d.Engine)
// Draw the window managed by Supervisor.
s.Supervisor.Present(d.Engine)
return nil
}
// Destroy the scene.
func (s *MenuScene) Destroy() error {
Optimize memory by freeing up SDL2 textures * Added to the F3 Debug Overlay is a "Texture:" label that counts the number of textures currently loaded by the (SDL2) render engine. * Added Teardown() functions to Level, Doodad and the Chunker they both use to free up SDL2 textures for all their cached graphics. * The Canvas.Destroy() function now cleans up all textures that the Canvas is responsible for: calling the Teardown() of the Level or Doodad, calling Destroy() on all level actors, and cleaning up Wallpaper textures. * The Destroy() method of the game's various Scenes will properly Destroy() their canvases to clean up when transitioning to another scene. The MainScene, MenuScene, EditorScene and PlayScene. * Fix the sprites package to actually cache the ui.Image widgets. The game has very few sprites so no need to free them just yet. Some tricky places that were leaking textures have been cleaned up: * Canvas.InstallActors() destroys the canvases of existing actors before it reinitializes the list and installs the replacements. * The DraggableActor when the user is dragging an actor around their level cleans up the blueprint masked drag/drop actor before nulling it out. Misc changes: * The player character cheats during Play Mode will immediately swap out the player character on the current level. * Properly call the Close() function instead of Hide() to dismiss popup windows. The Close() function itself calls Hide() but also triggers WindowClose event handlers. The Doodad Dropper subscribes to its close event to free textures for all its doodad canvases.
2022-04-09 21:41:24 +00:00
// Free (wallpaper) textures.
s.canvas.Destroy()
return nil
}