Android: Use input override system for touch controls

This is the first step of getting rid of the controller indirection
on Android. (Needing a way for touch controls to provide input
to the emulator core is the reason why the controller indirection
exists to begin with as far as I understand it.)
This commit is contained in:
JosJuice 2021-04-03 13:49:26 +02:00
parent b296248b49
commit 51ee05cb35
17 changed files with 819 additions and 252 deletions

View File

@ -280,9 +280,6 @@ public final class NativeLibrary
public static native void SetMotionSensorsEnabled(boolean accelerometerEnabled,
boolean gyroscopeEnabled);
// Angle is in radians and should be non-negative
public static native double GetInputRadiusAtAngle(int emu_pad_id, int stick, double angle);
/**
* Gets the Dolphin version string.
*

View File

@ -0,0 +1,84 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.input.model;
public final class InputOverrider
{
public static final class ControlId
{
public static final int GCPAD_A_BUTTON = 0;
public static final int GCPAD_B_BUTTON = 1;
public static final int GCPAD_X_BUTTON = 2;
public static final int GCPAD_Y_BUTTON = 3;
public static final int GCPAD_Z_BUTTON = 4;
public static final int GCPAD_START_BUTTON = 5;
public static final int GCPAD_DPAD_UP = 6;
public static final int GCPAD_DPAD_DOWN = 7;
public static final int GCPAD_DPAD_LEFT = 8;
public static final int GCPAD_DPAD_RIGHT = 9;
public static final int GCPAD_L_DIGITAL = 10;
public static final int GCPAD_R_DIGITAL = 11;
public static final int GCPAD_L_ANALOG = 12;
public static final int GCPAD_R_ANALOG = 13;
public static final int GCPAD_MAIN_STICK_X = 14;
public static final int GCPAD_MAIN_STICK_Y = 15;
public static final int GCPAD_C_STICK_X = 16;
public static final int GCPAD_C_STICK_Y = 17;
public static final int WIIMOTE_A_BUTTON = 18;
public static final int WIIMOTE_B_BUTTON = 19;
public static final int WIIMOTE_ONE_BUTTON = 20;
public static final int WIIMOTE_TWO_BUTTON = 21;
public static final int WIIMOTE_PLUS_BUTTON = 22;
public static final int WIIMOTE_MINUS_BUTTON = 23;
public static final int WIIMOTE_HOME_BUTTON = 24;
public static final int WIIMOTE_DPAD_UP = 25;
public static final int WIIMOTE_DPAD_DOWN = 26;
public static final int WIIMOTE_DPAD_LEFT = 27;
public static final int WIIMOTE_DPAD_RIGHT = 28;
public static final int WIIMOTE_IR_X = 29;
public static final int WIIMOTE_IR_Y = 30;
public static final int NUNCHUK_C_BUTTON = 31;
public static final int NUNCHUK_Z_BUTTON = 32;
public static final int NUNCHUK_STICK_X = 33;
public static final int NUNCHUK_STICK_Y = 34;
public static final int CLASSIC_A_BUTTON = 35;
public static final int CLASSIC_B_BUTTON = 36;
public static final int CLASSIC_X_BUTTON = 37;
public static final int CLASSIC_Y_BUTTON = 38;
public static final int CLASSIC_ZL_BUTTON = 39;
public static final int CLASSIC_ZR_BUTTON = 40;
public static final int CLASSIC_PLUS_BUTTON = 41;
public static final int CLASSIC_MINUS_BUTTON = 42;
public static final int CLASSIC_HOME_BUTTON = 43;
public static final int CLASSIC_DPAD_UP = 44;
public static final int CLASSIC_DPAD_DOWN = 45;
public static final int CLASSIC_DPAD_LEFT = 46;
public static final int CLASSIC_DPAD_RIGHT = 47;
public static final int CLASSIC_L_DIGITAL = 48;
public static final int CLASSIC_R_DIGITAL = 49;
public static final int CLASSIC_L_ANALOG = 50;
public static final int CLASSIC_R_ANALOG = 51;
public static final int CLASSIC_LEFT_STICK_X = 52;
public static final int CLASSIC_LEFT_STICK_Y = 53;
public static final int CLASSIC_RIGHT_STICK_X = 54;
public static final int CLASSIC_RIGHT_STICK_Y = 55;
}
public static native void registerGameCube(int controllerIndex);
public static native void registerWii(int controllerIndex);
public static native void unregisterGameCube(int controllerIndex);
public static native void unregisterWii(int controllerIndex);
public static native void setControlState(int controllerIndex, int control, double state);
public static native void clearControlState(int controllerIndex, int control);
// Angle is in radians and should be non-negative
public static native double getGateRadiusAtAngle(int emuPadId, int stick, double angle);
}

View File

@ -40,8 +40,7 @@ public enum IntSetting implements AbstractIntSetting
InputOverlayPointer.MODE_FOLLOW),
MAIN_DOUBLE_TAP_BUTTON(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
"DoubleTapButton",
InputOverlayPointer.DOUBLE_TAP_OPTIONS.get(InputOverlayPointer.DOUBLE_TAP_A)),
"DoubleTapButton", NativeLibrary.ButtonType.WIIMOTE_BUTTON_A),
SYSCONF_LANGUAGE(Settings.FILE_SYSCONF, "IPL", "LNG", 0x01),
SYSCONF_SOUND_MODE(Settings.FILE_SYSCONF, "IPL", "SND", 0x01),

View File

@ -138,6 +138,15 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
super.onPause();
}
@Override
public void onDestroy()
{
if (mInputOverlay != null)
mInputOverlay.onDestroy();
super.onDestroy();
}
@Override
public void onDetach()
{

View File

@ -26,9 +26,10 @@ import android.view.View.OnTouchListener;
import android.widget.Toast;
import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.NativeLibrary.ButtonState;
import org.dolphinemu.dolphinemu.NativeLibrary.ButtonType;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.features.input.model.InputOverrider;
import org.dolphinemu.dolphinemu.features.input.model.InputOverrider.ControlId;
import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting;
import org.dolphinemu.dolphinemu.features.settings.model.IntSetting;
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
@ -64,6 +65,8 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
private Rect mSurfacePosition = null;
private boolean mIsFirstRun = true;
private boolean mGameCubeRegistered = false;
private boolean mWiiRegistered = false;
private boolean mIsInEditMode = false;
private InputOverlayDrawableButton mButtonBeingConfigured;
private InputOverlayDrawableDpad mDpadBeingConfigured;
@ -158,12 +161,26 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
int doubleTapButton = IntSetting.MAIN_DOUBLE_TAP_BUTTON.getIntGlobal();
if (getConfiguredControllerType() != InputOverlay.OVERLAY_WIIMOTE_CLASSIC &&
doubleTapButton == InputOverlayPointer.DOUBLE_TAP_CLASSIC_A)
doubleTapButton == ButtonType.CLASSIC_BUTTON_A)
{
doubleTapButton = InputOverlayPointer.DOUBLE_TAP_A;
doubleTapButton = ButtonType.WIIMOTE_BUTTON_A;
}
overlayPointer = new InputOverlayPointer(mSurfacePosition, doubleTapButton,
int doubleTapControl = ControlId.WIIMOTE_A_BUTTON;
switch (doubleTapButton)
{
case ButtonType.WIIMOTE_BUTTON_A:
doubleTapControl = ControlId.WIIMOTE_A_BUTTON;
break;
case ButtonType.WIIMOTE_BUTTON_B:
doubleTapControl = ControlId.WIIMOTE_B_BUTTON;
break;
case ButtonType.WIIMOTE_BUTTON_2:
doubleTapControl = ControlId.WIIMOTE_TWO_BUTTON;
break;
}
overlayPointer = new InputOverlayPointer(mSurfacePosition, doubleTapControl,
IntSetting.MAIN_IR_MODE.getIntGlobal(),
BooleanSetting.MAIN_IR_ALWAYS_RECENTER.getBooleanGlobal());
}
@ -218,8 +235,11 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
button.setPressedState(true);
button.setTrackId(event.getPointerId(pointerIndex));
pressed = true;
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.getId(),
ButtonState.PRESSED);
InputOverrider.setControlState(0, button.getControl(), 1.0);
int analogControl = getAnalogControlForTrigger(button.getControl());
if (analogControl >= 0)
InputOverrider.setControlState(0, analogControl, 1.0);
}
break;
case MotionEvent.ACTION_UP:
@ -228,8 +248,12 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
if (button.getTrackId() == event.getPointerId(pointerIndex))
{
button.setPressedState(false);
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.getId(),
ButtonState.RELEASED);
InputOverrider.setControlState(0, button.getControl(), 0.0);
int analogControl = getAnalogControlForTrigger(button.getControl());
if (analogControl >= 0)
InputOverrider.setControlState(0, analogControl, 0.0);
button.setTrackId(-1);
}
break;
@ -270,8 +294,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
{
if (!dpadPressed[i])
{
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(i),
ButtonState.RELEASED);
InputOverrider.setControlState(0, dpad.getControl(i), 0.0);
}
}
// Press buttons
@ -279,8 +302,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
{
if (dpadPressed[i])
{
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(i),
ButtonState.PRESSED);
InputOverrider.setControlState(0, dpad.getControl(i), 1.0);
}
}
setDpadState(dpad, dpadPressed[0], dpadPressed[1], dpadPressed[2], dpadPressed[3]);
@ -294,8 +316,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
for (int i = 0; i < 4; i++)
{
dpad.setState(InputOverlayDrawableDpad.STATE_DEFAULT);
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(i),
ButtonState.RELEASED);
InputOverrider.setControlState(0, dpad.getControl(i), 0.0);
}
dpad.setTrackId(-1);
}
@ -310,27 +331,17 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
if (joystick.getTrackId() != -1)
pressed = true;
}
int[] axisIDs = joystick.getAxisIDs();
float[] axises = joystick.getAxisValues();
for (int i = 0; i < 4; i++)
{
NativeLibrary.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, axisIDs[i], axises[i]);
}
InputOverrider.setControlState(0, joystick.getXControl(), joystick.getX());
InputOverrider.setControlState(0, joystick.getYControl(), -joystick.getY());
}
// No button/joystick pressed, safe to move pointer
if (!pressed && overlayPointer != null)
{
overlayPointer.onTouch(event);
float[] axes = overlayPointer.getAxisValues();
for (int i = 0; i < 4; i++)
{
NativeLibrary
.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, ButtonType.WIIMOTE_IR_UP + i,
axes[i]);
}
InputOverrider.setControlState(0, ControlId.WIIMOTE_IR_X, overlayPointer.getX());
InputOverrider.setControlState(0, ControlId.WIIMOTE_IR_Y, -overlayPointer.getY());
}
invalidate();
@ -381,7 +392,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
if (mButtonBeingConfigured == button)
{
// Persist button position by saving new place.
saveControlPosition(mButtonBeingConfigured.getId(),
saveControlPosition(mButtonBeingConfigured.getLegacyId(),
mButtonBeingConfigured.getBounds().left,
mButtonBeingConfigured.getBounds().top, controller, orientation);
mButtonBeingConfigured = null;
@ -419,7 +430,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
if (mDpadBeingConfigured == dpad)
{
// Persist button position by saving new place.
saveControlPosition(mDpadBeingConfigured.getId(0),
saveControlPosition(mDpadBeingConfigured.getLegacyId(),
mDpadBeingConfigured.getBounds().left, mDpadBeingConfigured.getBounds().top,
controller, orientation);
mDpadBeingConfigured = null;
@ -452,7 +463,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
case MotionEvent.ACTION_POINTER_UP:
if (mJoystickBeingConfigured != null)
{
saveControlPosition(mJoystickBeingConfigured.getId(),
saveControlPosition(mJoystickBeingConfigured.getLegacyId(),
mJoystickBeingConfigured.getBounds().left,
mJoystickBeingConfigured.getBounds().top, controller, orientation);
mJoystickBeingConfigured = null;
@ -464,6 +475,40 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
return true;
}
public void onDestroy()
{
unregisterControllers();
}
private void unregisterControllers()
{
if (mGameCubeRegistered)
InputOverrider.unregisterGameCube(0);
if (mWiiRegistered)
InputOverrider.unregisterWii(0);
mGameCubeRegistered = false;
mWiiRegistered = false;
}
private int getAnalogControlForTrigger(int control)
{
switch (control)
{
case ControlId.GCPAD_L_DIGITAL:
return ControlId.GCPAD_L_ANALOG;
case ControlId.GCPAD_R_DIGITAL:
return ControlId.GCPAD_R_ANALOG;
case ControlId.CLASSIC_L_DIGITAL:
return ControlId.CLASSIC_L_ANALOG;
case ControlId.CLASSIC_R_DIGITAL:
return ControlId.CLASSIC_R_ANALOG;
default:
return -1;
}
}
private void setDpadState(InputOverlayDrawableDpad dpad, boolean up, boolean down, boolean left,
boolean right)
{
@ -500,61 +545,70 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
if (BooleanSetting.MAIN_BUTTON_TOGGLE_GC_0.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_a,
R.drawable.gcpad_a_pressed, ButtonType.BUTTON_A, orientation));
R.drawable.gcpad_a_pressed, ButtonType.BUTTON_A, ControlId.GCPAD_A_BUTTON,
orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_GC_1.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_b,
R.drawable.gcpad_b_pressed, ButtonType.BUTTON_B, orientation));
R.drawable.gcpad_b_pressed, ButtonType.BUTTON_B, ControlId.GCPAD_B_BUTTON,
orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_GC_2.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_x,
R.drawable.gcpad_x_pressed, ButtonType.BUTTON_X, orientation));
R.drawable.gcpad_x_pressed, ButtonType.BUTTON_X, ControlId.GCPAD_X_BUTTON,
orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_GC_3.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_y,
R.drawable.gcpad_y_pressed, ButtonType.BUTTON_Y, orientation));
R.drawable.gcpad_y_pressed, ButtonType.BUTTON_Y, ControlId.GCPAD_Y_BUTTON,
orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_GC_4.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_z,
R.drawable.gcpad_z_pressed, ButtonType.BUTTON_Z, orientation));
R.drawable.gcpad_z_pressed, ButtonType.BUTTON_Z, ControlId.GCPAD_Z_BUTTON,
orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_GC_5.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_start,
R.drawable.gcpad_start_pressed, ButtonType.BUTTON_START, orientation));
R.drawable.gcpad_start_pressed, ButtonType.BUTTON_START, ControlId.GCPAD_START_BUTTON,
orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_GC_6.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_l,
R.drawable.gcpad_l_pressed, ButtonType.TRIGGER_L, orientation));
R.drawable.gcpad_l_pressed, ButtonType.TRIGGER_L, ControlId.GCPAD_L_DIGITAL,
orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_GC_7.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_r,
R.drawable.gcpad_r_pressed, ButtonType.TRIGGER_R, orientation));
R.drawable.gcpad_r_pressed, ButtonType.TRIGGER_R, ControlId.GCPAD_R_DIGITAL,
orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_GC_8.getBooleanGlobal())
{
overlayDpads.add(initializeOverlayDpad(getContext(), R.drawable.gcwii_dpad,
R.drawable.gcwii_dpad_pressed_one_direction,
R.drawable.gcwii_dpad_pressed_two_directions,
ButtonType.BUTTON_UP, ButtonType.BUTTON_DOWN,
ButtonType.BUTTON_LEFT, ButtonType.BUTTON_RIGHT, orientation));
ButtonType.BUTTON_UP, ControlId.GCPAD_DPAD_UP, ControlId.GCPAD_DPAD_DOWN,
ControlId.GCPAD_DPAD_LEFT, ControlId.GCPAD_DPAD_RIGHT, orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_GC_9.getBooleanGlobal())
{
overlayJoysticks.add(initializeOverlayJoystick(getContext(), R.drawable.gcwii_joystick_range,
R.drawable.gcwii_joystick, R.drawable.gcwii_joystick_pressed, ButtonType.STICK_MAIN,
orientation));
ControlId.GCPAD_MAIN_STICK_X, ControlId.GCPAD_MAIN_STICK_Y, orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_GC_10.getBooleanGlobal())
{
overlayJoysticks.add(initializeOverlayJoystick(getContext(), R.drawable.gcwii_joystick_range,
R.drawable.gcpad_c, R.drawable.gcpad_c_pressed, ButtonType.STICK_C, orientation));
R.drawable.gcpad_c, R.drawable.gcpad_c_pressed, ButtonType.STICK_C,
ControlId.GCPAD_C_STICK_X, ControlId.GCPAD_C_STICK_Y, orientation));
}
}
@ -563,45 +617,52 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
if (BooleanSetting.MAIN_BUTTON_TOGGLE_WII_0.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_a,
R.drawable.wiimote_a_pressed, ButtonType.WIIMOTE_BUTTON_A, orientation));
R.drawable.wiimote_a_pressed, ButtonType.WIIMOTE_BUTTON_A, ControlId.WIIMOTE_A_BUTTON,
orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_WII_1.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_b,
R.drawable.wiimote_b_pressed, ButtonType.WIIMOTE_BUTTON_B, orientation));
R.drawable.wiimote_b_pressed, ButtonType.WIIMOTE_BUTTON_B, ControlId.WIIMOTE_B_BUTTON,
orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_WII_2.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_one,
R.drawable.wiimote_one_pressed, ButtonType.WIIMOTE_BUTTON_1, orientation));
R.drawable.wiimote_one_pressed, ButtonType.WIIMOTE_BUTTON_1,
ControlId.WIIMOTE_ONE_BUTTON, orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_WII_3.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_two,
R.drawable.wiimote_two_pressed, ButtonType.WIIMOTE_BUTTON_2, orientation));
R.drawable.wiimote_two_pressed, ButtonType.WIIMOTE_BUTTON_2,
ControlId.WIIMOTE_TWO_BUTTON, orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_WII_4.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_plus,
R.drawable.wiimote_plus_pressed, ButtonType.WIIMOTE_BUTTON_PLUS, orientation));
R.drawable.wiimote_plus_pressed, ButtonType.WIIMOTE_BUTTON_PLUS,
ControlId.WIIMOTE_PLUS_BUTTON, orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_WII_5.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_minus,
R.drawable.wiimote_minus_pressed, ButtonType.WIIMOTE_BUTTON_MINUS, orientation));
R.drawable.wiimote_minus_pressed, ButtonType.WIIMOTE_BUTTON_MINUS,
ControlId.WIIMOTE_MINUS_BUTTON, orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_WII_6.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_home,
R.drawable.wiimote_home_pressed, ButtonType.WIIMOTE_BUTTON_HOME, orientation));
R.drawable.wiimote_home_pressed, ButtonType.WIIMOTE_BUTTON_HOME,
ControlId.WIIMOTE_HOME_BUTTON, orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_WII_7.getBooleanGlobal())
{
overlayDpads.add(initializeOverlayDpad(getContext(), R.drawable.gcwii_dpad,
R.drawable.gcwii_dpad_pressed_one_direction,
R.drawable.gcwii_dpad_pressed_two_directions,
ButtonType.WIIMOTE_UP, ButtonType.WIIMOTE_DOWN,
ButtonType.WIIMOTE_LEFT, ButtonType.WIIMOTE_RIGHT, orientation));
ButtonType.WIIMOTE_UP, ControlId.WIIMOTE_DPAD_UP, ControlId.WIIMOTE_DPAD_DOWN,
ControlId.WIIMOTE_DPAD_LEFT, ControlId.WIIMOTE_DPAD_RIGHT, orientation));
}
}
@ -610,18 +671,21 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
if (BooleanSetting.MAIN_BUTTON_TOGGLE_WII_8.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.nunchuk_c,
R.drawable.nunchuk_c_pressed, ButtonType.NUNCHUK_BUTTON_C, orientation));
R.drawable.nunchuk_c_pressed, ButtonType.NUNCHUK_BUTTON_C, ControlId.NUNCHUK_C_BUTTON,
orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_WII_9.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.nunchuk_z,
R.drawable.nunchuk_z_pressed, ButtonType.NUNCHUK_BUTTON_Z, orientation));
R.drawable.nunchuk_z_pressed, ButtonType.NUNCHUK_BUTTON_Z, ControlId.NUNCHUK_Z_BUTTON,
orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_WII_10.getBooleanGlobal())
{
overlayJoysticks.add(initializeOverlayJoystick(getContext(), R.drawable.gcwii_joystick_range,
R.drawable.gcwii_joystick, R.drawable.gcwii_joystick_pressed,
ButtonType.NUNCHUK_STICK, orientation));
ButtonType.NUNCHUK_STICK, ControlId.NUNCHUK_STICK_X, ControlId.NUNCHUK_STICK_Y,
orientation));
}
}
@ -630,82 +694,97 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
if (BooleanSetting.MAIN_BUTTON_TOGGLE_CLASSIC_0.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_a,
R.drawable.classic_a_pressed, ButtonType.CLASSIC_BUTTON_A, orientation));
R.drawable.classic_a_pressed, ButtonType.CLASSIC_BUTTON_A, ControlId.CLASSIC_A_BUTTON,
orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_CLASSIC_1.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_b,
R.drawable.classic_b_pressed, ButtonType.CLASSIC_BUTTON_B, orientation));
R.drawable.classic_b_pressed, ButtonType.CLASSIC_BUTTON_B, ControlId.CLASSIC_B_BUTTON,
orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_CLASSIC_2.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_x,
R.drawable.classic_x_pressed, ButtonType.CLASSIC_BUTTON_X, orientation));
R.drawable.classic_x_pressed, ButtonType.CLASSIC_BUTTON_X, ControlId.CLASSIC_X_BUTTON,
orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_CLASSIC_3.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_y,
R.drawable.classic_y_pressed, ButtonType.CLASSIC_BUTTON_Y, orientation));
R.drawable.classic_y_pressed, ButtonType.CLASSIC_BUTTON_Y, ControlId.CLASSIC_Y_BUTTON,
orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_CLASSIC_4.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_plus,
R.drawable.wiimote_plus_pressed, ButtonType.CLASSIC_BUTTON_PLUS, orientation));
R.drawable.wiimote_plus_pressed, ButtonType.CLASSIC_BUTTON_PLUS,
ControlId.CLASSIC_PLUS_BUTTON, orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_CLASSIC_5.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_minus,
R.drawable.wiimote_minus_pressed, ButtonType.CLASSIC_BUTTON_MINUS, orientation));
R.drawable.wiimote_minus_pressed, ButtonType.CLASSIC_BUTTON_MINUS,
ControlId.CLASSIC_MINUS_BUTTON, orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_CLASSIC_6.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_home,
R.drawable.wiimote_home_pressed, ButtonType.CLASSIC_BUTTON_HOME, orientation));
R.drawable.wiimote_home_pressed, ButtonType.CLASSIC_BUTTON_HOME,
ControlId.CLASSIC_HOME_BUTTON, orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_CLASSIC_7.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_l,
R.drawable.classic_l_pressed, ButtonType.CLASSIC_TRIGGER_L, orientation));
R.drawable.classic_l_pressed, ButtonType.CLASSIC_TRIGGER_L,
ControlId.CLASSIC_L_DIGITAL, orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_CLASSIC_8.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_r,
R.drawable.classic_r_pressed, ButtonType.CLASSIC_TRIGGER_R, orientation));
R.drawable.classic_r_pressed, ButtonType.CLASSIC_TRIGGER_R,
ControlId.CLASSIC_R_DIGITAL, orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_CLASSIC_9.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_zl,
R.drawable.classic_zl_pressed, ButtonType.CLASSIC_BUTTON_ZL, orientation));
R.drawable.classic_zl_pressed, ButtonType.CLASSIC_BUTTON_ZL,
ControlId.CLASSIC_ZL_BUTTON, orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_CLASSIC_10.getBooleanGlobal())
{
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_zr,
R.drawable.classic_zr_pressed, ButtonType.CLASSIC_BUTTON_ZR, orientation));
R.drawable.classic_zr_pressed, ButtonType.CLASSIC_BUTTON_ZR,
ControlId.CLASSIC_ZR_BUTTON, orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_CLASSIC_11.getBooleanGlobal())
{
overlayDpads.add(initializeOverlayDpad(getContext(), R.drawable.gcwii_dpad,
R.drawable.gcwii_dpad_pressed_one_direction,
R.drawable.gcwii_dpad_pressed_two_directions,
ButtonType.CLASSIC_DPAD_UP, ButtonType.CLASSIC_DPAD_DOWN,
ButtonType.CLASSIC_DPAD_LEFT, ButtonType.CLASSIC_DPAD_RIGHT, orientation));
ButtonType.CLASSIC_DPAD_UP, ControlId.CLASSIC_DPAD_UP, ControlId.CLASSIC_DPAD_DOWN,
ControlId.CLASSIC_DPAD_LEFT, ControlId.CLASSIC_DPAD_RIGHT, orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_CLASSIC_12.getBooleanGlobal())
{
overlayJoysticks.add(initializeOverlayJoystick(getContext(), R.drawable.gcwii_joystick_range,
R.drawable.gcwii_joystick, R.drawable.gcwii_joystick_pressed,
ButtonType.CLASSIC_STICK_LEFT, orientation));
ButtonType.CLASSIC_STICK_LEFT, ControlId.CLASSIC_LEFT_STICK_X,
ControlId.CLASSIC_LEFT_STICK_Y, orientation));
}
if (BooleanSetting.MAIN_BUTTON_TOGGLE_CLASSIC_13.getBooleanGlobal())
{
overlayJoysticks.add(initializeOverlayJoystick(getContext(), R.drawable.gcwii_joystick_range,
R.drawable.gcwii_joystick, R.drawable.gcwii_joystick_pressed,
ButtonType.CLASSIC_STICK_RIGHT, orientation));
ButtonType.CLASSIC_STICK_RIGHT, ControlId.CLASSIC_RIGHT_STICK_X,
ControlId.CLASSIC_RIGHT_STICK_Y, orientation));
}
}
public void refreshControls()
{
unregisterControllers();
// Remove all the overlay buttons from the HashSet.
overlayButtons.removeAll(overlayButtons);
overlayDpads.removeAll(overlayDpads);
@ -734,6 +813,8 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
break;
case EMULATED_GAMECUBE_CONTROLLER:
InputOverrider.registerGameCube(0);
mGameCubeRegistered = true;
addGameCubeOverlayControls(orientation);
break;
@ -746,20 +827,28 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
switch (getConfiguredControllerType())
{
case OVERLAY_GAMECUBE:
InputOverrider.registerGameCube(0);
mGameCubeRegistered = true;
addGameCubeOverlayControls(orientation);
break;
case OVERLAY_WIIMOTE:
case OVERLAY_WIIMOTE_SIDEWAYS:
InputOverrider.registerWii(0);
mWiiRegistered = true;
addWiimoteOverlayControls(orientation);
break;
case OVERLAY_WIIMOTE_NUNCHUK:
InputOverrider.registerWii(0);
mWiiRegistered = true;
addWiimoteOverlayControls(orientation);
addNunchukOverlayControls(orientation);
break;
case OVERLAY_WIIMOTE_CLASSIC:
InputOverrider.registerWii(0);
mWiiRegistered = true;
addClassicOverlayControls(orientation);
break;
@ -768,6 +857,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
}
}
}
mIsFirstRun = false;
invalidate();
}
@ -891,11 +981,12 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
* @param context The current {@link Context}.
* @param defaultResId The resource ID of the {@link Drawable} to get the {@link Bitmap} of (Default State).
* @param pressedResId The resource ID of the {@link Drawable} to get the {@link Bitmap} of (Pressed State).
* @param buttonId Identifier for determining what type of button the initialized InputOverlayDrawableButton represents.
* @param legacyId Legacy identifier for the button the InputOverlayDrawableButton represents.
* @param control Control identifier for the button the InputOverlayDrawableButton represents.
* @return An {@link InputOverlayDrawableButton} with the correct drawing bounds set.
*/
private static InputOverlayDrawableButton initializeOverlayButton(Context context,
int defaultResId, int pressedResId, int buttonId, String orientation)
int defaultResId, int pressedResId, int legacyId, int control, String orientation)
{
// Resources handle for fetching the initial Drawable resource.
final Resources res = context.getResources();
@ -907,7 +998,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
// Decide scale based on button ID and user preference
float scale;
switch (buttonId)
switch (legacyId)
{
case ButtonType.BUTTON_A:
case ButtonType.WIIMOTE_BUTTON_B:
@ -961,12 +1052,13 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
final Bitmap pressedStateBitmap =
resizeBitmap(context, BitmapFactory.decodeResource(res, pressedResId), scale);
final InputOverlayDrawableButton overlayDrawable =
new InputOverlayDrawableButton(res, defaultStateBitmap, pressedStateBitmap, buttonId);
new InputOverlayDrawableButton(res, defaultStateBitmap, pressedStateBitmap, legacyId,
control);
// The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay.
// These were set in the input overlay configuration menu.
int drawableX = (int) sPrefs.getFloat(getXKey(buttonId, controller, orientation), 0f);
int drawableY = (int) sPrefs.getFloat(getYKey(buttonId, controller, orientation), 0f);
int drawableX = (int) sPrefs.getFloat(getXKey(legacyId, controller, orientation), 0f);
int drawableY = (int) sPrefs.getFloat(getYKey(legacyId, controller, orientation), 0f);
int width = overlayDrawable.getWidth();
int height = overlayDrawable.getHeight();
@ -989,20 +1081,22 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
* @param defaultResId The {@link Bitmap} resource ID of the default sate.
* @param pressedOneDirectionResId The {@link Bitmap} resource ID of the pressed sate in one direction.
* @param pressedTwoDirectionsResId The {@link Bitmap} resource ID of the pressed sate in two directions.
* @param buttonUp Identifier for the up button.
* @param buttonDown Identifier for the down button.
* @param buttonLeft Identifier for the left button.
* @param buttonRight Identifier for the right button.
* @param legacyId Legacy identifier for the up button.
* @param upControl Control identifier for the up button.
* @param downControl Control identifier for the down button.
* @param leftControl Control identifier for the left button.
* @param rightControl Control identifier for the right button.
* @return the initialized {@link InputOverlayDrawableDpad}
*/
private static InputOverlayDrawableDpad initializeOverlayDpad(Context context,
int defaultResId,
int pressedOneDirectionResId,
int pressedTwoDirectionsResId,
int buttonUp,
int buttonDown,
int buttonLeft,
int buttonRight,
int legacyId,
int upControl,
int downControl,
int leftControl,
int rightControl,
String orientation)
{
// Resources handle for fetching the initial Drawable resource.
@ -1015,7 +1109,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
// Decide scale based on button ID and user preference
float scale;
switch (buttonUp)
switch (legacyId)
{
case ButtonType.BUTTON_UP:
scale = 0.2375f;
@ -1046,12 +1140,12 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
final InputOverlayDrawableDpad overlayDrawable =
new InputOverlayDrawableDpad(res, defaultStateBitmap,
pressedOneDirectionStateBitmap, pressedTwoDirectionsStateBitmap,
buttonUp, buttonDown, buttonLeft, buttonRight);
legacyId, upControl, downControl, leftControl, rightControl);
// The X and Y coordinates of the InputOverlayDrawableDpad on the InputOverlay.
// These were set in the input overlay configuration menu.
int drawableX = (int) sPrefs.getFloat(getXKey(buttonUp, controller, orientation), 0f);
int drawableY = (int) sPrefs.getFloat(getYKey(buttonUp, controller, orientation), 0f);
int drawableX = (int) sPrefs.getFloat(getXKey(legacyId, controller, orientation), 0f);
int drawableY = (int) sPrefs.getFloat(getYKey(legacyId, controller, orientation), 0f);
int width = overlayDrawable.getWidth();
int height = overlayDrawable.getHeight();
@ -1074,11 +1168,14 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
* @param resOuter Resource ID for the outer image of the joystick (the static image that shows the circular bounds).
* @param defaultResInner Resource ID for the default inner image of the joystick (the one you actually move around).
* @param pressedResInner Resource ID for the pressed inner image of the joystick.
* @param joystick Identifier for which joystick this is.
* @param legacyId Legacy identifier (ButtonType) for which joystick this is.
* @param xControl Control identifier for the X axis.
* @param yControl Control identifier for the Y axis.
* @return the initialized {@link InputOverlayDrawableJoystick}.
*/
private static InputOverlayDrawableJoystick initializeOverlayJoystick(Context context,
int resOuter, int defaultResInner, int pressedResInner, int joystick, String orientation)
int resOuter, int defaultResInner, int pressedResInner, int legacyId, int xControl,
int yControl, String orientation)
{
// Resources handle for fetching the initial Drawable resource.
final Resources res = context.getResources();
@ -1100,13 +1197,13 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
// The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay.
// These were set in the input overlay configuration menu.
int drawableX = (int) sPrefs.getFloat(getXKey(joystick, controller, orientation), 0f);
int drawableY = (int) sPrefs.getFloat(getYKey(joystick, controller, orientation), 0f);
int drawableX = (int) sPrefs.getFloat(getXKey(legacyId, controller, orientation), 0f);
int drawableY = (int) sPrefs.getFloat(getYKey(legacyId, controller, orientation), 0f);
// Decide inner scale based on joystick ID
float innerScale;
if (joystick == ButtonType.STICK_C)
if (legacyId == ButtonType.STICK_C)
{
innerScale = 1.833f;
}
@ -1124,7 +1221,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
// Send the drawableId to the joystick so it can be referenced when saving control position.
final InputOverlayDrawableJoystick overlayDrawable =
new InputOverlayDrawableJoystick(res, bitmapOuter, bitmapInnerDefault,
bitmapInnerPressed, outerRect, innerRect, joystick);
bitmapInnerPressed, outerRect, innerRect, legacyId, xControl, yControl);
// Need to set the image's position
overlayDrawable.setPosition(drawableX, drawableY);

View File

@ -18,8 +18,9 @@ import android.view.MotionEvent;
*/
public final class InputOverlayDrawableButton
{
// The ID identifying what type of button this Drawable represents.
private int mButtonType;
// The legacy ID identifying what type of button this Drawable represents.
private int mLegacyId;
private int mControl;
private int mTrackId;
private int mPreviousTouchX, mPreviousTouchY;
private int mControlPositionX, mControlPositionY;
@ -35,28 +36,33 @@ public final class InputOverlayDrawableButton
* @param res {@link Resources} instance.
* @param defaultStateBitmap {@link Bitmap} to use with the default state Drawable.
* @param pressedStateBitmap {@link Bitmap} to use with the pressed state Drawable.
* @param buttonType Identifier for this type of button.
* @param legacyId Legacy identifier (ButtonType) for this type of button.
* @param control Control ID for this type of button.
*/
public InputOverlayDrawableButton(Resources res, Bitmap defaultStateBitmap,
Bitmap pressedStateBitmap, int buttonType)
Bitmap pressedStateBitmap, int legacyId, int control)
{
mTrackId = -1;
mDefaultStateBitmap = new BitmapDrawable(res, defaultStateBitmap);
mPressedStateBitmap = new BitmapDrawable(res, pressedStateBitmap);
mButtonType = buttonType;
mLegacyId = legacyId;
mControl = control;
mWidth = mDefaultStateBitmap.getIntrinsicWidth();
mHeight = mDefaultStateBitmap.getIntrinsicHeight();
}
/**
* Gets this InputOverlayDrawableButton's button ID.
*
* @return this InputOverlayDrawableButton's button ID.
* Gets this InputOverlayDrawableButton's legacy button ID.
*/
public int getId()
public int getLegacyId()
{
return mButtonType;
return mLegacyId;
}
public int getControl()
{
return mControl;
}
public void setTrackId(int trackId)

View File

@ -18,8 +18,9 @@ import android.view.MotionEvent;
*/
public final class InputOverlayDrawableDpad
{
// The ID identifying what type of button this Drawable represents.
private int[] mButtonType = new int[4];
// The legacy ID identifying what type of button this Drawable represents.
private int mLegacyId;
private int[] mControls = new int[4];
private int mTrackId;
private int mPreviousTouchX, mPreviousTouchY;
private int mControlPositionX, mControlPositionY;
@ -47,17 +48,15 @@ public final class InputOverlayDrawableDpad
* @param defaultStateBitmap {@link Bitmap} of the default state.
* @param pressedOneDirectionStateBitmap {@link Bitmap} of the pressed state in one direction.
* @param pressedTwoDirectionsStateBitmap {@link Bitmap} of the pressed state in two direction.
* @param buttonUp Identifier for the up button.
* @param buttonDown Identifier for the down button.
* @param buttonLeft Identifier for the left button.
* @param buttonRight Identifier for the right button.
* @param legacyId Legacy identifier (ButtonType) for the up button.
* @param upControl Control identifier for the up button.
* @param downControl Control identifier for the down button.
* @param leftControl Control identifier for the left button.
* @param rightControl Control identifier for the right button.
*/
public InputOverlayDrawableDpad(Resources res,
Bitmap defaultStateBitmap,
Bitmap pressedOneDirectionStateBitmap,
Bitmap pressedTwoDirectionsStateBitmap,
int buttonUp, int buttonDown,
int buttonLeft, int buttonRight)
public InputOverlayDrawableDpad(Resources res, Bitmap defaultStateBitmap,
Bitmap pressedOneDirectionStateBitmap, Bitmap pressedTwoDirectionsStateBitmap,
int legacyId, int upControl, int downControl, int leftControl, int rightControl)
{
mTrackId = -1;
mDefaultStateBitmap = new BitmapDrawable(res, defaultStateBitmap);
@ -67,10 +66,11 @@ public final class InputOverlayDrawableDpad
mWidth = mDefaultStateBitmap.getIntrinsicWidth();
mHeight = mDefaultStateBitmap.getIntrinsicHeight();
mButtonType[0] = buttonUp;
mButtonType[1] = buttonDown;
mButtonType[2] = buttonLeft;
mButtonType[3] = buttonRight;
mLegacyId = legacyId;
mControls[0] = upControl;
mControls[1] = downControl;
mControls[2] = leftControl;
mControls[3] = rightControl;
}
public void draw(Canvas canvas)
@ -127,14 +127,17 @@ public final class InputOverlayDrawableDpad
}
}
/**
* Gets one of the InputOverlayDrawableDpad's button IDs.
*
* @return the requested InputOverlayDrawableDpad's button ID.
*/
public int getId(int direction)
public int getLegacyId()
{
return mButtonType[direction];
return mLegacyId;
}
/**
* Gets one of the InputOverlayDrawableDpad's control IDs.
*/
public int getControl(int direction)
{
return mControls[direction];
}
public void setTrackId(int trackId)

View File

@ -12,7 +12,7 @@ import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.view.MotionEvent;
import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.features.input.model.InputOverrider;
import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting;
/**
@ -21,10 +21,12 @@ import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting;
*/
public final class InputOverlayDrawableJoystick
{
private final int[] axisIDs = {0, 0, 0, 0};
private final float[] axises = {0f, 0f};
private float mCurrentX = 0.0f;
private float mCurrentY = 0.0f;
private int trackId = -1;
private final int mJoystickType;
private final int mJoystickLegacyId;
private final int mJoystickXControl;
private final int mJoystickYControl;
private int mControlPositionX, mControlPositionY;
private int mPreviousTouchX, mPreviousTouchY;
private final int mWidth;
@ -47,16 +49,17 @@ public final class InputOverlayDrawableJoystick
* @param bitmapInnerPressed {@link Bitmap} which represents the pressed inner movable part of the joystick.
* @param rectOuter {@link Rect} which represents the outer joystick bounds.
* @param rectInner {@link Rect} which represents the inner joystick bounds.
* @param joystick Identifier for which joystick this is.
* @param legacyId Legacy identifier (ButtonType) for which joystick this is.
* @param xControl The control which the x value of the joystick will be written to.
* @param yControl The control which the y value of the joystick will be written to.
*/
public InputOverlayDrawableJoystick(Resources res, Bitmap bitmapOuter, Bitmap bitmapInnerDefault,
Bitmap bitmapInnerPressed, Rect rectOuter, Rect rectInner, int joystick)
Bitmap bitmapInnerPressed, Rect rectOuter, Rect rectInner, int legacyId, int xControl,
int yControl)
{
axisIDs[0] = joystick + 1;
axisIDs[1] = joystick + 2;
axisIDs[2] = joystick + 3;
axisIDs[3] = joystick + 4;
mJoystickType = joystick;
mJoystickLegacyId = legacyId;
mJoystickXControl = xControl;
mJoystickYControl = yControl;
mOuterBitmap = new BitmapDrawable(res, bitmapOuter);
mDefaultStateInnerBitmap = new BitmapDrawable(res, bitmapInnerDefault);
@ -76,13 +79,13 @@ public final class InputOverlayDrawableJoystick
}
/**
* Gets this InputOverlayDrawableJoystick's button ID.
* Gets this InputOverlayDrawableJoystick's legacy ID.
*
* @return this InputOverlayDrawableJoystick's button ID.
* @return this InputOverlayDrawableJoystick's legacy ID.
*/
public int getId()
public int getLegacyId()
{
return mJoystickType;
return mJoystickLegacyId;
}
public void draw(Canvas canvas)
@ -125,7 +128,7 @@ public final class InputOverlayDrawableJoystick
{
pressed = true;
mPressedState = false;
axises[0] = axises[1] = 0.0f;
mCurrentX = mCurrentY = 0.0f;
mOuterBitmap.setAlpha(mOpacity);
mBoundsBoxBitmap.setAlpha(0);
setVirtBounds(new Rect(mOrigBounds.left, mOrigBounds.top, mOrigBounds.right,
@ -153,10 +156,8 @@ public final class InputOverlayDrawableJoystick
maxX -= getVirtBounds().centerX();
touchY -= getVirtBounds().centerY();
maxY -= getVirtBounds().centerY();
final float AxisX = touchX / maxX;
final float AxisY = touchY / maxY;
axises[0] = AxisY;
axises[1] = AxisX;
mCurrentX = touchX / maxX;
mCurrentY = touchY / maxY;
SetInnerBounds();
}
@ -193,36 +194,40 @@ public final class InputOverlayDrawableJoystick
}
}
public float[] getAxisValues()
public float getX()
{
float[] joyaxises = {0f, 0f, 0f, 0f};
joyaxises[1] = Math.min(axises[0], 1.0f);
joyaxises[0] = Math.min(axises[0], 0.0f);
joyaxises[3] = Math.min(axises[1], 1.0f);
joyaxises[2] = Math.min(axises[1], 0.0f);
return joyaxises;
return mCurrentX;
}
public int[] getAxisIDs()
public float getY()
{
return axisIDs;
return mCurrentY;
}
public int getXControl()
{
return mJoystickXControl;
}
public int getYControl()
{
return mJoystickYControl;
}
private void SetInnerBounds()
{
double y = axises[0];
double x = axises[1];
double x = mCurrentX;
double y = mCurrentY;
double angle = Math.atan2(y, x) + Math.PI + Math.PI;
double radius = Math.hypot(y, x);
double maxRadius = NativeLibrary.GetInputRadiusAtAngle(0, mJoystickType, angle);
double maxRadius = InputOverrider.getGateRadiusAtAngle(0, mJoystickXControl, angle);
if (radius > maxRadius)
{
y = maxRadius * Math.sin(angle);
x = maxRadius * Math.cos(angle);
axises[0] = (float) y;
axises[1] = (float) x;
mCurrentY = (float) y;
mCurrentX = (float) x;
}
int pixelX = getVirtBounds().centerX() + (int) (x * (getVirtBounds().width() / 2));

View File

@ -7,22 +7,20 @@ import android.os.Handler;
import android.view.MotionEvent;
import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.features.input.model.InputOverrider;
import java.util.ArrayList;
public class InputOverlayPointer
{
public static final int DOUBLE_TAP_A = 0;
public static final int DOUBLE_TAP_B = 1;
public static final int DOUBLE_TAP_2 = 2;
public static final int DOUBLE_TAP_CLASSIC_A = 3;
public static final int MODE_DISABLED = 0;
public static final int MODE_FOLLOW = 1;
public static final int MODE_DRAG = 2;
private final float[] axes = {0f, 0f};
private final float[] oldaxes = {0f, 0f};
private float mCurrentX = 0.0f;
private float mCurrentY = 0.0f;
private float mOldX = 0.0f;
private float mOldY = 0.0f;
private float mGameCenterX;
private float mGameCenterY;
@ -36,7 +34,7 @@ public class InputOverlayPointer
private boolean mRecenter;
private boolean doubleTap = false;
private int doubleTapButton;
private int mDoubleTapControl;
private int trackId = -1;
public static ArrayList<Integer> DOUBLE_TAP_OPTIONS = new ArrayList<>();
@ -49,9 +47,9 @@ public class InputOverlayPointer
DOUBLE_TAP_OPTIONS.add(NativeLibrary.ButtonType.CLASSIC_BUTTON_A);
}
public InputOverlayPointer(Rect surfacePosition, int button, int mode, boolean recenter)
public InputOverlayPointer(Rect surfacePosition, int doubleTapControl, int mode, boolean recenter)
{
doubleTapButton = button;
mDoubleTapControl = doubleTapControl;
mMode = mode;
mRecenter = recenter;
@ -112,15 +110,15 @@ public class InputOverlayPointer
if (mMode == MODE_FOLLOW)
{
axes[0] = (event.getY(event.findPointerIndex(trackId)) - mGameCenterY) * mGameHeightHalfInv;
axes[1] = (event.getX(event.findPointerIndex(trackId)) - mGameCenterX) * mGameWidthHalfInv;
mCurrentX = (event.getX(event.findPointerIndex(trackId)) - mGameCenterX) * mGameWidthHalfInv;
mCurrentY = (event.getY(event.findPointerIndex(trackId)) - mGameCenterY) * mGameHeightHalfInv;
}
else if (mMode == MODE_DRAG)
{
axes[0] = oldaxes[0] +
(event.getY(event.findPointerIndex(trackId)) - mTouchStartY) * mGameHeightHalfInv;
axes[1] = oldaxes[1] +
mCurrentX = mOldX +
(event.getX(event.findPointerIndex(trackId)) - mTouchStartX) * mGameWidthHalfInv;
mCurrentY = mOldY +
(event.getY(event.findPointerIndex(trackId)) - mTouchStartY) * mGameHeightHalfInv;
}
}
@ -130,11 +128,9 @@ public class InputOverlayPointer
{
if (doubleTap)
{
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice,
doubleTapButton, NativeLibrary.ButtonState.PRESSED);
new Handler()
.postDelayed(() -> NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice,
doubleTapButton, NativeLibrary.ButtonState.RELEASED), 50);
InputOverrider.setControlState(0, mDoubleTapControl, 1.0);
new Handler().postDelayed(() -> InputOverrider.setControlState(0, mDoubleTapControl, 0.0),
50);
}
else
{
@ -146,23 +142,23 @@ public class InputOverlayPointer
private void updateOldAxes()
{
oldaxes[0] = axes[0];
oldaxes[1] = axes[1];
mOldX = mCurrentX;
mOldY = mCurrentY;
}
private void reset()
{
axes[0] = axes[1] = oldaxes[0] = oldaxes[1] = 0f;
mCurrentX = mCurrentY = mOldX = mOldY = 0.0f;
}
public float[] getAxisValues()
public float getX()
{
float[] iraxes = {0f, 0f, 0f, 0f};
iraxes[1] = axes[0];
iraxes[0] = axes[0];
iraxes[3] = axes[1];
iraxes[2] = axes[1];
return iraxes;
return mCurrentX;
}
public float getY()
{
return mCurrentY;
}
public void setMode(int mode)

View File

@ -10,6 +10,7 @@ add_library(main SHARED
GameList/GameFile.cpp
GameList/GameFile.h
GameList/GameFileCache.cpp
Input/InputOverrider.cpp
IniFile.cpp
MainAndroid.cpp
RiivolutionPatches.cpp

View File

@ -0,0 +1,62 @@
// Copyright 2021 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <jni.h>
#include "InputCommon/ControllerInterface/Touch/InputOverrider.h"
extern "C" {
JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_features_input_model_InputOverrider_registerGameCube(
JNIEnv*, jclass, int controller_index)
{
ciface::Touch::RegisterGameCubeInputOverrider(controller_index);
}
JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_features_input_model_InputOverrider_registerWii(JNIEnv*, jclass,
int controller_index)
{
ciface::Touch::RegisterWiiInputOverrider(controller_index);
}
JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_features_input_model_InputOverrider_unregisterGameCube(
JNIEnv*, jclass, int controller_index)
{
ciface::Touch::UnregisterGameCubeInputOverrider(controller_index);
}
JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_features_input_model_InputOverrider_unregisterWii(
JNIEnv*, jclass, int controller_index)
{
ciface::Touch::UnregisterWiiInputOverrider(controller_index);
}
JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_features_input_model_InputOverrider_setControlState(
JNIEnv*, jclass, int controller_index, int control, double state)
{
ciface::Touch::SetControlState(controller_index, static_cast<ciface::Touch::ControlID>(control),
state);
}
JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_features_input_model_InputOverrider_clearControlState(
JNIEnv*, jclass, int controller_index, int control)
{
ciface::Touch::ClearControlState(controller_index,
static_cast<ciface::Touch::ControlID>(control));
}
JNIEXPORT double JNICALL
Java_org_dolphinemu_dolphinemu_features_input_model_InputOverrider_getGateRadiusAtAngle(
JNIEnv*, jclass, int controller_index, int stick, double angle)
{
const auto casted_stick = static_cast<ciface::Touch::ControlID>(stick);
return ciface::Touch::GetGateRadiusAtAngle(controller_index, casted_stick, angle);
}
};

View File

@ -302,13 +302,6 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetMotionSen
ciface::Android::SetMotionSensorsEnabled(accelerometer_enabled, gyroscope_enabled);
}
JNIEXPORT double JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetInputRadiusAtAngle(
JNIEnv*, jclass, int emu_pad_id, int stick, double angle)
{
const auto casted_stick = static_cast<ButtonManager::ButtonType>(stick);
return ButtonManager::GetInputRadiusAtAngle(emu_pad_id, casted_stick, angle);
}
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetVersionString(JNIEnv* env,
jclass)
{

View File

@ -140,6 +140,8 @@ elseif(ANDROID)
ControllerInterface/Android/Android.h
ControllerInterface/Touch/ButtonManager.cpp
ControllerInterface/Touch/ButtonManager.h
ControllerInterface/Touch/InputOverrider.cpp
ControllerInterface/Touch/InputOverrider.h
ControllerInterface/Touch/Touchscreen.cpp
ControllerInterface/Touch/Touchscreen.h
)

View File

@ -9,23 +9,11 @@
#include <unordered_map>
#include <vector>
#include "Common/Assert.h"
#include "Common/FileUtil.h"
#include "Common/IniFile.h"
#include "Common/StringUtil.h"
#include "Common/Thread.h"
#include "Core/Core.h"
#include "Core/HW/GCPad.h"
#include "Core/HW/GCPadEmu.h"
#include "Core/HW/Wiimote.h"
#include "Core/HW/WiimoteEmu/Extension/Classic.h"
#include "Core/HW/WiimoteEmu/Extension/Nunchuk.h"
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h"
#include "InputCommon/ControllerEmu/StickGate.h"
namespace ButtonManager
{
namespace
@ -700,39 +688,6 @@ float GetAxisValue(int pad_id, ButtonType axis)
return value;
}
double GetInputRadiusAtAngle(int pad_id, ButtonType stick, double angle)
{
// To avoid a crash, don't access controllers before they've been initialized by the boot process
if (!Core::IsRunningAndStarted())
return 0;
ControllerEmu::ControlGroup* group;
switch (stick)
{
case STICK_MAIN:
group = Pad::GetGroup(pad_id, PadGroup::MainStick);
break;
case STICK_C:
group = Pad::GetGroup(pad_id, PadGroup::CStick);
break;
case NUNCHUK_STICK:
group = Wiimote::GetNunchukGroup(pad_id, WiimoteEmu::NunchukGroup::Stick);
break;
case CLASSIC_STICK_LEFT:
group = Wiimote::GetClassicGroup(pad_id, WiimoteEmu::ClassicGroup::LeftStick);
break;
case CLASSIC_STICK_RIGHT:
group = Wiimote::GetClassicGroup(pad_id, WiimoteEmu::ClassicGroup::RightStick);
break;
default:
ASSERT(false);
return 0;
}
return static_cast<ControllerEmu::ReshapableInput*>(group)->GetInputRadiusAtAngle(angle);
}
bool GamepadEvent(const std::string& dev, int button, int action)
{
auto it = m_controllers.find(dev);

View File

@ -272,9 +272,6 @@ void Init(const std::string&);
bool GetButtonPressed(int pad_id, ButtonType button);
float GetAxisValue(int pad_id, ButtonType axis);
// emu_pad_id is numbered 0 to 3 for both GC pads and Wiimotes
double GetInputRadiusAtAngle(int emu_pad_id, ButtonType stick, double angle);
bool GamepadEvent(const std::string& dev, int button, int action);
void GamepadAxisEvent(const std::string& dev, int axis, float value);

View File

@ -0,0 +1,272 @@
// Copyright 2021 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "InputCommon/ControllerInterface/Touch/InputOverrider.h"
#include <array>
#include <map>
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include "Common/Assert.h"
#include "Core/HW/GCPad.h"
#include "Core/HW/GCPadEmu.h"
#include "Core/HW/Wiimote.h"
#include "Core/HW/WiimoteEmu/Extension/Classic.h"
#include "Core/HW/WiimoteEmu/Extension/Nunchuk.h"
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
#include "InputCommon/ControllerEmu/ControlGroup/Attachments.h"
#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h"
#include "InputCommon/ControllerEmu/ControllerEmu.h"
#include "InputCommon/ControllerEmu/StickGate.h"
#include "InputCommon/ControllerInterface/CoreDevice.h"
#include "InputCommon/InputConfig.h"
namespace ciface::Touch
{
namespace
{
struct InputState
{
ControlState normal_state = 0;
ControlState override_state = 0;
bool overriding = false;
};
using ControlsMap = std::map<std::pair<std::string_view, std::string_view>, ControlID>;
using StateArray = std::array<InputState, ControlID::NUMBER_OF_CONTROLS>;
std::array<StateArray, 4> s_state_arrays;
const ControlsMap s_gcpad_controls_map = {{
{{GCPad::BUTTONS_GROUP, GCPad::A_BUTTON}, ControlID::GCPAD_A_BUTTON},
{{GCPad::BUTTONS_GROUP, GCPad::B_BUTTON}, ControlID::GCPAD_B_BUTTON},
{{GCPad::BUTTONS_GROUP, GCPad::X_BUTTON}, ControlID::GCPAD_X_BUTTON},
{{GCPad::BUTTONS_GROUP, GCPad::Y_BUTTON}, ControlID::GCPAD_Y_BUTTON},
{{GCPad::BUTTONS_GROUP, GCPad::Z_BUTTON}, ControlID::GCPAD_Z_BUTTON},
{{GCPad::BUTTONS_GROUP, GCPad::START_BUTTON}, ControlID::GCPAD_START_BUTTON},
{{GCPad::DPAD_GROUP, DIRECTION_UP}, ControlID::GCPAD_DPAD_UP},
{{GCPad::DPAD_GROUP, DIRECTION_DOWN}, ControlID::GCPAD_DPAD_DOWN},
{{GCPad::DPAD_GROUP, DIRECTION_LEFT}, ControlID::GCPAD_DPAD_LEFT},
{{GCPad::DPAD_GROUP, DIRECTION_RIGHT}, ControlID::GCPAD_DPAD_RIGHT},
{{GCPad::TRIGGERS_GROUP, GCPad::L_DIGITAL}, ControlID::GCPAD_L_DIGITAL},
{{GCPad::TRIGGERS_GROUP, GCPad::R_DIGITAL}, ControlID::GCPAD_R_DIGITAL},
{{GCPad::TRIGGERS_GROUP, GCPad::L_ANALOG}, ControlID::GCPAD_L_ANALOG},
{{GCPad::TRIGGERS_GROUP, GCPad::R_ANALOG}, ControlID::GCPAD_R_ANALOG},
{{GCPad::MAIN_STICK_GROUP, ControllerEmu::ReshapableInput::X_INPUT_OVERRIDE},
ControlID::GCPAD_MAIN_STICK_X},
{{GCPad::MAIN_STICK_GROUP, ControllerEmu::ReshapableInput::Y_INPUT_OVERRIDE},
ControlID::GCPAD_MAIN_STICK_Y},
{{GCPad::C_STICK_GROUP, ControllerEmu::ReshapableInput::X_INPUT_OVERRIDE},
ControlID::GCPAD_C_STICK_X},
{{GCPad::C_STICK_GROUP, ControllerEmu::ReshapableInput::Y_INPUT_OVERRIDE},
ControlID::GCPAD_C_STICK_Y},
}};
const ControlsMap s_wiimote_controls_map = {{
{{WiimoteEmu::Wiimote::BUTTONS_GROUP, WiimoteEmu::Wiimote::A_BUTTON},
ControlID::WIIMOTE_A_BUTTON},
{{WiimoteEmu::Wiimote::BUTTONS_GROUP, WiimoteEmu::Wiimote::B_BUTTON},
ControlID::WIIMOTE_B_BUTTON},
{{WiimoteEmu::Wiimote::BUTTONS_GROUP, WiimoteEmu::Wiimote::ONE_BUTTON},
ControlID::WIIMOTE_ONE_BUTTON},
{{WiimoteEmu::Wiimote::BUTTONS_GROUP, WiimoteEmu::Wiimote::TWO_BUTTON},
ControlID::WIIMOTE_TWO_BUTTON},
{{WiimoteEmu::Wiimote::BUTTONS_GROUP, WiimoteEmu::Wiimote::PLUS_BUTTON},
ControlID::WIIMOTE_PLUS_BUTTON},
{{WiimoteEmu::Wiimote::BUTTONS_GROUP, WiimoteEmu::Wiimote::MINUS_BUTTON},
ControlID::WIIMOTE_MINUS_BUTTON},
{{WiimoteEmu::Wiimote::BUTTONS_GROUP, WiimoteEmu::Wiimote::HOME_BUTTON},
ControlID::WIIMOTE_HOME_BUTTON},
{{WiimoteEmu::Wiimote::DPAD_GROUP, DIRECTION_UP}, ControlID::WIIMOTE_DPAD_UP},
{{WiimoteEmu::Wiimote::DPAD_GROUP, DIRECTION_DOWN}, ControlID::WIIMOTE_DPAD_DOWN},
{{WiimoteEmu::Wiimote::DPAD_GROUP, DIRECTION_LEFT}, ControlID::WIIMOTE_DPAD_LEFT},
{{WiimoteEmu::Wiimote::DPAD_GROUP, DIRECTION_RIGHT}, ControlID::WIIMOTE_DPAD_RIGHT},
{{WiimoteEmu::Wiimote::IR_GROUP, ControllerEmu::ReshapableInput::X_INPUT_OVERRIDE},
ControlID::WIIMOTE_IR_X},
{{WiimoteEmu::Wiimote::IR_GROUP, ControllerEmu::ReshapableInput::Y_INPUT_OVERRIDE},
ControlID::WIIMOTE_IR_Y},
}};
const ControlsMap s_nunchuk_controls_map = {{
{{WiimoteEmu::Nunchuk::BUTTONS_GROUP, WiimoteEmu::Nunchuk::C_BUTTON},
ControlID::NUNCHUK_C_BUTTON},
{{WiimoteEmu::Nunchuk::BUTTONS_GROUP, WiimoteEmu::Nunchuk::Z_BUTTON},
ControlID::NUNCHUK_Z_BUTTON},
{{WiimoteEmu::Nunchuk::STICK_GROUP, ControllerEmu::ReshapableInput::X_INPUT_OVERRIDE},
ControlID::NUNCHUK_STICK_X},
{{WiimoteEmu::Nunchuk::STICK_GROUP, ControllerEmu::ReshapableInput::Y_INPUT_OVERRIDE},
ControlID::NUNCHUK_STICK_Y},
}};
const ControlsMap s_classic_controls_map = {{
{{WiimoteEmu::Classic::BUTTONS_GROUP, WiimoteEmu::Classic::A_BUTTON},
ControlID::CLASSIC_A_BUTTON},
{{WiimoteEmu::Classic::BUTTONS_GROUP, WiimoteEmu::Classic::B_BUTTON},
ControlID::CLASSIC_B_BUTTON},
{{WiimoteEmu::Classic::BUTTONS_GROUP, WiimoteEmu::Classic::X_BUTTON},
ControlID::CLASSIC_X_BUTTON},
{{WiimoteEmu::Classic::BUTTONS_GROUP, WiimoteEmu::Classic::Y_BUTTON},
ControlID::CLASSIC_Y_BUTTON},
{{WiimoteEmu::Classic::BUTTONS_GROUP, WiimoteEmu::Classic::ZL_BUTTON},
ControlID::CLASSIC_ZL_BUTTON},
{{WiimoteEmu::Classic::BUTTONS_GROUP, WiimoteEmu::Classic::ZR_BUTTON},
ControlID::CLASSIC_ZR_BUTTON},
{{WiimoteEmu::Classic::BUTTONS_GROUP, WiimoteEmu::Classic::PLUS_BUTTON},
ControlID::CLASSIC_PLUS_BUTTON},
{{WiimoteEmu::Classic::BUTTONS_GROUP, WiimoteEmu::Classic::MINUS_BUTTON},
ControlID::CLASSIC_MINUS_BUTTON},
{{WiimoteEmu::Classic::BUTTONS_GROUP, WiimoteEmu::Classic::HOME_BUTTON},
ControlID::CLASSIC_HOME_BUTTON},
{{WiimoteEmu::Classic::DPAD_GROUP, DIRECTION_UP}, ControlID::CLASSIC_DPAD_UP},
{{WiimoteEmu::Classic::DPAD_GROUP, DIRECTION_DOWN}, ControlID::CLASSIC_DPAD_DOWN},
{{WiimoteEmu::Classic::DPAD_GROUP, DIRECTION_LEFT}, ControlID::CLASSIC_DPAD_LEFT},
{{WiimoteEmu::Classic::DPAD_GROUP, DIRECTION_RIGHT}, ControlID::CLASSIC_DPAD_RIGHT},
{{WiimoteEmu::Classic::TRIGGERS_GROUP, WiimoteEmu::Classic::L_DIGITAL},
ControlID::CLASSIC_L_DIGITAL},
{{WiimoteEmu::Classic::TRIGGERS_GROUP, WiimoteEmu::Classic::R_DIGITAL},
ControlID::CLASSIC_R_DIGITAL},
{{WiimoteEmu::Classic::TRIGGERS_GROUP, WiimoteEmu::Classic::L_ANALOG},
ControlID::CLASSIC_L_ANALOG},
{{WiimoteEmu::Classic::TRIGGERS_GROUP, WiimoteEmu::Classic::R_ANALOG},
ControlID::CLASSIC_R_ANALOG},
{{WiimoteEmu::Classic::LEFT_STICK_GROUP, ControllerEmu::ReshapableInput::X_INPUT_OVERRIDE},
ControlID::CLASSIC_LEFT_STICK_X},
{{WiimoteEmu::Classic::LEFT_STICK_GROUP, ControllerEmu::ReshapableInput::Y_INPUT_OVERRIDE},
ControlID::CLASSIC_LEFT_STICK_Y},
{{WiimoteEmu::Classic::RIGHT_STICK_GROUP, ControllerEmu::ReshapableInput::X_INPUT_OVERRIDE},
ControlID::CLASSIC_RIGHT_STICK_X},
{{WiimoteEmu::Classic::RIGHT_STICK_GROUP, ControllerEmu::ReshapableInput::Y_INPUT_OVERRIDE},
ControlID::CLASSIC_RIGHT_STICK_Y},
}};
ControllerEmu::InputOverrideFunction GetInputOverrideFunction(const ControlsMap& controls_map,
size_t i)
{
StateArray& state_array = s_state_arrays[i];
return [&](std::string_view group_name, std::string_view control_name,
ControlState controller_state) -> std::optional<ControlState> {
const auto it = controls_map.find(std::make_pair(group_name, control_name));
if (it == controls_map.end())
return std::nullopt;
const ControlID control = it->second;
InputState& input_state = state_array[control];
if (input_state.normal_state != controller_state)
{
input_state.normal_state = controller_state;
input_state.overriding = false;
}
return input_state.overriding ? std::make_optional(input_state.override_state) : std::nullopt;
};
}
} // namespace
void RegisterGameCubeInputOverrider(int controller_index)
{
Pad::GetConfig()
->GetController(controller_index)
->SetInputOverrideFunction(GetInputOverrideFunction(s_gcpad_controls_map, controller_index));
}
void RegisterWiiInputOverrider(int controller_index)
{
auto* wiimote =
static_cast<WiimoteEmu::Wiimote*>(Wiimote::GetConfig()->GetController(controller_index));
wiimote->SetInputOverrideFunction(
GetInputOverrideFunction(s_wiimote_controls_map, controller_index));
auto& attachments = static_cast<ControllerEmu::Attachments*>(
wiimote->GetWiimoteGroup(WiimoteEmu::WiimoteGroup::Attachments))
->GetAttachmentList();
attachments[WiimoteEmu::ExtensionNumber::NUNCHUK]->SetInputOverrideFunction(
GetInputOverrideFunction(s_nunchuk_controls_map, controller_index));
attachments[WiimoteEmu::ExtensionNumber::CLASSIC]->SetInputOverrideFunction(
GetInputOverrideFunction(s_classic_controls_map, controller_index));
}
void UnregisterGameCubeInputOverrider(int controller_index)
{
Pad::GetConfig()->GetController(controller_index)->ClearInputOverrideFunction();
for (size_t i = ControlID::FIRST_GC_CONTROL; i <= ControlID::LAST_GC_CONTROL; ++i)
s_state_arrays[controller_index][i].overriding = false;
}
void UnregisterWiiInputOverrider(int controller_index)
{
auto* wiimote =
static_cast<WiimoteEmu::Wiimote*>(Wiimote::GetConfig()->GetController(controller_index));
wiimote->ClearInputOverrideFunction();
auto& attachments = static_cast<ControllerEmu::Attachments*>(
wiimote->GetWiimoteGroup(WiimoteEmu::WiimoteGroup::Attachments))
->GetAttachmentList();
attachments[WiimoteEmu::ExtensionNumber::NUNCHUK]->ClearInputOverrideFunction();
attachments[WiimoteEmu::ExtensionNumber::CLASSIC]->ClearInputOverrideFunction();
for (size_t i = ControlID::FIRST_WII_CONTROL; i <= ControlID::LAST_WII_CONTROL; ++i)
s_state_arrays[controller_index][i].overriding = false;
}
void SetControlState(int controller_index, ControlID control, double state)
{
InputState& input_state = s_state_arrays[controller_index][control];
input_state.override_state = state;
input_state.overriding = true;
}
void ClearControlState(int controller_index, ControlID control)
{
InputState& input_state = s_state_arrays[controller_index][control];
input_state.overriding = false;
}
double GetGateRadiusAtAngle(int controller_index, ControlID stick, double angle)
{
ControllerEmu::ControlGroup* group;
switch (stick)
{
case ControlID::GCPAD_MAIN_STICK_X:
case ControlID::GCPAD_MAIN_STICK_Y:
group = Pad::GetGroup(controller_index, PadGroup::MainStick);
break;
case ControlID::GCPAD_C_STICK_X:
case ControlID::GCPAD_C_STICK_Y:
group = Pad::GetGroup(controller_index, PadGroup::CStick);
break;
case ControlID::NUNCHUK_STICK_X:
case ControlID::NUNCHUK_STICK_Y:
group = Wiimote::GetNunchukGroup(controller_index, WiimoteEmu::NunchukGroup::Stick);
break;
case ControlID::CLASSIC_LEFT_STICK_X:
case ControlID::CLASSIC_LEFT_STICK_Y:
group = Wiimote::GetClassicGroup(controller_index, WiimoteEmu::ClassicGroup::LeftStick);
break;
case ControlID::CLASSIC_RIGHT_STICK_X:
case ControlID::CLASSIC_RIGHT_STICK_Y:
group = Wiimote::GetClassicGroup(controller_index, WiimoteEmu::ClassicGroup::RightStick);
break;
default:
ASSERT(false);
return 0;
}
return static_cast<ControllerEmu::ReshapableInput*>(group)->GetGateRadiusAtAngle(angle);
}
} // namespace ciface::Touch

View File

@ -0,0 +1,89 @@
// Copyright 2021 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
namespace ciface::Touch
{
enum ControlID
{
GCPAD_A_BUTTON = 0,
GCPAD_B_BUTTON = 1,
GCPAD_X_BUTTON = 2,
GCPAD_Y_BUTTON = 3,
GCPAD_Z_BUTTON = 4,
GCPAD_START_BUTTON = 5,
GCPAD_DPAD_UP = 6,
GCPAD_DPAD_DOWN = 7,
GCPAD_DPAD_LEFT = 8,
GCPAD_DPAD_RIGHT = 9,
GCPAD_L_DIGITAL = 10,
GCPAD_R_DIGITAL = 11,
GCPAD_L_ANALOG = 12,
GCPAD_R_ANALOG = 13,
GCPAD_MAIN_STICK_X = 14,
GCPAD_MAIN_STICK_Y = 15,
GCPAD_C_STICK_X = 16,
GCPAD_C_STICK_Y = 17,
WIIMOTE_A_BUTTON = 18,
WIIMOTE_B_BUTTON = 19,
WIIMOTE_ONE_BUTTON = 20,
WIIMOTE_TWO_BUTTON = 21,
WIIMOTE_PLUS_BUTTON = 22,
WIIMOTE_MINUS_BUTTON = 23,
WIIMOTE_HOME_BUTTON = 24,
WIIMOTE_DPAD_UP = 25,
WIIMOTE_DPAD_DOWN = 26,
WIIMOTE_DPAD_LEFT = 27,
WIIMOTE_DPAD_RIGHT = 28,
WIIMOTE_IR_X = 29,
WIIMOTE_IR_Y = 30,
NUNCHUK_C_BUTTON = 31,
NUNCHUK_Z_BUTTON = 32,
NUNCHUK_STICK_X = 33,
NUNCHUK_STICK_Y = 34,
CLASSIC_A_BUTTON = 35,
CLASSIC_B_BUTTON = 36,
CLASSIC_X_BUTTON = 37,
CLASSIC_Y_BUTTON = 38,
CLASSIC_ZL_BUTTON = 39,
CLASSIC_ZR_BUTTON = 40,
CLASSIC_PLUS_BUTTON = 41,
CLASSIC_MINUS_BUTTON = 42,
CLASSIC_HOME_BUTTON = 43,
CLASSIC_DPAD_UP = 44,
CLASSIC_DPAD_DOWN = 45,
CLASSIC_DPAD_LEFT = 46,
CLASSIC_DPAD_RIGHT = 47,
CLASSIC_L_DIGITAL = 48,
CLASSIC_R_DIGITAL = 49,
CLASSIC_L_ANALOG = 50,
CLASSIC_R_ANALOG = 51,
CLASSIC_LEFT_STICK_X = 52,
CLASSIC_LEFT_STICK_Y = 53,
CLASSIC_RIGHT_STICK_X = 54,
CLASSIC_RIGHT_STICK_Y = 55,
NUMBER_OF_CONTROLS,
FIRST_GC_CONTROL = GCPAD_A_BUTTON,
LAST_GC_CONTROL = GCPAD_C_STICK_Y,
FIRST_WII_CONTROL = WIIMOTE_A_BUTTON,
LAST_WII_CONTROL = CLASSIC_RIGHT_STICK_Y,
};
void RegisterGameCubeInputOverrider(int controller_index);
void RegisterWiiInputOverrider(int controller_index);
void UnregisterGameCubeInputOverrider(int controller_index);
void UnregisterWiiInputOverrider(int controller_index);
void SetControlState(int controller_index, ControlID control, double state);
void ClearControlState(int controller_index, ControlID control);
// Angle is in radians and should be non-negative
double GetGateRadiusAtAngle(int controller_index, ControlID stick, double angle);
} // namespace ciface::Touch