diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java index dd2c4e84071f..960944604e4a 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java @@ -280,9 +280,6 @@ public static void rumble(int padID, double state) 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. * diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/InputOverrider.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/InputOverrider.java new file mode 100644 index 000000000000..6596c8dd914f --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/InputOverrider.java @@ -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); +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/IntSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/IntSetting.java index 98601a174134..f1a1b7a07ea6 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/IntSetting.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/IntSetting.java @@ -38,8 +38,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), diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java index 3f5c1de39f02..7af1c09dfa83 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java @@ -138,6 +138,15 @@ public void onPause() super.onPause(); } + @Override + public void onDestroy() + { + if (mInputOverlay != null) + mInputOverlay.onDestroy(); + + super.onDestroy(); + } + @Override public void onDetach() { diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlay.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlay.java index a614f21a645c..17e11f752e81 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlay.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlay.java @@ -26,9 +26,10 @@ 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; @@ -159,12 +162,26 @@ public void initTouchPointer() if (mPreferences.getInt("wiiController", OVERLAY_WIIMOTE_NUNCHUK) != 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()); } @@ -219,8 +236,11 @@ public boolean onTouch(View v, MotionEvent event) 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: @@ -229,8 +249,12 @@ public boolean onTouch(View v, MotionEvent event) 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; @@ -271,8 +295,7 @@ public boolean onTouch(View v, MotionEvent event) { if (!dpadPressed[i]) { - NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(i), - ButtonState.RELEASED); + InputOverrider.setControlState(0, dpad.getControl(i), 0.0); } } // Press buttons @@ -280,8 +303,7 @@ public boolean onTouch(View v, MotionEvent event) { 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]); @@ -295,8 +317,7 @@ public boolean onTouch(View v, MotionEvent event) 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); } @@ -311,27 +332,17 @@ public boolean onTouch(View v, MotionEvent event) 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(); @@ -383,7 +394,7 @@ public boolean onTouchWhileEditing(MotionEvent event) 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; @@ -421,7 +432,7 @@ public boolean onTouchWhileEditing(MotionEvent event) 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; @@ -454,7 +465,7 @@ public boolean onTouchWhileEditing(MotionEvent event) case MotionEvent.ACTION_POINTER_UP: if (mJoystickBeingConfigured != null) { - saveControlPosition(mJoystickBeingConfigured.getId(), + saveControlPosition(mJoystickBeingConfigured.getLegacyId(), mJoystickBeingConfigured.getBounds().left, mJoystickBeingConfigured.getBounds().top, controller, orientation); mJoystickBeingConfigured = null; @@ -466,6 +477,35 @@ public boolean onTouchWhileEditing(MotionEvent event) return true; } + public void onDestroy() + { + 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) { @@ -502,61 +542,70 @@ private void addGameCubeOverlayControls(String orientation) 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)); } } @@ -565,45 +614,52 @@ private void addWiimoteOverlayControls(String orientation) 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)); } } @@ -612,18 +668,21 @@ private void addNunchukOverlayControls(String orientation) 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)); } } @@ -632,77 +691,90 @@ private void addClassicOverlayControls(String orientation) 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)); } } @@ -717,6 +789,9 @@ public void refreshControls() getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT ? "-Portrait" : ""; + boolean showingGameCube = false; + boolean showingWii = false; + if (BooleanSetting.MAIN_SHOW_INPUT_OVERLAY.getBooleanGlobal()) { // Add all the enabled overlay items back to the HashSet. @@ -736,6 +811,7 @@ public void refreshControls() break; case EMULATED_GAMECUBE_CONTROLLER: + showingGameCube = true; addGameCubeOverlayControls(orientation); break; @@ -748,20 +824,24 @@ public void refreshControls() switch (mPreferences.getInt("wiiController", 3)) { case OVERLAY_GAMECUBE: + showingGameCube = true; addGameCubeOverlayControls(orientation); break; case OVERLAY_WIIMOTE: case OVERLAY_WIIMOTE_SIDEWAYS: + showingWii = true; addWiimoteOverlayControls(orientation); break; case OVERLAY_WIIMOTE_NUNCHUK: + showingWii = true; addWiimoteOverlayControls(orientation); addNunchukOverlayControls(orientation); break; case OVERLAY_WIIMOTE_CLASSIC: + showingWii = true; addClassicOverlayControls(orientation); break; @@ -770,6 +850,27 @@ public void refreshControls() } } } + + if (showingGameCube != mGameCubeRegistered) + { + if (showingGameCube) + InputOverrider.registerGameCube(0); + else + InputOverrider.unregisterGameCube(0); + + mGameCubeRegistered = showingGameCube; + } + + if (showingWii != mWiiRegistered) + { + if (showingWii) + InputOverrider.registerWii(0); + else + InputOverrider.unregisterWii(0); + + mWiiRegistered = showingWii; + } + mIsFirstRun = false; invalidate(); } @@ -882,11 +983,12 @@ private static String getYKey(int sharedPrefsId, int controller, String orientat * @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(); @@ -898,7 +1000,7 @@ private static InputOverlayDrawableButton initializeOverlayButton(Context contex // Decide scale based on button ID and user preference float scale; - switch (buttonId) + switch (legacyId) { case ButtonType.BUTTON_A: case ButtonType.WIIMOTE_BUTTON_B: @@ -952,12 +1054,13 @@ private static InputOverlayDrawableButton initializeOverlayButton(Context contex 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(); @@ -980,20 +1083,22 @@ private static InputOverlayDrawableButton initializeOverlayButton(Context contex * @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. @@ -1006,7 +1111,7 @@ private static InputOverlayDrawableDpad initializeOverlayDpad(Context context, // Decide scale based on button ID and user preference float scale; - switch (buttonUp) + switch (legacyId) { case ButtonType.BUTTON_UP: scale = 0.2375f; @@ -1037,12 +1142,12 @@ private static InputOverlayDrawableDpad initializeOverlayDpad(Context context, 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(); @@ -1065,11 +1170,14 @@ private static InputOverlayDrawableDpad initializeOverlayDpad(Context context, * @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(); @@ -1091,13 +1199,13 @@ private static InputOverlayDrawableJoystick initializeOverlayJoystick(Context co // 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; } @@ -1115,7 +1223,7 @@ private static InputOverlayDrawableJoystick initializeOverlayJoystick(Context co // 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); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableButton.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableButton.java index 83e97cc31a51..d997da94bf46 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableButton.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableButton.java @@ -18,8 +18,9 @@ */ 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 mLegacyId; + } + + public int getControl() { - return mButtonType; + return mControl; } public void setTrackId(int trackId) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableDpad.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableDpad.java index 755ed7e2ff9e..6542609ca02c 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableDpad.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableDpad.java @@ -18,8 +18,9 @@ */ 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 InputOverlayDrawableDpad(Resources res, 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 void draw(Canvas canvas) } } + public int getLegacyId() + { + return mLegacyId; + } + /** - * Gets one of the InputOverlayDrawableDpad's button IDs. - * - * @return the requested InputOverlayDrawableDpad's button ID. + * Gets one of the InputOverlayDrawableDpad's control IDs. */ - public int getId(int direction) + public int getControl(int direction) { - return mButtonType[direction]; + return mControls[direction]; } public void setTrackId(int trackId) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableJoystick.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableJoystick.java index 0e4e1f33f5bf..d580df7349a7 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableJoystick.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableJoystick.java @@ -12,7 +12,7 @@ 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 @@ */ 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 InputOverlayDrawableJoystick(Resources res, Bitmap bitmapOuter, Bitmap bi } /** - * 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 boolean TrackEvent(MotionEvent event) { 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 boolean TrackEvent(MotionEvent event) 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 void onConfigureTouch(MotionEvent event) } } + public float getX() + { + return mCurrentX; + } + + public float getY() + { + return mCurrentY; + } - public float[] getAxisValues() + public int getXControl() { - 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 mJoystickXControl; } - public int[] getAxisIDs() + public int getYControl() { - return axisIDs; + 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)); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayPointer.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayPointer.java index 67f8d23419ec..18de4f4b4777 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayPointer.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayPointer.java @@ -7,22 +7,20 @@ 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 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 void onTouch(MotionEvent event) 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 @@ private void touchPress() { 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 @@ private void touchPress() 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 getX() + { + return mCurrentX; } - public float[] getAxisValues() + public float getY() { - 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 mCurrentY; } public void setMode(int mode) diff --git a/Source/Android/jni/CMakeLists.txt b/Source/Android/jni/CMakeLists.txt index 74d9d90e037c..9f737b5af766 100644 --- a/Source/Android/jni/CMakeLists.txt +++ b/Source/Android/jni/CMakeLists.txt @@ -8,6 +8,7 @@ add_library(main SHARED GameList/GameFile.cpp GameList/GameFile.h GameList/GameFileCache.cpp + Input/InputOverrider.cpp IniFile.cpp MainAndroid.cpp RiivolutionPatches.cpp diff --git a/Source/Android/jni/Input/InputOverrider.cpp b/Source/Android/jni/Input/InputOverrider.cpp new file mode 100644 index 000000000000..26b823e03d7f --- /dev/null +++ b/Source/Android/jni/Input/InputOverrider.cpp @@ -0,0 +1,62 @@ +// Copyright 2021 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include + +#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(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(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(stick); + return ciface::Touch::GetGateRadiusAtAngle(controller_index, casted_stick, angle); +} +}; diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index 213193b0d2d7..aa09b853667e 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -287,13 +287,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(stick); - return ButtonManager::GetInputRadiusAtAngle(emu_pad_id, casted_stick, angle); -} - JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetVersionString(JNIEnv* env, jclass) { diff --git a/Source/Core/InputCommon/CMakeLists.txt b/Source/Core/InputCommon/CMakeLists.txt index 4f9510d7a53e..1775ac95404c 100644 --- a/Source/Core/InputCommon/CMakeLists.txt +++ b/Source/Core/InputCommon/CMakeLists.txt @@ -138,6 +138,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 ) diff --git a/Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.cpp b/Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.cpp index 7b15f92de955..d55284a65a40 100644 --- a/Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.cpp @@ -9,23 +9,11 @@ #include #include -#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(group)->GetInputRadiusAtAngle(angle); -} - bool GamepadEvent(const std::string& dev, int button, int action) { auto it = m_controllers.find(dev); diff --git a/Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.h b/Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.h index 136d15915f1f..08c4349c8453 100644 --- a/Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.h +++ b/Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.h @@ -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); diff --git a/Source/Core/InputCommon/ControllerInterface/Touch/InputOverrider.cpp b/Source/Core/InputCommon/ControllerInterface/Touch/InputOverrider.cpp new file mode 100644 index 000000000000..dcd7cffc71c7 --- /dev/null +++ b/Source/Core/InputCommon/ControllerInterface/Touch/InputOverrider.cpp @@ -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 +#include +#include +#include +#include +#include + +#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, ControlID>; +using StateArray = std::array; + +std::array 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 { + 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(Wiimote::GetConfig()->GetController(controller_index)); + + wiimote->SetInputOverrideFunction( + GetInputOverrideFunction(s_wiimote_controls_map, controller_index)); + + auto& attachments = static_cast( + 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[i][controller_index].overriding = false; +} + +void UnregisterWiiInputOverrider(int controller_index) +{ + auto* wiimote = + static_cast(Wiimote::GetConfig()->GetController(controller_index)); + + wiimote->ClearInputOverrideFunction(); + + auto& attachments = static_cast( + 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[i][controller_index].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(group)->GetGateRadiusAtAngle(angle); +} +} // namespace ciface::Touch diff --git a/Source/Core/InputCommon/ControllerInterface/Touch/InputOverrider.h b/Source/Core/InputCommon/ControllerInterface/Touch/InputOverrider.h new file mode 100644 index 000000000000..6217b44d4e9b --- /dev/null +++ b/Source/Core/InputCommon/ControllerInterface/Touch/InputOverrider.h @@ -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