Merge pull request #7250 from JosJuice/android-nonzero-axis
Android controller mapping: Ignore axes with constant values
This commit is contained in:
commit
448547c38f
|
@ -12,6 +12,7 @@ import org.dolphinemu.dolphinemu.model.settings.view.InputBindingSetting;
|
||||||
import org.dolphinemu.dolphinemu.utils.ControllerMappingHelper;
|
import org.dolphinemu.dolphinemu.utils.ControllerMappingHelper;
|
||||||
import org.dolphinemu.dolphinemu.utils.Log;
|
import org.dolphinemu.dolphinemu.utils.Log;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,7 +23,8 @@ public final class MotionAlertDialog extends AlertDialog
|
||||||
{
|
{
|
||||||
// The selected input preference
|
// The selected input preference
|
||||||
private final InputBindingSetting setting;
|
private final InputBindingSetting setting;
|
||||||
private final ControllerMappingHelper mControllerMappingHelper;
|
private final ArrayList<Float> mPreviousValues = new ArrayList<>();
|
||||||
|
private int mPrevDeviceId = 0;
|
||||||
private boolean mWaitingForEvent = true;
|
private boolean mWaitingForEvent = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,7 +38,6 @@ public final class MotionAlertDialog extends AlertDialog
|
||||||
super(context);
|
super(context);
|
||||||
|
|
||||||
this.setting = setting;
|
this.setting = setting;
|
||||||
this.mControllerMappingHelper = new ControllerMappingHelper();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean onKeyEvent(int keyCode, KeyEvent event)
|
public boolean onKeyEvent(int keyCode, KeyEvent event)
|
||||||
|
@ -45,7 +46,7 @@ public final class MotionAlertDialog extends AlertDialog
|
||||||
switch (event.getAction())
|
switch (event.getAction())
|
||||||
{
|
{
|
||||||
case KeyEvent.ACTION_DOWN:
|
case KeyEvent.ACTION_DOWN:
|
||||||
if (!mControllerMappingHelper.shouldKeyBeIgnored(event.getDevice(), keyCode))
|
if (!ControllerMappingHelper.shouldKeyBeIgnored(event.getDevice(), keyCode))
|
||||||
{
|
{
|
||||||
saveKeyInput(event);
|
saveKeyInput(event);
|
||||||
}
|
}
|
||||||
|
@ -82,24 +83,41 @@ public final class MotionAlertDialog extends AlertDialog
|
||||||
|
|
||||||
List<InputDevice.MotionRange> motionRanges = input.getMotionRanges();
|
List<InputDevice.MotionRange> motionRanges = input.getMotionRanges();
|
||||||
|
|
||||||
|
if (input.getId() != mPrevDeviceId)
|
||||||
|
{
|
||||||
|
mPreviousValues.clear();
|
||||||
|
}
|
||||||
|
mPrevDeviceId = input.getId();
|
||||||
|
boolean firstEvent = mPreviousValues.isEmpty();
|
||||||
|
|
||||||
int numMovedAxis = 0;
|
int numMovedAxis = 0;
|
||||||
float axisMoveValue = 0.0f;
|
float axisMoveValue = 0.0f;
|
||||||
InputDevice.MotionRange lastMovedRange = null;
|
InputDevice.MotionRange lastMovedRange = null;
|
||||||
char lastMovedDir = '?';
|
char lastMovedDir = '?';
|
||||||
if (mWaitingForEvent)
|
if (mWaitingForEvent)
|
||||||
{
|
{
|
||||||
// Get only the axis that seem to have moved (more than .5)
|
for (int i = 0; i < motionRanges.size(); i++)
|
||||||
for (InputDevice.MotionRange range : motionRanges)
|
|
||||||
{
|
{
|
||||||
|
InputDevice.MotionRange range = motionRanges.get(i);
|
||||||
int axis = range.getAxis();
|
int axis = range.getAxis();
|
||||||
float origValue = event.getAxisValue(axis);
|
float origValue = event.getAxisValue(axis);
|
||||||
float value = mControllerMappingHelper.scaleAxis(input, axis, origValue);
|
float value = ControllerMappingHelper.scaleAxis(input, axis, origValue);
|
||||||
if (Math.abs(value) > 0.5f)
|
if (firstEvent)
|
||||||
{
|
{
|
||||||
// It is common to have multiple axis with the same physical input. For example,
|
mPreviousValues.add(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float previousValue = mPreviousValues.get(i);
|
||||||
|
|
||||||
|
// Only handle the axes that are not neutral (more than 0.5)
|
||||||
|
// but ignore any axis that has a constant value (e.g. always 1)
|
||||||
|
if (Math.abs(value) > 0.5f && value != previousValue)
|
||||||
|
{
|
||||||
|
// It is common to have multiple axes with the same physical input. For example,
|
||||||
// shoulder butters are provided as both AXIS_LTRIGGER and AXIS_BRAKE.
|
// shoulder butters are provided as both AXIS_LTRIGGER and AXIS_BRAKE.
|
||||||
// To handle this, we ignore an axis motion that's the exact same as a motion
|
// To handle this, we ignore an axis motion that's the exact same as a motion
|
||||||
// we already saw. This way, we ignore axis with two names, but catch the case
|
// we already saw. This way, we ignore axes with two names, but catch the case
|
||||||
// where a joystick is moved in two directions.
|
// where a joystick is moved in two directions.
|
||||||
// ref: bottom of https://developer.android.com/training/game-controllers/controller-input.html
|
// ref: bottom of https://developer.android.com/training/game-controllers/controller-input.html
|
||||||
if (value != axisMoveValue)
|
if (value != axisMoveValue)
|
||||||
|
@ -110,6 +128,18 @@ public final class MotionAlertDialog extends AlertDialog
|
||||||
lastMovedDir = value < 0.0f ? '-' : '+';
|
lastMovedDir = value < 0.0f ? '-' : '+';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Special case for d-pads (axis value jumps between 0 and 1 without any values
|
||||||
|
// in between). Without this, the user would need to press the d-pad twice
|
||||||
|
// due to the first press being caught by the "if (firstEvent)" case further up.
|
||||||
|
else if (Math.abs(value) < 0.25f && Math.abs(previousValue) > 0.75f)
|
||||||
|
{
|
||||||
|
numMovedAxis++;
|
||||||
|
lastMovedRange = range;
|
||||||
|
lastMovedDir = previousValue < 0.0f ? '-' : '+';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mPreviousValues.set(i, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If only one axis moved, that's the winner.
|
// If only one axis moved, that's the winner.
|
||||||
|
|
|
@ -8,7 +8,7 @@ import android.view.MotionEvent;
|
||||||
public class ControllerMappingHelper
|
public class ControllerMappingHelper
|
||||||
{
|
{
|
||||||
/** Some controllers report extra button presses that can be ignored. */
|
/** Some controllers report extra button presses that can be ignored. */
|
||||||
public boolean shouldKeyBeIgnored(InputDevice inputDevice, int keyCode)
|
public static boolean shouldKeyBeIgnored(InputDevice inputDevice, int keyCode)
|
||||||
{
|
{
|
||||||
if (isDualShock4(inputDevice)) {
|
if (isDualShock4(inputDevice)) {
|
||||||
// The two analog triggers generate analog motion events as well as a keycode.
|
// The two analog triggers generate analog motion events as well as a keycode.
|
||||||
|
@ -20,7 +20,7 @@ public class ControllerMappingHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Scale an axis to be zero-centered with a proper range. */
|
/** Scale an axis to be zero-centered with a proper range. */
|
||||||
public float scaleAxis(InputDevice inputDevice, int axis, float value)
|
public static float scaleAxis(InputDevice inputDevice, int axis, float value)
|
||||||
{
|
{
|
||||||
if (isDualShock4(inputDevice))
|
if (isDualShock4(inputDevice))
|
||||||
{
|
{
|
||||||
|
@ -39,38 +39,19 @@ public class ControllerMappingHelper
|
||||||
{
|
{
|
||||||
return (value + 1) / 2.0f;
|
return (value + 1) / 2.0f;
|
||||||
}
|
}
|
||||||
if (axis == MotionEvent.AXIS_GENERIC_1)
|
|
||||||
{
|
|
||||||
// This axis is stuck at ~.5. Ignore it.
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (isMogaPro2Hid(inputDevice))
|
|
||||||
{
|
|
||||||
// This controller has a broken axis that reports a constant value. Ignore it.
|
|
||||||
if (axis == MotionEvent.AXIS_GENERIC_1)
|
|
||||||
{
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isDualShock4(InputDevice inputDevice)
|
private static boolean isDualShock4(InputDevice inputDevice)
|
||||||
{
|
{
|
||||||
// Sony DualShock 4 controller
|
// Sony DualShock 4 controller
|
||||||
return inputDevice.getVendorId() == 0x54c && inputDevice.getProductId() == 0x9cc;
|
return inputDevice.getVendorId() == 0x54c && inputDevice.getProductId() == 0x9cc;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isXboxOneWireless(InputDevice inputDevice)
|
private static boolean isXboxOneWireless(InputDevice inputDevice)
|
||||||
{
|
{
|
||||||
// Microsoft Xbox One controller
|
// Microsoft Xbox One controller
|
||||||
return inputDevice.getVendorId() == 0x45e && inputDevice.getProductId() == 0x2e0;
|
return inputDevice.getVendorId() == 0x45e && inputDevice.getProductId() == 0x2e0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isMogaPro2Hid(InputDevice inputDevice)
|
|
||||||
{
|
|
||||||
// Moga Pro 2 HID
|
|
||||||
return inputDevice.getVendorId() == 0x20d6 && inputDevice.getProductId() == 0x6271;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue