android: Convert InputOverlayDrawableDpad to Kotlin

merge-requests/60/head
Charles Lombardo 2023-03-08 20:49:24 +07:00 committed by bunnei
parent 0177e908e9
commit d85678a80f
2 changed files with 232 additions and 276 deletions

@ -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;
}
}

@ -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
}
}