From ffba83d568e6bd4dc98a26103320f97b6b0d9e6c Mon Sep 17 00:00:00 2001 From: Charles Lombardo Date: Mon, 22 May 2023 19:36:15 -0400 Subject: [PATCH] android: Add option for touch overlay haptics Disabled by default --- .../features/settings/model/Settings.kt | 1 + .../yuzu_emu/fragments/EmulationFragment.kt | 15 ++++++++--- .../org/yuzu/yuzu_emu/overlay/InputOverlay.kt | 26 +++++++++++++++++++ .../yuzu_emu/utils/EmulationMenuSettings.kt | 7 +++++ .../main/res/menu/menu_overlay_options.xml | 5 ++++ .../app/src/main/res/values/strings.xml | 1 + 6 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt index b712916097..a904c2011f 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt +++ b/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" 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 daa704565a..1d1c1333da 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 @@ -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() 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 5c3d79a166..95f358c219 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 @@ -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() diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/EmulationMenuSettings.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/EmulationMenuSettings.kt index 26ea2d77df..f5a81a7e5a 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/EmulationMenuSettings.kt +++ b/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( diff --git a/src/android/app/src/main/res/menu/menu_overlay_options.xml b/src/android/app/src/main/res/menu/menu_overlay_options.xml index 17ba5496d6..9acc294057 100644 --- a/src/android/app/src/main/res/menu/menu_overlay_options.xml +++ b/src/android/app/src/main/res/menu/menu_overlay_options.xml @@ -24,6 +24,11 @@ android:title="@string/emulation_dpad_slide" android:checkable="true" /> + + diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 03a5ffc7e0..6e4b1e630b 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -185,6 +185,7 @@ Toggle Controls Relative Stick Center DPad Slide + Haptics Show Overlay Toggle All Adjust Scale