android: frontend: MotionAlertDialog: Merge latest Dolphin code.
This commit is contained in:
parent
6363fe7581
commit
e69e13c15d
@ -3,6 +3,7 @@ package org.citra.citra_android.dialogs;
|
|||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Vibrator;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.view.InputDevice;
|
import android.view.InputDevice;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
@ -12,16 +13,19 @@ import org.citra.citra_android.model.settings.view.InputBindingSetting;
|
|||||||
import org.citra.citra_android.utils.ControllerMappingHelper;
|
import org.citra.citra_android.utils.ControllerMappingHelper;
|
||||||
import org.citra.citra_android.utils.Log;
|
import org.citra.citra_android.utils.Log;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link AlertDialog} derivative that listens for
|
* {@link AlertDialog} derivative that listens for
|
||||||
* motion events from controllers and joysticks.
|
* motion events from controllers and joysticks.
|
||||||
*/
|
*/
|
||||||
public final class MotionAlertDialog extends AlertDialog {
|
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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,20 +34,21 @@ public final class MotionAlertDialog extends AlertDialog {
|
|||||||
* @param context The current {@link Context}.
|
* @param context The current {@link Context}.
|
||||||
* @param setting The Preference to show this dialog for.
|
* @param setting The Preference to show this dialog for.
|
||||||
*/
|
*/
|
||||||
public MotionAlertDialog(Context context, InputBindingSetting setting) {
|
public MotionAlertDialog(Context context, InputBindingSetting setting)
|
||||||
|
{
|
||||||
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)
|
||||||
|
{
|
||||||
Log.debug("[MotionAlertDialog] Received key event: " + event.getAction());
|
Log.debug("[MotionAlertDialog] Received key event: " + event.getAction());
|
||||||
switch (event.getAction()) {
|
switch (event.getAction())
|
||||||
case KeyEvent.ACTION_DOWN:
|
{
|
||||||
if (!mControllerMappingHelper.shouldKeyBeIgnored(event.getDevice(), keyCode)) {
|
case KeyEvent.ACTION_UP:
|
||||||
saveKeyInput(event);
|
setting.onKeyInput(event);
|
||||||
}
|
dismiss();
|
||||||
// Even if we ignore the key, we still consume it. Thus return true regardless.
|
// Even if we ignore the key, we still consume it. Thus return true regardless.
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -53,18 +58,27 @@ public final class MotionAlertDialog extends AlertDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
public boolean onKeyLongPress(int keyCode, KeyEvent event)
|
||||||
|
{
|
||||||
|
return super.onKeyLongPress(keyCode, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean dispatchKeyEvent(KeyEvent event)
|
||||||
|
{
|
||||||
// Handle this key if we care about it, otherwise pass it down the framework
|
// Handle this key if we care about it, otherwise pass it down the framework
|
||||||
return onKeyEvent(event.getKeyCode(), event) || super.dispatchKeyEvent(event);
|
return onKeyEvent(event.getKeyCode(), event) || super.dispatchKeyEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean dispatchGenericMotionEvent(MotionEvent event) {
|
public boolean dispatchGenericMotionEvent(MotionEvent event)
|
||||||
|
{
|
||||||
// Handle this event if we care about it, otherwise pass it down the framework
|
// Handle this event if we care about it, otherwise pass it down the framework
|
||||||
return onMotionEvent(event) || super.dispatchGenericMotionEvent(event);
|
return onMotionEvent(event) || super.dispatchGenericMotionEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean onMotionEvent(MotionEvent event) {
|
private boolean onMotionEvent(MotionEvent event)
|
||||||
|
{
|
||||||
if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0)
|
if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0)
|
||||||
return false;
|
return false;
|
||||||
if (event.getAction() != MotionEvent.ACTION_MOVE)
|
if (event.getAction() != MotionEvent.ACTION_MOVE)
|
||||||
@ -74,85 +88,73 @@ 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 (InputDevice.MotionRange range : motionRanges) {
|
for (int i = 0; i < motionRanges.size(); i++)
|
||||||
|
{
|
||||||
|
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 = origValue;//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,
|
{
|
||||||
// shoulder butters are provided as both AXIS_LTRIGGER and AXIS_BRAKE.
|
mPreviousValues.add(value);
|
||||||
// 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
|
else
|
||||||
// where a joystick is moved in two directions.
|
{
|
||||||
// ref: bottom of https://developer.android.com/training/game-controllers/controller-input.html
|
float previousValue = mPreviousValues.get(i);
|
||||||
if (value != axisMoveValue) {
|
|
||||||
axisMoveValue = value;
|
// 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)
|
||||||
|
{
|
||||||
numMovedAxis++;
|
numMovedAxis++;
|
||||||
lastMovedRange = range;
|
lastMovedRange = range;
|
||||||
lastMovedDir = value < 0.0f ? '-' : '+';
|
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.
|
||||||
if (numMovedAxis == 1) {
|
if (numMovedAxis == 1)
|
||||||
|
{
|
||||||
mWaitingForEvent = false;
|
mWaitingForEvent = false;
|
||||||
saveMotionInput(input, lastMovedRange, lastMovedDir);
|
setting.onMotionInput(input, lastMovedRange, lastMovedDir);
|
||||||
|
dismiss();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves the provided key input setting both to the INI file (so native code can use it) and as
|
|
||||||
* an Android preference (so it persists correctly and is human-readable.)
|
|
||||||
*
|
|
||||||
* @param keyEvent KeyEvent of this key press.
|
|
||||||
*/
|
|
||||||
private void saveKeyInput(KeyEvent keyEvent) {
|
|
||||||
InputDevice device = keyEvent.getDevice();
|
|
||||||
String bindStr = "Device '" + device.getDescriptor() + "'-Button " + keyEvent.getKeyCode();
|
|
||||||
String uiString = device.getName() + ": Button " + keyEvent.getKeyCode();
|
|
||||||
|
|
||||||
saveInput(bindStr, uiString);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves the provided motion input setting both to the INI file (so native code can use it) and as
|
|
||||||
* an Android preference (so it persists correctly and is human-readable.)
|
|
||||||
*
|
|
||||||
* @param device InputDevice from which the input event originated.
|
|
||||||
* @param motionRange MotionRange of the movement
|
|
||||||
* @param axisDir Either '-' or '+'
|
|
||||||
*/
|
|
||||||
private void saveMotionInput(InputDevice device, InputDevice.MotionRange motionRange,
|
|
||||||
char axisDir) {
|
|
||||||
String bindStr =
|
|
||||||
"Device '" + device.getDescriptor() + "'-Axis " + motionRange.getAxis() + axisDir;
|
|
||||||
String uiString = device.getName() + ": Axis " + motionRange.getAxis() + axisDir;
|
|
||||||
|
|
||||||
saveInput(bindStr, uiString);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Save the input string to settings and SharedPreferences, then dismiss this Dialog.
|
|
||||||
*/
|
|
||||||
private void saveInput(String bind, String ui) {
|
|
||||||
setting.setValue(bind);
|
|
||||||
|
|
||||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
|
|
||||||
SharedPreferences.Editor editor = preferences.edit();
|
|
||||||
|
|
||||||
editor.putString(setting.getKey(), ui);
|
|
||||||
editor.apply();
|
|
||||||
|
|
||||||
dismiss();
|
|
||||||
}
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user