From 0bd0fa4f44ed95ce40acb298d04d9bcdc8ca4510 Mon Sep 17 00:00:00 2001 From: Charles Lombardo Date: Sat, 3 Jun 2023 19:06:59 -0400 Subject: [PATCH] Android: Convert InputOverlayPointer to Kotlin --- .../overlay/InputOverlayPointer.java | 180 ------------------ .../dolphinemu/overlay/InputOverlayPointer.kt | 148 ++++++++++++++ 2 files changed, 148 insertions(+), 180 deletions(-) delete mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayPointer.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayPointer.kt 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 deleted file mode 100644 index 09d02a174a..0000000000 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayPointer.java +++ /dev/null @@ -1,180 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.dolphinemu.dolphinemu.overlay; - -import android.graphics.Rect; -import android.os.Handler; -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 MODE_DISABLED = 0; - public static final int MODE_FOLLOW = 1; - public static final int MODE_DRAG = 2; - - 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; - private float mGameWidthHalfInv; - private float mGameHeightHalfInv; - - private float mTouchStartX; - private float mTouchStartY; - - private int mMode; - private boolean mRecenter; - private int mControllerIndex; - - private boolean doubleTap = false; - private int mDoubleTapControl; - private int trackId = -1; - - public static ArrayList DOUBLE_TAP_OPTIONS = new ArrayList<>(); - - static - { - DOUBLE_TAP_OPTIONS.add(NativeLibrary.ButtonType.WIIMOTE_BUTTON_A); - DOUBLE_TAP_OPTIONS.add(NativeLibrary.ButtonType.WIIMOTE_BUTTON_B); - DOUBLE_TAP_OPTIONS.add(NativeLibrary.ButtonType.WIIMOTE_BUTTON_2); - DOUBLE_TAP_OPTIONS.add(NativeLibrary.ButtonType.CLASSIC_BUTTON_A); - } - - public InputOverlayPointer(Rect surfacePosition, int doubleTapControl, int mode, boolean recenter, - int controllerIndex) - { - mDoubleTapControl = doubleTapControl; - mMode = mode; - mRecenter = recenter; - mControllerIndex = controllerIndex; - - mGameCenterX = (surfacePosition.left + surfacePosition.right) / 2.0f; - mGameCenterY = (surfacePosition.top + surfacePosition.bottom) / 2.0f; - - float gameWidth = surfacePosition.right - surfacePosition.left; - float gameHeight = surfacePosition.bottom - surfacePosition.top; - - // Adjusting for device's black bars. - float surfaceAR = gameWidth / gameHeight; - float gameAR = NativeLibrary.GetGameAspectRatio(); - - if (gameAR <= surfaceAR) - { - // Black bars on left/right - gameWidth = gameHeight * gameAR; - } - else - { - // Black bars on top/bottom - gameHeight = gameWidth / gameAR; - } - - mGameWidthHalfInv = 1.0f / (gameWidth * 0.5f); - mGameHeightHalfInv = 1.0f / (gameHeight * 0.5f); - } - - public void onTouch(MotionEvent event) - { - int action = event.getActionMasked(); - boolean firstPointer = action != MotionEvent.ACTION_POINTER_DOWN && - action != MotionEvent.ACTION_POINTER_UP; - int pointerIndex = firstPointer ? 0 : event.getActionIndex(); - - switch (action) - { - case MotionEvent.ACTION_DOWN: - case MotionEvent.ACTION_POINTER_DOWN: - trackId = event.getPointerId(pointerIndex); - mTouchStartX = event.getX(pointerIndex); - mTouchStartY = event.getY(pointerIndex); - touchPress(); - break; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_POINTER_UP: - if (trackId == event.getPointerId(pointerIndex)) - trackId = -1; - if (mMode == MODE_DRAG) - updateOldAxes(); - if (mRecenter) - reset(); - break; - } - - int eventPointerIndex = event.findPointerIndex(trackId); - if (trackId == -1 || eventPointerIndex == -1) - return; - - if (mMode == MODE_FOLLOW) - { - mCurrentX = (event.getX(eventPointerIndex) - mGameCenterX) * mGameWidthHalfInv; - mCurrentY = (event.getY(eventPointerIndex) - mGameCenterY) * mGameHeightHalfInv; - } - else if (mMode == MODE_DRAG) - { - mCurrentX = mOldX + - (event.getX(eventPointerIndex) - mTouchStartX) * mGameWidthHalfInv; - mCurrentY = mOldY + - (event.getY(eventPointerIndex) - mTouchStartY) * mGameHeightHalfInv; - } - } - - private void touchPress() - { - if (mMode != MODE_DISABLED) - { - if (doubleTap) - { - InputOverrider.setControlState(mControllerIndex, mDoubleTapControl, 1.0); - new Handler().postDelayed(() -> InputOverrider.setControlState(mControllerIndex, - mDoubleTapControl, 0.0), - 50); - } - else - { - doubleTap = true; - new Handler().postDelayed(() -> doubleTap = false, 300); - } - } - } - - private void updateOldAxes() - { - mOldX = mCurrentX; - mOldY = mCurrentY; - } - - private void reset() - { - mCurrentX = mCurrentY = mOldX = mOldY = 0.0f; - } - - public float getX() - { - return mCurrentX; - } - - public float getY() - { - return mCurrentY; - } - - public void setMode(int mode) - { - mMode = mode; - if (mode == MODE_DRAG) - updateOldAxes(); - } - - public void setRecenter(boolean recenter) - { - mRecenter = recenter; - } -} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayPointer.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayPointer.kt new file mode 100644 index 0000000000..138effca6f --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayPointer.kt @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.dolphinemu.dolphinemu.overlay + +import android.graphics.Rect +import android.os.Handler +import android.os.Looper +import android.view.MotionEvent +import org.dolphinemu.dolphinemu.NativeLibrary +import org.dolphinemu.dolphinemu.features.input.model.InputOverrider + +class InputOverlayPointer( + surfacePosition: Rect, + private val doubleTapControl: Int, + private var mode: Int, + private var recenter: Boolean, + private val controllerIndex: Int +) { + var x = 0.0f + var y = 0.0f + private var oldX = 0.0f + private var oldY = 0.0f + + private val gameCenterX: Float + private val gameCenterY: Float + private val gameWidthHalfInv: Float + private val gameHeightHalfInv: Float + + private var touchStartX = 0f + private var touchStartY = 0f + + private var doubleTap = false + private var trackId = -1 + + init { + gameCenterX = (surfacePosition.left + surfacePosition.right) / 2f + gameCenterY = (surfacePosition.top + surfacePosition.bottom) / 2f + + var gameWidth = (surfacePosition.right - surfacePosition.left).toFloat() + var gameHeight = (surfacePosition.bottom - surfacePosition.top).toFloat() + + // Adjusting for device's black bars. + val surfaceAR = gameWidth / gameHeight + val gameAR = NativeLibrary.GetGameAspectRatio() + if (gameAR <= surfaceAR) { + // Black bars on left/right + gameWidth = gameHeight * gameAR + } else { + // Black bars on top/bottom + gameHeight = gameWidth / gameAR + } + + gameWidthHalfInv = 1f / (gameWidth * 0.5f) + gameHeightHalfInv = 1f / (gameHeight * 0.5f) + } + + fun onTouch(event: MotionEvent) { + val action = event.actionMasked + val firstPointer = action != MotionEvent.ACTION_POINTER_DOWN && + action != MotionEvent.ACTION_POINTER_UP + val pointerIndex = if (firstPointer) 0 else event.actionIndex + + when (action) { + MotionEvent.ACTION_DOWN, + MotionEvent.ACTION_POINTER_DOWN -> { + trackId = event.getPointerId(pointerIndex) + touchStartX = event.getX(pointerIndex) + touchStartY = event.getY(pointerIndex) + touchPress() + } + + MotionEvent.ACTION_UP, + MotionEvent.ACTION_POINTER_UP -> { + if (trackId == event.getPointerId(pointerIndex)) + trackId = -1 + if (mode == MODE_DRAG) + updateOldAxes() + if (recenter) + reset() + } + } + + val eventPointerIndex = event.findPointerIndex(trackId) + if (trackId == -1 || eventPointerIndex == -1) + return + + if (mode == MODE_FOLLOW) { + x = (event.getX(eventPointerIndex) - gameCenterX) * gameWidthHalfInv + y = (event.getY(eventPointerIndex) - gameCenterY) * gameHeightHalfInv + } else if (mode == MODE_DRAG) { + x = oldX + (event.getX(eventPointerIndex) - touchStartX) * gameWidthHalfInv + y = oldY + (event.getY(eventPointerIndex) - touchStartY) * gameHeightHalfInv + } + } + + private fun touchPress() { + if (mode != MODE_DISABLED) { + if (doubleTap) { + InputOverrider.setControlState(controllerIndex, doubleTapControl, 1.0) + Handler(Looper.myLooper()!!).postDelayed( + { + InputOverrider.setControlState(controllerIndex, doubleTapControl, 0.0) + }, + 50 + ) + } else { + doubleTap = true + Handler(Looper.myLooper()!!).postDelayed({ doubleTap = false }, 300) + } + } + } + + private fun updateOldAxes() { + oldX = x + oldY = y + } + + private fun reset() { + oldY = 0.0f + oldX = 0.0f + y = 0.0f + x = 0.0f + } + + fun setMode(mode: Int) { + this.mode = mode + if (mode == MODE_DRAG) + updateOldAxes() + } + + fun setRecenter(recenter: Boolean) { + this.recenter = recenter + } + + companion object { + const val MODE_DISABLED = 0 + const val MODE_FOLLOW = 1 + const val MODE_DRAG = 2 + + @JvmField + var DOUBLE_TAP_OPTIONS = arrayListOf( + NativeLibrary.ButtonType.WIIMOTE_BUTTON_A, + NativeLibrary.ButtonType.WIIMOTE_BUTTON_B, + NativeLibrary.ButtonType.WIIMOTE_BUTTON_2, + NativeLibrary.ButtonType.CLASSIC_BUTTON_A + ) + } +}