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
4f1dc6a0f4
commit
e2f26b9dac
@ -244,12 +244,6 @@ public class EbitenView extends ViewGroup implements InputManager.InputDeviceLis
|
|||||||
int axisMask = getAxisMask(inputDevice);
|
int axisMask = getAxisMask(inputDevice);
|
||||||
|
|
||||||
Ebitenmobileview.onGamepadAdded(deviceId, inputDevice.getName(), gamepad.axes.size(), gamepad.hats.size()/2, descriptor, vendorId, productId, buttonMask, axisMask);
|
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:
|
// The implementation is copied from SDL:
|
||||||
|
@ -47,6 +47,7 @@ func (g *gamepads) addAndroidGamepad(androidDeviceID int, name, sdlID string, ax
|
|||||||
gp := g.add(name, sdlID)
|
gp := g.add(name, sdlID)
|
||||||
gp.native = &nativeGamepadImpl{
|
gp.native = &nativeGamepadImpl{
|
||||||
androidDeviceID: androidDeviceID,
|
androidDeviceID: androidDeviceID,
|
||||||
|
axesReady: make([]bool, axisCount),
|
||||||
axes: make([]float64, axisCount),
|
axes: make([]float64, axisCount),
|
||||||
buttons: make([]bool, gamepaddb.SDLControllerButtonMax+1),
|
buttons: make([]bool, gamepaddb.SDLControllerButtonMax+1),
|
||||||
hats: make([]int, hatCount),
|
hats: make([]int, hatCount),
|
||||||
@ -110,6 +111,13 @@ func (g *Gamepad) updateAndroidGamepadAxis(axis int, value float64) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
n.axes[axis] = value
|
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) {
|
func (g *Gamepad) updateAndroidGamepadButton(button Button, pressed bool) {
|
||||||
|
@ -243,6 +243,7 @@ type nativeGamepad interface {
|
|||||||
axisCount() int
|
axisCount() int
|
||||||
buttonCount() int
|
buttonCount() int
|
||||||
hatCount() int
|
hatCount() int
|
||||||
|
isAxisReady(axis int) bool
|
||||||
axisValue(axis int) float64
|
axisValue(axis int) float64
|
||||||
buttonValue(button int) float64
|
buttonValue(button int) float64
|
||||||
isButtonPressed(button int) bool
|
isButtonPressed(button int) bool
|
||||||
@ -296,6 +297,14 @@ func (g *Gamepad) HatCount() int {
|
|||||||
return g.native.hatCount()
|
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.
|
// Axis is concurrent-safe.
|
||||||
func (g *Gamepad) Axis(axis int) float64 {
|
func (g *Gamepad) Axis(axis int) float64 {
|
||||||
g.m.Lock()
|
g.m.Lock()
|
||||||
|
@ -39,9 +39,10 @@ func (*nativeGamepadsImpl) update(gamepads *gamepads) error {
|
|||||||
type nativeGamepadImpl struct {
|
type nativeGamepadImpl struct {
|
||||||
androidDeviceID int
|
androidDeviceID int
|
||||||
|
|
||||||
axes []float64
|
axesReady []bool
|
||||||
buttons []bool
|
axes []float64
|
||||||
hats []int
|
buttons []bool
|
||||||
|
hats []int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*nativeGamepadImpl) update(gamepad *gamepads) error {
|
func (*nativeGamepadImpl) update(gamepad *gamepads) error {
|
||||||
@ -73,6 +74,13 @@ func (g *nativeGamepadImpl) hatCount() int {
|
|||||||
return len(g.hats)
|
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 {
|
func (g *nativeGamepadImpl) axisValue(axis int) float64 {
|
||||||
if axis < 0 || axis >= len(g.axes) {
|
if axis < 0 || axis >= len(g.axes) {
|
||||||
return 0
|
return 0
|
||||||
|
@ -399,6 +399,10 @@ func (g *nativeGamepadImpl) hatCount() int {
|
|||||||
return len(g.hatValues)
|
return len(g.hatValues)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *nativeGamepadImpl) isAxisReady(axis int) bool {
|
||||||
|
return axis >= 0 && axis < g.axisCount()
|
||||||
|
}
|
||||||
|
|
||||||
func (g *nativeGamepadImpl) axisValue(axis int) float64 {
|
func (g *nativeGamepadImpl) axisValue(axis int) float64 {
|
||||||
if axis < 0 || axis >= len(g.axisValues) {
|
if axis < 0 || axis >= len(g.axisValues) {
|
||||||
return 0
|
return 0
|
||||||
|
@ -721,6 +721,10 @@ func (g *nativeGamepadDesktop) hatCount() int {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *nativeGamepadDesktop) isAxisReady(axis int) bool {
|
||||||
|
return axis >= 0 && axis < g.axisCount()
|
||||||
|
}
|
||||||
|
|
||||||
func (g *nativeGamepadDesktop) axisValue(axis int) float64 {
|
func (g *nativeGamepadDesktop) axisValue(axis int) float64 {
|
||||||
if g.usesDInput() {
|
if g.usesDInput() {
|
||||||
if axis < 0 || axis >= len(g.dinputAxes) {
|
if axis < 0 || axis >= len(g.dinputAxes) {
|
||||||
|
@ -78,6 +78,10 @@ func (g *nativeGamepadImpl) hatCount() int {
|
|||||||
return len(g.hats)
|
return len(g.hats)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *nativeGamepadImpl) isAxisReady(axis int) bool {
|
||||||
|
return axis >= 0 && axis < g.axisCount()
|
||||||
|
}
|
||||||
|
|
||||||
func (g *nativeGamepadImpl) axisValue(axis int) float64 {
|
func (g *nativeGamepadImpl) axisValue(axis int) float64 {
|
||||||
if axis < 0 || axis >= len(g.axes) {
|
if axis < 0 || axis >= len(g.axes) {
|
||||||
return 0
|
return 0
|
||||||
|
@ -152,6 +152,10 @@ func (g *nativeGamepadImpl) hatCount() int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *nativeGamepadImpl) isAxisReady(axis int) bool {
|
||||||
|
return axis >= 0 && axis < g.axisCount()
|
||||||
|
}
|
||||||
|
|
||||||
func (g *nativeGamepadImpl) axisValue(axis int) float64 {
|
func (g *nativeGamepadImpl) axisValue(axis int) float64 {
|
||||||
axes := g.value.Get("axes")
|
axes := g.value.Get("axes")
|
||||||
if axis < 0 || axis >= axes.Length() {
|
if axis < 0 || axis >= axes.Length() {
|
||||||
|
@ -592,6 +592,10 @@ func (g *nativeGamepadImpl) hatCount() int {
|
|||||||
return g.hatCount_
|
return g.hatCount_
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *nativeGamepadImpl) isAxisReady(axis int) bool {
|
||||||
|
return axis >= 0 && axis < g.axisCount()
|
||||||
|
}
|
||||||
|
|
||||||
func (g *nativeGamepadImpl) axisValue(axis int) float64 {
|
func (g *nativeGamepadImpl) axisValue(axis int) float64 {
|
||||||
if axis < 0 || axis >= g.axisCount_ {
|
if axis < 0 || axis >= g.axisCount_ {
|
||||||
return 0
|
return 0
|
||||||
|
@ -146,6 +146,10 @@ func (g *nativeGamepadImpl) hatCount() int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *nativeGamepadImpl) isAxisReady(axis int) bool {
|
||||||
|
return axis >= 0 && axis < g.axisCount()
|
||||||
|
}
|
||||||
|
|
||||||
func (g *nativeGamepadImpl) axisValue(axis int) float64 {
|
func (g *nativeGamepadImpl) axisValue(axis int) float64 {
|
||||||
if axis < 0 || axis >= len(g.axisValues) {
|
if axis < 0 || axis >= len(g.axisValues) {
|
||||||
return 0
|
return 0
|
||||||
|
@ -66,6 +66,10 @@ func (*nativeGamepadImpl) hatCount() int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *nativeGamepadImpl) isAxisReady(axis int) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (*nativeGamepadImpl) axisValue(axis int) float64 {
|
func (*nativeGamepadImpl) axisValue(axis int) float64 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
@ -192,6 +192,10 @@ func (n *nativeGamepadXbox) hatCount() int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *nativeGamepadXbox) isAxisReady(axis int) bool {
|
||||||
|
return axis >= 0 && axis < g.axisCount()
|
||||||
|
}
|
||||||
|
|
||||||
func (n *nativeGamepadXbox) axisValue(axis int) float64 {
|
func (n *nativeGamepadXbox) axisValue(axis int) float64 {
|
||||||
switch gamepaddb.StandardAxis(axis) {
|
switch gamepaddb.StandardAxis(axis) {
|
||||||
case gamepaddb.StandardAxisLeftStickHorizontal:
|
case gamepaddb.StandardAxisLeftStickHorizontal:
|
||||||
|
@ -390,6 +390,7 @@ func HasStandardLayoutMapping(id string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type GamepadState interface {
|
type GamepadState interface {
|
||||||
|
IsAxisReady(index int) bool
|
||||||
Axis(index int) float64
|
Axis(index int) float64
|
||||||
Button(index int) bool
|
Button(index int) bool
|
||||||
Hat(index int) int
|
Hat(index int) int
|
||||||
@ -435,6 +436,9 @@ func AxisValue(id string, axis StandardAxis, state GamepadState) float64 {
|
|||||||
|
|
||||||
switch mapping.Type {
|
switch mapping.Type {
|
||||||
case mappingTypeAxis:
|
case mappingTypeAxis:
|
||||||
|
if !state.IsAxisReady(mapping.Index) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
v := state.Axis(mapping.Index)*float64(mapping.AxisScale) + float64(mapping.AxisOffset)
|
v := state.Axis(mapping.Index)*float64(mapping.AxisScale) + float64(mapping.AxisOffset)
|
||||||
if v > 1 {
|
if v > 1 {
|
||||||
return 1
|
return 1
|
||||||
@ -496,6 +500,9 @@ func buttonValue(id string, button StandardButton, state GamepadState) float64 {
|
|||||||
|
|
||||||
switch mapping.Type {
|
switch mapping.Type {
|
||||||
case mappingTypeAxis:
|
case mappingTypeAxis:
|
||||||
|
if !state.IsAxisReady(mapping.Index) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
v := state.Axis(mapping.Index)*float64(mapping.AxisScale) + float64(mapping.AxisOffset)
|
v := state.Axis(mapping.Index)*float64(mapping.AxisScale) + float64(mapping.AxisOffset)
|
||||||
if v > 1 {
|
if v > 1 {
|
||||||
v = 1
|
v = 1
|
||||||
|
Loading…
Reference in New Issue
Block a user