Browse Source

Add Keyboard.AppendInput

master
Trevor Slocum 2 months ago
parent
commit
477569f21e
  1. 53
      demos/kibodo/game/game.go
  2. 8
      go.mod
  3. 26
      go.sum
  4. 2
      key.go
  5. 47
      keyboard.go
  6. 13
      keyboard_test.go

53
demos/kibodo/game/game.go

@ -16,6 +16,8 @@ type game struct {
userInput []byte
incomingInput []*kibodo.Input
op *ebiten.DrawImageOptions
spinnerIndex int
@ -54,31 +56,7 @@ func (g *game) showKeyboard() {
g.userInput = nil
// Show keyboard
ch := make(chan *kibodo.Input, 10)
g.k.Show(ch)
// Handle input
for input := range ch {
if input.Rune > 0 {
g.userInput = append(g.userInput, []byte(string(input.Rune))...)
continue
}
if input.Key == ebiten.KeyBackspace {
s := string(g.userInput)
if len(s) > 0 {
g.userInput = []byte(s[:len(s)-1])
}
continue
} else if input.Key == ebiten.KeyEnter {
g.userInput = nil
continue
} else if input.Key < 0 {
continue
}
g.userInput = append(g.userInput, []byte("<"+input.Key.String()+">")...)
}
g.userInput = []byte("(Hidden, click to show keyboard)")
g.k.Show()
}
func (g *game) Layout(outsideWidth, outsideHeight int) (int, int) {
@ -102,8 +80,29 @@ func (g *game) Layout(outsideWidth, outsideHeight int) (int, int) {
}
func (g *game) Update() error {
if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
go g.showKeyboard()
if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) && !g.k.Visible() {
g.showKeyboard()
}
g.incomingInput = g.k.AppendInput(g.incomingInput[:0])
for _, input := range g.incomingInput {
if input.Rune > 0 {
g.userInput = append(g.userInput, []byte(string(input.Rune))...)
continue
}
if input.Key == ebiten.KeyBackspace {
s := string(g.userInput)
if len(s) > 0 {
g.userInput = []byte(s[:len(s)-1])
}
continue
} else if input.Key == ebiten.KeyEnter {
g.userInput = nil
continue
} else if input.Key < 0 {
continue
}
g.userInput = append(g.userInput, []byte("<"+input.Key.String()+">")...)
}
return g.k.Update()

8
go.mod

@ -3,16 +3,16 @@ module code.rocketnine.space/tslocum/kibodo
go 1.17
require (
github.com/hajimehoshi/ebiten/v2 v2.2.0-alpha.14.0.20210916141036-9c321d1fcf27
github.com/hajimehoshi/ebiten/v2 v2.2.0
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d
)
require (
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20210727001814-0db043d8d5be // indirect
github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 // indirect
golang.org/x/exp v0.0.0-20210916165020-5cb4fee858ee // indirect
golang.org/x/mobile v0.0.0-20210902104108-5d9a33257ab5 // indirect
golang.org/x/exp v0.0.0-20211012155715-ffe10e552389 // indirect
golang.org/x/mobile v0.0.0-20210924032853-1c027f395ef7 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 // indirect
golang.org/x/sys v0.0.0-20211015200801-69063c4bb744 // indirect
golang.org/x/text v0.3.7 // indirect
)

26
go.sum

@ -98,12 +98,12 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hajimehoshi/bitmapfont/v2 v2.1.3 h1:JefUkL0M4nrdVwVq7MMZxSTh6mSxOylm+C4Anoucbb0=
github.com/hajimehoshi/bitmapfont/v2 v2.1.3/go.mod h1:2BnYrkTQGThpr/CY6LorYtt/zEPNzvE/ND69CRTaHMs=
github.com/hajimehoshi/ebiten/v2 v2.2.0-alpha.14.0.20210916141036-9c321d1fcf27 h1:QkZ/7JEkaoLrqMaNjskMvCoOV979VsfHTaDJzTBwGFw=
github.com/hajimehoshi/ebiten/v2 v2.2.0-alpha.14.0.20210916141036-9c321d1fcf27/go.mod h1:2sY8DHIXNs0Lf/pyTZXltEQtqCKZ2HyXbeUWzrLTlg0=
github.com/hajimehoshi/file2byteslice v0.0.0-20200812174855-0e5e8a80490e/go.mod h1:CqqAHp7Dk/AqQiwuhV1yT2334qbA/tFWQW0MD2dGqUE=
github.com/hajimehoshi/ebiten/v2 v2.2.0 h1:2mP9HrLLqiH9X3MajElYZEjVZU/CGh22iFkjatxhT4w=
github.com/hajimehoshi/ebiten/v2 v2.2.0/go.mod h1:olKl/qqhMBBAm2oI7Zy292nCtE+nitlmYKNF3UpbFn0=
github.com/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41/go.mod h1:CqqAHp7Dk/AqQiwuhV1yT2334qbA/tFWQW0MD2dGqUE=
github.com/hajimehoshi/go-mp3 v0.3.2/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM=
github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
github.com/hajimehoshi/oto/v2 v2.1.0-alpha.1/go.mod h1:rUKQmwMkqmRxe+IAof9+tuYA2ofm8cAWXFmSfzDN8vQ=
github.com/hajimehoshi/oto/v2 v2.1.0-alpha.2/go.mod h1:rUKQmwMkqmRxe+IAof9+tuYA2ofm8cAWXFmSfzDN8vQ=
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@ -253,6 +253,7 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
@ -285,8 +286,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
golang.org/x/exp v0.0.0-20210916165020-5cb4fee858ee h1:qlrAyYdKz4o7rWVUjiKqQJMa4PEpd55fqBU8jpsl4Iw=
golang.org/x/exp v0.0.0-20210916165020-5cb4fee858ee/go.mod h1:a3o/VtDNHN+dCVLEpzjjUHOzR+Ln3DHX056ZPzoZGGA=
golang.org/x/exp v0.0.0-20211012155715-ffe10e552389 h1:qFfBYVpJAdBCk6Nmd7ZbcyhGmKmv8fps+OyoOfpjvu8=
golang.org/x/exp v0.0.0-20211012155715-ffe10e552389/go.mod h1:a3o/VtDNHN+dCVLEpzjjUHOzR+Ln3DHX056ZPzoZGGA=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190703141733-d6a02ce849c9/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@ -300,8 +301,9 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4=
golang.org/x/mobile v0.0.0-20210902104108-5d9a33257ab5 h1:peBP2oZO/xVnGMaWMCyFEI0WENsGj71wx5K12mRELHQ=
golang.org/x/mobile v0.0.0-20210902104108-5d9a33257ab5/go.mod h1:c4YKU3ZylDmvbw+H/PSvm42vhdWbuxCzbonauEAP9B8=
golang.org/x/mobile v0.0.0-20210924032853-1c027f395ef7 h1:CyFUjc175y/mbMjxe+WdqI72jguLyjQChKCDe9mfTvg=
golang.org/x/mobile v0.0.0-20210924032853-1c027f395ef7/go.mod h1:c4YKU3ZylDmvbw+H/PSvm42vhdWbuxCzbonauEAP9B8=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
@ -327,6 +329,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -360,10 +363,12 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 h1:7ZDGnxgHAMw7thfC5bEos0RDAccZKxioiWBhfIe+tvw=
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211015200801-69063c4bb744 h1:KzbpndAYEM+4oHRp9JmB2ewj0NHHxO3Z0g7Gus2O1kk=
golang.org/x/sys v0.0.0-20211015200801-69063c4bb744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@ -391,6 +396,7 @@ golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

2
key.go

@ -18,7 +18,7 @@ type Key struct {
pressedTouchID ebiten.TouchID
}
// Input represents the input from a key press.
// Input represents the input event from a key press.
type Input struct {
Rune rune
Key ebiten.Key

47
keyboard.go

@ -24,8 +24,9 @@ type Keyboard struct {
passPhysical bool
allowUserHide bool
internalBuffer []rune
inputBuffer chan *Input
incomingBuffer []rune
inputEvents []*Input
keys [][]*Key
@ -211,7 +212,7 @@ func (k *Keyboard) Hit(key *Key) {
return
}
k.inputBuffer <- input
k.inputEvents = append(k.inputEvents, input)
}
// Update handles user input. This function is called by Ebiten.
@ -223,10 +224,10 @@ func (k *Keyboard) Update() error {
// Pass through physical keyboard input
if k.passPhysical {
// Read input characters
k.internalBuffer = ebiten.AppendInputChars(k.internalBuffer[:0])
if len(k.internalBuffer) > 0 {
for _, r := range k.internalBuffer {
k.inputBuffer <- &Input{Rune: r} // Pass through
k.incomingBuffer = ebiten.AppendInputChars(k.incomingBuffer[:0])
if len(k.incomingBuffer) > 0 {
for _, r := range k.incomingBuffer {
k.inputEvents = append(k.inputEvents, &Input{Rune: r}) // Pass through
}
} else {
// Read keys
@ -236,7 +237,7 @@ func (k *Keyboard) Update() error {
// Hidden
return nil
}
k.inputBuffer <- &Input{Key: key} // Pass through
k.inputEvents = append(k.inputEvents, &Input{Key: key}) // Pass through
}
}
}
@ -453,20 +454,20 @@ func (k *Keyboard) Draw(target *ebiten.Image) {
k.op.ColorM.Reset()
// Draw border
darkShade := color.RGBA{60, 60, 60, 255}
/*darkShade := color.RGBA{60, 60, 60, 255}
ox, oy := k.x+key.x, k.y+key.y
for j := 0; j < key.w; j++ {
target.Set(ox+j, oy, darkShade)
}
for j := 0; j < key.h; j++ {
target.Set(ox, oy+j, darkShade)
}
}*/
}
}
}
// SetAllowUserHide sets a flag that controls whether the widget may be hidden
// by the user. The input buffer channel is closed when the widget is hidden.
// by the user.
func (k *Keyboard) SetAllowUserHide(allow bool) {
k.allowUserHide = allow
}
@ -483,26 +484,24 @@ func (k *Keyboard) SetAlpha(alpha float64) {
k.alpha = alpha
}
// Show shows the widget and begins sending input to the provided channel. The
// channel is closed if the widget is hidden.
func (k *Keyboard) Show(inputBuffer chan *Input) {
if k.inputBuffer != nil {
close(k.inputBuffer)
}
k.inputBuffer = inputBuffer
// Show shows the widget.
func (k *Keyboard) Show() {
k.visible = true
}
// Visible returns whether the keyboard is currently shown.
// Visible returns whether the widget is currently shown.
func (k *Keyboard) Visible() bool {
return k.visible
}
// Hide hides the widget and closes the input buffer channel.
// Hide hides the widget.
func (k *Keyboard) Hide() {
if k.inputBuffer != nil {
close(k.inputBuffer)
k.inputBuffer = nil
}
k.visible = false
}
// AppendInput appends user input that was received since the function was last called.
func (k *Keyboard) AppendInput(events []*Input) []*Input {
events = append(events, k.inputEvents...)
k.inputEvents = nil
return events
}

13
keyboard_test.go

@ -11,14 +11,14 @@ import (
// TODO test presses registered
func TestKeyboard_Draw(t *testing.T) {
k, _ := newTestKeyboard()
k := newTestKeyboard()
// Warm caches
k.drawBackground()
}
func BenchmarkKeyboard_Draw(b *testing.B) {
k, _ := newTestKeyboard()
k := newTestKeyboard()
// Warm caches
k.drawBackground()
@ -34,7 +34,7 @@ func BenchmarkKeyboard_Press(b *testing.B) {
go func() {
time.Sleep(2 * time.Second)
k, _ := newTestKeyboard()
k := newTestKeyboard()
// Warm caches
k.drawBackground()
@ -57,14 +57,11 @@ func BenchmarkKeyboard_Press(b *testing.B) {
}
}
func newTestKeyboard() (*Keyboard, chan *Input) {
ch := make(chan *Input, 10)
func newTestKeyboard() *Keyboard {
k := NewKeyboard()
k.SetRect(0, 0, 300, 100)
k.Show(ch)
return k, ch
return k
}
type DummyGame struct {

Loading…
Cancel
Save