inpututil: refactoring: clean up gamepad implementations

This commit is contained in:
Hajime Hoshi 2024-10-26 17:06:59 +09:00
parent e6b8ebe8a2
commit 01dc4ed9b1

View File

@ -28,6 +28,11 @@ type pos struct {
y int y int
} }
type gamepadState struct {
buttonDurations [ebiten.GamepadButtonMax + 1]int
standardButtonDurations [ebiten.StandardGamepadButtonMax + 1]int
}
type inputState struct { type inputState struct {
keyDurations [ebiten.KeyMax + 1]int keyDurations [ebiten.KeyMax + 1]int
prevKeyDurations [ebiten.KeyMax + 1]int prevKeyDurations [ebiten.KeyMax + 1]int
@ -35,14 +40,8 @@ type inputState struct {
mouseButtonDurations [ebiten.MouseButtonMax + 1]int mouseButtonDurations [ebiten.MouseButtonMax + 1]int
prevMouseButtonDurations [ebiten.MouseButtonMax + 1]int prevMouseButtonDurations [ebiten.MouseButtonMax + 1]int
gamepadIDs map[ebiten.GamepadID]struct{} gamepadStates map[ebiten.GamepadID]gamepadState
prevGamepadIDs map[ebiten.GamepadID]struct{} prevGamepadStates map[ebiten.GamepadID]gamepadState
gamepadButtonDurations map[ebiten.GamepadID][]int
prevGamepadButtonDurations map[ebiten.GamepadID][]int
standardGamepadButtonDurations map[ebiten.GamepadID][]int
prevStandardGamepadButtonDurations map[ebiten.GamepadID][]int
touchIDs map[ebiten.TouchID]struct{} touchIDs map[ebiten.TouchID]struct{}
touchDurations map[ebiten.TouchID]int touchDurations map[ebiten.TouchID]int
@ -57,14 +56,8 @@ type inputState struct {
} }
var theInputState = &inputState{ var theInputState = &inputState{
gamepadIDs: map[ebiten.GamepadID]struct{}{}, gamepadStates: map[ebiten.GamepadID]gamepadState{},
prevGamepadIDs: map[ebiten.GamepadID]struct{}{}, prevGamepadStates: map[ebiten.GamepadID]gamepadState{},
gamepadButtonDurations: map[ebiten.GamepadID][]int{},
prevGamepadButtonDurations: map[ebiten.GamepadID][]int{},
standardGamepadButtonDurations: map[ebiten.GamepadID][]int{},
prevStandardGamepadButtonDurations: map[ebiten.GamepadID][]int{},
touchIDs: map[ebiten.TouchID]struct{}{}, touchIDs: map[ebiten.TouchID]struct{}{},
touchDurations: map[ebiten.TouchID]int{}, touchDurations: map[ebiten.TouchID]int{},
@ -106,58 +99,46 @@ func (i *inputState) update() {
// Gamepads // Gamepads
// Copy the gamepad IDs. // Copy the gamepad states.
clear(i.prevGamepadIDs) clear(i.prevGamepadStates)
for id := range i.gamepadIDs { for id, s := range i.gamepadStates {
i.prevGamepadIDs[id] = struct{}{} i.prevGamepadStates[id] = s
} }
// Copy the gamepad button durations.
clear(i.prevGamepadButtonDurations)
for id, ds := range i.gamepadButtonDurations {
i.prevGamepadButtonDurations[id] = append([]int{}, ds...)
}
clear(i.prevStandardGamepadButtonDurations)
for id, ds := range i.standardGamepadButtonDurations {
i.prevStandardGamepadButtonDurations[id] = append([]int{}, ds...)
}
clear(i.gamepadIDs)
i.gamepadIDsBuf = ebiten.AppendGamepadIDs(i.gamepadIDsBuf[:0]) i.gamepadIDsBuf = ebiten.AppendGamepadIDs(i.gamepadIDsBuf[:0])
for _, id := range i.gamepadIDsBuf { for _, id := range i.gamepadIDsBuf {
i.gamepadIDs[id] = struct{}{} state := i.gamepadStates[id]
if _, ok := i.gamepadButtonDurations[id]; !ok { for b := range i.gamepadStates[id].buttonDurations {
i.gamepadButtonDurations[id] = make([]int, ebiten.GamepadButtonMax+1) if ebiten.IsGamepadButtonPressed(id, ebiten.GamepadButton(b)) {
} state.buttonDurations[b]++
for b := ebiten.GamepadButton(0); b <= ebiten.GamepadButtonMax; b++ {
if ebiten.IsGamepadButtonPressed(id, b) {
i.gamepadButtonDurations[id][b]++
} else { } else {
i.gamepadButtonDurations[id][b] = 0 state.buttonDurations[b] = 0
} }
} }
if _, ok := i.standardGamepadButtonDurations[id]; !ok { for b := range i.gamepadStates[id].standardButtonDurations {
i.standardGamepadButtonDurations[id] = make([]int, ebiten.StandardGamepadButtonMax+1) if ebiten.IsStandardGamepadButtonPressed(id, ebiten.StandardGamepadButton(b)) {
} state.standardButtonDurations[b]++
for b := ebiten.StandardGamepadButton(0); b <= ebiten.StandardGamepadButtonMax; b++ {
if ebiten.IsStandardGamepadButtonPressed(id, b) {
i.standardGamepadButtonDurations[id][b]++
} else { } else {
i.standardGamepadButtonDurations[id][b] = 0 state.standardButtonDurations[b] = 0
} }
} }
i.gamepadStates[id] = state
} }
for id := range i.gamepadButtonDurations {
if _, ok := i.gamepadIDs[id]; !ok { // Remove disconnected gamepads.
delete(i.gamepadButtonDurations, id) for id := range i.gamepadStates {
var found bool
for _, id2 := range i.gamepadIDsBuf {
if id == id2 {
found = true
break
} }
} }
for id := range i.standardGamepadButtonDurations { if !found {
if _, ok := i.gamepadIDs[id]; !ok { delete(i.gamepadStates, id)
delete(i.standardGamepadButtonDurations, id)
} }
} }
@ -336,8 +317,8 @@ func AppendJustConnectedGamepadIDs(gamepadIDs []ebiten.GamepadID) []ebiten.Gamep
defer theInputState.m.RUnlock() defer theInputState.m.RUnlock()
origLen := len(gamepadIDs) origLen := len(gamepadIDs)
for id := range theInputState.gamepadIDs { for id := range theInputState.gamepadStates {
if _, ok := theInputState.prevGamepadIDs[id]; !ok { if _, ok := theInputState.prevGamepadStates[id]; !ok {
gamepadIDs = append(gamepadIDs, id) gamepadIDs = append(gamepadIDs, id)
} }
} }
@ -365,9 +346,9 @@ func IsGamepadJustDisconnected(id ebiten.GamepadID) bool {
theInputState.m.RLock() theInputState.m.RLock()
defer theInputState.m.RUnlock() defer theInputState.m.RUnlock()
_, prev := theInputState.prevGamepadIDs[id] _, current := theInputState.gamepadStates[id]
_, current := theInputState.gamepadIDs[id] _, prev := theInputState.prevGamepadStates[id]
return prev && !current return !current && prev
} }
// AppendPressedGamepadButtons append currently pressed gamepad buttons to buttons and returns the extended buffer. // AppendPressedGamepadButtons append currently pressed gamepad buttons to buttons and returns the extended buffer.
@ -380,11 +361,12 @@ func AppendPressedGamepadButtons(id ebiten.GamepadID, buttons []ebiten.GamepadBu
theInputState.m.RLock() theInputState.m.RLock()
defer theInputState.m.RUnlock() defer theInputState.m.RUnlock()
if _, ok := theInputState.gamepadButtonDurations[id]; !ok { state, ok := theInputState.gamepadStates[id]
if !ok {
return buttons return buttons
} }
for b, d := range theInputState.gamepadButtonDurations[id] { for b, d := range state.buttonDurations {
if d == 0 { if d == 0 {
continue continue
} }
@ -404,11 +386,12 @@ func AppendJustPressedGamepadButtons(id ebiten.GamepadID, buttons []ebiten.Gamep
theInputState.m.RLock() theInputState.m.RLock()
defer theInputState.m.RUnlock() defer theInputState.m.RUnlock()
if _, ok := theInputState.gamepadButtonDurations[id]; !ok { state, ok := theInputState.gamepadStates[id]
if !ok {
return buttons return buttons
} }
for b, d := range theInputState.gamepadButtonDurations[id] { for b, d := range state.buttonDurations {
if d != 1 { if d != 1 {
continue continue
} }
@ -428,21 +411,23 @@ func AppendJustReleasedGamepadButtons(id ebiten.GamepadID, buttons []ebiten.Game
theInputState.m.RLock() theInputState.m.RLock()
defer theInputState.m.RUnlock() defer theInputState.m.RUnlock()
if _, ok := theInputState.gamepadButtonDurations[id]; !ok { state, ok := theInputState.gamepadStates[id]
if !ok {
return buttons return buttons
} }
if _, ok := theInputState.prevGamepadButtonDurations[id]; !ok { prevState, ok := theInputState.prevGamepadStates[id]
if !ok {
return buttons return buttons
} }
for b := ebiten.GamepadButton(0); b <= ebiten.GamepadButtonMax; b++ { for b := range state.buttonDurations {
if theInputState.gamepadButtonDurations[id][b] != 0 { if state.buttonDurations[b] != 0 {
continue continue
} }
if theInputState.prevGamepadButtonDurations[id][b] == 0 { if prevState.buttonDurations[b] == 0 {
continue continue
} }
buttons = append(buttons, b) buttons = append(buttons, ebiten.GamepadButton(b))
} }
return buttons return buttons
@ -468,15 +453,16 @@ func IsGamepadButtonJustReleased(id ebiten.GamepadID, button ebiten.GamepadButto
theInputState.m.RLock() theInputState.m.RLock()
defer theInputState.m.RUnlock() defer theInputState.m.RUnlock()
var prev int state, ok := theInputState.gamepadStates[id]
if _, ok := theInputState.prevGamepadButtonDurations[id]; ok { if !ok {
prev = theInputState.prevGamepadButtonDurations[id][button] return false
} }
var current int prevState, ok := theInputState.prevGamepadStates[id]
if _, ok := theInputState.gamepadButtonDurations[id]; ok { if !ok {
current = theInputState.gamepadButtonDurations[id][button] return false
} }
return current == 0 && prev > 0
return state.buttonDurations[button] == 0 && prevState.buttonDurations[button] > 0
} }
// GamepadButtonPressDuration returns how long the gamepad button of the gamepad id is pressed in ticks (Update). // GamepadButtonPressDuration returns how long the gamepad button of the gamepad id is pressed in ticks (Update).
@ -488,11 +474,12 @@ func GamepadButtonPressDuration(id ebiten.GamepadID, button ebiten.GamepadButton
theInputState.m.RLock() theInputState.m.RLock()
defer theInputState.m.RUnlock() defer theInputState.m.RUnlock()
var s int state, ok := theInputState.gamepadStates[id]
if _, ok := theInputState.gamepadButtonDurations[id]; ok { if !ok {
s = theInputState.gamepadButtonDurations[id][button] return 0
} }
return s
return state.buttonDurations[button]
} }
// AppendPressedStandardGamepadButtons append currently pressed standard gamepad buttons to buttons and returns the extended buffer. // AppendPressedStandardGamepadButtons append currently pressed standard gamepad buttons to buttons and returns the extended buffer.
@ -505,15 +492,16 @@ func AppendPressedStandardGamepadButtons(id ebiten.GamepadID, buttons []ebiten.S
theInputState.m.RLock() theInputState.m.RLock()
defer theInputState.m.RUnlock() defer theInputState.m.RUnlock()
if _, ok := theInputState.standardGamepadButtonDurations[id]; !ok { state, ok := theInputState.gamepadStates[id]
if !ok {
return buttons return buttons
} }
for b, d := range theInputState.standardGamepadButtonDurations[id] { for i, d := range state.standardButtonDurations {
if d == 0 { if d == 0 {
continue continue
} }
buttons = append(buttons, ebiten.StandardGamepadButton(b)) buttons = append(buttons, ebiten.StandardGamepadButton(i))
} }
return buttons return buttons
@ -529,11 +517,12 @@ func AppendJustPressedStandardGamepadButtons(id ebiten.GamepadID, buttons []ebit
theInputState.m.RLock() theInputState.m.RLock()
defer theInputState.m.RUnlock() defer theInputState.m.RUnlock()
if _, ok := theInputState.gamepadButtonDurations[id]; !ok { state, ok := theInputState.gamepadStates[id]
if !ok {
return buttons return buttons
} }
for b, d := range theInputState.standardGamepadButtonDurations[id] { for b, d := range state.standardButtonDurations {
if d != 1 { if d != 1 {
continue continue
} }
@ -553,21 +542,23 @@ func AppendJustReleasedStandardGamepadButtons(id ebiten.GamepadID, buttons []ebi
theInputState.m.RLock() theInputState.m.RLock()
defer theInputState.m.RUnlock() defer theInputState.m.RUnlock()
if _, ok := theInputState.gamepadButtonDurations[id]; !ok { state, ok := theInputState.gamepadStates[id]
if !ok {
return buttons return buttons
} }
if _, ok := theInputState.prevGamepadButtonDurations[id]; !ok { prevState, ok := theInputState.prevGamepadStates[id]
if !ok {
return buttons return buttons
} }
for b := ebiten.StandardGamepadButton(0); b <= ebiten.StandardGamepadButtonMax; b++ { for b := range state.standardButtonDurations {
if theInputState.standardGamepadButtonDurations[id][b] != 0 { if state.standardButtonDurations[b] != 0 {
continue continue
} }
if theInputState.prevStandardGamepadButtonDurations[id][b] == 0 { if prevState.standardButtonDurations[b] == 0 {
continue continue
} }
buttons = append(buttons, b) buttons = append(buttons, ebiten.StandardGamepadButton(b))
} }
return buttons return buttons
@ -593,15 +584,16 @@ func IsStandardGamepadButtonJustReleased(id ebiten.GamepadID, button ebiten.Stan
theInputState.m.RLock() theInputState.m.RLock()
defer theInputState.m.RUnlock() defer theInputState.m.RUnlock()
var prev int state, ok := theInputState.gamepadStates[id]
if _, ok := theInputState.prevStandardGamepadButtonDurations[id]; ok { if !ok {
prev = theInputState.prevStandardGamepadButtonDurations[id][button] return false
} }
var current int prevState, ok := theInputState.prevGamepadStates[id]
if _, ok := theInputState.standardGamepadButtonDurations[id]; ok { if !ok {
current = theInputState.standardGamepadButtonDurations[id][button] return false
} }
return current == 0 && prev > 0
return state.standardButtonDurations[button] == 0 && prevState.standardButtonDurations[button] > 0
} }
// StandardGamepadButtonPressDuration returns how long the standard gamepad button of the gamepad id is pressed in ticks (Update). // StandardGamepadButtonPressDuration returns how long the standard gamepad button of the gamepad id is pressed in ticks (Update).
@ -613,10 +605,12 @@ func StandardGamepadButtonPressDuration(id ebiten.GamepadID, button ebiten.Stand
theInputState.m.RLock() theInputState.m.RLock()
defer theInputState.m.RUnlock() defer theInputState.m.RUnlock()
if _, ok := theInputState.standardGamepadButtonDurations[id]; ok { state, ok := theInputState.gamepadStates[id]
return theInputState.standardGamepadButtonDurations[id][button] if !ok {
}
return 0 return 0
}
return state.standardButtonDurations[button]
} }
// AppendJustPressedTouchIDs append touch IDs that are created just in the current tick to touchIDs, // AppendJustPressedTouchIDs append touch IDs that are created just in the current tick to touchIDs,