From d85678a80fe75b2b8c85d37b8ccd52972696fe9b Mon Sep 17 00:00:00 2001 From: Charles Lombardo Date: Wed, 8 Mar 2023 20:49:24 -0500 Subject: [PATCH] android: Convert InputOverlayDrawableDpad to Kotlin --- .../overlay/InputOverlayDrawableDpad.java | 276 ------------------ .../overlay/InputOverlayDrawableDpad.kt | 232 +++++++++++++++ 2 files changed, 232 insertions(+), 276 deletions(-) delete mode 100644 src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableDpad.java create mode 100644 src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableDpad.kt diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableDpad.java b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableDpad.java deleted file mode 100644 index 1d10b1e65e..0000000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableDpad.java +++ /dev/null @@ -1,276 +0,0 @@ -/** - * Copyright 2016 Dolphin Emulator Project - * Licensed under GPLv2+ - * Refer to the license.txt file included. - */ - -package org.yuzu.yuzu_emu.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.yuzu.yuzu_emu.NativeLibrary.ButtonState; - -/** - * Custom {@link BitmapDrawable} that is capable - * of storing it's own ID. - */ -public final class InputOverlayDrawableDpad { - public static final float VIRT_AXIS_DEADZONE = 0.5f; - // The ID identifying what type of button this Drawable represents. - private int mUpButtonId; - private int mDownButtonId; - private int mLeftButtonId; - private int mRightButtonId; - private int mTrackId; - private int mControlPositionX, mControlPositionY; - private int mWidth; - private int mHeight; - private BitmapDrawable mDefaultStateBitmap; - private BitmapDrawable mPressedOneDirectionStateBitmap; - private BitmapDrawable mPressedTwoDirectionsStateBitmap; - private boolean mUpButtonState; - private boolean mDownButtonState; - private boolean mLeftButtonState; - private boolean mRightButtonState; - - /** - * Constructor - * - * @param res {@link Resources} instance. - * @param defaultStateBitmap {@link Bitmap} of the default state. - * @param pressedOneDirectionStateBitmap {@link Bitmap} of the pressed state in one direction. - * @param pressedTwoDirectionsStateBitmap {@link Bitmap} of the pressed state in two direction. - * @param buttonUp Identifier for the up button. - * @param buttonDown Identifier for the down button. - * @param buttonLeft Identifier for the left button. - * @param buttonRight Identifier for the right button. - */ - public InputOverlayDrawableDpad(Resources res, - Bitmap defaultStateBitmap, - Bitmap pressedOneDirectionStateBitmap, - Bitmap pressedTwoDirectionsStateBitmap, - int buttonUp, int buttonDown, - int buttonLeft, int buttonRight) { - mDefaultStateBitmap = new BitmapDrawable(res, defaultStateBitmap); - mPressedOneDirectionStateBitmap = new BitmapDrawable(res, pressedOneDirectionStateBitmap); - mPressedTwoDirectionsStateBitmap = new BitmapDrawable(res, pressedTwoDirectionsStateBitmap); - - mWidth = mDefaultStateBitmap.getIntrinsicWidth(); - mHeight = mDefaultStateBitmap.getIntrinsicHeight(); - - mUpButtonId = buttonUp; - mDownButtonId = buttonDown; - mLeftButtonId = buttonLeft; - mRightButtonId = buttonRight; - - mTrackId = -1; - } - - public boolean updateStatus(MotionEvent event, boolean dpad_slide) { - 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; - - if (isActionDown) { - if (!getBounds().contains(xPosition, yPosition)) { - return false; - } - mTrackId = pointerId; - } - - if (isActionUp) { - if (mTrackId != pointerId) { - return false; - } - mTrackId = -1; - mUpButtonState = false; - mDownButtonState = false; - mLeftButtonState = false; - mRightButtonState = false; - return true; - } - - if (mTrackId == -1) { - return false; - } - - if (!dpad_slide && !isActionDown) { - return false; - } - - for (int i = 0; i < event.getPointerCount(); i++) { - if (mTrackId != event.getPointerId(i)) { - continue; - } - float touchX = event.getX(i); - float touchY = event.getY(i); - float maxY = getBounds().bottom; - float maxX = getBounds().right; - touchX -= getBounds().centerX(); - maxX -= getBounds().centerX(); - touchY -= getBounds().centerY(); - maxY -= getBounds().centerY(); - final float AxisX = touchX / maxX; - final float AxisY = touchY / maxY; - final boolean up_state = mUpButtonState; - final boolean down_state = mDownButtonState; - final boolean left_state = mLeftButtonState; - final boolean right_state = mRightButtonState; - - mUpButtonState = AxisY < -InputOverlayDrawableDpad.VIRT_AXIS_DEADZONE; - mDownButtonState = AxisY > InputOverlayDrawableDpad.VIRT_AXIS_DEADZONE; - mLeftButtonState = AxisX < -InputOverlayDrawableDpad.VIRT_AXIS_DEADZONE; - mRightButtonState = AxisX > InputOverlayDrawableDpad.VIRT_AXIS_DEADZONE; - return up_state != mUpButtonState || down_state != mDownButtonState || left_state != mLeftButtonState || right_state != mRightButtonState; - } - - return false; - } - - public void draw(Canvas canvas) { - int px = mControlPositionX + (getWidth() / 2); - int py = mControlPositionY + (getHeight() / 2); - - // Pressed up - if (mUpButtonState && !mLeftButtonState && !mRightButtonState) { - mPressedOneDirectionStateBitmap.draw(canvas); - return; - } - - // Pressed down - if (mDownButtonState && !mLeftButtonState && !mRightButtonState) { - canvas.save(); - canvas.rotate(180, px, py); - mPressedOneDirectionStateBitmap.draw(canvas); - canvas.restore(); - return; - } - - // Pressed left - if (mLeftButtonState && !mUpButtonState && !mDownButtonState) { - canvas.save(); - canvas.rotate(270, px, py); - mPressedOneDirectionStateBitmap.draw(canvas); - canvas.restore(); - return; - } - - // Pressed right - if (mRightButtonState && !mUpButtonState && !mDownButtonState) { - canvas.save(); - canvas.rotate(90, px, py); - mPressedOneDirectionStateBitmap.draw(canvas); - canvas.restore(); - return; - } - - // Pressed up left - if (mUpButtonState && mLeftButtonState && !mRightButtonState) { - mPressedTwoDirectionsStateBitmap.draw(canvas); - return; - } - - // Pressed up right - if (mUpButtonState && !mLeftButtonState && mRightButtonState) { - canvas.save(); - canvas.rotate(90, px, py); - mPressedTwoDirectionsStateBitmap.draw(canvas); - canvas.restore(); - return; - } - - // Pressed down left - if (mDownButtonState && mLeftButtonState && !mRightButtonState) { - canvas.save(); - canvas.rotate(270, px, py); - mPressedTwoDirectionsStateBitmap.draw(canvas); - canvas.restore(); - return; - } - - // Pressed down right - if (mDownButtonState && !mLeftButtonState && mRightButtonState) { - canvas.save(); - canvas.rotate(180, px, py); - mPressedTwoDirectionsStateBitmap.draw(canvas); - canvas.restore(); - return; - } - - // Not pressed - mDefaultStateBitmap.draw(canvas); - } - - /** - * Gets one of the InputOverlayDrawableDpad's button IDs. - * - * @return the requested InputOverlayDrawableDpad's button ID. - */ - public int getUpId() { - return mUpButtonId; - } - - public int getDownId() { - return mDownButtonId; - } - - public int getLeftId() { - return mLeftButtonId; - } - - public int getRightId() { - return mRightButtonId; - } - - public int getTrackId() { - return mTrackId; - } - - public int getUpStatus() { - return mUpButtonState ? ButtonState.PRESSED : ButtonState.RELEASED; - } - - public int getDownStatus() { - return mDownButtonState ? ButtonState.PRESSED : ButtonState.RELEASED; - } - - public int getLeftStatus() { - return mLeftButtonState ? ButtonState.PRESSED : ButtonState.RELEASED; - } - - public int getRightStatus() { - return mRightButtonState ? ButtonState.PRESSED : ButtonState.RELEASED; - } - - public void setPosition(int x, int y) { - mControlPositionX = x; - mControlPositionY = y; - } - - public void setBounds(int left, int top, int right, int bottom) { - mDefaultStateBitmap.setBounds(left, top, right, bottom); - mPressedOneDirectionStateBitmap.setBounds(left, top, right, bottom); - mPressedTwoDirectionsStateBitmap.setBounds(left, top, right, bottom); - } - - public Rect getBounds() { - return mDefaultStateBitmap.getBounds(); - } - - public int getWidth() { - return mWidth; - } - - public int getHeight() { - return mHeight; - } -} diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableDpad.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableDpad.kt new file mode 100644 index 0000000000..55e99d4657 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableDpad.kt @@ -0,0 +1,232 @@ +package org.yuzu.yuzu_emu.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.yuzu.yuzu_emu.NativeLibrary.ButtonState + +/** + * Custom [BitmapDrawable] that is capable + * of storing it's own ID. + * + * @param res [Resources] instance. + * @param defaultStateBitmap [Bitmap] of the default state. + * @param pressedOneDirectionStateBitmap [Bitmap] of the pressed state in one direction. + * @param pressedTwoDirectionsStateBitmap [Bitmap] of the pressed state in two direction. + * @param buttonUp Identifier for the up button. + * @param buttonDown Identifier for the down button. + * @param buttonLeft Identifier for the left button. + * @param buttonRight Identifier for the right button. + */ +class InputOverlayDrawableDpad( + res: Resources, + defaultStateBitmap: Bitmap, + pressedOneDirectionStateBitmap: Bitmap, + pressedTwoDirectionsStateBitmap: Bitmap, + buttonUp: Int, + buttonDown: Int, + buttonLeft: Int, + buttonRight: Int +) { + /** + * Gets one of the InputOverlayDrawableDpad's button IDs. + * + * @return the requested InputOverlayDrawableDpad's button ID. + */ + // The ID identifying what type of button this Drawable represents. + val upId: Int + val downId: Int + val leftId: Int + val rightId: Int + var trackId: Int + private var controlPositionX = 0 + private var controlPositionY = 0 + val width: Int + val height: Int + private val defaultStateBitmap: BitmapDrawable + private val pressedOneDirectionStateBitmap: BitmapDrawable + private val pressedTwoDirectionsStateBitmap: BitmapDrawable + private var upButtonState = false + private var downButtonState = false + private var leftButtonState = false + private var rightButtonState = false + + init { + this.defaultStateBitmap = BitmapDrawable(res, defaultStateBitmap) + this.pressedOneDirectionStateBitmap = BitmapDrawable(res, pressedOneDirectionStateBitmap) + this.pressedTwoDirectionsStateBitmap = BitmapDrawable(res, pressedTwoDirectionsStateBitmap) + width = this.defaultStateBitmap.intrinsicWidth + height = this.defaultStateBitmap.intrinsicHeight + upId = buttonUp + downId = buttonDown + leftId = buttonLeft + rightId = buttonRight + trackId = -1 + } + + fun updateStatus(event: MotionEvent, dpad_slide: Boolean): Boolean { + val pointerIndex = event.actionIndex + val xPosition = event.getX(pointerIndex).toInt() + val yPosition = event.getY(pointerIndex).toInt() + val pointerId = event.getPointerId(pointerIndex) + val motionEvent = event.action and MotionEvent.ACTION_MASK + val isActionDown = + motionEvent == MotionEvent.ACTION_DOWN || motionEvent == MotionEvent.ACTION_POINTER_DOWN + val isActionUp = + motionEvent == MotionEvent.ACTION_UP || motionEvent == MotionEvent.ACTION_POINTER_UP + if (isActionDown) { + if (!bounds.contains(xPosition, yPosition)) { + return false + } + trackId = pointerId + } + if (isActionUp) { + if (trackId != pointerId) { + return false + } + trackId = -1 + upButtonState = false + downButtonState = false + leftButtonState = false + rightButtonState = false + return true + } + if (trackId == -1) { + return false + } + if (!dpad_slide && !isActionDown) { + return false + } + for (i in 0 until event.pointerCount) { + if (trackId != event.getPointerId(i)) { + continue + } + + var touchX = event.getX(i) + var touchY = event.getY(i) + var maxY = bounds.bottom.toFloat() + var maxX = bounds.right.toFloat() + touchX -= bounds.centerX().toFloat() + maxX -= bounds.centerX().toFloat() + touchY -= bounds.centerY().toFloat() + maxY -= bounds.centerY().toFloat() + val axisX = touchX / maxX + val axisY = touchY / maxY + val oldUpState = upButtonState + val oldDownState = downButtonState + val oldLeftState = leftButtonState + val oldRightState = rightButtonState + + upButtonState = axisY < -VIRT_AXIS_DEADZONE + downButtonState = axisY > VIRT_AXIS_DEADZONE + leftButtonState = axisX < -VIRT_AXIS_DEADZONE + rightButtonState = axisX > VIRT_AXIS_DEADZONE + return oldUpState != upButtonState || oldDownState != downButtonState || oldLeftState != leftButtonState || oldRightState != rightButtonState + } + return false + } + + fun draw(canvas: Canvas) { + val px = controlPositionX + width / 2 + val py = controlPositionY + height / 2 + + // Pressed up + if (upButtonState && !leftButtonState && !rightButtonState) { + pressedOneDirectionStateBitmap.draw(canvas) + return + } + + // Pressed down + if (downButtonState && !leftButtonState && !rightButtonState) { + canvas.save() + canvas.rotate(180f, px.toFloat(), py.toFloat()) + pressedOneDirectionStateBitmap.draw(canvas) + canvas.restore() + return + } + + // Pressed left + if (leftButtonState && !upButtonState && !downButtonState) { + canvas.save() + canvas.rotate(270f, px.toFloat(), py.toFloat()) + pressedOneDirectionStateBitmap.draw(canvas) + canvas.restore() + return + } + + // Pressed right + if (rightButtonState && !upButtonState && !downButtonState) { + canvas.save() + canvas.rotate(90f, px.toFloat(), py.toFloat()) + pressedOneDirectionStateBitmap.draw(canvas) + canvas.restore() + return + } + + // Pressed up left + if (upButtonState && leftButtonState && !rightButtonState) { + pressedTwoDirectionsStateBitmap.draw(canvas) + return + } + + // Pressed up right + if (upButtonState && !leftButtonState && rightButtonState) { + canvas.save() + canvas.rotate(90f, px.toFloat(), py.toFloat()) + pressedTwoDirectionsStateBitmap.draw(canvas) + canvas.restore() + return + } + + // Pressed down right + if (downButtonState && !leftButtonState && rightButtonState) { + canvas.save() + canvas.rotate(180f, px.toFloat(), py.toFloat()) + pressedTwoDirectionsStateBitmap.draw(canvas) + canvas.restore() + return + } + + // Pressed down left + if (downButtonState && leftButtonState && !rightButtonState) { + canvas.save() + canvas.rotate(270f, px.toFloat(), py.toFloat()) + pressedTwoDirectionsStateBitmap.draw(canvas) + canvas.restore() + return + } + + // Not pressed + defaultStateBitmap.draw(canvas) + } + + val upStatus: Int + get() = if (upButtonState) ButtonState.PRESSED else ButtonState.RELEASED + val downStatus: Int + get() = if (downButtonState) ButtonState.PRESSED else ButtonState.RELEASED + val leftStatus: Int + get() = if (leftButtonState) ButtonState.PRESSED else ButtonState.RELEASED + val rightStatus: Int + get() = if (rightButtonState) ButtonState.PRESSED else ButtonState.RELEASED + + fun setPosition(x: Int, y: Int) { + controlPositionX = x + controlPositionY = y + } + + fun setBounds(left: Int, top: Int, right: Int, bottom: Int) { + defaultStateBitmap.setBounds(left, top, right, bottom) + pressedOneDirectionStateBitmap.setBounds(left, top, right, bottom) + pressedTwoDirectionsStateBitmap.setBounds(left, top, right, bottom) + } + + val bounds: Rect + get() = defaultStateBitmap.bounds + + companion object { + const val VIRT_AXIS_DEADZONE = 0.5f + } +}