From 3be891ea6faffb10d34eb780f5650d35d7a50bc3 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Mon, 13 Feb 2023 13:15:57 -0600 Subject: [PATCH] android: Clean joystick overlay --- .../java/org/yuzu/yuzu_emu/NativeLibrary.java | 8 + .../yuzu/yuzu_emu/overlay/InputOverlay.java | 27 +- .../overlay/InputOverlayDrawableJoystick.java | 231 +++++++++--------- 3 files changed, 131 insertions(+), 135 deletions(-) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java index dbbc339ec..2ab3a834a 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.java @@ -637,6 +637,14 @@ public final class NativeLibrary { public static final int BUTTON_CAPTURE = 19; } + /** + * Stick type for use in onTouchEvent + */ + public static final class StickType { + public static final int STICK_L = 0; + public static final int STICK_R = 1; + } + /** * Button states */ diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.java index c316a63b1..6b51a596f 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.java +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.java @@ -26,8 +26,8 @@ import android.view.View; import android.view.View.OnTouchListener; import org.yuzu.yuzu_emu.NativeLibrary; -import org.yuzu.yuzu_emu.NativeLibrary.ButtonState; import org.yuzu.yuzu_emu.NativeLibrary.ButtonType; +import org.yuzu.yuzu_emu.NativeLibrary.StickType; import org.yuzu.yuzu_emu.R; import org.yuzu.yuzu_emu.utils.EmulationMenuSettings; @@ -271,10 +271,11 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener { * @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 button Identifier for which joystick button this is. * @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 joystick, int button, String orientation) { // Resources handle for fetching the initial Drawable resource. final Resources res = context.getResources(); @@ -294,8 +295,8 @@ 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(joystick + orientation + "-X", 0f); - int drawableY = (int) sPrefs.getFloat(joystick + orientation + "-Y", 0f); + int drawableX = (int) sPrefs.getFloat(button + orientation + "-X", 0f); + int drawableY = (int) sPrefs.getFloat(button + orientation + "-Y", 0f); float outerScale = 1.3f; @@ -309,7 +310,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener { final InputOverlayDrawableJoystick overlayDrawable = new InputOverlayDrawableJoystick(res, bitmapOuter, bitmapInnerDefault, bitmapInnerPressed, - outerRect, innerRect, joystick); + outerRect, innerRect, joystick, button); // Need to set the image's position overlayDrawable.setPosition(drawableX, drawableY); @@ -386,12 +387,12 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener { } for (InputOverlayDrawableJoystick joystick : overlayJoysticks) { - joystick.TrackEvent(event); - int axisID = joystick.getId(); - float[] axises = joystick.getAxisValues(); - - NativeLibrary - .onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, axisID, axises[0], axises[1]); + if (!joystick.updateStatus(event)) { + continue; + } + int axisID = joystick.getJoystickId(); + NativeLibrary.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, axisID, joystick.getXAxis(), joystick.getYAxis()); + NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, joystick.getButtonId(), joystick.getButtonStatus()); } invalidate(); @@ -455,11 +456,11 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener { if (mPreferences.getBoolean("buttonToggle11", true)) { overlayJoysticks.add(initializeOverlayJoystick(getContext(), R.drawable.stick_main_range, R.drawable.stick_main, R.drawable.stick_main_pressed, - ButtonType.STICK_L, orientation)); + StickType.STICK_L, ButtonType.STICK_L, orientation)); } if (mPreferences.getBoolean("buttonToggle12", true)) { overlayJoysticks.add(initializeOverlayJoystick(getContext(), R.drawable.stick_main_range, - R.drawable.stick_main, R.drawable.stick_main_pressed, ButtonType.STICK_R, orientation)); + R.drawable.stick_main, R.drawable.stick_main_pressed, StickType.STICK_R, ButtonType.STICK_R, orientation)); } if (mPreferences.getBoolean("buttonToggle13", true)) { overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.button_a, diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.java index 03d38862b..4a0b9fd86 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.java +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.java @@ -13,6 +13,7 @@ import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.view.MotionEvent; +import org.yuzu.yuzu_emu.NativeLibrary; import org.yuzu.yuzu_emu.NativeLibrary.ButtonType; import org.yuzu.yuzu_emu.utils.EmulationMenuSettings; @@ -21,12 +22,15 @@ import org.yuzu.yuzu_emu.utils.EmulationMenuSettings; * of storing it's own ID. */ public final class InputOverlayDrawableJoystick { - private final int[] axisIDs = {0, 0, 0, 0}; - private final float[] axises = {0f, 0f}; - private int trackId = -1; - private int mJoystickType; + // The ID value what type of joystick this Drawable represents. + private int mJoystickId; + // The ID value what type of button this Drawable represents. + private int mButtonId; + // The ID value what motion event is tracking + private int mTrackId = -1; + private float mXAxis; + private float mYAxis; private int mControlPositionX, mControlPositionY; - private int mPreviousTouchX, mPreviousTouchY; private int mWidth; private int mHeight; private Rect mVirtBounds; @@ -50,12 +54,9 @@ public final class InputOverlayDrawableJoystick { */ public InputOverlayDrawableJoystick(Resources res, Bitmap bitmapOuter, Bitmap bitmapInnerDefault, Bitmap bitmapInnerPressed, - Rect rectOuter, Rect rectInner, int joystick) { - axisIDs[0] = joystick + 1; // Up - axisIDs[1] = joystick + 2; // Down - axisIDs[2] = joystick + 3; // Left - axisIDs[3] = joystick + 4; // Right - mJoystickType = joystick; + Rect rectOuter, Rect rectInner, int joystick, int button) { + mJoystickId = joystick; + mButtonId = button; mOuterBitmap = new BitmapDrawable(res, bitmapOuter); mDefaultStateInnerBitmap = new BitmapDrawable(res, bitmapInnerDefault); @@ -74,131 +75,90 @@ public final class InputOverlayDrawableJoystick { SetInnerBounds(); } - /** - * Gets this InputOverlayDrawableJoystick's button ID. - * - * @return this InputOverlayDrawableJoystick's button ID. - */ - public int getId() { - return mJoystickType; - } - public void draw(Canvas canvas) { mOuterBitmap.draw(canvas); getCurrentStateBitmapDrawable().draw(canvas); mBoundsBoxBitmap.draw(canvas); } - public void TrackEvent(MotionEvent event) { + public boolean updateStatus(MotionEvent event) { int pointerIndex = event.getActionIndex(); + int xPosition = (int) event.getX(pointerIndex); + int yPosition = (int) event.getY(pointerIndex); + int pointerId = event.getPointerId(pointerIndex); + int motion_event = event.getAction() & MotionEvent.ACTION_MASK; + boolean isActionDown = motion_event == MotionEvent.ACTION_DOWN || motion_event == MotionEvent.ACTION_POINTER_DOWN; + boolean isActionUp = motion_event == MotionEvent.ACTION_UP || motion_event == MotionEvent.ACTION_POINTER_UP; - switch (event.getAction() & MotionEvent.ACTION_MASK) { - case MotionEvent.ACTION_DOWN: - case MotionEvent.ACTION_POINTER_DOWN: - if (getBounds().contains((int) event.getX(pointerIndex), (int) event.getY(pointerIndex))) { - mPressedState = true; - mOuterBitmap.setAlpha(0); - mBoundsBoxBitmap.setAlpha(255); - if (EmulationMenuSettings.getJoystickRelCenter()) { - getVirtBounds().offset((int) event.getX(pointerIndex) - getVirtBounds().centerX(), - (int) event.getY(pointerIndex) - getVirtBounds().centerY()); - } - mBoundsBoxBitmap.setBounds(getVirtBounds()); - trackId = event.getPointerId(pointerIndex); - } - break; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_POINTER_UP: - if (trackId == event.getPointerId(pointerIndex)) { - mPressedState = false; - axises[0] = axises[1] = 0.0f; - mOuterBitmap.setAlpha(255); - mBoundsBoxBitmap.setAlpha(0); - setVirtBounds(new Rect(mOrigBounds.left, mOrigBounds.top, mOrigBounds.right, - mOrigBounds.bottom)); - setBounds(new Rect(mOrigBounds.left, mOrigBounds.top, mOrigBounds.right, - mOrigBounds.bottom)); - SetInnerBounds(); - trackId = -1; - } - break; + if (isActionDown) { + if (!getBounds().contains(xPosition, yPosition)) { + return false; + } + mPressedState = true; + mOuterBitmap.setAlpha(0); + mBoundsBoxBitmap.setAlpha(255); + if (EmulationMenuSettings.getJoystickRelCenter()) { + getVirtBounds().offset(xPosition - getVirtBounds().centerX(), + yPosition - getVirtBounds().centerY()); + } + mBoundsBoxBitmap.setBounds(getVirtBounds()); + mTrackId = pointerId; } - if (trackId == -1) - return; + if (isActionUp) { + if (mTrackId != pointerId) { + return false; + } + mPressedState = false; + mXAxis = 0.0f; + mYAxis = 0.0f; + mOuterBitmap.setAlpha(255); + mBoundsBoxBitmap.setAlpha(0); + setVirtBounds(new Rect(mOrigBounds.left, mOrigBounds.top, mOrigBounds.right, + mOrigBounds.bottom)); + setBounds(new Rect(mOrigBounds.left, mOrigBounds.top, mOrigBounds.right, + mOrigBounds.bottom)); + SetInnerBounds(); + mTrackId = -1; + return true; + } + + if (mTrackId == -1) + return false; for (int i = 0; i < event.getPointerCount(); i++) { - if (trackId == event.getPointerId(i)) { - float touchX = event.getX(i); - float touchY = event.getY(i); - float maxY = getVirtBounds().bottom; - float maxX = getVirtBounds().right; - touchX -= getVirtBounds().centerX(); - maxX -= getVirtBounds().centerX(); - touchY -= getVirtBounds().centerY(); - maxY -= getVirtBounds().centerY(); - final float AxisX = touchX / maxX; - final float AxisY = touchY / maxY; - - // Clamp the circle pad input to a circle - final float angle = (float) Math.atan2(AxisY, AxisX); - float radius = (float) Math.sqrt(AxisX * AxisX + AxisY * AxisY); - if (radius > 1.0f) { - radius = 1.0f; - } - axises[0] = ((float) Math.cos(angle) * radius); - axises[1] = ((float) Math.sin(angle) * radius); - SetInnerBounds(); + if (mTrackId != event.getPointerId(i)) { + continue; } + float touchX = event.getX(i); + float touchY = event.getY(i); + float maxY = getVirtBounds().bottom; + float maxX = getVirtBounds().right; + touchX -= getVirtBounds().centerX(); + maxX -= getVirtBounds().centerX(); + touchY -= getVirtBounds().centerY(); + maxY -= getVirtBounds().centerY(); + final float AxisX = touchX / maxX; + final float AxisY = touchY / maxY; + + // Clamp the circle pad input to a circle + final float angle = (float) Math.atan2(AxisY, AxisX); + float radius = (float) Math.sqrt(AxisX * AxisX + AxisY * AxisY); + if (radius > 1.0f) { + radius = 1.0f; + } + mXAxis = ((float) Math.cos(angle) * radius); + mYAxis = ((float) Math.sin(angle) * radius); + SetInnerBounds(); + return true; } - } - public boolean onConfigureTouch(MotionEvent event) { - int pointerIndex = event.getActionIndex(); - int fingerPositionX = (int) event.getX(pointerIndex); - int fingerPositionY = (int) event.getY(pointerIndex); - - int scale = 1; - - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - mPreviousTouchX = fingerPositionX; - mPreviousTouchY = fingerPositionY; - break; - case MotionEvent.ACTION_MOVE: - int deltaX = fingerPositionX - mPreviousTouchX; - int deltaY = fingerPositionY - mPreviousTouchY; - mControlPositionX += deltaX; - mControlPositionY += deltaY; - setBounds(new Rect(mControlPositionX, mControlPositionY, - mOuterBitmap.getIntrinsicWidth() / scale + mControlPositionX, - mOuterBitmap.getIntrinsicHeight() / scale + mControlPositionY)); - setVirtBounds(new Rect(mControlPositionX, mControlPositionY, - mOuterBitmap.getIntrinsicWidth() / scale + mControlPositionX, - mOuterBitmap.getIntrinsicHeight() / scale + mControlPositionY)); - SetInnerBounds(); - setOrigBounds(new Rect(new Rect(mControlPositionX, mControlPositionY, - mOuterBitmap.getIntrinsicWidth() / scale + mControlPositionX, - mOuterBitmap.getIntrinsicHeight() / scale + mControlPositionY))); - mPreviousTouchX = fingerPositionX; - mPreviousTouchY = fingerPositionY; - break; - } - return true; - } - - - public float[] getAxisValues() { - return axises; - } - - public int[] getAxisIDs() { - return axisIDs; + return false; } private void SetInnerBounds() { - int X = getVirtBounds().centerX() + (int) ((axises[0]) * (getVirtBounds().width() / 2)); - int Y = getVirtBounds().centerY() + (int) ((axises[1]) * (getVirtBounds().height() / 2)); + int X = getVirtBounds().centerX() + (int) ((mXAxis) * (getVirtBounds().width() / 2)); + int Y = getVirtBounds().centerY() + (int) ((mYAxis) * (getVirtBounds().height() / 2)); if (X > getVirtBounds().centerX() + (getVirtBounds().width() / 2)) X = getVirtBounds().centerX() + (getVirtBounds().width() / 2); @@ -224,6 +184,37 @@ public final class InputOverlayDrawableJoystick { return mPressedState ? mPressedStateInnerBitmap : mDefaultStateInnerBitmap; } + /** + * Gets this InputOverlayDrawableJoystick's button ID. + * + * @return this InputOverlayDrawableJoystick's button ID. + */ + public int getJoystickId() { + return mJoystickId; + } + + public float getXAxis() { + return mXAxis; + } + + public float getYAxis() { + // Nintendo joysticks have y axis inverted + return -mYAxis; + } + + public int getButtonId() { + return mButtonId; + } + + public int getTrackId() { + return mTrackId; + } + + public int getButtonStatus() { + // TODO: Add button support + return NativeLibrary.ButtonState.RELEASED; + } + public Rect getBounds() { return mOuterBitmap.getBounds(); } @@ -232,10 +223,6 @@ public final class InputOverlayDrawableJoystick { mOuterBitmap.setBounds(bounds); } - private void setOrigBounds(Rect bounds) { - mOrigBounds = bounds; - } - private Rect getVirtBounds() { return mVirtBounds; }