summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCharles Lombardo <clombardo169@gmail.com>2023-03-24 08:18:19 +0100
committerbunnei <bunneidev@gmail.com>2023-06-03 09:05:47 +0200
commitb0a434b99fbfa9052ad44b15a70c4fef99aff1e3 (patch)
treeea64daea6849b5850ca5e0adc2f15d267308f971
parentandroid: Fix popup menu going out of bounds (diff)
downloadyuzu-b0a434b99fbfa9052ad44b15a70c4fef99aff1e3.tar
yuzu-b0a434b99fbfa9052ad44b15a70c4fef99aff1e3.tar.gz
yuzu-b0a434b99fbfa9052ad44b15a70c4fef99aff1e3.tar.bz2
yuzu-b0a434b99fbfa9052ad44b15a70c4fef99aff1e3.tar.lz
yuzu-b0a434b99fbfa9052ad44b15a70c4fef99aff1e3.tar.xz
yuzu-b0a434b99fbfa9052ad44b15a70c4fef99aff1e3.tar.zst
yuzu-b0a434b99fbfa9052ad44b15a70c4fef99aff1e3.zip
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt1
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt113
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableButton.kt48
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableDpad.kt36
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.kt72
5 files changed, 245 insertions, 25 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
index 4ba283ddd..18517bdf8 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
@@ -90,7 +90,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
binding.doneControlConfig.setOnClickListener { stopConfiguringControls() }
// Setup overlay.
- resetInputOverlay()
updateShowFpsOverlay()
binding.inGameMenu.getHeaderView(0).findViewById<TextView>(R.id.text_game_title).text =
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt
index acd4a1fe2..97e0ba3df 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt
@@ -45,9 +45,15 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
private val overlayButtons: MutableSet<InputOverlayDrawableButton> = HashSet()
private val overlayDpads: MutableSet<InputOverlayDrawableDpad> = HashSet()
private val overlayJoysticks: MutableSet<InputOverlayDrawableJoystick> = HashSet()
+
private var inEditMode = false
+ private var buttonBeingConfigured: InputOverlayDrawableButton? = null
+ private var dpadBeingConfigured: InputOverlayDrawableDpad? = null
+ private var joystickBeingConfigured: InputOverlayDrawableJoystick? = null
+
private val preferences: SharedPreferences =
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
+
private val gyro = FloatArray(3)
private val accel = FloatArray(3)
private var motionTimestamp: Long = 0
@@ -114,7 +120,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
}
NativeLibrary.onGamePadButtonEvent(
NativeLibrary.Player1Device,
- button.id,
+ button.buttonId,
button.status
)
shouldUpdateView = true
@@ -224,8 +230,109 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
return false
}
- private fun onTouchWhileEditing(event: MotionEvent?): Boolean {
- // TODO: Reimplement this
+ private fun onTouchWhileEditing(event: MotionEvent): Boolean {
+ val pointerIndex = event.actionIndex
+ val fingerPositionX = event.getX(pointerIndex).toInt()
+ val fingerPositionY = event.getY(pointerIndex).toInt()
+
+ // TODO: Provide support for portrait layout
+ //val orientation =
+ // if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) "-Portrait" else ""
+
+ for (button in overlayButtons) {
+ // Determine the button state to apply based on the MotionEvent action flag.
+ when (event.action and MotionEvent.ACTION_MASK) {
+ MotionEvent.ACTION_DOWN,
+ MotionEvent.ACTION_POINTER_DOWN ->
+ // If no button is being moved now, remember the currently touched button to move.
+ if (buttonBeingConfigured == null &&
+ button.bounds.contains(
+ fingerPositionX,
+ fingerPositionY
+ )
+ ) {
+ buttonBeingConfigured = button
+ buttonBeingConfigured!!.onConfigureTouch(event)
+ }
+ MotionEvent.ACTION_MOVE -> if (buttonBeingConfigured != null) {
+ buttonBeingConfigured!!.onConfigureTouch(event)
+ invalidate()
+ return true
+ }
+ MotionEvent.ACTION_UP,
+ MotionEvent.ACTION_POINTER_UP -> if (buttonBeingConfigured === button) {
+ // Persist button position by saving new place.
+ saveControlPosition(
+ buttonBeingConfigured!!.buttonId,
+ buttonBeingConfigured!!.bounds.centerX(),
+ buttonBeingConfigured!!.bounds.centerY(),
+ ""
+ )
+ buttonBeingConfigured = null
+ }
+ }
+ }
+
+ for (dpad in overlayDpads) {
+ // Determine the button state to apply based on the MotionEvent action flag.
+ when (event.action and MotionEvent.ACTION_MASK) {
+ MotionEvent.ACTION_DOWN,
+ MotionEvent.ACTION_POINTER_DOWN ->
+ // If no button is being moved now, remember the currently touched button to move.
+ if (buttonBeingConfigured == null &&
+ dpad.bounds.contains(fingerPositionX, fingerPositionY)
+ ) {
+ dpadBeingConfigured = dpad
+ dpadBeingConfigured!!.onConfigureTouch(event)
+ }
+ MotionEvent.ACTION_MOVE -> if (dpadBeingConfigured != null) {
+ dpadBeingConfigured!!.onConfigureTouch(event)
+ invalidate()
+ return true
+ }
+ MotionEvent.ACTION_UP,
+ MotionEvent.ACTION_POINTER_UP -> if (dpadBeingConfigured === dpad) {
+ // Persist button position by saving new place.
+ saveControlPosition(
+ dpadBeingConfigured!!.upId,
+ dpadBeingConfigured!!.bounds.centerX(),
+ dpadBeingConfigured!!.bounds.centerY(),
+ ""
+ )
+ dpadBeingConfigured = null
+ }
+ }
+ }
+
+ for (joystick in overlayJoysticks) {
+ when (event.action) {
+ MotionEvent.ACTION_DOWN,
+ MotionEvent.ACTION_POINTER_DOWN -> if (joystickBeingConfigured == null &&
+ joystick.bounds.contains(
+ fingerPositionX,
+ fingerPositionY
+ )
+ ) {
+ joystickBeingConfigured = joystick
+ joystickBeingConfigured!!.onConfigureTouch(event)
+ }
+ MotionEvent.ACTION_MOVE -> if (joystickBeingConfigured != null) {
+ joystickBeingConfigured!!.onConfigureTouch(event)
+ invalidate()
+ }
+ MotionEvent.ACTION_UP,
+ MotionEvent.ACTION_POINTER_UP -> if (joystickBeingConfigured != null) {
+ saveControlPosition(
+ joystickBeingConfigured!!.buttonId,
+ joystickBeingConfigured!!.bounds.centerX(),
+ joystickBeingConfigured!!.bounds.centerY(),
+ ""
+ )
+ joystickBeingConfigured = null
+ }
+ }
+ }
+
return true
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableButton.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableButton.kt
index bf0c2f3e6..99d7d9521 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableButton.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableButton.kt
@@ -24,32 +24,30 @@ class InputOverlayDrawableButton(
res: Resources,
defaultStateBitmap: Bitmap,
pressedStateBitmap: Bitmap,
- buttonId: Int
+ val buttonId: Int
) {
- /**
- * Gets this InputOverlayDrawableButton's button ID.
- *
- * @return this InputOverlayDrawableButton's button ID.
- */
- // The ID value what type of button this Drawable represents.
- val id: Int
-
// The ID value what motion event is tracking
var trackId: Int
// The drawable position on the screen
private var buttonPositionX = 0
private var buttonPositionY = 0
+
val width: Int
val height: Int
+
private val defaultStateBitmap: BitmapDrawable
private val pressedStateBitmap: BitmapDrawable
private var pressedState = false
+ private var previousTouchX = 0
+ private var previousTouchY = 0
+ var controlPositionX = 0
+ var controlPositionY = 0
+
init {
this.defaultStateBitmap = BitmapDrawable(res, defaultStateBitmap)
this.pressedStateBitmap = BitmapDrawable(res, pressedStateBitmap)
- id = buttonId
trackId = -1
width = this.defaultStateBitmap.intrinsicWidth
height = this.defaultStateBitmap.intrinsicHeight
@@ -104,6 +102,34 @@ class InputOverlayDrawableButton(
private val currentStateBitmapDrawable: BitmapDrawable
get() = if (pressedState) pressedStateBitmap else defaultStateBitmap
+ fun onConfigureTouch(event: MotionEvent): Boolean {
+ val pointerIndex = event.actionIndex
+ val fingerPositionX = event.getX(pointerIndex).toInt()
+ val fingerPositionY = event.getY(pointerIndex).toInt()
+
+ when (event.action) {
+ MotionEvent.ACTION_DOWN -> {
+ previousTouchX = fingerPositionX
+ previousTouchY = fingerPositionY
+ controlPositionX = fingerPositionX - (width / 2)
+ controlPositionY = fingerPositionY - (height / 2)
+ }
+ MotionEvent.ACTION_MOVE -> {
+ controlPositionX += fingerPositionX - previousTouchX
+ controlPositionY += fingerPositionY - previousTouchY
+ setBounds(
+ controlPositionX,
+ controlPositionY,
+ width + controlPositionX,
+ height + controlPositionY
+ )
+ previousTouchX = fingerPositionX
+ previousTouchY = fingerPositionY
+ }
+ }
+ return true
+ }
+
fun setBounds(left: Int, top: Int, right: Int, bottom: Int) {
defaultStateBitmap.setBounds(left, top, right, bottom)
pressedStateBitmap.setBounds(left, top, right, bottom)
@@ -111,6 +137,6 @@ class InputOverlayDrawableButton(
val status: Int
get() = if (pressedState) ButtonState.PRESSED else ButtonState.RELEASED
- private val bounds: Rect
+ val bounds: Rect
get() = defaultStateBitmap.bounds
}
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
index 34d18eb1d..625cad661 100644
--- 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
@@ -45,13 +45,19 @@ class InputOverlayDrawableDpad(
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 previousTouchX = 0
+ private var previousTouchY = 0
+ private var controlPositionX = 0
+ private var controlPositionY = 0
+
private var upButtonState = false
private var downButtonState = false
private var leftButtonState = false
@@ -215,6 +221,32 @@ class InputOverlayDrawableDpad(
val rightStatus: Int
get() = if (rightButtonState) ButtonState.PRESSED else ButtonState.RELEASED
+ fun onConfigureTouch(event: MotionEvent): Boolean {
+ val pointerIndex = event.actionIndex
+ val fingerPositionX = event.getX(pointerIndex).toInt()
+ val fingerPositionY = event.getY(pointerIndex).toInt()
+
+ when (event.action) {
+ MotionEvent.ACTION_DOWN -> {
+ previousTouchX = fingerPositionX
+ previousTouchY = fingerPositionY
+ }
+ MotionEvent.ACTION_MOVE -> {
+ controlPositionX += fingerPositionX - previousTouchX
+ controlPositionY += fingerPositionY - previousTouchY
+ setBounds(
+ controlPositionX,
+ controlPositionY,
+ width + controlPositionX,
+ height + controlPositionY
+ )
+ previousTouchX = fingerPositionX
+ previousTouchY = fingerPositionY
+ }
+ }
+ return true
+ }
+
fun setPosition(x: Int, y: Int) {
controlPositionX = x
controlPositionY = y
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.kt
index 11ab0b829..1960eaff0 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.kt
@@ -39,31 +39,39 @@ class InputOverlayDrawableJoystick(
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 var origBounds: Rect
+
private val outerBitmap: BitmapDrawable
private val defaultStateInnerBitmap: BitmapDrawable
private val pressedStateInnerBitmap: BitmapDrawable
+
+ private var previousTouchX = 0
+ private var previousTouchY = 0
+ var controlPositionX = 0
+ var controlPositionY = 0
+
private val boundsBoxBitmap: BitmapDrawable
+
private var pressedState = false
// TODO: Add button support
val buttonStatus: Int
get() =
NativeLibrary.ButtonState.RELEASED
- var bounds: Rect?
+ var bounds: Rect
get() = outerBitmap.bounds
set(bounds) {
- outerBitmap.bounds = bounds!!
+ outerBitmap.bounds = bounds
}
// Nintendo joysticks have y axis inverted
@@ -83,7 +91,7 @@ class InputOverlayDrawableJoystick(
bounds = rectOuter
defaultStateInnerBitmap.bounds = rectInner
pressedStateInnerBitmap.bounds = rectInner
- virtBounds = bounds!!
+ virtBounds = bounds
origBounds = outerBitmap.copyBounds()
boundsBoxBitmap.alpha = 0
boundsBoxBitmap.bounds = virtBounds
@@ -106,8 +114,9 @@ class InputOverlayDrawableJoystick(
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)) {
+ if (!bounds.contains(xPosition, yPosition)) {
return false
}
pressedState = true
@@ -122,6 +131,7 @@ class InputOverlayDrawableJoystick(
boundsBoxBitmap.bounds = virtBounds
trackId = pointerId
}
+
if (isActionUp) {
if (trackId != pointerId) {
return false
@@ -147,7 +157,9 @@ class InputOverlayDrawableJoystick(
trackId = -1
return true
}
+
if (trackId == -1) return false
+
for (i in 0 until event.pointerCount) {
if (trackId != event.getPointerId(i)) {
continue
@@ -179,6 +191,50 @@ class InputOverlayDrawableJoystick(
return false
}
+ fun onConfigureTouch(event: MotionEvent): Boolean {
+ val pointerIndex = event.actionIndex
+ val fingerPositionX = event.getX(pointerIndex).toInt()
+ val fingerPositionY = event.getY(pointerIndex).toInt()
+
+ when (event.action) {
+ MotionEvent.ACTION_DOWN -> {
+ previousTouchX = fingerPositionX
+ previousTouchY = fingerPositionY
+ controlPositionX = fingerPositionX - (width / 2)
+ controlPositionY = fingerPositionY - (height / 2)
+ }
+ MotionEvent.ACTION_MOVE -> {
+ controlPositionX += fingerPositionX - previousTouchX
+ controlPositionY += fingerPositionY - previousTouchY
+ bounds = Rect(
+ controlPositionX,
+ controlPositionY,
+ outerBitmap.intrinsicWidth + controlPositionX,
+ outerBitmap.intrinsicHeight + controlPositionY
+ )
+ virtBounds = Rect(
+ controlPositionX,
+ controlPositionY,
+ outerBitmap.intrinsicWidth + controlPositionX,
+ outerBitmap.intrinsicHeight + controlPositionY
+ )
+ setInnerBounds()
+ bounds = Rect(
+ Rect(
+ controlPositionX,
+ controlPositionY,
+ outerBitmap.intrinsicWidth + controlPositionX,
+ outerBitmap.intrinsicHeight + controlPositionY
+ )
+ )
+ previousTouchX = fingerPositionX
+ previousTouchY = fingerPositionY
+ }
+ }
+ origBounds = outerBitmap.copyBounds()
+ return true
+ }
+
private fun setInnerBounds() {
var x = virtBounds.centerX() + (xAxis * (virtBounds.width() / 2)).toInt()
var y = virtBounds.centerY() + (yAxis * (virtBounds.height() / 2)).toInt()