From 69118f50b2ffa9fa740e08ef0171e329e3fd66e9 Mon Sep 17 00:00:00 2001 From: Trevor Slocum Date: Fri, 27 Oct 2023 22:04:50 -0700 Subject: [PATCH] Improve input handling --- box.go | 6 +---- button.go | 2 +- flex.go | 2 +- game.go | 72 +++++++++++++++++++++++++++++++++++-------------------- go.mod | 2 +- go.sum | 4 ++-- grid.go | 2 +- input.go | 14 ++++------- text.go | 13 ++++------ widget.go | 3 +-- window.go | 2 +- 11 files changed, 64 insertions(+), 58 deletions(-) diff --git a/box.go b/box.go index 9e9ff1d..e3c6085 100644 --- a/box.go +++ b/box.go @@ -70,11 +70,7 @@ func (b *Box) HandleMouse(cursor image.Point, pressed bool, clicked bool) (handl return true, nil } -func (b *Box) HandleKeyboard() (handled bool, err error) { - return false, nil -} - -func (b *Box) HandleKeyboardEvent(key ebiten.Key, r rune) (handled bool, err error) { +func (b *Box) HandleKeyboard(key ebiten.Key, r rune) (handled bool, err error) { return false, nil } diff --git a/button.go b/button.go index 27de38b..e15a5d0 100644 --- a/button.go +++ b/button.go @@ -58,7 +58,7 @@ func (b *Button) HandleMouse(cursor image.Point, pressed bool, clicked bool) (ha return true, onSelected() } -func (b *Button) HandleKeyboard() (handled bool, err error) { +func (b *Button) HandleKeyboard(ebiten.Key, rune) (handled bool, err error) { return false, nil } diff --git a/flex.go b/flex.go index 0841393..bfe2e01 100644 --- a/flex.go +++ b/flex.go @@ -42,7 +42,7 @@ func (f *Flex) HandleMouse(cursor image.Point, pressed bool, clicked bool) (hand return false, nil } -func (f *Flex) HandleKeyboard() (handled bool, err error) { +func (f *Flex) HandleKeyboard(ebiten.Key, rune) (handled bool, err error) { return false, nil } diff --git a/game.go b/game.go index 21e5b16..5074b70 100644 --- a/game.go +++ b/game.go @@ -22,6 +22,9 @@ var ( focusedWidget Widget lastBackspaceRepeat time.Time + + keyBuffer []ebiten.Key + runeBuffer []rune ) const ( @@ -72,14 +75,17 @@ func Update() error { // Handle touch input. + var pressed bool + var clicked bool var touchInput bool - var clicked bool touchIDs = inpututil.AppendJustPressedTouchIDs(touchIDs[:0]) for _, id := range touchIDs { x, y := ebiten.TouchPosition(id) if x != 0 || y != 0 { cursor = image.Point{x, y} + + pressed = true clicked = true touchInput = true } @@ -87,7 +93,6 @@ func Update() error { // Handle mouse input. - var pressed bool if !touchInput { x, y := ebiten.CursorPosition() cursor = image.Point{x, y} @@ -110,23 +115,44 @@ func Update() error { } } + _, err := update(root, cursor, pressed, clicked, false) + if err != nil { + return fmt.Errorf("failed to handle widget mouse input: %s", err) + } + // Handle keyboard input. - if focusedWidget != nil && ebiten.IsKeyPressed(ebiten.KeyBackspace) { - if inpututil.IsKeyJustPressed(ebiten.KeyBackspace) { - lastBackspaceRepeat = time.Now().Add(backspaceRepeatWait) - } else if time.Since(lastBackspaceRepeat) >= backspaceRepeatTime { - lastBackspaceRepeat = time.Now() + if focusedWidget != nil { + if ebiten.IsKeyPressed(ebiten.KeyBackspace) { + if inpututil.IsKeyJustPressed(ebiten.KeyBackspace) { + lastBackspaceRepeat = time.Now().Add(backspaceRepeatWait) + } else if time.Since(lastBackspaceRepeat) >= backspaceRepeatTime { + lastBackspaceRepeat = time.Now() - _, err := focusedWidget.HandleKeyboardEvent(ebiten.KeyBackspace, 0) + _, err := focusedWidget.HandleKeyboard(ebiten.KeyBackspace, 0) + if err != nil { + return err + } + } + } + + keyBuffer = inpututil.AppendJustPressedKeys(keyBuffer[:0]) + for _, key := range keyBuffer { + _, err := focusedWidget.HandleKeyboard(key, 0) if err != nil { - return err + return fmt.Errorf("failed to handle widget keyboard input: %s", err) + } + } + + runeBuffer = ebiten.AppendInputChars(runeBuffer[:0]) + for _, r := range runeBuffer { + _, err := focusedWidget.HandleKeyboard(-1, r) + if err != nil { + return fmt.Errorf("failed to handle widget keyboard input: %s", err) } } } - - _, _, err := update(root, cursor, pressed, clicked, false, false) - return err + return nil } func getWidgetAt(w Widget, cursor image.Point) Widget { @@ -150,37 +176,31 @@ func getWidgetAt(w Widget, cursor image.Point) Widget { return w } -func update(w Widget, cursor image.Point, pressed bool, clicked bool, mouseHandled bool, keyboardHandled bool) (bool, bool, error) { +func update(w Widget, cursor image.Point, pressed bool, clicked bool, mouseHandled bool) (bool, error) { if !w.Visible() { - return mouseHandled, keyboardHandled, nil + return mouseHandled, nil } var err error children := w.Children() for _, child := range children { - mouseHandled, keyboardHandled, err = update(child, cursor, pressed, clicked, mouseHandled, keyboardHandled) + mouseHandled, err = update(child, cursor, pressed, clicked, mouseHandled) if err != nil { - return false, false, err - } else if mouseHandled && keyboardHandled { - return true, true, nil + return false, err + } else if mouseHandled { + return true, nil } } if !mouseHandled && cursor.In(w.Rect()) { mouseHandled, err = w.HandleMouse(cursor, pressed, clicked) if err != nil { - return false, false, fmt.Errorf("failed to handle widget mouse input: %s", err) + return false, fmt.Errorf("failed to handle widget mouse input: %s", err) } if clicked && mouseHandled { SetFocus(w) } } - if !keyboardHandled && w == focusedWidget { - keyboardHandled, err = w.HandleKeyboard() - if err != nil { - return false, false, fmt.Errorf("failed to handle widget keyboard input: %s", err) - } - } - return mouseHandled, keyboardHandled, nil + return mouseHandled, nil } func Draw(screen *ebiten.Image) error { diff --git a/go.mod b/go.mod index ce19454..1ced948 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module code.rocket9labs.com/tslocum/etk go 1.18 require ( - code.rocketnine.space/tslocum/messeji v1.0.5-0.20231027235104-784342f8110a + code.rocketnine.space/tslocum/messeji v1.0.5-0.20231028050054-75c3e5625ec6 github.com/hajimehoshi/ebiten/v2 v2.6.2 golang.org/x/image v0.13.0 ) diff --git a/go.sum b/go.sum index 4fd3955..0f20178 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -code.rocketnine.space/tslocum/messeji v1.0.5-0.20231027235104-784342f8110a h1:s3mTWILsEJxS69ETQWDj+aaajCLt/KDZ0iqJPGRW7kY= -code.rocketnine.space/tslocum/messeji v1.0.5-0.20231027235104-784342f8110a/go.mod h1:xszLyTZtpyjCVaGmznizLSAlnvraPOSoanlzUBeqGco= +code.rocketnine.space/tslocum/messeji v1.0.5-0.20231028050054-75c3e5625ec6 h1:HdPb+xfqoRxKJcB9dPshwBALGTSCCMxlzLMgmHAXv2U= +code.rocketnine.space/tslocum/messeji v1.0.5-0.20231028050054-75c3e5625ec6/go.mod h1:xszLyTZtpyjCVaGmznizLSAlnvraPOSoanlzUBeqGco= github.com/ebitengine/purego v0.5.0 h1:JrMGKfRIAM4/QVKaesIIT7m/UVjTj5GYhRSQYwfVdpo= github.com/ebitengine/purego v0.5.0/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ= github.com/hajimehoshi/bitmapfont/v3 v3.0.0 h1:r2+6gYK38nfztS/et50gHAswb9hXgxXECYgE8Nczmi4= diff --git a/grid.go b/grid.go index 031fc3b..68eb0bb 100644 --- a/grid.go +++ b/grid.go @@ -96,7 +96,7 @@ func (g *Grid) HandleMouse(cursor image.Point, pressed bool, clicked bool) (hand return false, nil } -func (g *Grid) HandleKeyboard() (handled bool, err error) { +func (g *Grid) HandleKeyboard(ebiten.Key, rune) (handled bool, err error) { if g.updated { g.reposition() g.updated = false diff --git a/input.go b/input.go index d646d98..457184a 100644 --- a/input.go +++ b/input.go @@ -73,22 +73,16 @@ func (i *Input) Focused() bool { return i.focus } -func (i *Input) HandleMouse(cursor image.Point, pressed bool, clicked bool) (handled bool, err error) { - return true, i.Field.Update() -} - -func (i *Input) HandleKeyboard() (handled bool, err error) { +func (i *Input) HandleKeyboard(key ebiten.Key, r rune) (handled bool, err error) { if !i.focus { return false, nil } - err = i.Field.Update() - return true, err + return i.Field.HandleKeyboardEvent(key, r) } -func (i *Input) HandleKeyboardEvent(key ebiten.Key, r rune) (handled bool, err error) { - i.Field.HandleKeyboardEvent(key, r) - return true, nil +func (i *Input) HandleMouse(cursor image.Point, pressed bool, clicked bool) (handled bool, err error) { + return i.Field.HandleMouseEvent(cursor, pressed, clicked) } func (i *Input) Draw(screen *ebiten.Image) error { diff --git a/text.go b/text.go index f0a41d2..5252ff3 100644 --- a/text.go +++ b/text.go @@ -22,6 +22,7 @@ func NewText(text string) *Text { l.SetText(text) l.SetForegroundColor(textColor) l.SetBackgroundColor(Style.TextBgColor) + l.SetHandleKeyboard(true) return &Text{ TextField: l, @@ -78,18 +79,14 @@ func (t *Text) Text() string { return t.TextField.Text() } +func (t *Text) HandleKeyboard(key ebiten.Key, r rune) (handled bool, err error) { + return t.TextField.HandleKeyboardEvent(key, r) +} + func (t *Text) HandleMouse(cursor image.Point, pressed bool, clicked bool) (handled bool, err error) { return t.TextField.HandleMouseEvent(cursor, pressed, clicked) } -func (t *Text) HandleKeyboard() (handled bool, err error) { - return false, nil -} - -func (t *Text) HandleKeyboardEvent(key ebiten.Key, r rune) (handled bool, err error) { - return t.TextField.HandleKeyboardEvent(key, r) -} - func (t *Text) Draw(screen *ebiten.Image) error { // Draw label. t.TextField.Draw(screen) diff --git a/widget.go b/widget.go index 7e9d3ed..11e9c16 100644 --- a/widget.go +++ b/widget.go @@ -15,9 +15,8 @@ type Widget interface { SetFocus(focus bool) (accept bool) SetVisible(visible bool) Visible() bool + HandleKeyboard(ebiten.Key, rune) (handled bool, err error) HandleMouse(cursor image.Point, pressed bool, clicked bool) (handled bool, err error) - HandleKeyboard() (handled bool, err error) - HandleKeyboardEvent(ebiten.Key, rune) (handled bool, err error) Draw(screen *ebiten.Image) error Children() []Widget } diff --git a/window.go b/window.go index 331149a..540402f 100644 --- a/window.go +++ b/window.go @@ -75,7 +75,7 @@ func (w *Window) HandleMouse(cursor image.Point, pressed bool, clicked bool) (ha return true, nil } -func (w *Window) HandleKeyboard() (handled bool, err error) { +func (w *Window) HandleKeyboard(ebiten.Key, rune) (handled bool, err error) { return true, nil }