android: input: Add support for gamepads.
This commit is contained in:
parent
a1f58cb5eb
commit
c8f37a97fd
@ -390,6 +390,7 @@ public final class NativeLibrary {
|
||||
public static final int STICK_C_RIGHT = 772;
|
||||
public static final int TRIGGER_L = 773;
|
||||
public static final int TRIGGER_R = 774;
|
||||
public static final int DPAD = 780;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -32,6 +32,7 @@ import org.citra.citra_android.NativeLibrary;
|
||||
import org.citra.citra_android.R;
|
||||
import org.citra.citra_android.fragments.EmulationFragment;
|
||||
import org.citra.citra_android.fragments.MenuFragment;
|
||||
import org.citra.citra_android.model.settings.view.InputBindingSetting;
|
||||
import org.citra.citra_android.ui.main.MainPresenter;
|
||||
import org.citra.citra_android.utils.Animations;
|
||||
import org.citra.citra_android.utils.ControllerMappingHelper;
|
||||
@ -462,6 +463,7 @@ public final class EmulationActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
int action;
|
||||
int button = mPreferences.getInt(InputBindingSetting.getInputButtonKey(event.getKeyCode()), event.getKeyCode());
|
||||
|
||||
switch (event.getAction()) {
|
||||
case KeyEvent.ACTION_DOWN:
|
||||
@ -481,7 +483,7 @@ public final class EmulationActivity extends AppCompatActivity {
|
||||
return false;
|
||||
}
|
||||
InputDevice input = event.getDevice();
|
||||
return NativeLibrary.onGamePadEvent(input.getDescriptor(), event.getKeyCode(), action);
|
||||
return NativeLibrary.onGamePadEvent(input.getDescriptor(), button, action);
|
||||
}
|
||||
|
||||
private void toggleControls() {
|
||||
@ -586,37 +588,88 @@ public final class EmulationActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
// Don't attempt to do anything if we are disconnecting a device.
|
||||
if (event.getActionMasked() == MotionEvent.ACTION_CANCEL)
|
||||
if (event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
InputDevice input = event.getDevice();
|
||||
List<InputDevice.MotionRange> motions = input.getMotionRanges();
|
||||
|
||||
float[] axisValues = {0.0f, 0.0f};
|
||||
float[] axisValuesCirclePad = {0.0f, 0.0f};
|
||||
float[] axisValuesCStick = {0.0f, 0.0f};
|
||||
float[] axisValuesDPad = {0.0f, 0.0f};
|
||||
boolean isTriggerPressedL = false;
|
||||
boolean isTriggerPressedR = false;
|
||||
boolean isTriggerPressedZL = false;
|
||||
boolean isTriggerPressedZR = false;
|
||||
|
||||
for (InputDevice.MotionRange range : motions) {
|
||||
boolean consumed = false;
|
||||
int axis = range.getAxis();
|
||||
float origValue = event.getAxisValue(axis);
|
||||
float value = mControllerMappingHelper.scaleAxis(input, axis, origValue);
|
||||
int nextMapping = mPreferences.getInt(InputBindingSetting.getInputAxisButtonKey(axis), -1);
|
||||
int guestOrientation = mPreferences.getInt(InputBindingSetting.getInputAxisOrientationKey(axis), -1);
|
||||
|
||||
if (axis == AXIS_X || axis == AXIS_Z) {
|
||||
axisValues[0] = value;
|
||||
} else if (axis == AXIS_Y || axis == AXIS_RZ) {
|
||||
axisValues[1] = value;
|
||||
if (nextMapping == -1 || guestOrientation == -1) {
|
||||
// Axis is unmapped
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the input is still in the "flat" area, that means it's really zero.
|
||||
// This is used to compensate for imprecision in joysticks.
|
||||
if (Math.abs(axisValues[0]) > range.getFlat() || Math.abs(axisValues[1]) > range.getFlat()) {
|
||||
consumed = NativeLibrary.onGamePadMoveEvent(input.getDescriptor(), axis, axisValues[0], axisValues[1]);
|
||||
} else {
|
||||
consumed = NativeLibrary.onGamePadMoveEvent(input.getDescriptor(), axis, 0.0f, 0.0f);
|
||||
if ((value > 0.f && value < 0.1f) || (value < 0.f && value > -0.1f)) {
|
||||
// Skip joystick wobble
|
||||
value = 0.f;
|
||||
}
|
||||
|
||||
return NativeLibrary.onGamePadAxisEvent(input.getDescriptor(), axis, value) || consumed;
|
||||
if (nextMapping == NativeLibrary.ButtonType.STICK_LEFT) {
|
||||
axisValuesCirclePad[guestOrientation] = value;
|
||||
} else if (nextMapping == NativeLibrary.ButtonType.STICK_C) {
|
||||
axisValuesCStick[guestOrientation] = value;
|
||||
} else if (nextMapping == NativeLibrary.ButtonType.DPAD) {
|
||||
axisValuesDPad[guestOrientation] = value;
|
||||
} else if (nextMapping == NativeLibrary.ButtonType.TRIGGER_L && value != 0.f) {
|
||||
isTriggerPressedL = true;
|
||||
} else if (nextMapping == NativeLibrary.ButtonType.TRIGGER_R && value != 0.f) {
|
||||
isTriggerPressedR = true;
|
||||
} else if (nextMapping == NativeLibrary.ButtonType.BUTTON_ZL && value != 0.f) {
|
||||
isTriggerPressedZL = true;
|
||||
} else if (nextMapping == NativeLibrary.ButtonType.BUTTON_ZR && value != 0.f) {
|
||||
isTriggerPressedZR = true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
// Circle-Pad and C-Stick status
|
||||
NativeLibrary.onGamePadMoveEvent(input.getDescriptor(), NativeLibrary.ButtonType.STICK_LEFT, axisValuesCirclePad[0], axisValuesCirclePad[1]);
|
||||
NativeLibrary.onGamePadMoveEvent(input.getDescriptor(), NativeLibrary.ButtonType.STICK_C, axisValuesCStick[0], axisValuesCStick[1]);
|
||||
|
||||
// Triggers L/R and ZL/ZR
|
||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, NativeLibrary.ButtonType.TRIGGER_L, isTriggerPressedL ? NativeLibrary.ButtonState.PRESSED : NativeLibrary.ButtonState.RELEASED);
|
||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, NativeLibrary.ButtonType.TRIGGER_R, isTriggerPressedR ? NativeLibrary.ButtonState.PRESSED : NativeLibrary.ButtonState.RELEASED);
|
||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, NativeLibrary.ButtonType.BUTTON_ZL, isTriggerPressedZL ? NativeLibrary.ButtonState.PRESSED : NativeLibrary.ButtonState.RELEASED);
|
||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, NativeLibrary.ButtonType.BUTTON_ZR, isTriggerPressedZR ? NativeLibrary.ButtonState.PRESSED : NativeLibrary.ButtonState.RELEASED);
|
||||
|
||||
// Work-around to allow D-pad axis to be bound to emulated buttons
|
||||
if (axisValuesDPad[0] == 0.f) {
|
||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, NativeLibrary.ButtonType.DPAD_LEFT, NativeLibrary.ButtonState.RELEASED);
|
||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, NativeLibrary.ButtonType.DPAD_RIGHT, NativeLibrary.ButtonState.RELEASED);
|
||||
} if (axisValuesDPad[0] < 0.f) {
|
||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, NativeLibrary.ButtonType.DPAD_LEFT, NativeLibrary.ButtonState.PRESSED);
|
||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, NativeLibrary.ButtonType.DPAD_RIGHT, NativeLibrary.ButtonState.RELEASED);
|
||||
} if (axisValuesDPad[0] > 0.f) {
|
||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, NativeLibrary.ButtonType.DPAD_LEFT, NativeLibrary.ButtonState.RELEASED);
|
||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, NativeLibrary.ButtonType.DPAD_RIGHT, NativeLibrary.ButtonState.PRESSED);
|
||||
}
|
||||
if (axisValuesDPad[1] == 0.f) {
|
||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, NativeLibrary.ButtonType.DPAD_UP, NativeLibrary.ButtonState.RELEASED);
|
||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, NativeLibrary.ButtonType.DPAD_DOWN, NativeLibrary.ButtonState.RELEASED);
|
||||
} if (axisValuesDPad[1] < 0.f) {
|
||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, NativeLibrary.ButtonType.DPAD_UP, NativeLibrary.ButtonState.PRESSED);
|
||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, NativeLibrary.ButtonType.DPAD_DOWN, NativeLibrary.ButtonState.RELEASED);
|
||||
} if (axisValuesDPad[1] > 0.f) {
|
||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, NativeLibrary.ButtonType.DPAD_UP, NativeLibrary.ButtonState.RELEASED);
|
||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, NativeLibrary.ButtonType.DPAD_DOWN, NativeLibrary.ButtonState.PRESSED);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isActivityRecreated() {
|
||||
|
@ -1,9 +1,21 @@
|
||||
package org.citra.citra_android.model.settings.view;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.InputDevice;
|
||||
import android.view.KeyEvent;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.citra.citra_android.NativeLibrary;
|
||||
import org.citra.citra_android.R;
|
||||
import org.citra.citra_android.DolphinApplication;
|
||||
import org.citra.citra_android.model.settings.Setting;
|
||||
import org.citra.citra_android.model.settings.StringSetting;
|
||||
import org.citra.citra_android.utils.SettingsFile;
|
||||
|
||||
public final class InputBindingSetting extends SettingsItem {
|
||||
private static final String INPUT_MAPPING_PREFIX = "InputMapping";
|
||||
|
||||
public InputBindingSetting(String key, String section, int file, int titleId, Setting setting) {
|
||||
super(key, section, file, setting, titleId, 0);
|
||||
}
|
||||
@ -18,20 +30,355 @@ public final class InputBindingSetting extends SettingsItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a value to the backing string. If that string was previously null,
|
||||
* initializes a new one and returns it, so it can be added to the Hashmap.
|
||||
*
|
||||
* @param bind The input that will be bound
|
||||
* @return null if overwritten successfully; otherwise, a newly created StringSetting.
|
||||
* Returns true if this key is for the 3DS Circle Pad
|
||||
*/
|
||||
public StringSetting setValue(String bind) {
|
||||
private boolean IsCirclePad()
|
||||
{
|
||||
switch (getKey()) {
|
||||
case SettingsFile.KEY_CIRCLEPAD_AXIS_HORIZONTAL:
|
||||
case SettingsFile.KEY_CIRCLEPAD_AXIS_VERTICAL:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this key is for a horizontal axis for a 3DS analog stick or D-pad
|
||||
*/
|
||||
public boolean IsHorizontalOrientation()
|
||||
{
|
||||
switch (getKey()) {
|
||||
case SettingsFile.KEY_CIRCLEPAD_AXIS_HORIZONTAL:
|
||||
case SettingsFile.KEY_CSTICK_AXIS_HORIZONTAL:
|
||||
case SettingsFile.KEY_DPAD_AXIS_HORIZONTAL:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this key is for the 3DS C-Stick
|
||||
*/
|
||||
private boolean IsCStick()
|
||||
{
|
||||
switch (getKey()) {
|
||||
case SettingsFile.KEY_CSTICK_AXIS_HORIZONTAL:
|
||||
case SettingsFile.KEY_CSTICK_AXIS_VERTICAL:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this key is for the 3DS D-Pad
|
||||
*/
|
||||
private boolean IsDPad()
|
||||
{
|
||||
switch (getKey()) {
|
||||
case SettingsFile.KEY_DPAD_AXIS_HORIZONTAL:
|
||||
case SettingsFile.KEY_DPAD_AXIS_VERTICAL:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this key is for the 3DS L/R or ZL/ZR buttons. Note, these are not real
|
||||
* triggers on the 3DS, but we support them as such on a physical gamepad.
|
||||
*/
|
||||
public boolean IsTrigger() {
|
||||
switch (getKey()) {
|
||||
case SettingsFile.KEY_BUTTON_L:
|
||||
case SettingsFile.KEY_BUTTON_R:
|
||||
case SettingsFile.KEY_BUTTON_ZL:
|
||||
case SettingsFile.KEY_BUTTON_ZR:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a gamepad axis can be used to map this key.
|
||||
*/
|
||||
public boolean IsAxisMappingSupported()
|
||||
{
|
||||
return IsCirclePad() || IsCStick() || IsDPad() || IsTrigger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a gamepad button can be used to map this key.
|
||||
*/
|
||||
private boolean IsButtonMappingSupported()
|
||||
{
|
||||
return !IsAxisMappingSupported() || IsTrigger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Citra button code for the settings key.
|
||||
*/
|
||||
private int getButtonCode() {
|
||||
switch (getKey()) {
|
||||
case SettingsFile.KEY_BUTTON_A:
|
||||
return NativeLibrary.ButtonType.BUTTON_A;
|
||||
case SettingsFile.KEY_BUTTON_B:
|
||||
return NativeLibrary.ButtonType.BUTTON_B;
|
||||
case SettingsFile.KEY_BUTTON_X:
|
||||
return NativeLibrary.ButtonType.BUTTON_X;
|
||||
case SettingsFile.KEY_BUTTON_Y:
|
||||
return NativeLibrary.ButtonType.BUTTON_Y;
|
||||
case SettingsFile.KEY_BUTTON_L:
|
||||
return NativeLibrary.ButtonType.TRIGGER_L;
|
||||
case SettingsFile.KEY_BUTTON_R:
|
||||
return NativeLibrary.ButtonType.TRIGGER_R;
|
||||
case SettingsFile.KEY_BUTTON_ZL:
|
||||
return NativeLibrary.ButtonType.BUTTON_ZL;
|
||||
case SettingsFile.KEY_BUTTON_ZR:
|
||||
return NativeLibrary.ButtonType.BUTTON_ZR;
|
||||
case SettingsFile.KEY_BUTTON_SELECT:
|
||||
return NativeLibrary.ButtonType.BUTTON_SELECT;
|
||||
case SettingsFile.KEY_BUTTON_START:
|
||||
return NativeLibrary.ButtonType.BUTTON_START;
|
||||
case SettingsFile.KEY_BUTTON_UP:
|
||||
return NativeLibrary.ButtonType.DPAD_UP;
|
||||
case SettingsFile.KEY_BUTTON_DOWN:
|
||||
return NativeLibrary.ButtonType.DPAD_DOWN;
|
||||
case SettingsFile.KEY_BUTTON_LEFT:
|
||||
return NativeLibrary.ButtonType.DPAD_LEFT;
|
||||
case SettingsFile.KEY_BUTTON_RIGHT:
|
||||
return NativeLibrary.ButtonType.DPAD_RIGHT;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the settings key for the specified Citra button code.
|
||||
*/
|
||||
private static String getButtonKey(int buttonCode) {
|
||||
switch (buttonCode) {
|
||||
case NativeLibrary.ButtonType.BUTTON_A:
|
||||
return SettingsFile.KEY_BUTTON_A;
|
||||
case NativeLibrary.ButtonType.BUTTON_B:
|
||||
return SettingsFile.KEY_BUTTON_B;
|
||||
case NativeLibrary.ButtonType.BUTTON_X:
|
||||
return SettingsFile.KEY_BUTTON_X;
|
||||
case NativeLibrary.ButtonType.BUTTON_Y:
|
||||
return SettingsFile.KEY_BUTTON_Y;
|
||||
case NativeLibrary.ButtonType.TRIGGER_L:
|
||||
return SettingsFile.KEY_BUTTON_L;
|
||||
case NativeLibrary.ButtonType.TRIGGER_R:
|
||||
return SettingsFile.KEY_BUTTON_R;
|
||||
case NativeLibrary.ButtonType.BUTTON_ZL:
|
||||
return SettingsFile.KEY_BUTTON_ZL;
|
||||
case NativeLibrary.ButtonType.BUTTON_ZR:
|
||||
return SettingsFile.KEY_BUTTON_ZR;
|
||||
case NativeLibrary.ButtonType.BUTTON_SELECT:
|
||||
return SettingsFile.KEY_BUTTON_SELECT;
|
||||
case NativeLibrary.ButtonType.BUTTON_START:
|
||||
return SettingsFile.KEY_BUTTON_START;
|
||||
case NativeLibrary.ButtonType.DPAD_UP:
|
||||
return SettingsFile.KEY_BUTTON_UP;
|
||||
case NativeLibrary.ButtonType.DPAD_DOWN:
|
||||
return SettingsFile.KEY_BUTTON_DOWN;
|
||||
case NativeLibrary.ButtonType.DPAD_LEFT:
|
||||
return SettingsFile.KEY_BUTTON_LEFT;
|
||||
case NativeLibrary.ButtonType.DPAD_RIGHT:
|
||||
return SettingsFile.KEY_BUTTON_RIGHT;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key used to lookup the reverse mapping for this key, which is used to cleanup old
|
||||
* settings on re-mapping or clearing of a setting.
|
||||
*/
|
||||
private String getReverseKey() {
|
||||
String reverseKey = INPUT_MAPPING_PREFIX + "_ReverseMapping_" + getKey();
|
||||
|
||||
if (IsAxisMappingSupported() && !IsTrigger()) {
|
||||
// Triggers are the only axis-supported mappings without orientation
|
||||
reverseKey += "_" + (IsHorizontalOrientation() ? 0 : 1);
|
||||
}
|
||||
|
||||
return reverseKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the old mapping for this key from the settings, e.g. on user clearing the setting.
|
||||
*/
|
||||
public void removeOldMapping() {
|
||||
// Get preferences editor
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(DolphinApplication.getAppContext());
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
|
||||
// Try remove all possible keys we wrote for this setting
|
||||
String oldKey = preferences.getString(getReverseKey(), "");
|
||||
if (oldKey != "") {
|
||||
editor.remove(getKey()); // Used for ui text
|
||||
editor.remove(oldKey); // Used for button mapping
|
||||
editor.remove(oldKey + "_GuestOrientation"); // Used for axis orientation
|
||||
editor.remove(oldKey + "_GuestButton"); // Used for axis button
|
||||
}
|
||||
|
||||
// Apply changes
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to get the settings key for an gamepad button.
|
||||
*/
|
||||
public static String getInputButtonKey(int keyCode) {
|
||||
return INPUT_MAPPING_PREFIX + "_Button_" + keyCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to get the settings key for an gamepad axis.
|
||||
*/
|
||||
public static String getInputAxisKey(int axis) {
|
||||
return INPUT_MAPPING_PREFIX + "_HostAxis_" + axis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to get the settings key for an gamepad axis button (stick or trigger).
|
||||
*/
|
||||
public static String getInputAxisButtonKey(int axis) {
|
||||
return getInputAxisKey(axis) + "_GuestButton";
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to get the settings key for an gamepad axis orientation.
|
||||
*/
|
||||
public static String getInputAxisOrientationKey(int axis) {
|
||||
return getInputAxisKey(axis) + "_GuestOrientation";
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to write a gamepad button mapping for the setting.
|
||||
*/
|
||||
private void WriteButtonMapping(String key) {
|
||||
// Get preferences editor
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(DolphinApplication.getAppContext());
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
|
||||
// Remove mapping for another setting using this input
|
||||
int oldButtonCode = preferences.getInt(key, -1);
|
||||
if (oldButtonCode != -1) {
|
||||
String oldKey = getButtonKey(oldButtonCode);
|
||||
editor.remove(oldKey); // Only need to remove UI text setting, others will be overwritten
|
||||
}
|
||||
|
||||
// Cleanup old mapping for this setting
|
||||
removeOldMapping();
|
||||
|
||||
// Write new mapping
|
||||
editor.putInt(key, getButtonCode());
|
||||
|
||||
// Write next reverse mapping for future cleanup
|
||||
editor.putString(getReverseKey(), key);
|
||||
|
||||
// Apply changes
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to write a gamepad axis mapping for the setting.
|
||||
*/
|
||||
private void WriteAxisMapping(int axis, int value) {
|
||||
// Get preferences editor
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(DolphinApplication.getAppContext());
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
|
||||
// Cleanup old mapping
|
||||
removeOldMapping();
|
||||
|
||||
// Write new mapping
|
||||
editor.putInt(getInputAxisOrientationKey(axis), IsHorizontalOrientation() ? 0 : 1);
|
||||
editor.putInt(getInputAxisButtonKey(axis), value);
|
||||
|
||||
// Write next reverse mapping for future cleanup
|
||||
editor.putString(getReverseKey(), getInputAxisKey(axis));
|
||||
|
||||
// Apply changes
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the provided key input setting as an Android preference.
|
||||
*
|
||||
* @param keyEvent KeyEvent of this key press.
|
||||
*/
|
||||
public void onKeyInput(KeyEvent keyEvent)
|
||||
{
|
||||
if (!IsButtonMappingSupported()) {
|
||||
Toast.makeText(DolphinApplication.getAppContext(), R.string.input_message_analog_only, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
InputDevice device = keyEvent.getDevice();
|
||||
|
||||
WriteButtonMapping(getInputButtonKey(keyEvent.getKeyCode()));
|
||||
|
||||
String uiString = device.getName() + ": Button " + keyEvent.getKeyCode();
|
||||
setUiString(uiString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the provided motion input setting as an Android preference.
|
||||
*
|
||||
* @param device InputDevice from which the input event originated.
|
||||
* @param motionRange MotionRange of the movement
|
||||
* @param axisDir Either '-' or '+' (currently unused)
|
||||
*/
|
||||
public void onMotionInput(InputDevice device, InputDevice.MotionRange motionRange,
|
||||
char axisDir)
|
||||
{
|
||||
if (!IsAxisMappingSupported()) {
|
||||
Toast.makeText(DolphinApplication.getAppContext(), R.string.input_message_button_only, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(DolphinApplication.getAppContext());
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
|
||||
int button;
|
||||
if (IsCirclePad()) {
|
||||
button = NativeLibrary.ButtonType.STICK_LEFT;
|
||||
} else if (IsCStick()) {
|
||||
button = NativeLibrary.ButtonType.STICK_C;
|
||||
} else if (IsDPad()){
|
||||
button = NativeLibrary.ButtonType.DPAD;
|
||||
} else {
|
||||
button = getButtonCode();
|
||||
}
|
||||
|
||||
WriteAxisMapping(motionRange.getAxis(), button);
|
||||
|
||||
String uiString = device.getName() + ": Axis " + motionRange.getAxis();
|
||||
setUiString(uiString);
|
||||
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the string to use in the configuration UI for the gamepad input.
|
||||
*/
|
||||
private StringSetting setUiString(String ui) {
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(DolphinApplication.getAppContext());
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
|
||||
if (getSetting() == null) {
|
||||
StringSetting setting = new StringSetting(getKey(), getSection(), getFile(), bind);
|
||||
StringSetting setting = new StringSetting(getKey(), getSection(), getFile(), "");
|
||||
setSetting(setting);
|
||||
|
||||
editor.putString(setting.getKey(), ui);
|
||||
editor.apply();
|
||||
|
||||
return setting;
|
||||
} else {
|
||||
StringSetting setting = (StringSetting) getSetting();
|
||||
setting.setValue(bind);
|
||||
|
||||
editor.putString(setting.getKey(), ui);
|
||||
editor.apply();
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -250,16 +250,22 @@ public final class SettingsAdapter extends RecyclerView.Adapter<SettingViewHolde
|
||||
public void onInputBindingClick(final InputBindingSetting item, final int position) {
|
||||
final MotionAlertDialog dialog = new MotionAlertDialog(mContext, item);
|
||||
dialog.setTitle(R.string.input_binding);
|
||||
dialog.setMessage(String.format(mContext.getString(R.string.input_binding_description), mContext.getString(item.getNameId())));
|
||||
|
||||
int messageResId = R.string.input_binding_description;
|
||||
if (item.IsAxisMappingSupported() && !item.IsTrigger()) {
|
||||
// Use specialized message for axis left/right or up/down
|
||||
if (item.IsHorizontalOrientation()) {
|
||||
messageResId = R.string.input_binding_description_horizontal_axis;
|
||||
} else {
|
||||
messageResId = R.string.input_binding_description_vertical_axis;
|
||||
}
|
||||
}
|
||||
|
||||
dialog.setMessage(String.format(mContext.getString(messageResId), mContext.getString(item.getNameId())));
|
||||
dialog.setButton(AlertDialog.BUTTON_NEGATIVE, mContext.getString(R.string.cancel), this);
|
||||
dialog.setButton(AlertDialog.BUTTON_NEUTRAL, mContext.getString(R.string.clear), (dialogInterface, i) ->
|
||||
{
|
||||
item.setValue("");
|
||||
|
||||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.remove(item.getKey());
|
||||
editor.apply();
|
||||
item.removeOldMapping();
|
||||
});
|
||||
dialog.setOnDismissListener(dialog1 ->
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user