Optimize drawing uppercase keyboard
parent
ff90b25a4b
commit
d678f08fd4
|
@ -2,7 +2,6 @@ package game
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
|
||||
|
@ -73,6 +72,8 @@ func (g *game) showKeyboard() {
|
|||
} 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()+">")...)
|
||||
}
|
||||
|
@ -89,10 +90,13 @@ func (g *game) Layout(outsideWidth, outsideHeight int) (int, int) {
|
|||
|
||||
g.w, g.h = outsideWidth, outsideHeight
|
||||
|
||||
g.buffer = ebiten.NewImageFromImage(image.NewRGBA(image.Rect(0, 0, g.w, g.h)))
|
||||
g.buffer = ebiten.NewImage(g.w, g.h)
|
||||
|
||||
sizeH := 200
|
||||
g.k.SetRect(0, sizeH, g.w, g.h-sizeH)
|
||||
y := 200
|
||||
if g.h > g.w && (g.h-g.w) > 200 {
|
||||
y = g.h - g.w
|
||||
}
|
||||
g.k.SetRect(0, y, g.w, g.h-y)
|
||||
|
||||
return outsideWidth, outsideHeight
|
||||
}
|
||||
|
|
7
go.mod
7
go.mod
|
@ -3,15 +3,16 @@ module code.rocketnine.space/tslocum/kibodo
|
|||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/hajimehoshi/ebiten/v2 v2.2.0-alpha.13.0.20210909171729-37771717cc52
|
||||
github.com/hajimehoshi/ebiten/v2 v2.2.0-alpha.14.0.20210915040438-ec2f82342091
|
||||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20210727001814-0db043d8d5be // indirect
|
||||
golang.org/x/exp v0.0.0-20210910231120-3d0173ecaa1e // indirect
|
||||
github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 // indirect
|
||||
golang.org/x/exp v0.0.0-20210915225539-aeb18aa42a84 // indirect
|
||||
golang.org/x/mobile v0.0.0-20210902104108-5d9a33257ab5 // indirect
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||
golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0 // indirect
|
||||
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
)
|
||||
|
|
16
go.sum
16
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.13.0.20210909171729-37771717cc52 h1:FVGJlUvpO/i9TiN/S1kpkPxIge7nR7R15Ux0zF3jr+4=
|
||||
github.com/hajimehoshi/ebiten/v2 v2.2.0-alpha.13.0.20210909171729-37771717cc52/go.mod h1:44O6eBPGyRv8YctRbfzaqUH2sek5UdXh0aLWOP02ELI=
|
||||
github.com/hajimehoshi/ebiten/v2 v2.2.0-alpha.14.0.20210915040438-ec2f82342091 h1:z3+aOqAqZhE0ppbhy89l5T3RDB7d+S9TiyGbtVJ3NvA=
|
||||
github.com/hajimehoshi/ebiten/v2 v2.2.0-alpha.14.0.20210915040438-ec2f82342091/go.mod h1:fS7PLZeV3mclX0J6qubENa9ms3NWmZdNJkCOeEHmF74=
|
||||
github.com/hajimehoshi/file2byteslice v0.0.0-20200812174855-0e5e8a80490e/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.0.0-alpha.2/go.mod h1:rUKQmwMkqmRxe+IAof9+tuYA2ofm8cAWXFmSfzDN8vQ=
|
||||
github.com/hajimehoshi/oto/v2 v2.1.0-alpha.0.20210912073017-18657977e3dc/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=
|
||||
|
@ -129,6 +129,8 @@ github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmK
|
|||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/jakecoffman/cp v1.1.0/go.mod h1:JjY/Fp6d8E1CHnu74gWNnU0+b9VzEdUVPoJxg2PsTQg=
|
||||
github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 h1:dy+DS31tGEGCsZzB45HmJJNHjur8GDgtRNX9U7HnSX4=
|
||||
github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240/go.mod h1:3P4UH/k22rXyHIJD2w4h2XMqPX4Of/eySEZq9L6wqc4=
|
||||
github.com/jfreymuth/oggvorbis v1.0.3/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII=
|
||||
github.com/jfreymuth/vorbis v1.0.2/go.mod h1:DoftRo4AznKnShRl1GxiTFCseHr4zR9BN3TWXyuzrqQ=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
|
@ -283,8 +285,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-20210910231120-3d0173ecaa1e h1:W9ijN+u/MsYtKK8c9OVJM3Wc3GyrQO2hlRdbrwyzJMc=
|
||||
golang.org/x/exp v0.0.0-20210910231120-3d0173ecaa1e/go.mod h1:a3o/VtDNHN+dCVLEpzjjUHOzR+Ln3DHX056ZPzoZGGA=
|
||||
golang.org/x/exp v0.0.0-20210915225539-aeb18aa42a84 h1:rZZoVfcp9bNtyV7GbMqs6qTtgn/htRKdyfzKQ4EiLFE=
|
||||
golang.org/x/exp v0.0.0-20210915225539-aeb18aa42a84/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=
|
||||
|
@ -360,8 +362,8 @@ golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/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-20210910150752-751e447fb3d0 h1:xrCZDmdtoloIiooiA9q0OQb9r8HejIHYoHGhGCe1pGg=
|
||||
golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/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/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=
|
||||
|
|
5
key.go
5
key.go
|
@ -4,6 +4,7 @@ import (
|
|||
"github.com/hajimehoshi/ebiten/v2"
|
||||
)
|
||||
|
||||
// Key represents a virtual key.
|
||||
type Key struct {
|
||||
LowerLabel string
|
||||
UpperLabel string
|
||||
|
@ -13,9 +14,11 @@ type Key struct {
|
|||
x, y int
|
||||
w, h int
|
||||
|
||||
pressed bool
|
||||
pressed bool
|
||||
pressedTouchID ebiten.TouchID
|
||||
}
|
||||
|
||||
// Input represents the input from a key press.
|
||||
type Input struct {
|
||||
Rune rune
|
||||
Key ebiten.Key
|
||||
|
|
165
keyboard.go
165
keyboard.go
|
@ -29,7 +29,8 @@ type Keyboard struct {
|
|||
|
||||
keys [][]*Key
|
||||
|
||||
background *ebiten.Image
|
||||
backgroundLower *ebiten.Image
|
||||
backgroundUpper *ebiten.Image
|
||||
backgroundDirty bool
|
||||
|
||||
op *ebiten.DrawImageOptions
|
||||
|
@ -46,7 +47,7 @@ type Keyboard struct {
|
|||
labelFont font.Face
|
||||
}
|
||||
|
||||
// NewKeyboard returns a new Keyboard.
|
||||
// NewKeyboard returns a new Keyboard widget.
|
||||
func NewKeyboard() *Keyboard {
|
||||
fontFace, err := defaultFontFace(64)
|
||||
if err != nil {
|
||||
|
@ -58,7 +59,9 @@ func NewKeyboard() *Keyboard {
|
|||
op: &ebiten.DrawImageOptions{
|
||||
Filter: ebiten.FilterNearest,
|
||||
},
|
||||
background: ebiten.NewImage(1, 1),
|
||||
keys: KeysQWERTY,
|
||||
backgroundLower: ebiten.NewImage(1, 1),
|
||||
backgroundUpper: ebiten.NewImage(1, 1),
|
||||
backgroundColor: color.Black,
|
||||
labelFont: fontFace,
|
||||
}
|
||||
|
@ -93,10 +96,12 @@ func (k *Keyboard) SetRect(x, y, w, h int) {
|
|||
k.backgroundDirty = true
|
||||
}
|
||||
|
||||
// GetKeys returns the keys of the keyboard.
|
||||
func (k *Keyboard) GetKeys() [][]*Key {
|
||||
return k.keys
|
||||
}
|
||||
|
||||
// SetKeys sets the keys of the keyboard.
|
||||
func (k *Keyboard) SetKeys(keys [][]*Key) {
|
||||
k.keys = keys
|
||||
|
||||
|
@ -104,12 +109,15 @@ func (k *Keyboard) SetKeys(keys [][]*Key) {
|
|||
k.backgroundDirty = true
|
||||
}
|
||||
|
||||
// SetLabelFont sets the key label font.
|
||||
func (k *Keyboard) SetLabelFont(face font.Face) {
|
||||
k.labelFont = face
|
||||
|
||||
k.backgroundDirty = true
|
||||
}
|
||||
|
||||
// SetHideShortcuts sets the key shortcuts which, when pressed, will hide the
|
||||
// keyboard.
|
||||
func (k *Keyboard) SetHideShortcuts(shortcuts []ebiten.Key) {
|
||||
k.hideShortcuts = shortcuts
|
||||
}
|
||||
|
@ -126,8 +134,9 @@ func (k *Keyboard) updateKeyRects() {
|
|||
}
|
||||
}
|
||||
|
||||
cellPaddingW := 7
|
||||
cellPaddingH := 7
|
||||
// TODO user configurable
|
||||
cellPaddingW := 2
|
||||
cellPaddingH := 2
|
||||
|
||||
cellH := (k.h - (cellPaddingH * (len(k.keys) - 1))) / len(k.keys)
|
||||
|
||||
|
@ -186,6 +195,7 @@ func (k *Keyboard) handleHideKey(inputKey ebiten.Key) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// Hit handles a key press.
|
||||
func (k *Keyboard) Hit(key *Key) {
|
||||
input := key.LowerInput
|
||||
if k.shift {
|
||||
|
@ -194,7 +204,7 @@ func (k *Keyboard) Hit(key *Key) {
|
|||
|
||||
if input.Key == ebiten.KeyShift {
|
||||
k.shift = !k.shift
|
||||
k.backgroundDirty = true
|
||||
ebiten.ScheduleFrame()
|
||||
return
|
||||
} else if k.handleHideKey(input.Key) {
|
||||
// Hidden
|
||||
|
@ -204,7 +214,7 @@ func (k *Keyboard) Hit(key *Key) {
|
|||
k.inputBuffer <- input
|
||||
}
|
||||
|
||||
// Update handles user input.
|
||||
// Update handles user input. This function is called by Ebiten.
|
||||
func (k *Keyboard) Update() error {
|
||||
if !k.visible {
|
||||
return nil
|
||||
|
@ -232,6 +242,7 @@ func (k *Keyboard) Update() error {
|
|||
}
|
||||
}
|
||||
// Handle mouse input
|
||||
pressDuration := 50 * time.Millisecond
|
||||
if inpututil.IsMouseButtonJustReleased(ebiten.MouseButtonLeft) {
|
||||
x, y := ebiten.CursorPosition()
|
||||
|
||||
|
@ -248,7 +259,7 @@ func (k *Keyboard) Update() error {
|
|||
|
||||
// TODO replace with pressUntil
|
||||
go func() {
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
time.Sleep(pressDuration)
|
||||
|
||||
key.pressed = false
|
||||
ebiten.ScheduleFrame()
|
||||
|
@ -260,6 +271,15 @@ func (k *Keyboard) Update() error {
|
|||
key := k.at(x, y)
|
||||
if key != nil {
|
||||
key.pressed = true
|
||||
|
||||
for _, rowKeys := range k.keys {
|
||||
for _, rowKey := range rowKeys {
|
||||
if rowKey == key || !rowKey.pressed {
|
||||
continue
|
||||
}
|
||||
rowKey.pressed = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Handle touch input
|
||||
|
@ -268,17 +288,47 @@ func (k *Keyboard) Update() error {
|
|||
x, y := ebiten.TouchPosition(id)
|
||||
|
||||
key := k.at(x, y)
|
||||
if key != nil {
|
||||
if key != nil && !key.pressed {
|
||||
key.pressed = true
|
||||
key.pressedTouchID = id
|
||||
|
||||
for _, rowKeys := range k.keys {
|
||||
for _, rowKey := range rowKeys {
|
||||
if rowKey != key && rowKey.pressed {
|
||||
rowKey.pressed = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
k.Hit(key)
|
||||
|
||||
// TODO replace with pressUntil
|
||||
go func() {
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
var touchIDs []ebiten.TouchID
|
||||
t := time.NewTicker(pressDuration)
|
||||
for range t.C {
|
||||
touchIDs = ebiten.AppendTouchIDs(touchIDs[:0])
|
||||
|
||||
key.pressed = false
|
||||
ebiten.ScheduleFrame()
|
||||
var found bool
|
||||
for _, touchID := range touchIDs {
|
||||
if id == touchID {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if found {
|
||||
tx, ty := ebiten.TouchPosition(id)
|
||||
if tx != 0 || ty != 0 {
|
||||
x, y = tx, ty
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
key.pressed = false
|
||||
ebiten.ScheduleFrame()
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
@ -294,44 +344,63 @@ func (k *Keyboard) drawBackground() {
|
|||
return
|
||||
}
|
||||
|
||||
if k.background == nil || k.background.Bounds() != image.Rect(0, 0, k.w, k.h) || k.backgroundColor != k.lastBackgroundColor {
|
||||
k.background = ebiten.NewImageFromImage(image.NewRGBA(image.Rect(0, 0, k.w, k.h)))
|
||||
k.background.Fill(k.backgroundColor)
|
||||
if k.backgroundLower.Bounds() != image.Rect(0, 0, k.w, k.h) || k.backgroundUpper.Bounds() != image.Rect(0, 0, k.w, k.h) || k.backgroundColor != k.lastBackgroundColor {
|
||||
k.backgroundLower = ebiten.NewImage(k.w, k.h)
|
||||
k.backgroundLower.Fill(k.backgroundColor)
|
||||
|
||||
k.backgroundUpper = ebiten.NewImage(k.w, k.h)
|
||||
k.backgroundUpper.Fill(k.backgroundColor)
|
||||
|
||||
k.lastBackgroundColor = k.backgroundColor
|
||||
}
|
||||
|
||||
for _, rowKeys := range k.keys {
|
||||
for _, key := range rowKeys {
|
||||
label := key.LowerLabel
|
||||
if k.shift {
|
||||
label = key.UpperLabel
|
||||
var img *ebiten.Image
|
||||
for i := 0; i < 2; i++ {
|
||||
shift := i == 1
|
||||
for _, rowKeys := range k.keys {
|
||||
for _, key := range rowKeys {
|
||||
if img == nil {
|
||||
img = ebiten.NewImage(key.w, key.h)
|
||||
} else {
|
||||
bounds := img.Bounds()
|
||||
if bounds.Dx() != key.w || bounds.Dy() != key.h {
|
||||
img = ebiten.NewImage(key.w, key.h)
|
||||
}
|
||||
}
|
||||
|
||||
label := key.LowerLabel
|
||||
if shift {
|
||||
label = key.UpperLabel
|
||||
}
|
||||
|
||||
// Draw key background
|
||||
img.Fill(color.RGBA{100, 100, 100, 255})
|
||||
|
||||
// Draw key label
|
||||
bounds := text.BoundString(k.labelFont, label)
|
||||
x := (key.w - bounds.Dx()) / 2
|
||||
if x < 0 {
|
||||
x = 0
|
||||
}
|
||||
y := key.h / 2
|
||||
text.Draw(img, label, k.labelFont, x, y, color.White)
|
||||
|
||||
// Draw key
|
||||
k.op.GeoM.Reset()
|
||||
k.op.GeoM.Translate(float64(key.x), float64(key.y))
|
||||
|
||||
if !shift {
|
||||
k.backgroundLower.DrawImage(img, k.op)
|
||||
} else {
|
||||
k.backgroundUpper.DrawImage(img, k.op)
|
||||
}
|
||||
k.op.ColorM.Reset()
|
||||
}
|
||||
|
||||
// Draw key background
|
||||
img := ebiten.NewImageFromImage(image.NewRGBA(image.Rect(0, 0, key.w, key.h)))
|
||||
img.Fill(color.RGBA{100, 100, 100, 255})
|
||||
|
||||
// Draw key label
|
||||
bounds := text.BoundString(k.labelFont, label)
|
||||
x := (key.w - bounds.Dx()) / 2
|
||||
if x < 0 {
|
||||
x = 0
|
||||
}
|
||||
y := key.h / 2
|
||||
text.Draw(img, label, k.labelFont, x, y, color.White)
|
||||
|
||||
// Draw key
|
||||
k.op.GeoM.Reset()
|
||||
k.op.GeoM.Translate(float64(key.x), float64(key.y))
|
||||
k.background.DrawImage(img, k.op)
|
||||
|
||||
k.op.ColorM.Reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw draws the widget on the provided image.
|
||||
// Draw draws the widget on the provided image. This function is called by Ebiten.
|
||||
func (k *Keyboard) Draw(target *ebiten.Image) {
|
||||
if !k.visible {
|
||||
return
|
||||
|
@ -342,10 +411,17 @@ func (k *Keyboard) Draw(target *ebiten.Image) {
|
|||
k.backgroundDirty = false
|
||||
}
|
||||
|
||||
var background *ebiten.Image
|
||||
if !k.shift {
|
||||
background = k.backgroundLower
|
||||
} else {
|
||||
background = k.backgroundUpper
|
||||
}
|
||||
|
||||
k.op.GeoM.Reset()
|
||||
k.op.GeoM.Translate(float64(k.x), float64(k.y))
|
||||
k.op.ColorM.Scale(1, 1, 1, k.alpha)
|
||||
target.DrawImage(k.background, k.op)
|
||||
target.DrawImage(background, k.op)
|
||||
k.op.ColorM.Reset()
|
||||
|
||||
// Draw pressed keys
|
||||
|
@ -360,7 +436,7 @@ func (k *Keyboard) Draw(target *ebiten.Image) {
|
|||
k.op.GeoM.Translate(float64(k.x+key.x), float64(k.y+key.y))
|
||||
k.op.ColorM.Scale(0.75, 0.75, 0.75, k.alpha)
|
||||
|
||||
target.DrawImage(k.background.SubImage(image.Rect(key.x, key.y, key.x+key.w, key.y+key.h)).(*ebiten.Image), k.op)
|
||||
target.DrawImage(background.SubImage(image.Rect(key.x, key.y, key.x+key.w, key.y+key.h)).(*ebiten.Image), k.op)
|
||||
k.op.ColorM.Reset()
|
||||
}
|
||||
}
|
||||
|
@ -394,6 +470,7 @@ func (k *Keyboard) Show(inputBuffer chan *Input) {
|
|||
k.visible = true
|
||||
}
|
||||
|
||||
// Visible returns whether the keyboard is currently shown.
|
||||
func (k *Keyboard) Visible() bool {
|
||||
return k.visible
|
||||
}
|
||||
|
|
|
@ -1,15 +1,24 @@
|
|||
package kibodo
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
)
|
||||
|
||||
func BenchmarkKeyboard_Draw(b *testing.B) {
|
||||
ch := make(chan *Input, 10)
|
||||
// TODO test presses registered
|
||||
|
||||
k := NewKeyboard()
|
||||
k.SetRect(0, 0, 100, 100)
|
||||
k.Show(ch)
|
||||
func TestKeyboard_Draw(t *testing.T) {
|
||||
k, _ := newTestKeyboard()
|
||||
|
||||
// Warm caches
|
||||
k.drawBackground()
|
||||
}
|
||||
|
||||
func BenchmarkKeyboard_Draw(b *testing.B) {
|
||||
k, _ := newTestKeyboard()
|
||||
|
||||
// Warm caches
|
||||
k.drawBackground()
|
||||
|
@ -20,3 +29,60 @@ func BenchmarkKeyboard_Draw(b *testing.B) {
|
|||
k.drawBackground()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkKeyboard_Press(b *testing.B) {
|
||||
go func() {
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
k, _ := newTestKeyboard()
|
||||
|
||||
// Warm caches
|
||||
k.drawBackground()
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
k.drawBackground()
|
||||
k.keys[0][0].pressed = true
|
||||
k.drawBackground()
|
||||
k.keys[0][0].pressed = false
|
||||
}
|
||||
}()
|
||||
|
||||
runtime.LockOSThread()
|
||||
|
||||
err := ebiten.RunGame(NewDummyGame())
|
||||
if err != nil {
|
||||
b.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func newTestKeyboard() (*Keyboard, chan *Input) {
|
||||
ch := make(chan *Input, 10)
|
||||
|
||||
k := NewKeyboard()
|
||||
k.SetRect(0, 0, 300, 100)
|
||||
k.Show(ch)
|
||||
|
||||
return k, ch
|
||||
}
|
||||
|
||||
type DummyGame struct {
|
||||
ready bool
|
||||
}
|
||||
|
||||
func (d *DummyGame) Update() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DummyGame) Draw(screen *ebiten.Image) {
|
||||
d.ready = true
|
||||
}
|
||||
|
||||
func (d *DummyGame) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) {
|
||||
return outsideWidth, outsideHeight
|
||||
}
|
||||
|
||||
func NewDummyGame() *DummyGame {
|
||||
return &DummyGame{}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue