Skip to content

Commit

Permalink
Merge pull request #7250 from JosJuice/android-nonzero-axis
Browse files Browse the repository at this point in the history
Android controller mapping: Ignore axes with constant values
  • Loading branch information
JosJuice committed Jul 21, 2018
2 parents a21d536 + 7f6be99 commit 448547c
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.dolphinemu.dolphinemu.utils.ControllerMappingHelper;
import org.dolphinemu.dolphinemu.utils.Log;

import java.util.ArrayList;
import java.util.List;

/**
Expand All @@ -22,7 +23,8 @@ public final class MotionAlertDialog extends AlertDialog
{
// The selected input preference
private final InputBindingSetting setting;
private final ControllerMappingHelper mControllerMappingHelper;
private final ArrayList<Float> mPreviousValues = new ArrayList<>();
private int mPrevDeviceId = 0;
private boolean mWaitingForEvent = true;

/**
Expand All @@ -36,7 +38,6 @@ public MotionAlertDialog(Context context, InputBindingSetting setting)
super(context);

this.setting = setting;
this.mControllerMappingHelper = new ControllerMappingHelper();
}

public boolean onKeyEvent(int keyCode, KeyEvent event)
Expand All @@ -45,7 +46,7 @@ public boolean onKeyEvent(int keyCode, KeyEvent event)
switch (event.getAction())
{
case KeyEvent.ACTION_DOWN:
if (!mControllerMappingHelper.shouldKeyBeIgnored(event.getDevice(), keyCode))
if (!ControllerMappingHelper.shouldKeyBeIgnored(event.getDevice(), keyCode))
{
saveKeyInput(event);
}
Expand Down Expand Up @@ -82,34 +83,63 @@ private boolean onMotionEvent(MotionEvent event)

List<InputDevice.MotionRange> motionRanges = input.getMotionRanges();

if (input.getId() != mPrevDeviceId)
{
mPreviousValues.clear();
}
mPrevDeviceId = input.getId();
boolean firstEvent = mPreviousValues.isEmpty();

int numMovedAxis = 0;
float axisMoveValue = 0.0f;
InputDevice.MotionRange lastMovedRange = null;
char lastMovedDir = '?';
if (mWaitingForEvent)
{
// Get only the axis that seem to have moved (more than .5)
for (InputDevice.MotionRange range : motionRanges)
for (int i = 0; i < motionRanges.size(); i++)
{
InputDevice.MotionRange range = motionRanges.get(i);
int axis = range.getAxis();
float origValue = event.getAxisValue(axis);
float value = mControllerMappingHelper.scaleAxis(input, axis, origValue);
if (Math.abs(value) > 0.5f)
float value = ControllerMappingHelper.scaleAxis(input, axis, origValue);
if (firstEvent)
{
mPreviousValues.add(value);
}
else
{
// It is common to have multiple axis with the same physical input. For example,
// 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
// we already saw. This way, we ignore axis with two names, but catch the case
// where a joystick is moved in two directions.
// ref: bottom of https://developer.android.com/training/game-controllers/controller-input.html
if (value != axisMoveValue)
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.
// To handle this, we ignore an axis motion that's the exact same as a motion
// we already saw. This way, we ignore axes with two names, but catch the case
// where a joystick is moved in two directions.
// ref: bottom of https://developer.android.com/training/game-controllers/controller-input.html
if (value != axisMoveValue)
{
axisMoveValue = value;
numMovedAxis++;
lastMovedRange = range;
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)
{
axisMoveValue = value;
numMovedAxis++;
lastMovedRange = range;
lastMovedDir = value < 0.0f ? '-' : '+';
lastMovedDir = previousValue < 0.0f ? '-' : '+';
}
}

mPreviousValues.set(i, value);
}

// If only one axis moved, that's the winner.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
public class ControllerMappingHelper
{
/** 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)) {
// The two analog triggers generate analog motion events as well as a keycode.
Expand All @@ -20,7 +20,7 @@ public boolean shouldKeyBeIgnored(InputDevice inputDevice, int keyCode)
}

/** 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))
{
Expand All @@ -39,38 +39,19 @@ else if (isXboxOneWireless(inputDevice))
{
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;
}

private boolean isDualShock4(InputDevice inputDevice)
private static boolean isDualShock4(InputDevice inputDevice)
{
// Sony DualShock 4 controller
return inputDevice.getVendorId() == 0x54c && inputDevice.getProductId() == 0x9cc;
}

private boolean isXboxOneWireless(InputDevice inputDevice)
private static boolean isXboxOneWireless(InputDevice inputDevice)
{
// Microsoft Xbox One controller
return inputDevice.getVendorId() == 0x45e && inputDevice.getProductId() == 0x2e0;
}

private boolean isMogaPro2Hid(InputDevice inputDevice)
{
// Moga Pro 2 HID
return inputDevice.getVendorId() == 0x20d6 && inputDevice.getProductId() == 0x6271;
}
}

0 comments on commit 448547c

Please sign in to comment.