mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
internal/gamepad: ignore the very first MotionEvent with 0 value for Android
On Android, MotionEvent with 0 values might come for axes when connecting a gamepad, even though a user didn't touch any axes. This is problematic especially for tirgger axes, where the default value should be -1. This change fixes the issue by adding a new state `axesReady` to check if an axis is really touched or not. If an axis is not touched yet, a button value for a standard (trigger) button always returns 0. This change also removes an old hack to initialize axis values for triggers. Closes #2598
This commit is contained in:
parent
4b1c0526a7
commit
b7dd45c0e4
@ -244,12 +244,6 @@ public class EbitenView extends ViewGroup implements InputManager.InputDeviceLis
|
||||
int axisMask = getAxisMask(inputDevice);
|
||||
|
||||
Ebitenmobileview.onGamepadAdded(deviceId, inputDevice.getName(), gamepad.axes.size(), gamepad.hats.size()/2, descriptor, vendorId, productId, buttonMask, axisMask);
|
||||
|
||||
// Initialize the trigger axes values explicitly, or the initial button values would be 0.5 instead of 0.
|
||||
if (gamepad.axes.size() >= 6) {
|
||||
Ebitenmobileview.onGamepadAxisChanged(deviceId, 4, -1);
|
||||
Ebitenmobileview.onGamepadAxisChanged(deviceId, 5, -1);
|
||||
}
|
||||
}
|
||||
|
||||
// The implementation is copied from SDL:
|
||||
|
@ -45,6 +45,7 @@ func (g *gamepads) addAndroidGamepad(androidDeviceID int, name, sdlID string, ax
|
||||
gp := g.add(name, sdlID)
|
||||
gp.native = &nativeGamepadImpl{
|
||||
androidDeviceID: androidDeviceID,
|
||||
axesReady: make([]bool, axisCount),
|
||||
axes: make([]float64, axisCount),
|
||||
buttons: make([]bool, gamepaddb.SDLControllerButtonMax+1),
|
||||
hats: make([]int, hatCount),
|
||||
@ -108,6 +109,13 @@ func (g *Gamepad) updateAndroidGamepadAxis(axis int, value float64) {
|
||||
return
|
||||
}
|
||||
n.axes[axis] = value
|
||||
|
||||
// MotionEvent with 0 value can be sent when a gamepad is connected even though an axis is not touched (#2598).
|
||||
// This is problematic when an axis is a trigger button where -1 should be the default value.
|
||||
// When MotionEvent with non-0 value is sent, it seems fine to assume that the axis is actually touched and ready.
|
||||
if value != 0 {
|
||||
n.axesReady[axis] = true
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Gamepad) updateAndroidGamepadButton(button Button, pressed bool) {
|
||||
|
@ -243,6 +243,7 @@ type nativeGamepad interface {
|
||||
axisCount() int
|
||||
buttonCount() int
|
||||
hatCount() int
|
||||
isAxisReady(axis int) bool
|
||||
axisValue(axis int) float64
|
||||
buttonValue(button int) float64
|
||||
isButtonPressed(button int) bool
|
||||
@ -296,6 +297,14 @@ func (g *Gamepad) HatCount() int {
|
||||
return g.native.hatCount()
|
||||
}
|
||||
|
||||
// IsAxisReady is concurrent-safe.
|
||||
func (g *Gamepad) IsAxisReady(axis int) bool {
|
||||
g.m.Lock()
|
||||
defer g.m.Unlock()
|
||||
|
||||
return g.native.isAxisReady(axis)
|
||||
}
|
||||
|
||||
// Axis is concurrent-safe.
|
||||
func (g *Gamepad) Axis(axis int) float64 {
|
||||
g.m.Lock()
|
||||
|
@ -37,9 +37,10 @@ func (*nativeGamepadsImpl) update(gamepads *gamepads) error {
|
||||
type nativeGamepadImpl struct {
|
||||
androidDeviceID int
|
||||
|
||||
axes []float64
|
||||
buttons []bool
|
||||
hats []int
|
||||
axesReady []bool
|
||||
axes []float64
|
||||
buttons []bool
|
||||
hats []int
|
||||
}
|
||||
|
||||
func (*nativeGamepadImpl) update(gamepad *gamepads) error {
|
||||
@ -71,6 +72,13 @@ func (g *nativeGamepadImpl) hatCount() int {
|
||||
return len(g.hats)
|
||||
}
|
||||
|
||||
func (g *nativeGamepadImpl) isAxisReady(axis int) bool {
|
||||
if axis < 0 || axis >= len(g.axesReady) {
|
||||
return false
|
||||
}
|
||||
return g.axesReady[axis]
|
||||
}
|
||||
|
||||
func (g *nativeGamepadImpl) axisValue(axis int) float64 {
|
||||
if axis < 0 || axis >= len(g.axes) {
|
||||
return 0
|
||||
|
@ -399,6 +399,10 @@ func (g *nativeGamepadImpl) hatCount() int {
|
||||
return len(g.hatValues)
|
||||
}
|
||||
|
||||
func (g *nativeGamepadImpl) isAxisReady(axis int) bool {
|
||||
return axis >= 0 && axis < g.axisCount()
|
||||
}
|
||||
|
||||
func (g *nativeGamepadImpl) axisValue(axis int) float64 {
|
||||
if axis < 0 || axis >= len(g.axisValues) {
|
||||
return 0
|
||||
|
@ -719,6 +719,10 @@ func (g *nativeGamepadDesktop) hatCount() int {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (g *nativeGamepadDesktop) isAxisReady(axis int) bool {
|
||||
return axis >= 0 && axis < g.axisCount()
|
||||
}
|
||||
|
||||
func (g *nativeGamepadDesktop) axisValue(axis int) float64 {
|
||||
if g.usesDInput() {
|
||||
if axis < 0 || axis >= len(g.dinputAxes) {
|
||||
|
@ -76,6 +76,10 @@ func (g *nativeGamepadImpl) hatCount() int {
|
||||
return len(g.hats)
|
||||
}
|
||||
|
||||
func (g *nativeGamepadImpl) isAxisReady(axis int) bool {
|
||||
return axis >= 0 && axis < g.axisCount()
|
||||
}
|
||||
|
||||
func (g *nativeGamepadImpl) axisValue(axis int) float64 {
|
||||
if axis < 0 || axis >= len(g.axes) {
|
||||
return 0
|
||||
|
@ -152,6 +152,10 @@ func (g *nativeGamepadImpl) hatCount() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (g *nativeGamepadImpl) isAxisReady(axis int) bool {
|
||||
return axis >= 0 && axis < g.axisCount()
|
||||
}
|
||||
|
||||
func (g *nativeGamepadImpl) axisValue(axis int) float64 {
|
||||
axes := g.value.Get("axes")
|
||||
if axis < 0 || axis >= axes.Length() {
|
||||
|
@ -592,6 +592,10 @@ func (g *nativeGamepadImpl) hatCount() int {
|
||||
return g.hatCount_
|
||||
}
|
||||
|
||||
func (g *nativeGamepadImpl) isAxisReady(axis int) bool {
|
||||
return axis >= 0 && axis < g.axisCount()
|
||||
}
|
||||
|
||||
func (g *nativeGamepadImpl) axisValue(axis int) float64 {
|
||||
if axis < 0 || axis >= g.axisCount_ {
|
||||
return 0
|
||||
|
@ -146,6 +146,10 @@ func (g *nativeGamepadImpl) hatCount() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (g *nativeGamepadImpl) isAxisReady(axis int) bool {
|
||||
return axis >= 0 && axis < g.axisCount()
|
||||
}
|
||||
|
||||
func (g *nativeGamepadImpl) axisValue(axis int) float64 {
|
||||
if axis < 0 || axis >= len(g.axisValues) {
|
||||
return 0
|
||||
|
@ -66,6 +66,10 @@ func (*nativeGamepadImpl) hatCount() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (g *nativeGamepadImpl) isAxisReady(axis int) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (*nativeGamepadImpl) axisValue(axis int) float64 {
|
||||
return 0
|
||||
}
|
||||
|
@ -190,6 +190,10 @@ func (n *nativeGamepadXbox) hatCount() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (g *nativeGamepadXbox) isAxisReady(axis int) bool {
|
||||
return axis >= 0 && axis < g.axisCount()
|
||||
}
|
||||
|
||||
func (n *nativeGamepadXbox) axisValue(axis int) float64 {
|
||||
switch gamepaddb.StandardAxis(axis) {
|
||||
case gamepaddb.StandardAxisLeftStickHorizontal:
|
||||
|
@ -390,6 +390,7 @@ func HasStandardLayoutMapping(id string) bool {
|
||||
}
|
||||
|
||||
type GamepadState interface {
|
||||
IsAxisReady(index int) bool
|
||||
Axis(index int) float64
|
||||
Button(index int) bool
|
||||
Hat(index int) int
|
||||
@ -430,6 +431,9 @@ func StandardAxisValue(id string, axis StandardAxis, state GamepadState) float64
|
||||
|
||||
switch mapping.Type {
|
||||
case mappingTypeAxis:
|
||||
if !state.IsAxisReady(mapping.Index) {
|
||||
return 0
|
||||
}
|
||||
v := state.Axis(mapping.Index)*mapping.AxisScale + mapping.AxisOffset
|
||||
if v > 1 {
|
||||
return 1
|
||||
@ -486,6 +490,9 @@ func standardButtonValue(id string, button StandardButton, state GamepadState) f
|
||||
|
||||
switch mapping.Type {
|
||||
case mappingTypeAxis:
|
||||
if !state.IsAxisReady(mapping.Index) {
|
||||
return 0
|
||||
}
|
||||
v := state.Axis(mapping.Index)*mapping.AxisScale + mapping.AxisOffset
|
||||
if v > 1 {
|
||||
v = 1
|
||||
|
Loading…
Reference in New Issue
Block a user