Improve input handling

This commit is contained in:
Trevor Slocum 2023-10-27 22:04:50 -07:00
parent 80d56f9c28
commit 69118f50b2
11 changed files with 64 additions and 58 deletions

6
box.go
View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

72
game.go
View file

@ -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 {

2
go.mod
View file

@ -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
)

4
go.sum
View file

@ -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=

View file

@ -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

View file

@ -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 {

13
text.go
View file

@ -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)

View file

@ -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
}

View file

@ -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
}