Explorar o código

android: Add option for touch overlay haptics

Disabled by default
Charles Lombardo %!s(int64=3) %!d(string=hai) anos
pai
achega
ffba83d568

+ 1 - 0
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt

@@ -130,6 +130,7 @@ class Settings {
 
         const val PREF_MENU_SETTINGS_JOYSTICK_REL_CENTER = "EmulationMenuSettings_JoystickRelCenter"
         const val PREF_MENU_SETTINGS_DPAD_SLIDE = "EmulationMenuSettings_DpadSlideEnable"
+        const val PREF_MENU_SETTINGS_HAPTICS = "EmulationMenuSettings_Haptics"
         const val PREF_MENU_SETTINGS_LANDSCAPE = "EmulationMenuSettings_LandscapeScreenLayout"
         const val PREF_MENU_SETTINGS_SHOW_FPS = "EmulationMenuSettings_ShowFps"
         const val PREF_MENU_SETTINGS_SHOW_OVERLAY = "EmulationMenuSettings_ShowOverlay"

+ 11 - 4
src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt

@@ -223,10 +223,12 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
 
         popup.menuInflater.inflate(R.menu.menu_overlay_options, popup.menu)
 
-        popup.menu.findItem(R.id.menu_rel_stick_center).isChecked =
-            EmulationMenuSettings.joystickRelCenter
-        popup.menu.findItem(R.id.menu_dpad_slide).isChecked = EmulationMenuSettings.dpadSlide
-        popup.menu.findItem(R.id.menu_show_overlay).isChecked = EmulationMenuSettings.showOverlay
+        popup.menu.apply {
+            findItem(R.id.menu_rel_stick_center).isChecked = EmulationMenuSettings.joystickRelCenter
+            findItem(R.id.menu_dpad_slide).isChecked = EmulationMenuSettings.dpadSlide
+            findItem(R.id.menu_show_overlay).isChecked = EmulationMenuSettings.showOverlay
+            findItem(R.id.menu_haptics).isChecked = EmulationMenuSettings.hapticFeedback
+        }
 
         popup.setOnMenuItemClickListener {
             when (it.itemId) {
@@ -290,6 +292,11 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
                     EmulationMenuSettings.dpadSlide = it.isChecked
                     true
                 }
+                R.id.menu_haptics -> {
+                    it.isChecked = !it.isChecked
+                    EmulationMenuSettings.hapticFeedback = it.isChecked
+                    true
+                }
                 R.id.menu_reset_overlay -> {
                     binding.drawerLayout.close()
                     resetInputOverlay()

+ 26 - 0
src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt

@@ -14,6 +14,7 @@ import android.graphics.drawable.Drawable
 import android.graphics.drawable.VectorDrawable
 import android.os.Build
 import android.util.AttributeSet
+import android.view.HapticFeedbackConstants
 import android.view.MotionEvent
 import android.view.SurfaceView
 import android.view.View
@@ -105,6 +106,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
                 button.buttonId,
                 button.status
             )
+            playHaptics(event)
             shouldUpdateView = true
         }
 
@@ -132,6 +134,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
                 dpad.rightId,
                 dpad.rightStatus
             )
+            playHaptics(event)
             shouldUpdateView = true
         }
 
@@ -151,6 +154,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
                 joystick.buttonId,
                 joystick.buttonStatus
             )
+            playHaptics(event)
             shouldUpdateView = true
         }
 
@@ -193,6 +197,20 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
         return true
     }
 
+    private fun playHaptics(event: MotionEvent) {
+        if (EmulationMenuSettings.hapticFeedback) {
+            when (event.actionMasked) {
+                MotionEvent.ACTION_DOWN,
+                MotionEvent.ACTION_POINTER_DOWN ->
+                    performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY)
+
+                MotionEvent.ACTION_UP,
+                MotionEvent.ACTION_POINTER_UP ->
+                    performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY_RELEASE)
+            }
+        }
+    }
+
     private fun isTouchInputConsumed(track_id: Int): Boolean {
         for (button in overlayButtons) {
             if (button.trackId == track_id) {
@@ -236,11 +254,13 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
                         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.
@@ -267,11 +287,13 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
                         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.
@@ -298,10 +320,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
                     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(
@@ -795,10 +819,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
                 ButtonType.BUTTON_CAPTURE,
                 ButtonType.BUTTON_PLUS,
                 ButtonType.BUTTON_MINUS -> 0.07f
+
                 ButtonType.TRIGGER_L,
                 ButtonType.TRIGGER_R,
                 ButtonType.TRIGGER_ZL,
                 ButtonType.TRIGGER_ZR -> 0.26f
+
                 else -> 0.11f
             }
             scale *= (sPrefs.getInt(Settings.PREF_CONTROL_SCALE, 50) + 50).toFloat()

+ 7 - 0
src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/EmulationMenuSettings.kt

@@ -33,6 +33,13 @@ object EmulationMenuSettings {
                 .putBoolean(Settings.PREF_MENU_SETTINGS_DPAD_SLIDE, value)
                 .apply()
         }
+    var hapticFeedback: Boolean
+        get() = preferences.getBoolean(Settings.PREF_MENU_SETTINGS_HAPTICS, false)
+        set(value) {
+            preferences.edit()
+                .putBoolean(Settings.PREF_MENU_SETTINGS_HAPTICS, value)
+                .apply()
+        }
 
     var landscapeScreenLayout: Int
         get() = preferences.getInt(

+ 5 - 0
src/android/app/src/main/res/menu/menu_overlay_options.xml

@@ -24,6 +24,11 @@
         android:title="@string/emulation_dpad_slide"
         android:checkable="true" />
 
+    <item
+        android:id="@+id/menu_haptics"
+        android:title="@string/emulation_haptics"
+        android:checkable="true" />
+
     <item
         android:id="@+id/menu_reset_overlay"
         android:title="@string/emulation_touch_overlay_reset" />

+ 1 - 0
src/android/app/src/main/res/values/strings.xml

@@ -185,6 +185,7 @@
     <string name="emulation_toggle_controls">Toggle Controls</string>
     <string name="emulation_rel_stick_center">Relative Stick Center</string>
     <string name="emulation_dpad_slide">DPad Slide</string>
+    <string name="emulation_haptics">Haptics</string>
     <string name="emulation_show_overlay">Show Overlay</string>
     <string name="emulation_toggle_all">Toggle All</string>
     <string name="emulation_control_scale">Adjust Scale</string>