android: Clean joystick overlay

This commit is contained in:
Narr the Reg 2023-02-13 13:15:57 -06:00 committed by bunnei
parent 639a1f885c
commit 3be891ea6f
3 changed files with 131 additions and 135 deletions

View file

@ -637,6 +637,14 @@ public final class NativeLibrary {
public static final int BUTTON_CAPTURE = 19; 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 * Button states
*/ */

View file

@ -26,8 +26,8 @@ import android.view.View;
import android.view.View.OnTouchListener; import android.view.View.OnTouchListener;
import org.yuzu.yuzu_emu.NativeLibrary; 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.ButtonType;
import org.yuzu.yuzu_emu.NativeLibrary.StickType;
import org.yuzu.yuzu_emu.R; import org.yuzu.yuzu_emu.R;
import org.yuzu.yuzu_emu.utils.EmulationMenuSettings; 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 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 pressedResInner Resource ID for the pressed inner image of the joystick.
* @param joystick Identifier for which joystick this is. * @param joystick Identifier for which joystick this is.
* @param button Identifier for which joystick button this is.
* @return the initialized {@link InputOverlayDrawableJoystick}. * @return the initialized {@link InputOverlayDrawableJoystick}.
*/ */
private static InputOverlayDrawableJoystick initializeOverlayJoystick(Context context, 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. // Resources handle for fetching the initial Drawable resource.
final Resources res = context.getResources(); 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. // The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay.
// These were set in the input overlay configuration menu. // These were set in the input overlay configuration menu.
int drawableX = (int) sPrefs.getFloat(joystick + orientation + "-X", 0f); int drawableX = (int) sPrefs.getFloat(button + orientation + "-X", 0f);
int drawableY = (int) sPrefs.getFloat(joystick + orientation + "-Y", 0f); int drawableY = (int) sPrefs.getFloat(button + orientation + "-Y", 0f);
float outerScale = 1.3f; float outerScale = 1.3f;
@ -309,7 +310,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener {
final InputOverlayDrawableJoystick overlayDrawable final InputOverlayDrawableJoystick overlayDrawable
= new InputOverlayDrawableJoystick(res, bitmapOuter, = new InputOverlayDrawableJoystick(res, bitmapOuter,
bitmapInnerDefault, bitmapInnerPressed, bitmapInnerDefault, bitmapInnerPressed,
outerRect, innerRect, joystick); outerRect, innerRect, joystick, button);
// Need to set the image's position // Need to set the image's position
overlayDrawable.setPosition(drawableX, drawableY); overlayDrawable.setPosition(drawableX, drawableY);
@ -386,12 +387,12 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener {
} }
for (InputOverlayDrawableJoystick joystick : overlayJoysticks) { for (InputOverlayDrawableJoystick joystick : overlayJoysticks) {
joystick.TrackEvent(event); if (!joystick.updateStatus(event)) {
int axisID = joystick.getId(); continue;
float[] axises = joystick.getAxisValues(); }
int axisID = joystick.getJoystickId();
NativeLibrary NativeLibrary.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, axisID, joystick.getXAxis(), joystick.getYAxis());
.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, axisID, axises[0], axises[1]); NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, joystick.getButtonId(), joystick.getButtonStatus());
} }
invalidate(); invalidate();
@ -455,11 +456,11 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener {
if (mPreferences.getBoolean("buttonToggle11", true)) { if (mPreferences.getBoolean("buttonToggle11", true)) {
overlayJoysticks.add(initializeOverlayJoystick(getContext(), R.drawable.stick_main_range, overlayJoysticks.add(initializeOverlayJoystick(getContext(), R.drawable.stick_main_range,
R.drawable.stick_main, R.drawable.stick_main_pressed, 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)) { if (mPreferences.getBoolean("buttonToggle12", true)) {
overlayJoysticks.add(initializeOverlayJoystick(getContext(), R.drawable.stick_main_range, 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)) { if (mPreferences.getBoolean("buttonToggle13", true)) {
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.button_a, overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.button_a,

View file

@ -13,6 +13,7 @@ import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.view.MotionEvent; import android.view.MotionEvent;
import org.yuzu.yuzu_emu.NativeLibrary;
import org.yuzu.yuzu_emu.NativeLibrary.ButtonType; import org.yuzu.yuzu_emu.NativeLibrary.ButtonType;
import org.yuzu.yuzu_emu.utils.EmulationMenuSettings; import org.yuzu.yuzu_emu.utils.EmulationMenuSettings;
@ -21,12 +22,15 @@ import org.yuzu.yuzu_emu.utils.EmulationMenuSettings;
* of storing it's own ID. * of storing it's own ID.
*/ */
public final class InputOverlayDrawableJoystick { public final class InputOverlayDrawableJoystick {
private final int[] axisIDs = {0, 0, 0, 0}; // The ID value what type of joystick this Drawable represents.
private final float[] axises = {0f, 0f}; private int mJoystickId;
private int trackId = -1; // The ID value what type of button this Drawable represents.
private int mJoystickType; 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 mControlPositionX, mControlPositionY;
private int mPreviousTouchX, mPreviousTouchY;
private int mWidth; private int mWidth;
private int mHeight; private int mHeight;
private Rect mVirtBounds; private Rect mVirtBounds;
@ -50,12 +54,9 @@ public final class InputOverlayDrawableJoystick {
*/ */
public InputOverlayDrawableJoystick(Resources res, Bitmap bitmapOuter, public InputOverlayDrawableJoystick(Resources res, Bitmap bitmapOuter,
Bitmap bitmapInnerDefault, Bitmap bitmapInnerPressed, Bitmap bitmapInnerDefault, Bitmap bitmapInnerPressed,
Rect rectOuter, Rect rectInner, int joystick) { Rect rectOuter, Rect rectInner, int joystick, int button) {
axisIDs[0] = joystick + 1; // Up mJoystickId = joystick;
axisIDs[1] = joystick + 2; // Down mButtonId = button;
axisIDs[2] = joystick + 3; // Left
axisIDs[3] = joystick + 4; // Right
mJoystickType = joystick;
mOuterBitmap = new BitmapDrawable(res, bitmapOuter); mOuterBitmap = new BitmapDrawable(res, bitmapOuter);
mDefaultStateInnerBitmap = new BitmapDrawable(res, bitmapInnerDefault); mDefaultStateInnerBitmap = new BitmapDrawable(res, bitmapInnerDefault);
@ -74,131 +75,90 @@ public final class InputOverlayDrawableJoystick {
SetInnerBounds(); SetInnerBounds();
} }
/**
* Gets this InputOverlayDrawableJoystick's button ID.
*
* @return this InputOverlayDrawableJoystick's button ID.
*/
public int getId() {
return mJoystickType;
}
public void draw(Canvas canvas) { public void draw(Canvas canvas) {
mOuterBitmap.draw(canvas); mOuterBitmap.draw(canvas);
getCurrentStateBitmapDrawable().draw(canvas); getCurrentStateBitmapDrawable().draw(canvas);
mBoundsBoxBitmap.draw(canvas); mBoundsBoxBitmap.draw(canvas);
} }
public void TrackEvent(MotionEvent event) { public boolean updateStatus(MotionEvent event) {
int pointerIndex = event.getActionIndex(); 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) { if (isActionDown) {
case MotionEvent.ACTION_DOWN: if (!getBounds().contains(xPosition, yPosition)) {
case MotionEvent.ACTION_POINTER_DOWN: return false;
if (getBounds().contains((int) event.getX(pointerIndex), (int) event.getY(pointerIndex))) { }
mPressedState = true; mPressedState = true;
mOuterBitmap.setAlpha(0); mOuterBitmap.setAlpha(0);
mBoundsBoxBitmap.setAlpha(255); mBoundsBoxBitmap.setAlpha(255);
if (EmulationMenuSettings.getJoystickRelCenter()) { if (EmulationMenuSettings.getJoystickRelCenter()) {
getVirtBounds().offset((int) event.getX(pointerIndex) - getVirtBounds().centerX(), getVirtBounds().offset(xPosition - getVirtBounds().centerX(),
(int) event.getY(pointerIndex) - getVirtBounds().centerY()); yPosition - getVirtBounds().centerY());
} }
mBoundsBoxBitmap.setBounds(getVirtBounds()); mBoundsBoxBitmap.setBounds(getVirtBounds());
trackId = event.getPointerId(pointerIndex); mTrackId = pointerId;
}
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 (trackId == -1) if (isActionUp) {
return; 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++) { for (int i = 0; i < event.getPointerCount(); i++) {
if (trackId == event.getPointerId(i)) { if (mTrackId != event.getPointerId(i)) {
float touchX = event.getX(i); continue;
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();
} }
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) { return false;
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;
} }
private void SetInnerBounds() { private void SetInnerBounds() {
int X = getVirtBounds().centerX() + (int) ((axises[0]) * (getVirtBounds().width() / 2)); int X = getVirtBounds().centerX() + (int) ((mXAxis) * (getVirtBounds().width() / 2));
int Y = getVirtBounds().centerY() + (int) ((axises[1]) * (getVirtBounds().height() / 2)); int Y = getVirtBounds().centerY() + (int) ((mYAxis) * (getVirtBounds().height() / 2));
if (X > getVirtBounds().centerX() + (getVirtBounds().width() / 2)) if (X > getVirtBounds().centerX() + (getVirtBounds().width() / 2))
X = getVirtBounds().centerX() + (getVirtBounds().width() / 2); X = getVirtBounds().centerX() + (getVirtBounds().width() / 2);
@ -224,6 +184,37 @@ public final class InputOverlayDrawableJoystick {
return mPressedState ? mPressedStateInnerBitmap : mDefaultStateInnerBitmap; 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() { public Rect getBounds() {
return mOuterBitmap.getBounds(); return mOuterBitmap.getBounds();
} }
@ -232,10 +223,6 @@ public final class InputOverlayDrawableJoystick {
mOuterBitmap.setBounds(bounds); mOuterBitmap.setBounds(bounds);
} }
private void setOrigBounds(Rect bounds) {
mOrigBounds = bounds;
}
private Rect getVirtBounds() { private Rect getVirtBounds() {
return mVirtBounds; return mVirtBounds;
} }