From db75509ec5d2cd15036a5cda629f952c2b860d6e Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 28 Jun 2020 23:32:36 +0200 Subject: [PATCH] Android: Enfore correct stick gate in overlay Currently, the touch controller overlay uses a square gate for sticks. This commit changes that so that it instead uses the stick gate configured in the INI, which ensures that the values sent to the core are appropriately scaled regardless of what is configured in the INI and makes the overlay look nicer if the INI is set to a stick gate that matches the graphics. --- .../dolphinemu/dolphinemu/NativeLibrary.java | 3 ++ .../overlay/InputOverlayDrawableJoystick.java | 30 ++++++++----- Source/Android/jni/MainAndroid.cpp | 9 ++++ .../Touch/ButtonManager.cpp | 45 +++++++++++++++++++ .../ControllerInterface/Touch/ButtonManager.h | 7 +++ 5 files changed, 83 insertions(+), 11 deletions(-) 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 3751385be8..24ec356751 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 @@ -269,6 +269,9 @@ 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); + public static native void NewGameIniFile(); public static native void LoadGameIniFile(String gameId); 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 55f6347096..a32155686e 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 @@ -14,6 +14,8 @@ import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.view.MotionEvent; +import org.dolphinemu.dolphinemu.NativeLibrary; + /** * Custom {@link BitmapDrawable} that is capable * of storing it's own ID. @@ -214,21 +216,27 @@ public final class InputOverlayDrawableJoystick private void SetInnerBounds() { - int X = getVirtBounds().centerX() + (int) ((axises[1]) * (getVirtBounds().width() / 2)); - int Y = getVirtBounds().centerY() + (int) ((axises[0]) * (getVirtBounds().height() / 2)); + double y = axises[0]; + double x = axises[1]; - if (X > getVirtBounds().centerX() + (getVirtBounds().width() / 2)) - X = getVirtBounds().centerX() + (getVirtBounds().width() / 2); - if (X < getVirtBounds().centerX() - (getVirtBounds().width() / 2)) - X = getVirtBounds().centerX() - (getVirtBounds().width() / 2); - if (Y > getVirtBounds().centerY() + (getVirtBounds().height() / 2)) - Y = getVirtBounds().centerY() + (getVirtBounds().height() / 2); - if (Y < getVirtBounds().centerY() - (getVirtBounds().height() / 2)) - Y = getVirtBounds().centerY() - (getVirtBounds().height() / 2); + double angle = Math.atan2(y, x) + Math.PI + Math.PI; + double radius = Math.hypot(y, x); + double maxRadius = NativeLibrary.GetInputRadiusAtAngle(0, mJoystickType, angle); + if (radius > maxRadius) + { + y = maxRadius * Math.sin(angle); + x = maxRadius * Math.cos(angle); + axises[0] = (float) y; + axises[1] = (float) x; + } + + int pixelX = getVirtBounds().centerX() + (int) (x * (getVirtBounds().width() / 2)); + int pixelY = getVirtBounds().centerY() + (int) (y * (getVirtBounds().height() / 2)); int width = mPressedStateInnerBitmap.getBounds().width() / 2; int height = mPressedStateInnerBitmap.getBounds().height() / 2; - mDefaultStateInnerBitmap.setBounds(X - width, Y - height, X + width, Y + height); + mDefaultStateInnerBitmap.setBounds(pixelX - width, pixelY - height, pixelX + width, + pixelY + height); mPressedStateInnerBitmap.setBounds(mDefaultStateInnerBitmap.getBounds()); } diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index 469d719869..eb9e02c32b 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -201,6 +201,8 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_onGamePadMov JNIEnv* env, jobject obj, jstring jDevice, jint Axis, jfloat Value); JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetMotionSensorsEnabled( JNIEnv* env, jobject obj, jboolean accelerometer_enabled, jboolean gyroscope_enabled); +JNIEXPORT double JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetInputRadiusAtAngle( + JNIEnv* env, jobject obj, int emu_pad_id, int stick, double angle); JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetVersionString(JNIEnv* env, jobject obj); JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetGitRevision(JNIEnv* env, @@ -315,6 +317,13 @@ 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* env, jobject obj, 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, jobject obj) { diff --git a/Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.cpp b/Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.cpp index 22b05952f6..75f69b8823 100644 --- a/Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.cpp @@ -8,10 +8,22 @@ #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" #include "InputCommon/ControllerInterface/Touch/ButtonManager.h" namespace ButtonManager @@ -688,6 +700,39 @@ 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 5d6a19ef78..2139c2e2ca 100644 --- a/Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.h +++ b/Source/Core/InputCommon/ControllerInterface/Touch/ButtonManager.h @@ -268,9 +268,16 @@ public: }; void Init(const std::string&); + +// pad_id is numbered 0 to 3 for GC pads and 4 to 7 for Wiimotes 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); + void Shutdown(); } // namespace ButtonManager