android: Re-implement overlay editing
This commit is contained in:
		| @@ -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 = | ||||
|   | ||||
| @@ -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 | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user