From 82d384940294ad48ca4f495300fb9ca24ca6a4c6 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Tue, 14 Apr 2020 12:12:37 +0100 Subject: [PATCH] Increase dialogue modality, display keyboard dialogue --- internal/flow/drivers.go | 14 +++++++ internal/flow/flow.go | 16 ++++++++ internal/flow/keyboard.go | 25 ++++++++++++ internal/flow/options.go | 8 +--- internal/ui/driver.go | 86 ++++++++++++++++++++++++++------------- internal/ui/list_box.go | 16 ++++++++ internal/ui/value.go | 21 +++------- 7 files changed, 136 insertions(+), 50 deletions(-) create mode 100644 internal/flow/keyboard.go diff --git a/internal/flow/drivers.go b/internal/flow/drivers.go index 397f4f2..c8f62df 100644 --- a/internal/flow/drivers.go +++ b/internal/flow/drivers.go @@ -38,6 +38,20 @@ var ( } ) +func (f *Flow) returnToLastDriver(from driverName) func() { + return func() { + to, ok := f.returns[from] + if !ok { + f.exit = fmt.Errorf("Couldn't work out where to return to from %v", from) + return + } + + delete(f.returns, 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] diff --git a/internal/flow/flow.go b/internal/flow/flow.go index b005dc9..e27eb24 100644 --- a/internal/flow/flow.go +++ b/internal/flow/flow.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "log" + "strings" "github.com/hajimehoshi/ebiten" @@ -233,6 +234,21 @@ func (f *Flow) playNextScenario(from driverName) func() { } } +func (f *Flow) showDialogue(driver driverName, id string) func() { + return func() { + f.drivers[driver].ShowDialogue(locator(driver, id)) + } +} + +func (f *Flow) hideDialogue(driver driverName) func() { + return f.drivers[driver].HideDialogue +} + func (f *Flow) setExit() { f.exit = ErrExit } + +// TODO: convert all to locators +func locator(d driverName, id string) string { + return fmt.Sprintf("%v:%v", strings.ToLower(string(d)), id) +} diff --git a/internal/flow/keyboard.go b/internal/flow/keyboard.go new file mode 100644 index 0000000..e623a4d --- /dev/null +++ b/internal/flow/keyboard.go @@ -0,0 +1,25 @@ +package flow + +import ( + "fmt" + "log" +) + +func (f *Flow) linkKeyboard() { + // Keyboard settings + // TODO: implement keybindings save/load behaviour + f.onClick(kbd, "3.1", f.returnToLastDriver(kbd)) // Done button + f.onClick(kbd, "3.2", f.returnToLastDriver(kbd)) // Cancel button + f.onClick(kbd, "3.4", func() {}) // TODO: Reset to defaults button + + for i := 1; i <= 13; i++ { + f.onClick(kbd, fmt.Sprintf("2.%v", i), f.captureKeybinding(i)) + } +} + +func (f *Flow) captureKeybinding(forLine int) func() { + return func() { + log.Printf("HELLO %v", forLine) + f.showDialogue(kbd, "4")() + } +} diff --git a/internal/flow/options.go b/internal/flow/options.go index aa4b3a3..61ffdb0 100644 --- a/internal/flow/options.go +++ b/internal/flow/options.go @@ -5,7 +5,7 @@ import ( ) func (f *Flow) linkOptions() { - f.onClick(options, "2.8", f.setDriver(kbd)) // Keyboard settings button + f.onClick(options, "2.8", f.setReturningDriver(options, kbd)) // Keyboard settings button f.configureSlider(options, "2.9", h3Slider) // Resolution slider f.configureSlider(options, "2.10", v10Slider) // Music volume slider @@ -17,11 +17,7 @@ func (f *Flow) linkOptions() { f.configureSlider(options, "2.26", h9Slider) // Unit speed slider f.configureSlider(options, "2.27", h9Slider) // Animation speed slider - // Keyboard settings - // TODO: implement keybindings save/load behaviour - f.onClick(kbd, "3.1", f.setDriver(options)) // Done button - f.onClick(kbd, "3.2", f.setDriver(options)) // Cancel button - f.onClick(kbd, "3.4", func() {}) // TODO: Reset to defaults button + f.linkKeyboard() } // FIXME: exiting is a bit OTT. Perhaps display "save failed"? diff --git a/internal/ui/driver.go b/internal/ui/driver.go index d53044e..ab9481e 100644 --- a/internal/ui/driver.go +++ b/internal/ui/driver.go @@ -94,7 +94,7 @@ func (d *Driver) Update(screenX, screenY int) error { d.cursorOrig = image.Pt(int(mnX), int(mnY)) // Dispatch notifications to our widgets - for _, hoverable := range d.hoverables() { + for _, hoverable := range d.activeHoverables() { inBounds := d.cursorOrig.In(hoverable.bounds()) d.hoverStartEvent(hoverable, inBounds) @@ -106,7 +106,7 @@ func (d *Driver) Update(screenX, screenY int) error { } mouseIsDown := ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) - for _, clickable := range d.clickables() { + for _, clickable := range d.activeClickables() { inBounds := d.cursorOrig.In(clickable.bounds()) mouseWasDown := clickable.mouseDownState() @@ -115,7 +115,7 @@ func (d *Driver) Update(screenX, screenY int) error { d.mouseUpEvent(clickable, inBounds, mouseWasDown, mouseIsDown) } - for _, mouseable := range d.mouseables() { + for _, mouseable := range d.activeMouseables() { mouseable.registerMousePosition(d.cursorOrig) } @@ -130,7 +130,7 @@ func (d *Driver) Draw(screen *ebiten.Image) error { var do ebiten.DrawImageOptions - for _, paint := range d.paintables() { + for _, paint := range d.activePaintables() { for _, region := range paint.regions(d.ticks) { x, y := d.orig2native.Apply(float64(region.offset.X), float64(region.offset.Y)) @@ -165,29 +165,66 @@ func (d *Driver) Cursor() (*ebiten.Image, *ebiten.DrawImageOptions, error) { return cursor.Image, op, nil } -func (d *Driver) clickables() []clickable { +func (d *Driver) allClickables() []clickable { var out []clickable for _, widget := range d.widgets { out = append(out, widget.clickables()...) } + for _, widget := range d.dialogues { + out = append(out, widget.clickables()...) + } + + return out +} + +func (d *Driver) allFreezables() []freezable { + var out []freezable + for _, widget := range d.widgets { + out = append(out, widget.freezables()...) + } + + for _, widget := range d.dialogues { + out = append(out, widget.freezables()...) + } + + return out +} + +func (d *Driver) allValueables() []valueable { + var out []valueable + + for _, widget := range d.widgets { + out = append(out, widget.valueables()...) + } + + for _, widget := range d.dialogues { + out = append(out, widget.valueables()...) + } + + return out +} + +func (d *Driver) activeClickables() []clickable { + if d.activeDialogue != nil { + return d.activeDialogue.clickables() + } + + var out []clickable + for _, widget := range d.widgets { + out = append(out, widget.clickables()...) + } + return out } -func (d *Driver) freezables() []freezable { - var out []freezable - - for _, widget := range d.widgets { - out = append(out, widget.freezables()...) +func (d *Driver) activeHoverables() []hoverable { + if d.activeDialogue != nil { + return d.activeDialogue.hoverables() } - return out -} - -func (d *Driver) hoverables() []hoverable { var out []hoverable - for _, widget := range d.widgets { out = append(out, widget.hoverables()...) } @@ -195,9 +232,12 @@ func (d *Driver) hoverables() []hoverable { return out } -func (d *Driver) mouseables() []mouseable { - var out []mouseable +func (d *Driver) activeMouseables() []mouseable { + if d.activeDialogue != nil { + return d.activeDialogue.mouseables() + } + var out []mouseable for _, widget := range d.widgets { out = append(out, widget.mouseables()...) } @@ -205,7 +245,7 @@ func (d *Driver) mouseables() []mouseable { return out } -func (d *Driver) paintables() []paintable { +func (d *Driver) activePaintables() []paintable { var out []paintable for _, widget := range d.widgets { @@ -218,13 +258,3 @@ func (d *Driver) paintables() []paintable { return out } - -func (d *Driver) valueables() []valueable { - var out []valueable - - for _, widget := range d.widgets { - out = append(out, widget.valueables()...) - } - - return out -} diff --git a/internal/ui/list_box.go b/internal/ui/list_box.go index f4e4bb4..50a996a 100644 --- a/internal/ui/list_box.go +++ b/internal/ui/list_box.go @@ -14,6 +14,8 @@ import ( // // TODO: multi-select functionality? Is it needed? type listBox struct { + locator string + upBtn *button downBtn *button @@ -52,6 +54,7 @@ func (d *Driver) buildListBox(group *menus.Group, up, down, thumb *menus.Record, } element := &listBox{ + locator: group.Locator, // TODO: upBtn needs to be frozen when offset == 0; downBtn when offset == max upBtn: upElem, downBtn: downElem, @@ -75,6 +78,7 @@ func (d *Driver) buildListBox(group *menus.Group, up, down, thumb *menus.Record, widget := &Widget{ Children: []*Widget{upWidget, downWidget}, ownPaintables: []paintable{element}, + ownValueables: []valueable{element}, } // FIXME: we should be able to freeze/unfreeze as a group. @@ -86,6 +90,7 @@ func (d *Driver) buildListBox(group *menus.Group, up, down, thumb *menus.Record, if err != nil { return nil, nil, err } + niWidget.ownClickables = append(niWidget.ownClickables, ni) // TODO: pick the correct font ni.label = &label{ @@ -102,6 +107,17 @@ func (d *Driver) buildListBox(group *menus.Group, up, down, thumb *menus.Record, return element, widget, nil } +func (l *listBox) id() string { + return l.locator +} + +func (l *listBox) value() string { + return "" +} + +func (l *listBox) setValue(s string) { +} + func (l *listBox) SetStrings(to []string) { if len(to) < len(l.strings) { l.offset = 0 // FIXME: unconditional? Trim to max? diff --git a/internal/ui/value.go b/internal/ui/value.go index a9ed43b..366bc5f 100644 --- a/internal/ui/value.go +++ b/internal/ui/value.go @@ -10,7 +10,7 @@ func (d *Driver) realId(id string) string { } func (d *Driver) Value(id string, into *string) error { - for _, valueable := range d.valueables() { + for _, valueable := range d.allValueables() { if valueable.id() == d.realId(id) { *into = valueable.value() return nil @@ -21,7 +21,7 @@ func (d *Driver) Value(id string, into *string) error { } func (d *Driver) SetValue(id, value string) error { - for _, valueable := range d.valueables() { + for _, valueable := range d.allValueables() { if valueable.id() == d.realId(id) { valueable.setValue(value) return nil @@ -51,7 +51,7 @@ func (d *Driver) SetValueBool(id string, value bool) error { } func (d *Driver) SetFreeze(id string, value bool) error { - for _, freezable := range d.freezables() { + for _, freezable := range d.allFreezables() { if freezable.id() == d.realId(id) { freezable.setFreezeState(value) return nil @@ -62,30 +62,19 @@ func (d *Driver) SetFreeze(id string, value bool) error { } func (d *Driver) OnClick(id string, f func()) error { - for _, clickable := range d.clickables() { + for _, clickable := range d.allClickables() { if clickable.id() == d.realId(id) { clickable.onClick(f) return nil } } - // We need to be able to wire up items inside dialogues too - for _, dialogue := range d.dialogues { - for _, clickable := range dialogue.clickables() { - if clickable.id() == d.realId(id) { - clickable.onClick(f) - return nil - } - } - } - return fmt.Errorf("Couldn't find clickable widget %v:%v", d.menu.Name, id) } // FIXME: HURK. Surely I'm missing something? steps is value:offset func (d *Driver) ConfigureSlider(id string, steps map[int]int) error { - - for _, clickable := range d.clickables() { + for _, clickable := range d.activeClickables() { if slider, ok := clickable.(*slider); ok && slider.id() == d.realId(id) { slider.steps = steps