diff options
Diffstat (limited to 'src/android/app/src')
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()  | 
