inpututil: refactoring

This commit is contained in:
Hajime Hoshi 2024-10-26 16:06:39 +09:00
parent c7880a5ad6
commit a6b278d0e5

View File

@ -16,7 +16,7 @@
package inpututil package inpututil
import ( import (
"sort" "slices"
"sync" "sync"
"github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2"
@ -29,11 +29,11 @@ type pos struct {
} }
type inputState struct { type inputState struct {
keyDurations []int keyDurations [ebiten.KeyMax + 1]int
prevKeyDurations []int prevKeyDurations [ebiten.KeyMax + 1]int
mouseButtonDurations map[ebiten.MouseButton]int mouseButtonDurations [ebiten.MouseButtonMax + 1]int
prevMouseButtonDurations map[ebiten.MouseButton]int prevMouseButtonDurations [ebiten.MouseButtonMax + 1]int
gamepadIDs map[ebiten.GamepadID]struct{} gamepadIDs map[ebiten.GamepadID]struct{}
prevGamepadIDs map[ebiten.GamepadID]struct{} prevGamepadIDs map[ebiten.GamepadID]struct{}
@ -57,12 +57,6 @@ type inputState struct {
} }
var theInputState = &inputState{ var theInputState = &inputState{
keyDurations: make([]int, ebiten.KeyMax+1),
prevKeyDurations: make([]int, ebiten.KeyMax+1),
mouseButtonDurations: map[ebiten.MouseButton]int{},
prevMouseButtonDurations: map[ebiten.MouseButton]int{},
gamepadIDs: map[ebiten.GamepadID]struct{}{}, gamepadIDs: map[ebiten.GamepadID]struct{}{},
prevGamepadIDs: map[ebiten.GamepadID]struct{}{}, prevGamepadIDs: map[ebiten.GamepadID]struct{}{},
@ -91,22 +85,22 @@ func (i *inputState) update() {
defer i.m.Unlock() defer i.m.Unlock()
// Keyboard // Keyboard
copy(i.prevKeyDurations, i.keyDurations) copy(i.prevKeyDurations[:], i.keyDurations[:])
for k := ebiten.Key(0); k <= ebiten.KeyMax; k++ { for idx := range i.keyDurations {
if ebiten.IsKeyPressed(k) { if ebiten.IsKeyPressed(ebiten.Key(idx)) {
i.keyDurations[k]++ i.keyDurations[idx]++
} else { } else {
i.keyDurations[k] = 0 i.keyDurations[idx] = 0
} }
} }
// Mouse // Mouse
for b := ebiten.MouseButton(0); b <= ebiten.MouseButtonMax; b++ { copy(i.prevMouseButtonDurations[:], i.mouseButtonDurations[:])
i.prevMouseButtonDurations[b] = i.mouseButtonDurations[b] for idx := range i.mouseButtonDurations {
if ebiten.IsMouseButtonPressed(b) { if ebiten.IsMouseButtonPressed(ebiten.MouseButton(idx)) {
i.mouseButtonDurations[b]++ i.mouseButtonDurations[idx]++
} else { } else {
i.mouseButtonDurations[b] = 0 i.mouseButtonDurations[idx] = 0
} }
} }
@ -266,14 +260,14 @@ func AppendJustReleasedKeys(keys []ebiten.Key) []ebiten.Key {
theInputState.m.RLock() theInputState.m.RLock()
defer theInputState.m.RUnlock() defer theInputState.m.RUnlock()
for k := ebiten.Key(0); k <= ebiten.KeyMax; k++ { for i := range theInputState.keyDurations {
if theInputState.keyDurations[k] != 0 { if theInputState.keyDurations[i] != 0 {
continue continue
} }
if theInputState.prevKeyDurations[k] == 0 { if theInputState.prevKeyDurations[i] == 0 {
continue continue
} }
keys = append(keys, k) keys = append(keys, ebiten.Key(i))
} }
return keys return keys
} }
@ -296,9 +290,8 @@ func IsKeyJustPressed(key ebiten.Key) bool {
// IsKeyJustReleased is concurrent safe. // IsKeyJustReleased is concurrent safe.
func IsKeyJustReleased(key ebiten.Key) bool { func IsKeyJustReleased(key ebiten.Key) bool {
theInputState.m.RLock() theInputState.m.RLock()
r := theInputState.keyDurations[key] == 0 && theInputState.prevKeyDurations[key] > 0 defer theInputState.m.RUnlock()
theInputState.m.RUnlock() return theInputState.keyDurations[key] == 0 && theInputState.prevKeyDurations[key] > 0
return r
} }
// KeyPressDuration returns how long the key is pressed in ticks (Update). // KeyPressDuration returns how long the key is pressed in ticks (Update).
@ -308,9 +301,8 @@ func IsKeyJustReleased(key ebiten.Key) bool {
// KeyPressDuration is concurrent safe. // KeyPressDuration is concurrent safe.
func KeyPressDuration(key ebiten.Key) int { func KeyPressDuration(key ebiten.Key) int {
theInputState.m.RLock() theInputState.m.RLock()
s := theInputState.keyDurations[key] defer theInputState.m.RUnlock()
theInputState.m.RUnlock() return theInputState.keyDurations[key]
return s
} }
// IsMouseButtonJustPressed returns a boolean value indicating // IsMouseButtonJustPressed returns a boolean value indicating
@ -331,10 +323,8 @@ func IsMouseButtonJustPressed(button ebiten.MouseButton) bool {
// IsMouseButtonJustReleased is concurrent safe. // IsMouseButtonJustReleased is concurrent safe.
func IsMouseButtonJustReleased(button ebiten.MouseButton) bool { func IsMouseButtonJustReleased(button ebiten.MouseButton) bool {
theInputState.m.RLock() theInputState.m.RLock()
r := theInputState.mouseButtonDurations[button] == 0 && defer theInputState.m.RUnlock()
theInputState.prevMouseButtonDurations[button] > 0 return theInputState.mouseButtonDurations[button] == 0 && theInputState.prevMouseButtonDurations[button] > 0
theInputState.m.RUnlock()
return r
} }
// MouseButtonPressDuration returns how long the mouse button is pressed in ticks (Update). // MouseButtonPressDuration returns how long the mouse button is pressed in ticks (Update).
@ -344,9 +334,8 @@ func IsMouseButtonJustReleased(button ebiten.MouseButton) bool {
// MouseButtonPressDuration is concurrent safe. // MouseButtonPressDuration is concurrent safe.
func MouseButtonPressDuration(button ebiten.MouseButton) int { func MouseButtonPressDuration(button ebiten.MouseButton) int {
theInputState.m.RLock() theInputState.m.RLock()
s := theInputState.mouseButtonDurations[button] defer theInputState.m.RUnlock()
theInputState.m.RUnlock() return theInputState.mouseButtonDurations[button]
return s
} }
// AppendJustConnectedGamepadIDs appends gamepad IDs that are connected just in the current tick to gamepadIDs, // AppendJustConnectedGamepadIDs appends gamepad IDs that are connected just in the current tick to gamepadIDs,
@ -357,18 +346,17 @@ func MouseButtonPressDuration(button ebiten.MouseButton) int {
// //
// AppendJustConnectedGamepadIDs is concurrent safe. // AppendJustConnectedGamepadIDs is concurrent safe.
func AppendJustConnectedGamepadIDs(gamepadIDs []ebiten.GamepadID) []ebiten.GamepadID { func AppendJustConnectedGamepadIDs(gamepadIDs []ebiten.GamepadID) []ebiten.GamepadID {
origLen := len(gamepadIDs)
theInputState.m.RLock() theInputState.m.RLock()
defer theInputState.m.RUnlock()
origLen := len(gamepadIDs)
for id := range theInputState.gamepadIDs { for id := range theInputState.gamepadIDs {
if _, ok := theInputState.prevGamepadIDs[id]; !ok { if _, ok := theInputState.prevGamepadIDs[id]; !ok {
gamepadIDs = append(gamepadIDs, id) gamepadIDs = append(gamepadIDs, id)
} }
} }
theInputState.m.RUnlock()
s := gamepadIDs[origLen:] slices.Sort(gamepadIDs[origLen:])
sort.Slice(s, func(a, b int) bool {
return s[a] < s[b]
})
return gamepadIDs return gamepadIDs
} }
@ -389,9 +377,10 @@ func JustConnectedGamepadIDs() []ebiten.GamepadID {
// IsGamepadJustDisconnected is concurrent safe. // IsGamepadJustDisconnected is concurrent safe.
func IsGamepadJustDisconnected(id ebiten.GamepadID) bool { func IsGamepadJustDisconnected(id ebiten.GamepadID) bool {
theInputState.m.RLock() theInputState.m.RLock()
defer theInputState.m.RUnlock()
_, prev := theInputState.prevGamepadIDs[id] _, prev := theInputState.prevGamepadIDs[id]
_, current := theInputState.gamepadIDs[id] _, current := theInputState.gamepadIDs[id]
theInputState.m.RUnlock()
return prev && !current return prev && !current
} }
@ -493,15 +482,16 @@ func IsGamepadButtonJustPressed(id ebiten.GamepadID, button ebiten.GamepadButton
// IsGamepadButtonJustReleased is concurrent safe. // IsGamepadButtonJustReleased is concurrent safe.
func IsGamepadButtonJustReleased(id ebiten.GamepadID, button ebiten.GamepadButton) bool { func IsGamepadButtonJustReleased(id ebiten.GamepadID, button ebiten.GamepadButton) bool {
theInputState.m.RLock() theInputState.m.RLock()
prev := 0 defer theInputState.m.RUnlock()
var prev int
if _, ok := theInputState.prevGamepadButtonDurations[id]; ok { if _, ok := theInputState.prevGamepadButtonDurations[id]; ok {
prev = theInputState.prevGamepadButtonDurations[id][button] prev = theInputState.prevGamepadButtonDurations[id][button]
} }
current := 0 var current int
if _, ok := theInputState.gamepadButtonDurations[id]; ok { if _, ok := theInputState.gamepadButtonDurations[id]; ok {
current = theInputState.gamepadButtonDurations[id][button] current = theInputState.gamepadButtonDurations[id][button]
} }
theInputState.m.RUnlock()
return current == 0 && prev > 0 return current == 0 && prev > 0
} }
@ -512,11 +502,12 @@ func IsGamepadButtonJustReleased(id ebiten.GamepadID, button ebiten.GamepadButto
// GamepadButtonPressDuration is concurrent safe. // GamepadButtonPressDuration is concurrent safe.
func GamepadButtonPressDuration(id ebiten.GamepadID, button ebiten.GamepadButton) int { func GamepadButtonPressDuration(id ebiten.GamepadID, button ebiten.GamepadButton) int {
theInputState.m.RLock() theInputState.m.RLock()
s := 0 defer theInputState.m.RUnlock()
var s int
if _, ok := theInputState.gamepadButtonDurations[id]; ok { if _, ok := theInputState.gamepadButtonDurations[id]; ok {
s = theInputState.gamepadButtonDurations[id][button] s = theInputState.gamepadButtonDurations[id][button]
} }
theInputState.m.RUnlock()
return s return s
} }
@ -664,11 +655,7 @@ func AppendJustPressedTouchIDs(touchIDs []ebiten.TouchID) []ebiten.TouchID {
} }
} }
s := touchIDs[origLen:] slices.Sort(touchIDs[origLen:])
sort.Slice(s, func(a, b int) bool {
return s[a] < s[b]
})
return touchIDs return touchIDs
} }
@ -699,11 +686,7 @@ func AppendJustReleasedTouchIDs(touchIDs []ebiten.TouchID) []ebiten.TouchID {
} }
} }
s := touchIDs[origLen:] slices.Sort(touchIDs[origLen:])
sort.Slice(s, func(a, b int) bool {
return s[a] < s[b]
})
return touchIDs return touchIDs
} }
@ -727,9 +710,8 @@ func IsTouchJustReleased(id ebiten.TouchID) bool {
// TouchPressDuration is concurrent safe. // TouchPressDuration is concurrent safe.
func TouchPressDuration(id ebiten.TouchID) int { func TouchPressDuration(id ebiten.TouchID) int {
theInputState.m.RLock() theInputState.m.RLock()
s := theInputState.touchDurations[id] defer theInputState.m.RUnlock()
theInputState.m.RUnlock() return theInputState.touchDurations[id]
return s
} }
// TouchPositionInPreviousTick returns the position in the previous tick. // TouchPositionInPreviousTick returns the position in the previous tick.