summaryrefslogtreecommitdiff
path: root/Source/Android/app/src/main/java
diff options
context:
space:
mode:
authorCharles Lombardo <clombardo169@gmail.com>2023-06-03 19:06:33 -0400
committerCharles Lombardo <clombardo169@gmail.com>2023-06-05 14:29:39 -0400
commitddb0de04104ca132762ba7a6644d5c9145b47bf6 (patch)
tree35bb2355a985cf58825d7d93da5215737c62e488 /Source/Android/app/src/main/java
parentfb60b708f52c47e829673e4d0e227a9a90fc6a01 (diff)
Android: Convert InputOverlayDrawableJoystick to Kotlin
Diffstat (limited to 'Source/Android/app/src/main/java')
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableJoystick.java318
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableJoystick.kt258
2 files changed, 258 insertions, 318 deletions
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
deleted file mode 100644
index 6ebe731341..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableJoystick.java
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright 2013 Dolphin Emulator Project
- * SPDX-License-Identifier: GPL-2.0-or-later
- */
-
-package org.dolphinemu.dolphinemu.overlay;
-
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
-import android.view.MotionEvent;
-
-import org.dolphinemu.dolphinemu.features.input.model.InputOverrider;
-import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting;
-
-/**
- * Custom {@link BitmapDrawable} that is capable
- * of storing it's own ID.
- */
-public final class InputOverlayDrawableJoystick
-{
- private float mCurrentX = 0.0f;
- private float mCurrentY = 0.0f;
- private int trackId = -1;
- private final int mJoystickLegacyId;
- private final int mJoystickXControl;
- private final int mJoystickYControl;
- private int mControlPositionX, mControlPositionY;
- private int mPreviousTouchX, mPreviousTouchY;
- private final int mWidth;
- private final int mHeight;
- private final int mControllerIndex;
- private Rect mVirtBounds;
- private Rect mOrigBounds;
- private int mOpacity;
- private final BitmapDrawable mOuterBitmap;
- private final BitmapDrawable mDefaultStateInnerBitmap;
- private final BitmapDrawable mPressedStateInnerBitmap;
- private final BitmapDrawable mBoundsBoxBitmap;
- private boolean mPressedState = false;
-
- /**
- * Constructor
- *
- * @param res {@link Resources} instance.
- * @param bitmapOuter {@link Bitmap} which represents the outer non-movable part of the joystick.
- * @param bitmapInnerDefault {@link Bitmap} which represents the default inner movable part of the joystick.
- * @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 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 legacyId, int xControl,
- int yControl, int controllerIndex)
- {
- mJoystickLegacyId = legacyId;
- mJoystickXControl = xControl;
- mJoystickYControl = yControl;
-
- mOuterBitmap = new BitmapDrawable(res, bitmapOuter);
- mDefaultStateInnerBitmap = new BitmapDrawable(res, bitmapInnerDefault);
- mPressedStateInnerBitmap = new BitmapDrawable(res, bitmapInnerPressed);
- mBoundsBoxBitmap = new BitmapDrawable(res, bitmapOuter);
- mWidth = bitmapOuter.getWidth();
- mHeight = bitmapOuter.getHeight();
-
- if (controllerIndex < 0 || controllerIndex >= 4)
- throw new IllegalArgumentException("controllerIndex must be 0-3");
- mControllerIndex = controllerIndex;
-
- setBounds(rectOuter);
- mDefaultStateInnerBitmap.setBounds(rectInner);
- mPressedStateInnerBitmap.setBounds(rectInner);
- mVirtBounds = getBounds();
- mOrigBounds = mOuterBitmap.copyBounds();
- mBoundsBoxBitmap.setAlpha(0);
- mBoundsBoxBitmap.setBounds(getVirtBounds());
- SetInnerBounds();
- }
-
- /**
- * Gets this InputOverlayDrawableJoystick's legacy ID.
- *
- * @return this InputOverlayDrawableJoystick's legacy ID.
- */
- public int getLegacyId()
- {
- return mJoystickLegacyId;
- }
-
- public void draw(Canvas canvas)
- {
- mOuterBitmap.draw(canvas);
- getCurrentStateBitmapDrawable().draw(canvas);
- mBoundsBoxBitmap.draw(canvas);
- }
-
- public boolean TrackEvent(MotionEvent event)
- {
- boolean reCenter = BooleanSetting.MAIN_JOYSTICK_REL_CENTER.getBoolean();
- int action = event.getActionMasked();
- boolean firstPointer = action != MotionEvent.ACTION_POINTER_DOWN &&
- action != MotionEvent.ACTION_POINTER_UP;
- int pointerIndex = firstPointer ? 0 : event.getActionIndex();
- boolean pressed = false;
-
- switch (action)
- {
- case MotionEvent.ACTION_DOWN:
- case MotionEvent.ACTION_POINTER_DOWN:
- if (getBounds().contains((int) event.getX(pointerIndex), (int) event.getY(pointerIndex)))
- {
- mPressedState = pressed = true;
- mOuterBitmap.setAlpha(0);
- mBoundsBoxBitmap.setAlpha(mOpacity);
- if (reCenter)
- {
- 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))
- {
- pressed = true;
- mPressedState = false;
- mCurrentX = mCurrentY = 0.0f;
- mOuterBitmap.setAlpha(mOpacity);
- 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)
- return pressed;
-
- 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();
- mCurrentX = touchX / maxX;
- mCurrentY = touchY / maxY;
-
- SetInnerBounds();
- }
- }
- return pressed;
- }
-
- public void onConfigureTouch(MotionEvent event)
- {
- switch (event.getAction())
- {
- case MotionEvent.ACTION_DOWN:
- mPreviousTouchX = (int) event.getX();
- mPreviousTouchY = (int) event.getY();
- break;
- case MotionEvent.ACTION_MOVE:
- int deltaX = (int) event.getX() - mPreviousTouchX;
- int deltaY = (int) event.getY() - mPreviousTouchY;
- mControlPositionX += deltaX;
- mControlPositionY += deltaY;
- setBounds(new Rect(mControlPositionX, mControlPositionY,
- mOuterBitmap.getIntrinsicWidth() + mControlPositionX,
- mOuterBitmap.getIntrinsicHeight() + mControlPositionY));
- setVirtBounds(new Rect(mControlPositionX, mControlPositionY,
- mOuterBitmap.getIntrinsicWidth() + mControlPositionX,
- mOuterBitmap.getIntrinsicHeight() + mControlPositionY));
- SetInnerBounds();
- setOrigBounds(new Rect(new Rect(mControlPositionX, mControlPositionY,
- mOuterBitmap.getIntrinsicWidth() + mControlPositionX,
- mOuterBitmap.getIntrinsicHeight() + mControlPositionY)));
- mPreviousTouchX = (int) event.getX();
- mPreviousTouchY = (int) event.getY();
- break;
- }
- }
-
- public float getX()
- {
- return mCurrentX;
- }
-
- public float getY()
- {
- return mCurrentY;
- }
-
- public int getXControl()
- {
- return mJoystickXControl;
- }
-
- public int getYControl()
- {
- return mJoystickYControl;
- }
-
- private void SetInnerBounds()
- {
- double x = mCurrentX;
- double y = mCurrentY;
-
- double angle = Math.atan2(y, x) + Math.PI + Math.PI;
- double radius = Math.hypot(y, x);
- double maxRadius = InputOverrider.getGateRadiusAtAngle(mControllerIndex, mJoystickXControl,
- angle);
- if (radius > maxRadius)
- {
- y = maxRadius * Math.sin(angle);
- x = maxRadius * Math.cos(angle);
- mCurrentY = (float) y;
- mCurrentX = (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(pixelX - width, pixelY - height, pixelX + width,
- pixelY + height);
- mPressedStateInnerBitmap.setBounds(mDefaultStateInnerBitmap.getBounds());
- }
-
- public void setPosition(int x, int y)
- {
- mControlPositionX = x;
- mControlPositionY = y;
- }
-
- private BitmapDrawable getCurrentStateBitmapDrawable()
- {
- return mPressedState ? mPressedStateInnerBitmap : mDefaultStateInnerBitmap;
- }
-
- public void setBounds(Rect bounds)
- {
- mOuterBitmap.setBounds(bounds);
- }
-
- public void setOpacity(int value)
- {
- mOpacity = value;
-
- mDefaultStateInnerBitmap.setAlpha(value);
- mPressedStateInnerBitmap.setAlpha(value);
-
- if (trackId == -1)
- {
- mOuterBitmap.setAlpha(value);
- mBoundsBoxBitmap.setAlpha(0);
- }
- else
- {
- mOuterBitmap.setAlpha(0);
- mBoundsBoxBitmap.setAlpha(value);
- }
- }
-
- public Rect getBounds()
- {
- return mOuterBitmap.getBounds();
- }
-
- private void setVirtBounds(Rect bounds)
- {
- mVirtBounds = bounds;
- }
-
- private void setOrigBounds(Rect bounds)
- {
- mOrigBounds = bounds;
- }
-
- private Rect getVirtBounds()
- {
- return mVirtBounds;
- }
-
- public int getWidth()
- {
- return mWidth;
- }
-
- public int getHeight()
- {
- return mHeight;
- }
-
- public int getTrackId()
- {
- return trackId;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableJoystick.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableJoystick.kt
new file mode 100644
index 0000000000..7dff339dcf
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableJoystick.kt
@@ -0,0 +1,258 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.overlay
+
+import android.content.res.Resources
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.Rect
+import android.graphics.drawable.BitmapDrawable
+import android.view.MotionEvent
+import org.dolphinemu.dolphinemu.features.input.model.InputOverrider
+import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting
+import kotlin.math.atan2
+import kotlin.math.cos
+import kotlin.math.hypot
+import kotlin.math.sin
+
+/**
+ * Custom [BitmapDrawable] that is capable
+ * of storing it's own ID.
+ *
+ * @param res [Resources] instance.
+ * @param bitmapOuter [Bitmap] which represents the outer non-movable part of the joystick.
+ * @param bitmapInnerDefault [Bitmap] which represents the default inner movable part of the joystick.
+ * @param bitmapInnerPressed [Bitmap] which represents the pressed inner movable part of the joystick.
+ * @param rectOuter [Rect] which represents the outer joystick bounds.
+ * @param rectInner [Rect] which represents the inner joystick bounds.
+ * @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.
+ */
+class InputOverlayDrawableJoystick(
+ res: Resources,
+ bitmapOuter: Bitmap,
+ bitmapInnerDefault: Bitmap,
+ bitmapInnerPressed: Bitmap,
+ rectOuter: Rect,
+ rectInner: Rect,
+ val legacyId: Int,
+ val xControl: Int,
+ val yControl: Int,
+ private val controllerIndex: Int
+) {
+ var x = 0.0f
+ private set
+ var y = 0.0f
+ private set
+ var trackId = -1
+ private set
+ private var controlPositionX = 0
+ private var controlPositionY = 0
+ private var previousTouchX = 0
+ private var previousTouchY = 0
+ val width: Int
+ val height: Int
+ private var virtBounds: Rect
+ private var origBounds: Rect
+ private var opacity = 0
+ private val outerBitmap: BitmapDrawable
+ private val defaultStateInnerBitmap: BitmapDrawable
+ private val pressedStateInnerBitmap: BitmapDrawable
+ private val boundsBoxBitmap: BitmapDrawable
+ private var pressedState = false
+
+ var bounds: Rect
+ get() = outerBitmap.bounds
+ set(bounds) {
+ outerBitmap.bounds = bounds
+ }
+
+ init {
+ outerBitmap = BitmapDrawable(res, bitmapOuter)
+ defaultStateInnerBitmap = BitmapDrawable(res, bitmapInnerDefault)
+ pressedStateInnerBitmap = BitmapDrawable(res, bitmapInnerPressed)
+ boundsBoxBitmap = BitmapDrawable(res, bitmapOuter)
+ width = bitmapOuter.width
+ height = bitmapOuter.height
+
+ require(!(controllerIndex < 0 || controllerIndex >= 4)) { "controllerIndex must be 0-3" }
+
+ bounds = rectOuter
+ defaultStateInnerBitmap.bounds = rectInner
+ pressedStateInnerBitmap.bounds = rectInner
+ virtBounds = bounds
+ origBounds = outerBitmap.copyBounds()
+ boundsBoxBitmap.alpha = 0
+ boundsBoxBitmap.bounds = virtBounds
+ setInnerBounds()
+ }
+
+ fun draw(canvas: Canvas) {
+ outerBitmap.draw(canvas)
+ currentStateBitmapDrawable.draw(canvas)
+ boundsBoxBitmap.draw(canvas)
+ }
+
+ fun trackEvent(event: MotionEvent): Boolean {
+ val reCenter = BooleanSetting.MAIN_JOYSTICK_REL_CENTER.boolean
+ val action = event.actionMasked
+ val firstPointer = action != MotionEvent.ACTION_POINTER_DOWN &&
+ action != MotionEvent.ACTION_POINTER_UP
+ val pointerIndex = if (firstPointer) 0 else event.actionIndex
+ var pressed = false
+
+ when (action) {
+ MotionEvent.ACTION_DOWN,
+ MotionEvent.ACTION_POINTER_DOWN -> {
+ if (bounds.contains(
+ event.getX(pointerIndex).toInt(),
+ event.getY(pointerIndex).toInt()
+ )
+ ) {
+ pressed = true
+ pressedState = true
+ outerBitmap.alpha = 0
+ boundsBoxBitmap.alpha = opacity
+ if (reCenter) {
+ virtBounds.offset(
+ event.getX(pointerIndex).toInt() - virtBounds.centerX(),
+ event.getY(pointerIndex).toInt() - virtBounds.centerY()
+ )
+ }
+ boundsBoxBitmap.bounds = virtBounds
+ trackId = event.getPointerId(pointerIndex)
+ }
+ }
+
+ MotionEvent.ACTION_UP,
+ MotionEvent.ACTION_POINTER_UP -> {
+ if (trackId == event.getPointerId(pointerIndex)) {
+ pressed = true
+ pressedState = false
+ y = 0f
+ x = y
+ outerBitmap.alpha = opacity
+ boundsBoxBitmap.alpha = 0
+ virtBounds =
+ Rect(origBounds.left, origBounds.top, origBounds.right, origBounds.bottom)
+ bounds =
+ Rect(origBounds.left, origBounds.top, origBounds.right, origBounds.bottom)
+ setInnerBounds()
+ trackId = -1
+ }
+ }
+ }
+
+ if (trackId == -1)
+ return pressed
+
+ for (i in 0 until event.pointerCount) {
+ if (trackId == event.getPointerId(i)) {
+ var touchX = event.getX(i)
+ var touchY = event.getY(i)
+ var maxY = virtBounds.bottom.toFloat()
+ var maxX = virtBounds.right.toFloat()
+ touchX -= virtBounds.centerX().toFloat()
+ maxX -= virtBounds.centerX().toFloat()
+ touchY -= virtBounds.centerY().toFloat()
+ maxY -= virtBounds.centerY().toFloat()
+ x = touchX / maxX
+ y = touchY / maxY
+
+ setInnerBounds()
+ }
+ }
+ return pressed
+ }
+
+ fun onConfigureTouch(event: MotionEvent) {
+ when (event.action) {
+ MotionEvent.ACTION_DOWN -> {
+ previousTouchX = event.x.toInt()
+ previousTouchY = event.y.toInt()
+ }
+
+ MotionEvent.ACTION_MOVE -> {
+ val deltaX = event.x.toInt() - previousTouchX
+ val deltaY = event.y.toInt() - previousTouchY
+ controlPositionX += deltaX
+ controlPositionY += deltaY
+ bounds = Rect(
+ controlPositionX,
+ controlPositionY,
+ outerBitmap.intrinsicWidth + controlPositionX,
+ outerBitmap.intrinsicHeight + controlPositionY
+ )
+ virtBounds = Rect(
+ controlPositionX,
+ controlPositionY,
+ outerBitmap.intrinsicWidth + controlPositionX,
+ outerBitmap.intrinsicHeight + controlPositionY
+ )
+ setInnerBounds()
+ origBounds = Rect(
+ Rect(
+ controlPositionX,
+ controlPositionY,
+ outerBitmap.intrinsicWidth + controlPositionX,
+ outerBitmap.intrinsicHeight + controlPositionY
+ )
+ )
+ previousTouchX = event.x.toInt()
+ previousTouchY = event.y.toInt()
+ }
+ }
+ }
+
+ private fun setInnerBounds() {
+ var x = x.toDouble()
+ var y = y.toDouble()
+
+ val angle = atan2(y, x) + Math.PI + Math.PI
+ val radius = hypot(y, x)
+ val maxRadius = InputOverrider.getGateRadiusAtAngle(controllerIndex, xControl, angle)
+ if (radius > maxRadius) {
+ x = maxRadius * cos(angle)
+ y = maxRadius * sin(angle)
+ this.x = x.toFloat()
+ this.y = y.toFloat()
+ }
+
+ val pixelX = virtBounds.centerX() + (x * (virtBounds.width() / 2)).toInt()
+ val pixelY = virtBounds.centerY() + (y * (virtBounds.height() / 2)).toInt()
+
+ val width = pressedStateInnerBitmap.bounds.width() / 2
+ val height = pressedStateInnerBitmap.bounds.height() / 2
+ defaultStateInnerBitmap.setBounds(
+ pixelX - width,
+ pixelY - height,
+ pixelX + width,
+ pixelY + height
+ )
+ pressedStateInnerBitmap.bounds = defaultStateInnerBitmap.bounds
+ }
+
+ fun setPosition(x: Int, y: Int) {
+ controlPositionX = x
+ controlPositionY = y
+ }
+
+ private val currentStateBitmapDrawable: BitmapDrawable
+ get() = if (pressedState) pressedStateInnerBitmap else defaultStateInnerBitmap
+
+ fun setOpacity(value: Int) {
+ opacity = value
+
+ defaultStateInnerBitmap.alpha = value
+ pressedStateInnerBitmap.alpha = value
+
+ if (trackId == -1) {
+ outerBitmap.alpha = value
+ boundsBoxBitmap.alpha = 0
+ } else {
+ outerBitmap.alpha = 0
+ boundsBoxBitmap.alpha = value
+ }
+ }
+}