Link various screens accessible from the bridge
This kind of linking is starting to creak...
This commit is contained in:
@@ -17,13 +17,13 @@ const (
|
|||||||
TypeMenu MenuType = 1
|
TypeMenu MenuType = 1
|
||||||
TypeDragMenu MenuType = 2 // Only seen in Configure_Vehicle_{Chaos,Ultra}
|
TypeDragMenu MenuType = 2 // Only seen in Configure_Vehicle_{Chaos,Ultra}
|
||||||
TypeSimpleButton MenuType = 3
|
TypeSimpleButton MenuType = 3
|
||||||
TypeDoorHotspot MenuType = 30 // Like a button I guess? FONTTYPE is animation speed
|
TypeDoorHotspot MenuType = 30 // Like a button I guess? "FONTTYPE is animation speed"
|
||||||
TypeUnknown1 MenuType = 31 // ??? Needed for ChaEquip.mnu
|
TypeDoorHotspot2 MenuType = 31 // Seems like a duplicate of the above? What's different?
|
||||||
TypeLineKbd MenuType = 40
|
TypeLineKbd MenuType = 40
|
||||||
TypeThumb MenuType = 45
|
TypeThumb MenuType = 45
|
||||||
TypeLineBriefing MenuType = 41
|
TypeLineBriefing MenuType = 41
|
||||||
TypeInvokeButton MenuType = 50
|
TypeInvokeButton MenuType = 50
|
||||||
TypeSquadButton MenuType = 60 // Maybe? Appears in Arrange.mnu
|
TypeDoorHotspot3 MenuType = 60 // Maybe? Appears in Arrange.mnu
|
||||||
TypeOverlay MenuType = 61
|
TypeOverlay MenuType = 61
|
||||||
TypeHypertext MenuType = 70
|
TypeHypertext MenuType = 70
|
||||||
TypeCheckbox MenuType = 91
|
TypeCheckbox MenuType = 91
|
||||||
|
@@ -3,9 +3,40 @@ package flow
|
|||||||
func (f *Flow) linkBridge() {
|
func (f *Flow) linkBridge() {
|
||||||
// FIXME: sometimes these doors are frozen, depending on game state
|
// FIXME: sometimes these doors are frozen, depending on game state
|
||||||
|
|
||||||
f.onClick(bridge, "2.1", f.setDriver(briefing)) // Mission briefing clickable
|
//f.onClick(bridge, "2.1", f.setDriver(briefing)) // TODO: Mission briefing clickable
|
||||||
f.onClick(bridge, "2.2", f.setDriver(choices)) // Options door hotspot
|
f.onClick(bridge, "2.2", f.setDriver(choices)) // Options door hotspot
|
||||||
f.setFreeze(bridge, "2.4", false) // FIXME: Enter combat door hotspot (!!!)
|
f.setFreeze(bridge, "2.4", false) // FIXME: Enter combat door hotspot (!!!)
|
||||||
f.onClick(bridge, "2.6", f.setDriver(configureVehiclesUltra)) // Vehicle configure door hotspot
|
f.setFreeze(bridge, "2.6", false) // FIXME: Vehicle configure door hotspot
|
||||||
f.onClick(bridge, "2.8", f.setDriver(configureUltEquip)) // Squads configure door hotspot
|
f.onClick(bridge, "2.8", f.setDriver(arrange)) // Squads configure door hotspot
|
||||||
|
|
||||||
|
// link children
|
||||||
|
f.linkChoices()
|
||||||
|
f.linkArrange()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Flow) linkChoices() {
|
||||||
|
f.onClick(choices, "2.1", f.setDriver(loadGame)) // Load another game button
|
||||||
|
f.onClick(choices, "2.2", f.setDriver(saveGame)) // Save this game button
|
||||||
|
f.onClick(choices, "2.3", f.setReturningDriver(choices, options)) // More options button
|
||||||
|
|
||||||
|
// FIXME: wipe out game state when this goes through
|
||||||
|
f.onClick(choices, "2.4", f.setDriver(main)) // Restart button
|
||||||
|
|
||||||
|
f.onClick(choices, "2.5", f.setDriver(credits)) // Credits button
|
||||||
|
f.onClick(choices, "2.6", f.setExit) // Quit button
|
||||||
|
f.onClick(choices, "2.7", f.setDriver(bridge)) // Back button
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Flow) linkArrange() {
|
||||||
|
// FIXME: we should be operating on game data in here
|
||||||
|
f.onClick(arrange, "8.1", f.setDriver(bridge)) // Return to bridge ("cathedral")
|
||||||
|
f.onClick(arrange, "8.3", f.setDriver(configureUltEquip)) // Configure squads
|
||||||
|
|
||||||
|
f.linkConfigureUltEquip()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Flow) linkConfigureUltEquip() {
|
||||||
|
// FIXME: we should be modifying loadouts of selected squad members here
|
||||||
|
|
||||||
|
f.onClick(configureUltEquip, "8.1", f.setDriver(bridge)) // Return to bridge
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@ package flow
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
"github.com/hajimehoshi/ebiten"
|
||||||
|
|
||||||
@@ -19,6 +20,13 @@ type Flow struct {
|
|||||||
current *ui.Driver
|
current *ui.Driver
|
||||||
drivers map[driverName]*ui.Driver
|
drivers map[driverName]*ui.Driver
|
||||||
|
|
||||||
|
// Some screens can be returned to from more than one place. Where this is
|
||||||
|
// the case, instead of hardcoding it, we'll store an entry in here so we
|
||||||
|
// know where we're going back to
|
||||||
|
//
|
||||||
|
// FIXME: this really suggests wiring everything up at the start is wrong.
|
||||||
|
returns map[driverName]driverName
|
||||||
|
|
||||||
exit error
|
exit error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,10 +45,12 @@ const (
|
|||||||
bridge driverName = "Bridge"
|
bridge driverName = "Bridge"
|
||||||
briefing driverName = "Briefing"
|
briefing driverName = "Briefing"
|
||||||
choices driverName = "Choices"
|
choices driverName = "Choices"
|
||||||
ultEquip driverName = "UltEquip"
|
saveGame driverName = "SaveGame"
|
||||||
|
credits driverName = "Credits"
|
||||||
|
arrange driverName = "Arrange"
|
||||||
|
|
||||||
configureUltEquip driverName = "Configure_UltEquip"
|
configureUltEquip driverName = "Configure_UltEquip"
|
||||||
configureVehiclesUltra driverName = "Configure_vehicles_ultra"
|
configureVehiclesUltra driverName = "Configure_Vehicles_Ultra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -48,8 +58,8 @@ var (
|
|||||||
|
|
||||||
driverNames = []driverName{
|
driverNames = []driverName{
|
||||||
main, levelPly, singles, randomMap, newGame, loadGame, options, kbd,
|
main, levelPly, singles, randomMap, newGame, loadGame, options, kbd,
|
||||||
bridge, briefing, choices, ultEquip,
|
bridge, briefing, choices, saveGame, credits, arrange,
|
||||||
configureVehiclesUltra,
|
configureUltEquip, configureVehiclesUltra,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constants used for sliders
|
// Constants used for sliders
|
||||||
@@ -74,6 +84,7 @@ func New(assets *assetstore.AssetStore, config *config.Config) (*Flow, error) {
|
|||||||
assets: assets,
|
assets: assets,
|
||||||
config: config,
|
config: config,
|
||||||
drivers: make(map[driverName]*ui.Driver, len(driverNames)),
|
drivers: make(map[driverName]*ui.Driver, len(driverNames)),
|
||||||
|
returns: make(map[driverName]driverName),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load all the drivers upfront
|
// Load all the drivers upfront
|
||||||
@@ -129,11 +140,11 @@ func (f *Flow) Draw(screen *ebiten.Image) error {
|
|||||||
|
|
||||||
func (f *Flow) linkDrivers() {
|
func (f *Flow) linkDrivers() {
|
||||||
// linkMain
|
// linkMain
|
||||||
f.onClick(main, "2.1", f.setDriver(newGame)) // New game
|
f.onClick(main, "2.1", f.setDriver(newGame)) // New game
|
||||||
f.onClick(main, "2.2", f.setDriver(loadGame)) // Load game
|
f.onClick(main, "2.2", f.setDriver(loadGame)) // Load game
|
||||||
f.setFreeze(main, "2.3", true) // Multiplayer - disable for now
|
f.setFreeze(main, "2.3", true) // Multiplayer - disable for now
|
||||||
f.onClick(main, "2.4", f.setDriver(options)) // Options
|
f.onClick(main, "2.4", f.setReturningDriver(main, options)) // Options
|
||||||
f.onClick(main, "2.5", f.setExit) // Quit
|
f.onClick(main, "2.5", f.setExit) // Quit
|
||||||
|
|
||||||
// Now link immediate children. They will link their children, and so on
|
// Now link immediate children. They will link their children, and so on
|
||||||
f.linkNewGame()
|
f.linkNewGame()
|
||||||
@@ -142,6 +153,14 @@ func (f *Flow) linkDrivers() {
|
|||||||
f.linkOptions()
|
f.linkOptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func maybeErr(driver driverName, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%v: %v", driver, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (f *Flow) configureSlider(driver driverName, id string, steps map[int]int) {
|
func (f *Flow) configureSlider(driver driverName, id string, steps map[int]int) {
|
||||||
if f.exit != nil {
|
if f.exit != nil {
|
||||||
return
|
return
|
||||||
@@ -155,7 +174,7 @@ func (f *Flow) onClick(driver driverName, id string, fn func()) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
f.exit = f.drivers[driver].OnClick(id, fn)
|
f.exit = maybeErr(driver, f.drivers[driver].OnClick(id, fn))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Flow) setFreeze(driver driverName, id string, value bool) {
|
func (f *Flow) setFreeze(driver driverName, id string, value bool) {
|
||||||
@@ -163,7 +182,7 @@ func (f *Flow) setFreeze(driver driverName, id string, value bool) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
f.exit = f.drivers[driver].SetFreeze(id, value)
|
f.exit = maybeErr(driver, f.drivers[driver].SetFreeze(id, value))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Flow) setValueBool(driver driverName, id string, value bool) {
|
func (f *Flow) setValueBool(driver driverName, id string, value bool) {
|
||||||
@@ -184,6 +203,27 @@ func (f *Flow) setDriverNow(name driverName) {
|
|||||||
f.current = f.drivers[name]
|
f.current = f.drivers[name]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// from is the parent menu, to is the child
|
||||||
|
func (f *Flow) setReturningDriver(from, to driverName) func() {
|
||||||
|
return func() {
|
||||||
|
f.returns[to] = from
|
||||||
|
f.setDriverNow(to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// from is the child menu, to is the parent
|
||||||
|
func (f *Flow) returnToLastDriverNow(from driverName) error {
|
||||||
|
to, ok := f.returns[from]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Couldn't work out where to return to from %v", from)
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(f.returns, from)
|
||||||
|
|
||||||
|
f.setDriverNow(to)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (f *Flow) setExit() {
|
func (f *Flow) setExit() {
|
||||||
f.exit = ErrExit
|
f.exit = ErrExit
|
||||||
}
|
}
|
||||||
|
@@ -26,10 +26,13 @@ func (f *Flow) linkLevelPly() {
|
|||||||
f.setDriverNow(newGame)
|
f.setDriverNow(newGame)
|
||||||
})
|
})
|
||||||
|
|
||||||
// FIXME: we should select a savegame if Mighty Here is selected here
|
// FIXME: we should select a savegame if Mighty Hero is selected here
|
||||||
// FIXME: we should show a movie here. Need an internal SMK player first
|
// FIXME: we should show a movie here. Need an internal SMK player first
|
||||||
// FIXME: we should set up new game state here!
|
// FIXME: we should set up new game state here!
|
||||||
f.onClick(levelPly, "2.7", f.setDriver(bridge)) // Select button
|
f.onClick(levelPly, "2.7", f.setDriver(bridge)) // Select button
|
||||||
|
|
||||||
|
// Link children
|
||||||
|
f.linkBridge()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Flow) linkSingles() {
|
func (f *Flow) linkSingles() {
|
||||||
|
@@ -44,7 +44,7 @@ func (f *Flow) cancelOptions() func() {
|
|||||||
log.Printf("Saving options to config failed: %v", err)
|
log.Printf("Saving options to config failed: %v", err)
|
||||||
f.exit = err
|
f.exit = err
|
||||||
} else {
|
} else {
|
||||||
f.setDriverNow(main)
|
f.exit = f.returnToLastDriverNow(options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,9 @@ func init() {
|
|||||||
registerBuilder(menus.TypeSimpleButton, registerSimpleButton)
|
registerBuilder(menus.TypeSimpleButton, registerSimpleButton)
|
||||||
registerBuilder(menus.TypeInvokeButton, registerInvokeButton)
|
registerBuilder(menus.TypeInvokeButton, registerInvokeButton)
|
||||||
registerBuilder(menus.TypeMainButton, registerMainButton)
|
registerBuilder(menus.TypeMainButton, registerMainButton)
|
||||||
registerBuilder(menus.TypeDoorHotspot, registerDebug("Unimplemented DoorHotspot", nil))
|
registerBuilder(menus.TypeDoorHotspot, registerDoorHotspot)
|
||||||
|
registerBuilder(menus.TypeDoorHotspot2, registerDoorHotspot)
|
||||||
|
registerBuilder(menus.TypeDoorHotspot3, registerDoorHotspot)
|
||||||
}
|
}
|
||||||
|
|
||||||
// A button without hover animation
|
// A button without hover animation
|
||||||
@@ -79,6 +81,29 @@ func registerMainButton(d *Driver, r *menus.Record) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func registerDoorHotspot(d *Driver, r *menus.Record) error {
|
||||||
|
sprites, err := d.menu.Sprites(r.Share, 2) // base, pressed
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
btn := &button{
|
||||||
|
path: r.Path(),
|
||||||
|
baseSpr: sprites[0],
|
||||||
|
clickSpr: sprites[1],
|
||||||
|
frozenSpr: sprites[0], // No disabled sprite
|
||||||
|
hoverImpl: hoverImpl{text: r.Text},
|
||||||
|
}
|
||||||
|
|
||||||
|
d.clickables = append(d.clickables, btn)
|
||||||
|
d.freezables = append(d.freezables, btn)
|
||||||
|
d.hoverables = append(d.hoverables, btn)
|
||||||
|
d.paintables = append(d.paintables, btn)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func registerButton(d *Driver, r *menus.Record, spriteId int) error {
|
func registerButton(d *Driver, r *menus.Record, spriteId int) error {
|
||||||
sprites, err := d.menu.Sprites(spriteId, 3) // base, pressed, disabled
|
sprites, err := d.menu.Sprites(spriteId, 3) // base, pressed, disabled
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"log"
|
"log"
|
||||||
|
"runtime/debug"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten"
|
"github.com/hajimehoshi/ebiten"
|
||||||
@@ -24,14 +25,10 @@ func init() {
|
|||||||
registerBuilder(menus.TypeLineKbd, registerDebug("Unimplemented LineKbd", nil))
|
registerBuilder(menus.TypeLineKbd, registerDebug("Unimplemented LineKbd", nil))
|
||||||
registerBuilder(menus.TypeDialogue, registerDebug("Unimplemented Dialogue", nil))
|
registerBuilder(menus.TypeDialogue, registerDebug("Unimplemented Dialogue", nil))
|
||||||
|
|
||||||
// Needed for Arrange.mnu (???)
|
|
||||||
registerBuilder(menus.TypeSquadButton, registerDebug("Unimplemented SquadButton", nil))
|
|
||||||
|
|
||||||
// Needed for Briefing.mnu
|
// Needed for Briefing.mnu
|
||||||
registerBuilder(menus.TypeLineBriefing, registerDebug("Unimplemented LineBriefing", nil))
|
registerBuilder(menus.TypeLineBriefing, registerDebug("Unimplemented LineBriefing", nil))
|
||||||
|
|
||||||
// Needed for ChaEquip.mnu
|
// Needed for ChaEquip.mnu
|
||||||
registerBuilder(menus.TypeUnknown1, registerDebug("Unimplemented Unknown1", nil))
|
|
||||||
registerBuilder(menus.TypeThumb, registerDebug("Unimplemented Thumb", nil))
|
registerBuilder(menus.TypeThumb, registerDebug("Unimplemented Thumb", nil))
|
||||||
|
|
||||||
// Needed for MainGameChaos.mnu
|
// Needed for MainGameChaos.mnu
|
||||||
@@ -226,6 +223,11 @@ func (d *Driver) SetValueInt(id string, value int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) Update(screenX, screenY int) error {
|
func (d *Driver) Update(screenX, screenY int) error {
|
||||||
|
if d == nil {
|
||||||
|
debug.PrintStack()
|
||||||
|
return fmt.Errorf("Tried to update a nil ui.Driver")
|
||||||
|
}
|
||||||
|
|
||||||
// This will be updated while processing hovers
|
// This will be updated while processing hovers
|
||||||
d.tooltip = ""
|
d.tooltip = ""
|
||||||
d.ticks += 1
|
d.ticks += 1
|
||||||
@@ -274,6 +276,11 @@ func (d *Driver) Update(screenX, screenY int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) Draw(screen *ebiten.Image) error {
|
func (d *Driver) Draw(screen *ebiten.Image) error {
|
||||||
|
if d == nil {
|
||||||
|
debug.PrintStack()
|
||||||
|
return fmt.Errorf("Tried to draw a nil ui.Driver")
|
||||||
|
}
|
||||||
|
|
||||||
var do ebiten.DrawImageOptions
|
var do ebiten.DrawImageOptions
|
||||||
|
|
||||||
for _, paint := range d.paintables {
|
for _, paint := range d.paintables {
|
||||||
|
@@ -15,7 +15,7 @@ func init() {
|
|||||||
registerBuilder(menus.TypeHypertext, registerHypertext)
|
registerBuilder(menus.TypeHypertext, registerHypertext)
|
||||||
registerBuilder(menus.TypeOverlay, registerOverlay)
|
registerBuilder(menus.TypeOverlay, registerOverlay)
|
||||||
registerBuilder(menus.TypeAnimationSample, registerAnimation)
|
registerBuilder(menus.TypeAnimationSample, registerAnimation)
|
||||||
registerBuilder(menus.TypeAnimationHover, registerDebug("WIP AnimationHover", registerAnimationHover))
|
registerBuilder(menus.TypeAnimationHover, registerAnimationHover)
|
||||||
}
|
}
|
||||||
|
|
||||||
// A non-interactive element is not a widget; it merely displays some pixels and
|
// A non-interactive element is not a widget; it merely displays some pixels and
|
||||||
|
Reference in New Issue
Block a user