summaryrefslogtreecommitdiffstats
path: root/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableButton.kt
diff options
context:
space:
mode:
Diffstat (limited to 'src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableButton.kt')
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableButton.kt148
1 files changed, 148 insertions, 0 deletions
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
new file mode 100644
index 000000000..4a93e0b14
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableButton.kt
@@ -0,0 +1,148 @@
+// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+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] to use with the default state Drawable.
+ * @param pressedStateBitmap [Bitmap] to use with the pressed state Drawable.
+ * @param buttonId Identifier for this type of button.
+ */
+class InputOverlayDrawableButton(
+ res: Resources,
+ defaultStateBitmap: Bitmap,
+ pressedStateBitmap: Bitmap,
+ val buttonId: 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)
+ trackId = -1
+ width = this.defaultStateBitmap.intrinsicWidth
+ height = this.defaultStateBitmap.intrinsicHeight
+ }
+
+ /**
+ * Updates button status based on the motion event.
+ *
+ * @return true if value was changed
+ */
+ 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
+ trackId = pointerId
+ return true
+ }
+
+ if (isActionUp) {
+ if (trackId != pointerId) {
+ return false
+ }
+ pressedState = false
+ trackId = -1
+ return true
+ }
+
+ return false
+ }
+
+ fun setPosition(x: Int, y: Int) {
+ buttonPositionX = x
+ buttonPositionY = y
+ }
+
+ fun draw(canvas: Canvas?) {
+ currentStateBitmapDrawable.draw(canvas!!)
+ }
+
+ 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)
+ }
+
+ fun setOpacity(value: Int) {
+ defaultStateBitmap.alpha = value
+ pressedStateBitmap.alpha = value
+ }
+
+ val status: Int
+ get() = if (pressedState) ButtonState.PRESSED else ButtonState.RELEASED
+ val bounds: Rect
+ get() = defaultStateBitmap.bounds
+}