mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-22 23:02:47 +01:00
android: Convert InputOverlayDrawableJoystick to Kotlin
This commit is contained in:
parent
5c8372a566
commit
42b3e72e96
2 changed files with 205 additions and 243 deletions
|
@ -1,243 +0,0 @@
|
|||
/**
|
||||
* Copyright 2013 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;
|
||||
import org.yuzu.yuzu_emu.NativeLibrary.ButtonType;
|
||||
import org.yuzu.yuzu_emu.utils.EmulationMenuSettings;
|
||||
|
||||
/**
|
||||
* Custom {@link BitmapDrawable} that is capable
|
||||
* of storing it's own ID.
|
||||
*/
|
||||
public final class InputOverlayDrawableJoystick {
|
||||
// The ID value what type of joystick this Drawable represents.
|
||||
private int mJoystickId;
|
||||
// The ID value what type of button this Drawable represents.
|
||||
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 mWidth;
|
||||
private int mHeight;
|
||||
private Rect mVirtBounds;
|
||||
private Rect mOrigBounds;
|
||||
private BitmapDrawable mOuterBitmap;
|
||||
private BitmapDrawable mDefaultStateInnerBitmap;
|
||||
private BitmapDrawable mPressedStateInnerBitmap;
|
||||
private 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 joystick Identifier for which joystick this is.
|
||||
*/
|
||||
public InputOverlayDrawableJoystick(Resources res, Bitmap bitmapOuter,
|
||||
Bitmap bitmapInnerDefault, Bitmap bitmapInnerPressed,
|
||||
Rect rectOuter, Rect rectInner, int joystick, int button) {
|
||||
mJoystickId = joystick;
|
||||
mButtonId = button;
|
||||
|
||||
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();
|
||||
|
||||
setBounds(rectOuter);
|
||||
mDefaultStateInnerBitmap.setBounds(rectInner);
|
||||
mPressedStateInnerBitmap.setBounds(rectInner);
|
||||
mVirtBounds = getBounds();
|
||||
mOrigBounds = mOuterBitmap.copyBounds();
|
||||
mBoundsBoxBitmap.setAlpha(0);
|
||||
mBoundsBoxBitmap.setBounds(getVirtBounds());
|
||||
SetInnerBounds();
|
||||
}
|
||||
|
||||
public void draw(Canvas canvas) {
|
||||
mOuterBitmap.draw(canvas);
|
||||
getCurrentStateBitmapDrawable().draw(canvas);
|
||||
mBoundsBoxBitmap.draw(canvas);
|
||||
}
|
||||
|
||||
public boolean updateStatus(MotionEvent event) {
|
||||
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;
|
||||
}
|
||||
mPressedState = true;
|
||||
mOuterBitmap.setAlpha(0);
|
||||
mBoundsBoxBitmap.setAlpha(255);
|
||||
if (EmulationMenuSettings.getJoystickRelCenter()) {
|
||||
getVirtBounds().offset(xPosition - getVirtBounds().centerX(),
|
||||
yPosition - getVirtBounds().centerY());
|
||||
}
|
||||
mBoundsBoxBitmap.setBounds(getVirtBounds());
|
||||
mTrackId = pointerId;
|
||||
}
|
||||
|
||||
if (isActionUp) {
|
||||
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++) {
|
||||
if (mTrackId != event.getPointerId(i)) {
|
||||
continue;
|
||||
}
|
||||
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;
|
||||
final float oldXAxis = mXAxis;
|
||||
final float oldYAxis = mYAxis;
|
||||
|
||||
// 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 oldXAxis != mXAxis && oldYAxis != mYAxis;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SetInnerBounds() {
|
||||
int X = getVirtBounds().centerX() + (int) ((mXAxis) * (getVirtBounds().width() / 2));
|
||||
int Y = getVirtBounds().centerY() + (int) ((mYAxis) * (getVirtBounds().height() / 2));
|
||||
|
||||
if (X > getVirtBounds().centerX() + (getVirtBounds().width() / 2))
|
||||
X = getVirtBounds().centerX() + (getVirtBounds().width() / 2);
|
||||
if (X < getVirtBounds().centerX() - (getVirtBounds().width() / 2))
|
||||
X = getVirtBounds().centerX() - (getVirtBounds().width() / 2);
|
||||
if (Y > getVirtBounds().centerY() + (getVirtBounds().height() / 2))
|
||||
Y = getVirtBounds().centerY() + (getVirtBounds().height() / 2);
|
||||
if (Y < getVirtBounds().centerY() - (getVirtBounds().height() / 2))
|
||||
Y = getVirtBounds().centerY() - (getVirtBounds().height() / 2);
|
||||
|
||||
int width = mPressedStateInnerBitmap.getBounds().width() / 2;
|
||||
int height = mPressedStateInnerBitmap.getBounds().height() / 2;
|
||||
mDefaultStateInnerBitmap.setBounds(X - width, Y - height, X + width, Y + height);
|
||||
mPressedStateInnerBitmap.setBounds(mDefaultStateInnerBitmap.getBounds());
|
||||
}
|
||||
|
||||
public void setPosition(int x, int y) {
|
||||
mControlPositionX = x;
|
||||
mControlPositionY = y;
|
||||
}
|
||||
|
||||
private BitmapDrawable getCurrentStateBitmapDrawable() {
|
||||
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() {
|
||||
return mOuterBitmap.getBounds();
|
||||
}
|
||||
|
||||
public void setBounds(Rect bounds) {
|
||||
mOuterBitmap.setBounds(bounds);
|
||||
}
|
||||
|
||||
private Rect getVirtBounds() {
|
||||
return mVirtBounds;
|
||||
}
|
||||
|
||||
private void setVirtBounds(Rect bounds) {
|
||||
mVirtBounds = bounds;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return mWidth;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return mHeight;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
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
|
||||
import org.yuzu.yuzu_emu.utils.EmulationMenuSettings
|
||||
import kotlin.math.atan2
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
import kotlin.math.sqrt
|
||||
|
||||
/**
|
||||
* 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 joystickId The ID value what type of joystick this Drawable represents.
|
||||
* @param buttonId The ID value what type of button this Drawable represents.
|
||||
*/
|
||||
class InputOverlayDrawableJoystick(
|
||||
res: Resources,
|
||||
bitmapOuter: Bitmap,
|
||||
bitmapInnerDefault: Bitmap,
|
||||
bitmapInnerPressed: Bitmap,
|
||||
rectOuter: Rect,
|
||||
rectInner: Rect,
|
||||
val joystickId: Int,
|
||||
val buttonId: Int
|
||||
) {
|
||||
|
||||
// The ID value what motion event is tracking
|
||||
var trackId = -1
|
||||
var xAxis = 0f
|
||||
private var yAxis = 0f
|
||||
private var controlPositionX = 0
|
||||
private var controlPositionY = 0
|
||||
val width: Int
|
||||
val height: Int
|
||||
private var virtBounds: Rect
|
||||
private val origBounds: Rect
|
||||
private val outerBitmap: BitmapDrawable
|
||||
private val defaultStateInnerBitmap: BitmapDrawable
|
||||
private val pressedStateInnerBitmap: BitmapDrawable
|
||||
private val boundsBoxBitmap: BitmapDrawable
|
||||
private var pressedState = false
|
||||
|
||||
// TODO: Add button support
|
||||
val buttonStatus: Int
|
||||
get() =
|
||||
NativeLibrary.ButtonState.RELEASED
|
||||
var bounds: Rect?
|
||||
get() = outerBitmap.bounds
|
||||
set(bounds) {
|
||||
outerBitmap.bounds = bounds!!
|
||||
}
|
||||
|
||||
// Nintendo joysticks have y axis inverted
|
||||
val realYAxis: Float
|
||||
get() = -yAxis
|
||||
|
||||
private val currentStateBitmapDrawable: BitmapDrawable
|
||||
get() = if (pressedState) pressedStateInnerBitmap else defaultStateInnerBitmap
|
||||
|
||||
init {
|
||||
outerBitmap = BitmapDrawable(res, bitmapOuter)
|
||||
defaultStateInnerBitmap = BitmapDrawable(res, bitmapInnerDefault)
|
||||
pressedStateInnerBitmap = BitmapDrawable(res, bitmapInnerPressed)
|
||||
boundsBoxBitmap = BitmapDrawable(res, bitmapOuter)
|
||||
width = bitmapOuter.width
|
||||
height = bitmapOuter.height
|
||||
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 updateStatus(event: MotionEvent): 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
|
||||
}
|
||||
pressedState = true
|
||||
outerBitmap.alpha = 0
|
||||
boundsBoxBitmap.alpha = 255
|
||||
if (EmulationMenuSettings.joystickRelCenter) {
|
||||
virtBounds.offset(
|
||||
xPosition - virtBounds.centerX(),
|
||||
yPosition - virtBounds.centerY()
|
||||
)
|
||||
}
|
||||
boundsBoxBitmap.bounds = virtBounds
|
||||
trackId = pointerId
|
||||
}
|
||||
if (isActionUp) {
|
||||
if (trackId != pointerId) {
|
||||
return false
|
||||
}
|
||||
pressedState = false
|
||||
xAxis = 0.0f
|
||||
yAxis = 0.0f
|
||||
outerBitmap.alpha = 255
|
||||
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
|
||||
return true
|
||||
}
|
||||
if (trackId == -1) 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 = virtBounds.bottom.toFloat()
|
||||
var maxX = virtBounds.right.toFloat()
|
||||
touchX -= virtBounds.centerX().toFloat()
|
||||
maxX -= virtBounds.centerX().toFloat()
|
||||
touchY -= virtBounds.centerY().toFloat()
|
||||
maxY -= virtBounds.centerY().toFloat()
|
||||
val axisX = touchX / maxX
|
||||
val axisY = touchY / maxY
|
||||
val oldXAxis = xAxis
|
||||
val oldYAxis = yAxis
|
||||
|
||||
// Clamp the circle pad input to a circle
|
||||
val angle = atan2(axisY.toDouble(), axisX.toDouble()).toFloat()
|
||||
var radius = sqrt((axisX * axisX + axisY * axisY).toDouble()).toFloat()
|
||||
if (radius > 1.0f) {
|
||||
radius = 1.0f
|
||||
}
|
||||
xAxis = cos(angle.toDouble()).toFloat() * radius
|
||||
yAxis = sin(angle.toDouble()).toFloat() * radius
|
||||
setInnerBounds()
|
||||
return oldXAxis != xAxis && oldYAxis != yAxis
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun setInnerBounds() {
|
||||
var x = virtBounds.centerX() + (xAxis * (virtBounds.width() / 2)).toInt()
|
||||
var y = virtBounds.centerY() + (yAxis * (virtBounds.height() / 2)).toInt()
|
||||
if (x > virtBounds.centerX() + virtBounds.width() / 2) x =
|
||||
virtBounds.centerX() + virtBounds.width() / 2
|
||||
if (x < virtBounds.centerX() - virtBounds.width() / 2) x =
|
||||
virtBounds.centerX() - virtBounds.width() / 2
|
||||
if (y > virtBounds.centerY() + virtBounds.height() / 2) y =
|
||||
virtBounds.centerY() + virtBounds.height() / 2
|
||||
if (y < virtBounds.centerY() - virtBounds.height() / 2) y =
|
||||
virtBounds.centerY() - virtBounds.height() / 2
|
||||
val width = pressedStateInnerBitmap.bounds.width() / 2
|
||||
val height = pressedStateInnerBitmap.bounds.height() / 2
|
||||
defaultStateInnerBitmap.setBounds(
|
||||
x - width,
|
||||
y - height,
|
||||
x + width,
|
||||
y + height
|
||||
)
|
||||
pressedStateInnerBitmap.bounds = defaultStateInnerBitmap.bounds
|
||||
}
|
||||
|
||||
fun setPosition(x: Int, y: Int) {
|
||||
controlPositionX = x
|
||||
controlPositionY = y
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue