236 lines
5.6 KiB
Go
236 lines
5.6 KiB
Go
package ordoor
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
|
|
"code.ur.gs/lupine/ordoor/internal/ui"
|
|
)
|
|
|
|
func try(result error, into *error) {
|
|
if *into == nil {
|
|
*into = result
|
|
}
|
|
}
|
|
|
|
// These are UI interfaces covering the game entrypoint
|
|
|
|
func (o *Ordoor) ifaceMain() (*ui.Interface, error) {
|
|
// Start in the "main" menu
|
|
main, err := o.buildInterface("main")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
options, err := o.ifaceOptions(main)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// TODO: clicking these buttons should load other interfaces
|
|
try(wireupClick(main, func() {}, "2.1"), &err) // New game
|
|
try(wireupClick(main, func() {}, "2.2"), &err) // Load game
|
|
try(disableWidget(main, "2.3"), &err) // Multiplayer - disable for now
|
|
try(wireupClick(main, func() { o.iface = options }, "2.4"), &err) // Options
|
|
try(wireupClick(main, func() { o.nextState = StateExit }, "2.5"), &err) // Quit
|
|
|
|
return main, err
|
|
}
|
|
|
|
// Options needs to know how to go back to main
|
|
func (o *Ordoor) ifaceOptions(main *ui.Interface) (*ui.Interface, error) {
|
|
options, err := o.buildInterface("options")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := o.configIntoOptions(options); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// TODO: load current options state into UI
|
|
try(wireupClick(options, func() {}, "2.8"), &err) // Keyboard settings button
|
|
// Resolution slider is 2.9
|
|
// Music volume slider is 2.10
|
|
// Sound FX volume slider is 2.11
|
|
|
|
// Accept button
|
|
try(wireupClick(
|
|
options, func() {
|
|
if err := o.optionsIntoConfig(options); err != nil {
|
|
// FIXME: exiting is a bit OTT. Perhaps display "save failed"?
|
|
log.Printf("Saving options to config failed: %v", err)
|
|
o.nextState = StateExit
|
|
} else {
|
|
o.iface = main
|
|
}
|
|
},
|
|
"2.12",
|
|
), &err)
|
|
|
|
// 13...23 are "hypertext"
|
|
|
|
// Cancel button
|
|
try(
|
|
wireupClick(
|
|
options,
|
|
func() {
|
|
// FIXME: again, exiting is OTT. We're just resetting the state of
|
|
// the interface to the values in config.
|
|
if err := o.configIntoOptions(options); err != nil {
|
|
log.Printf("Saving options to config failed: %v", err)
|
|
o.nextState = StateExit
|
|
} else {
|
|
o.iface = main
|
|
}
|
|
},
|
|
"2.24",
|
|
), &err)
|
|
// Unit speed slider is 2,26
|
|
// Looping effect speed slider is 2,27
|
|
// Sample of unit speed animation is 2,28
|
|
// Sample of effect speed animation is 2,29
|
|
|
|
// 30...35 are "hypertext"
|
|
|
|
return options, err
|
|
}
|
|
|
|
func (o *Ordoor) configIntoOptions(options *ui.Interface) error {
|
|
cfg := &o.config.Options
|
|
var err error
|
|
|
|
try(setWidgetValueBool(options, cfg.PlayMovies, "2.1"), &err)
|
|
try(setWidgetValueBool(options, cfg.Animations, "2.2"), &err)
|
|
try(setWidgetValueBool(options, cfg.PlayMusic, "2.3"), &err)
|
|
try(setWidgetValueBool(options, cfg.CombatVoices, "2.4"), &err)
|
|
try(setWidgetValueBool(options, cfg.ShowGrid, "2.5"), &err)
|
|
try(setWidgetValueBool(options, cfg.ShowPaths, "2.6"), &err)
|
|
try(setWidgetValueBool(options, cfg.PointSaving, "2.7"), &err)
|
|
try(setWidgetValueBool(options, cfg.AutoCutLevel, "2.25"), &err)
|
|
|
|
return err
|
|
}
|
|
|
|
func (o *Ordoor) optionsIntoConfig(options *ui.Interface) error {
|
|
cfg := &o.config.Options
|
|
var err error
|
|
|
|
try(getWidgetValueBool(options, &cfg.PlayMovies, "2.1"), &err)
|
|
try(getWidgetValueBool(options, &cfg.Animations, "2.2"), &err)
|
|
try(getWidgetValueBool(options, &cfg.PlayMusic, "2.3"), &err)
|
|
try(getWidgetValueBool(options, &cfg.CombatVoices, "2.4"), &err)
|
|
try(getWidgetValueBool(options, &cfg.ShowGrid, "2.5"), &err)
|
|
try(getWidgetValueBool(options, &cfg.ShowPaths, "2.6"), &err)
|
|
try(getWidgetValueBool(options, &cfg.PointSaving, "2.7"), &err)
|
|
try(getWidgetValueBool(options, &cfg.AutoCutLevel, "2.25"), &err)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := o.config.Save(); err != nil {
|
|
return err
|
|
}
|
|
|
|
// TODO: emit events, rather than just modifying state here
|
|
if o.music != nil && o.music.IsPlaying() != cfg.PlayMusic {
|
|
if cfg.PlayMusic {
|
|
o.music.Rewind()
|
|
o.music.Play()
|
|
} else {
|
|
o.music.Pause()
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (o *Ordoor) buildInterface(name string) (*ui.Interface, error) {
|
|
menu, err := o.assets.Menu(name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
iface, err := ui.NewInterface(menu)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return iface, nil
|
|
}
|
|
|
|
func findWidget(iface *ui.Interface, spec string) (*ui.Widget, error) {
|
|
widget, err := iface.Widget(spec)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Couldn't find widget %v:%+v", iface.Name, spec)
|
|
}
|
|
|
|
return widget, nil
|
|
}
|
|
|
|
func getWidgetValue(iface *ui.Interface, spec string) (string, error) {
|
|
widget, err := findWidget(iface, spec)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return widget.Value, nil
|
|
}
|
|
|
|
func setWidgetValue(iface *ui.Interface, value string, spec string) error {
|
|
widget, err := findWidget(iface, spec)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
widget.Value = value
|
|
|
|
return nil
|
|
}
|
|
|
|
func getWidgetValueBool(iface *ui.Interface, into *bool, spec string) error {
|
|
vStr, err := getWidgetValue(iface, spec)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
*into = vStr == "1"
|
|
return nil
|
|
}
|
|
|
|
func setWidgetValueBool(iface *ui.Interface, value bool, spec string) error {
|
|
vStr := "0"
|
|
if value {
|
|
vStr = "1"
|
|
}
|
|
|
|
return setWidgetValue(iface, vStr, spec)
|
|
}
|
|
|
|
func wireupClick(iface *ui.Interface, f func(), spec string) error {
|
|
widget, err := findWidget(iface, spec)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if widget.OnMouseClick != nil {
|
|
return fmt.Errorf("Widget %#+v already has an OnMouseClick handler", widget)
|
|
}
|
|
|
|
widget.OnMouseClick = f
|
|
|
|
return nil
|
|
}
|
|
|
|
func disableWidget(iface *ui.Interface, spec string) error {
|
|
widget, err := findWidget(iface, spec)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
widget.Disable()
|
|
|
|
return nil
|
|
}
|