diff options
| author | 2023-12-24 15:42:28 -0500 | |
|---|---|---|
| committer | 2023-12-30 15:11:36 -0500 | |
| commit | d163b182081401dbdcc5fc92c1692ff3209f2353 (patch) | |
| tree | e5ed8e3c24c03966f4544d5433a7f4c553c28b40 | |
| parent | frontend_common: config: Refactor WriteSetting to stricter types (diff) | |
| download | yuzu-d163b182081401dbdcc5fc92c1692ff3209f2353.tar.gz yuzu-d163b182081401dbdcc5fc92c1692ff3209f2353.tar.xz yuzu-d163b182081401dbdcc5fc92c1692ff3209f2353.zip | |
android: Migrate in-game overlay settings to ini
27 files changed, 1209 insertions, 847 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt index 9b08f008d..93c8ce922 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt | |||
| @@ -49,6 +49,7 @@ import org.yuzu.yuzu_emu.utils.ForegroundService | |||
| 49 | import org.yuzu.yuzu_emu.utils.InputHandler | 49 | import org.yuzu.yuzu_emu.utils.InputHandler |
| 50 | import org.yuzu.yuzu_emu.utils.Log | 50 | import org.yuzu.yuzu_emu.utils.Log |
| 51 | import org.yuzu.yuzu_emu.utils.MemoryUtil | 51 | import org.yuzu.yuzu_emu.utils.MemoryUtil |
| 52 | import org.yuzu.yuzu_emu.utils.NativeConfig | ||
| 52 | import org.yuzu.yuzu_emu.utils.NfcReader | 53 | import org.yuzu.yuzu_emu.utils.NfcReader |
| 53 | import org.yuzu.yuzu_emu.utils.ThemeHelper | 54 | import org.yuzu.yuzu_emu.utils.ThemeHelper |
| 54 | import java.text.NumberFormat | 55 | import java.text.NumberFormat |
| @@ -170,6 +171,11 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener { | |||
| 170 | stopMotionSensorListener() | 171 | stopMotionSensorListener() |
| 171 | } | 172 | } |
| 172 | 173 | ||
| 174 | override fun onStop() { | ||
| 175 | super.onStop() | ||
| 176 | NativeConfig.saveGlobalConfig() | ||
| 177 | } | ||
| 178 | |||
| 173 | override fun onUserLeaveHint() { | 179 | override fun onUserLeaveHint() { |
| 174 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { | 180 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { |
| 175 | if (BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && !isInPictureInPictureMode) { | 181 | if (BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && !isInPictureInPictureMode) { |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt index 110d15f1c..86bd33672 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt | |||
| @@ -19,7 +19,13 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting { | |||
| 19 | RENDERER_DEBUG("debug"), | 19 | RENDERER_DEBUG("debug"), |
| 20 | PICTURE_IN_PICTURE("picture_in_picture"), | 20 | PICTURE_IN_PICTURE("picture_in_picture"), |
| 21 | USE_CUSTOM_RTC("custom_rtc_enabled"), | 21 | USE_CUSTOM_RTC("custom_rtc_enabled"), |
| 22 | BLACK_BACKGROUNDS("black_backgrounds"); | 22 | BLACK_BACKGROUNDS("black_backgrounds"), |
| 23 | JOYSTICK_REL_CENTER("joystick_rel_center"), | ||
| 24 | DPAD_SLIDE("dpad_slide"), | ||
| 25 | HAPTIC_FEEDBACK("haptic_feedback"), | ||
| 26 | SHOW_PERFORMANCE_OVERLAY("show_performance_overlay"), | ||
| 27 | SHOW_INPUT_OVERLAY("show_input_overlay"), | ||
| 28 | TOUCHSCREEN("touchscreen"); | ||
| 23 | 29 | ||
| 24 | override fun getBoolean(needsGlobal: Boolean): Boolean = | 30 | override fun getBoolean(needsGlobal: Boolean): Boolean = |
| 25 | NativeConfig.getBoolean(key, needsGlobal) | 31 | NativeConfig.getBoolean(key, needsGlobal) |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt index b0193d83e..16fb87614 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt | |||
| @@ -21,7 +21,9 @@ enum class IntSetting(override val key: String) : AbstractIntSetting { | |||
| 21 | AUDIO_OUTPUT_ENGINE("output_engine"), | 21 | AUDIO_OUTPUT_ENGINE("output_engine"), |
| 22 | MAX_ANISOTROPY("max_anisotropy"), | 22 | MAX_ANISOTROPY("max_anisotropy"), |
| 23 | THEME("theme"), | 23 | THEME("theme"), |
| 24 | THEME_MODE("theme_mode"); | 24 | THEME_MODE("theme_mode"), |
| 25 | OVERLAY_SCALE("control_scale"), | ||
| 26 | OVERLAY_OPACITY("control_opacity"); | ||
| 25 | 27 | ||
| 26 | override fun getInt(needsGlobal: Boolean): Int = NativeConfig.getInt(key, needsGlobal) | 28 | override fun getInt(needsGlobal: Boolean): Int = NativeConfig.getInt(key, needsGlobal) |
| 27 | 29 | ||
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 360bdaf3e..43caac989 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 | |||
| @@ -15,18 +15,10 @@ object Settings { | |||
| 15 | SECTION_DEBUG(R.string.preferences_debug); | 15 | SECTION_DEBUG(R.string.preferences_debug); |
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch" | ||
| 18 | const val PREF_MEMORY_WARNING_SHOWN = "MemoryWarningShown" | 19 | const val PREF_MEMORY_WARNING_SHOWN = "MemoryWarningShown" |
| 19 | 20 | ||
| 20 | const val PREF_OVERLAY_VERSION = "OverlayVersion" | 21 | // Deprecated input overlay preference keys |
| 21 | const val PREF_LANDSCAPE_OVERLAY_VERSION = "LandscapeOverlayVersion" | ||
| 22 | const val PREF_PORTRAIT_OVERLAY_VERSION = "PortraitOverlayVersion" | ||
| 23 | const val PREF_FOLDABLE_OVERLAY_VERSION = "FoldableOverlayVersion" | ||
| 24 | val overlayLayoutPrefs = listOf( | ||
| 25 | PREF_LANDSCAPE_OVERLAY_VERSION, | ||
| 26 | PREF_PORTRAIT_OVERLAY_VERSION, | ||
| 27 | PREF_FOLDABLE_OVERLAY_VERSION | ||
| 28 | ) | ||
| 29 | |||
| 30 | const val PREF_CONTROL_SCALE = "controlScale" | 22 | const val PREF_CONTROL_SCALE = "controlScale" |
| 31 | const val PREF_CONTROL_OPACITY = "controlOpacity" | 23 | const val PREF_CONTROL_OPACITY = "controlOpacity" |
| 32 | const val PREF_TOUCH_ENABLED = "isTouchEnabled" | 24 | const val PREF_TOUCH_ENABLED = "isTouchEnabled" |
| @@ -47,24 +39,12 @@ object Settings { | |||
| 47 | const val PREF_BUTTON_STICK_R = "buttonToggle14" | 39 | const val PREF_BUTTON_STICK_R = "buttonToggle14" |
| 48 | const val PREF_BUTTON_HOME = "buttonToggle15" | 40 | const val PREF_BUTTON_HOME = "buttonToggle15" |
| 49 | const val PREF_BUTTON_SCREENSHOT = "buttonToggle16" | 41 | const val PREF_BUTTON_SCREENSHOT = "buttonToggle16" |
| 50 | |||
| 51 | const val PREF_MENU_SETTINGS_JOYSTICK_REL_CENTER = "EmulationMenuSettings_JoystickRelCenter" | 42 | const val PREF_MENU_SETTINGS_JOYSTICK_REL_CENTER = "EmulationMenuSettings_JoystickRelCenter" |
| 52 | const val PREF_MENU_SETTINGS_DPAD_SLIDE = "EmulationMenuSettings_DpadSlideEnable" | 43 | const val PREF_MENU_SETTINGS_DPAD_SLIDE = "EmulationMenuSettings_DpadSlideEnable" |
| 53 | const val PREF_MENU_SETTINGS_HAPTICS = "EmulationMenuSettings_Haptics" | 44 | const val PREF_MENU_SETTINGS_HAPTICS = "EmulationMenuSettings_Haptics" |
| 54 | const val PREF_MENU_SETTINGS_SHOW_FPS = "EmulationMenuSettings_ShowFps" | 45 | const val PREF_MENU_SETTINGS_SHOW_FPS = "EmulationMenuSettings_ShowFps" |
| 55 | const val PREF_MENU_SETTINGS_SHOW_OVERLAY = "EmulationMenuSettings_ShowOverlay" | 46 | const val PREF_MENU_SETTINGS_SHOW_OVERLAY = "EmulationMenuSettings_ShowOverlay" |
| 56 | |||
| 57 | // Deprecated theme preference keys | ||
| 58 | const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch" | ||
| 59 | const val PREF_THEME = "Theme" | ||
| 60 | const val PREF_THEME_MODE = "ThemeMode" | ||
| 61 | const val PREF_BLACK_BACKGROUNDS = "BlackBackgrounds" | ||
| 62 | |||
| 63 | val overlayPreferences = listOf( | 47 | val overlayPreferences = listOf( |
| 64 | PREF_OVERLAY_VERSION, | ||
| 65 | PREF_CONTROL_SCALE, | ||
| 66 | PREF_CONTROL_OPACITY, | ||
| 67 | PREF_TOUCH_ENABLED, | ||
| 68 | PREF_BUTTON_A, | 48 | PREF_BUTTON_A, |
| 69 | PREF_BUTTON_B, | 49 | PREF_BUTTON_B, |
| 70 | PREF_BUTTON_X, | 50 | PREF_BUTTON_X, |
| @@ -84,6 +64,21 @@ object Settings { | |||
| 84 | PREF_BUTTON_STICK_R | 64 | PREF_BUTTON_STICK_R |
| 85 | ) | 65 | ) |
| 86 | 66 | ||
| 67 | // Deprecated layout preference keys | ||
| 68 | const val PREF_LANDSCAPE_SUFFIX = "_Landscape" | ||
| 69 | const val PREF_PORTRAIT_SUFFIX = "_Portrait" | ||
| 70 | const val PREF_FOLDABLE_SUFFIX = "_Foldable" | ||
| 71 | val overlayLayoutSuffixes = listOf( | ||
| 72 | PREF_LANDSCAPE_SUFFIX, | ||
| 73 | PREF_PORTRAIT_SUFFIX, | ||
| 74 | PREF_FOLDABLE_SUFFIX | ||
| 75 | ) | ||
| 76 | |||
| 77 | // Deprecated theme preference keys | ||
| 78 | const val PREF_THEME = "Theme" | ||
| 79 | const val PREF_THEME_MODE = "ThemeMode" | ||
| 80 | const val PREF_BLACK_BACKGROUNDS = "BlackBackgrounds" | ||
| 81 | |||
| 87 | const val LayoutOption_Unspecified = 0 | 82 | const val LayoutOption_Unspecified = 0 |
| 88 | const val LayoutOption_MobilePortrait = 4 | 83 | const val LayoutOption_MobilePortrait = 4 |
| 89 | const val LayoutOption_MobileLandscape = 5 | 84 | const val LayoutOption_MobileLandscape = 5 |
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 d7b38f62d..6e5dd1dba 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 | |||
| @@ -7,7 +7,6 @@ import android.annotation.SuppressLint | |||
| 7 | import android.app.AlertDialog | 7 | import android.app.AlertDialog |
| 8 | import android.content.Context | 8 | import android.content.Context |
| 9 | import android.content.DialogInterface | 9 | import android.content.DialogInterface |
| 10 | import android.content.SharedPreferences | ||
| 11 | import android.content.pm.ActivityInfo | 10 | import android.content.pm.ActivityInfo |
| 12 | import android.content.res.Configuration | 11 | import android.content.res.Configuration |
| 13 | import android.net.Uri | 12 | import android.net.Uri |
| @@ -33,7 +32,6 @@ import androidx.lifecycle.lifecycleScope | |||
| 33 | import androidx.lifecycle.repeatOnLifecycle | 32 | import androidx.lifecycle.repeatOnLifecycle |
| 34 | import androidx.navigation.findNavController | 33 | import androidx.navigation.findNavController |
| 35 | import androidx.navigation.fragment.navArgs | 34 | import androidx.navigation.fragment.navArgs |
| 36 | import androidx.preference.PreferenceManager | ||
| 37 | import androidx.window.layout.FoldingFeature | 35 | import androidx.window.layout.FoldingFeature |
| 38 | import androidx.window.layout.WindowInfoTracker | 36 | import androidx.window.layout.WindowInfoTracker |
| 39 | import androidx.window.layout.WindowLayoutInfo | 37 | import androidx.window.layout.WindowLayoutInfo |
| @@ -46,22 +44,22 @@ import kotlinx.coroutines.launch | |||
| 46 | import org.yuzu.yuzu_emu.HomeNavigationDirections | 44 | import org.yuzu.yuzu_emu.HomeNavigationDirections |
| 47 | import org.yuzu.yuzu_emu.NativeLibrary | 45 | import org.yuzu.yuzu_emu.NativeLibrary |
| 48 | import org.yuzu.yuzu_emu.R | 46 | import org.yuzu.yuzu_emu.R |
| 49 | import org.yuzu.yuzu_emu.YuzuApplication | ||
| 50 | import org.yuzu.yuzu_emu.activities.EmulationActivity | 47 | import org.yuzu.yuzu_emu.activities.EmulationActivity |
| 51 | import org.yuzu.yuzu_emu.databinding.DialogOverlayAdjustBinding | 48 | import org.yuzu.yuzu_emu.databinding.DialogOverlayAdjustBinding |
| 52 | import org.yuzu.yuzu_emu.databinding.FragmentEmulationBinding | 49 | import org.yuzu.yuzu_emu.databinding.FragmentEmulationBinding |
| 50 | import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting | ||
| 53 | import org.yuzu.yuzu_emu.features.settings.model.IntSetting | 51 | import org.yuzu.yuzu_emu.features.settings.model.IntSetting |
| 54 | import org.yuzu.yuzu_emu.features.settings.model.Settings | 52 | import org.yuzu.yuzu_emu.features.settings.model.Settings |
| 55 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile | 53 | import org.yuzu.yuzu_emu.features.settings.utils.SettingsFile |
| 56 | import org.yuzu.yuzu_emu.model.DriverViewModel | 54 | import org.yuzu.yuzu_emu.model.DriverViewModel |
| 57 | import org.yuzu.yuzu_emu.model.Game | 55 | import org.yuzu.yuzu_emu.model.Game |
| 58 | import org.yuzu.yuzu_emu.model.EmulationViewModel | 56 | import org.yuzu.yuzu_emu.model.EmulationViewModel |
| 59 | import org.yuzu.yuzu_emu.overlay.InputOverlay | 57 | import org.yuzu.yuzu_emu.overlay.model.OverlayControl |
| 58 | import org.yuzu.yuzu_emu.overlay.model.OverlayLayout | ||
| 60 | import org.yuzu.yuzu_emu.utils.* | 59 | import org.yuzu.yuzu_emu.utils.* |
| 61 | import java.lang.NullPointerException | 60 | import java.lang.NullPointerException |
| 62 | 61 | ||
| 63 | class EmulationFragment : Fragment(), SurfaceHolder.Callback { | 62 | class EmulationFragment : Fragment(), SurfaceHolder.Callback { |
| 64 | private lateinit var preferences: SharedPreferences | ||
| 65 | private lateinit var emulationState: EmulationState | 63 | private lateinit var emulationState: EmulationState |
| 66 | private var emulationActivity: EmulationActivity? = null | 64 | private var emulationActivity: EmulationActivity? = null |
| 67 | private var perfStatsUpdater: (() -> Unit)? = null | 65 | private var perfStatsUpdater: (() -> Unit)? = null |
| @@ -141,7 +139,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 141 | 139 | ||
| 142 | // So this fragment doesn't restart on configuration changes; i.e. rotation. | 140 | // So this fragment doesn't restart on configuration changes; i.e. rotation. |
| 143 | retainInstance = true | 141 | retainInstance = true |
| 144 | preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) | ||
| 145 | emulationState = EmulationState(game.path) | 142 | emulationState = EmulationState(game.path) |
| 146 | } | 143 | } |
| 147 | 144 | ||
| @@ -382,24 +379,25 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 382 | } | 379 | } |
| 383 | 380 | ||
| 384 | updateScreenLayout() | 381 | updateScreenLayout() |
| 382 | val showInputOverlay = BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean() | ||
| 385 | if (emulationActivity?.isInPictureInPictureMode == true) { | 383 | if (emulationActivity?.isInPictureInPictureMode == true) { |
| 386 | if (binding.drawerLayout.isOpen) { | 384 | if (binding.drawerLayout.isOpen) { |
| 387 | binding.drawerLayout.close() | 385 | binding.drawerLayout.close() |
| 388 | } | 386 | } |
| 389 | if (EmulationMenuSettings.showOverlay) { | 387 | if (showInputOverlay) { |
| 390 | binding.surfaceInputOverlay.visibility = View.INVISIBLE | 388 | binding.surfaceInputOverlay.visibility = View.INVISIBLE |
| 391 | } | 389 | } |
| 392 | } else { | 390 | } else { |
| 393 | if (EmulationMenuSettings.showOverlay && emulationViewModel.emulationStarted.value) { | 391 | if (showInputOverlay && emulationViewModel.emulationStarted.value) { |
| 394 | binding.surfaceInputOverlay.visibility = View.VISIBLE | 392 | binding.surfaceInputOverlay.visibility = View.VISIBLE |
| 395 | } else { | 393 | } else { |
| 396 | binding.surfaceInputOverlay.visibility = View.INVISIBLE | 394 | binding.surfaceInputOverlay.visibility = View.INVISIBLE |
| 397 | } | 395 | } |
| 398 | if (!isInFoldableLayout) { | 396 | if (!isInFoldableLayout) { |
| 399 | if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { | 397 | if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { |
| 400 | binding.surfaceInputOverlay.layout = InputOverlay.PORTRAIT | 398 | binding.surfaceInputOverlay.layout = OverlayLayout.Portrait |
| 401 | } else { | 399 | } else { |
| 402 | binding.surfaceInputOverlay.layout = InputOverlay.LANDSCAPE | 400 | binding.surfaceInputOverlay.layout = OverlayLayout.Landscape |
| 403 | } | 401 | } |
| 404 | } | 402 | } |
| 405 | } | 403 | } |
| @@ -423,17 +421,15 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 423 | } | 421 | } |
| 424 | 422 | ||
| 425 | private fun resetInputOverlay() { | 423 | private fun resetInputOverlay() { |
| 426 | preferences.edit() | 424 | IntSetting.OVERLAY_SCALE.reset() |
| 427 | .remove(Settings.PREF_CONTROL_SCALE) | 425 | IntSetting.OVERLAY_OPACITY.reset() |
| 428 | .remove(Settings.PREF_CONTROL_OPACITY) | ||
| 429 | .apply() | ||
| 430 | binding.surfaceInputOverlay.post { | 426 | binding.surfaceInputOverlay.post { |
| 431 | binding.surfaceInputOverlay.resetLayoutVisibilityAndPlacement() | 427 | binding.surfaceInputOverlay.resetLayoutVisibilityAndPlacement() |
| 432 | } | 428 | } |
| 433 | } | 429 | } |
| 434 | 430 | ||
| 435 | private fun updateShowFpsOverlay() { | 431 | private fun updateShowFpsOverlay() { |
| 436 | if (EmulationMenuSettings.showFps) { | 432 | if (BooleanSetting.SHOW_PERFORMANCE_OVERLAY.getBoolean()) { |
| 437 | val SYSTEM_FPS = 0 | 433 | val SYSTEM_FPS = 0 |
| 438 | val FPS = 1 | 434 | val FPS = 1 |
| 439 | val FRAMETIME = 2 | 435 | val FRAMETIME = 2 |
| @@ -496,7 +492,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 496 | binding.inGameMenu.layoutParams.height = it.bounds.bottom | 492 | binding.inGameMenu.layoutParams.height = it.bounds.bottom |
| 497 | 493 | ||
| 498 | isInFoldableLayout = true | 494 | isInFoldableLayout = true |
| 499 | binding.surfaceInputOverlay.layout = InputOverlay.FOLDABLE | 495 | binding.surfaceInputOverlay.layout = OverlayLayout.Foldable |
| 500 | } | 496 | } |
| 501 | } | 497 | } |
| 502 | it.isSeparating | 498 | it.isSeparating |
| @@ -535,18 +531,21 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 535 | popup.menuInflater.inflate(R.menu.menu_overlay_options, popup.menu) | 531 | popup.menuInflater.inflate(R.menu.menu_overlay_options, popup.menu) |
| 536 | 532 | ||
| 537 | popup.menu.apply { | 533 | popup.menu.apply { |
| 538 | findItem(R.id.menu_toggle_fps).isChecked = EmulationMenuSettings.showFps | 534 | findItem(R.id.menu_toggle_fps).isChecked = |
| 539 | findItem(R.id.menu_rel_stick_center).isChecked = EmulationMenuSettings.joystickRelCenter | 535 | BooleanSetting.SHOW_PERFORMANCE_OVERLAY.getBoolean() |
| 540 | findItem(R.id.menu_dpad_slide).isChecked = EmulationMenuSettings.dpadSlide | 536 | findItem(R.id.menu_rel_stick_center).isChecked = |
| 541 | findItem(R.id.menu_show_overlay).isChecked = EmulationMenuSettings.showOverlay | 537 | BooleanSetting.JOYSTICK_REL_CENTER.getBoolean() |
| 542 | findItem(R.id.menu_haptics).isChecked = EmulationMenuSettings.hapticFeedback | 538 | findItem(R.id.menu_dpad_slide).isChecked = BooleanSetting.DPAD_SLIDE.getBoolean() |
| 539 | findItem(R.id.menu_show_overlay).isChecked = | ||
| 540 | BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean() | ||
| 541 | findItem(R.id.menu_haptics).isChecked = BooleanSetting.HAPTIC_FEEDBACK.getBoolean() | ||
| 543 | } | 542 | } |
| 544 | 543 | ||
| 545 | popup.setOnMenuItemClickListener { | 544 | popup.setOnMenuItemClickListener { |
| 546 | when (it.itemId) { | 545 | when (it.itemId) { |
| 547 | R.id.menu_toggle_fps -> { | 546 | R.id.menu_toggle_fps -> { |
| 548 | it.isChecked = !it.isChecked | 547 | it.isChecked = !it.isChecked |
| 549 | EmulationMenuSettings.showFps = it.isChecked | 548 | BooleanSetting.SHOW_PERFORMANCE_OVERLAY.setBoolean(it.isChecked) |
| 550 | updateShowFpsOverlay() | 549 | updateShowFpsOverlay() |
| 551 | true | 550 | true |
| 552 | } | 551 | } |
| @@ -564,11 +563,12 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 564 | } | 563 | } |
| 565 | 564 | ||
| 566 | R.id.menu_toggle_controls -> { | 565 | R.id.menu_toggle_controls -> { |
| 567 | val preferences = | 566 | val overlayControlData = NativeConfig.getOverlayControlData() |
| 568 | PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) | 567 | val optionsArray = BooleanArray(overlayControlData.size) |
| 569 | val optionsArray = BooleanArray(Settings.overlayPreferences.size) | 568 | overlayControlData.forEachIndexed { i, _ -> |
| 570 | Settings.overlayPreferences.forEachIndexed { i, _ -> | 569 | optionsArray[i] = overlayControlData.firstOrNull { data -> |
| 571 | optionsArray[i] = preferences.getBoolean("buttonToggle$i", i < 15) | 570 | OverlayControl.entries[i].id == data.id |
| 571 | }?.enabled == true | ||
| 572 | } | 572 | } |
| 573 | 573 | ||
| 574 | val dialog = MaterialAlertDialogBuilder(requireContext()) | 574 | val dialog = MaterialAlertDialogBuilder(requireContext()) |
| @@ -577,11 +577,13 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 577 | R.array.gamepadButtons, | 577 | R.array.gamepadButtons, |
| 578 | optionsArray | 578 | optionsArray |
| 579 | ) { _, indexSelected, isChecked -> | 579 | ) { _, indexSelected, isChecked -> |
| 580 | preferences.edit() | 580 | overlayControlData.firstOrNull { data -> |
| 581 | .putBoolean("buttonToggle$indexSelected", isChecked) | 581 | OverlayControl.entries[indexSelected].id == data.id |
| 582 | .apply() | 582 | }?.enabled = isChecked |
| 583 | } | 583 | } |
| 584 | .setPositiveButton(android.R.string.ok) { _, _ -> | 584 | .setPositiveButton(android.R.string.ok) { _, _ -> |
| 585 | NativeConfig.setOverlayControlData(overlayControlData) | ||
| 586 | NativeConfig.saveGlobalConfig() | ||
| 585 | binding.surfaceInputOverlay.refreshControls() | 587 | binding.surfaceInputOverlay.refreshControls() |
| 586 | } | 588 | } |
| 587 | .setNegativeButton(android.R.string.cancel, null) | 589 | .setNegativeButton(android.R.string.cancel, null) |
| @@ -592,12 +594,10 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 592 | dialog.getButton(AlertDialog.BUTTON_NEUTRAL) | 594 | dialog.getButton(AlertDialog.BUTTON_NEUTRAL) |
| 593 | .setOnClickListener { | 595 | .setOnClickListener { |
| 594 | val isChecked = !optionsArray[0] | 596 | val isChecked = !optionsArray[0] |
| 595 | Settings.overlayPreferences.forEachIndexed { i, _ -> | 597 | overlayControlData.forEachIndexed { i, _ -> |
| 596 | optionsArray[i] = isChecked | 598 | optionsArray[i] = isChecked |
| 597 | dialog.listView.setItemChecked(i, isChecked) | 599 | dialog.listView.setItemChecked(i, isChecked) |
| 598 | preferences.edit() | 600 | overlayControlData[i].enabled = isChecked |
| 599 | .putBoolean("buttonToggle$i", isChecked) | ||
| 600 | .apply() | ||
| 601 | } | 601 | } |
| 602 | } | 602 | } |
| 603 | true | 603 | true |
| @@ -605,26 +605,26 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 605 | 605 | ||
| 606 | R.id.menu_show_overlay -> { | 606 | R.id.menu_show_overlay -> { |
| 607 | it.isChecked = !it.isChecked | 607 | it.isChecked = !it.isChecked |
| 608 | EmulationMenuSettings.showOverlay = it.isChecked | 608 | BooleanSetting.SHOW_INPUT_OVERLAY.setBoolean(it.isChecked) |
| 609 | binding.surfaceInputOverlay.refreshControls() | 609 | binding.surfaceInputOverlay.refreshControls() |
| 610 | true | 610 | true |
| 611 | } | 611 | } |
| 612 | 612 | ||
| 613 | R.id.menu_rel_stick_center -> { | 613 | R.id.menu_rel_stick_center -> { |
| 614 | it.isChecked = !it.isChecked | 614 | it.isChecked = !it.isChecked |
| 615 | EmulationMenuSettings.joystickRelCenter = it.isChecked | 615 | BooleanSetting.JOYSTICK_REL_CENTER.setBoolean(it.isChecked) |
| 616 | true | 616 | true |
| 617 | } | 617 | } |
| 618 | 618 | ||
| 619 | R.id.menu_dpad_slide -> { | 619 | R.id.menu_dpad_slide -> { |
| 620 | it.isChecked = !it.isChecked | 620 | it.isChecked = !it.isChecked |
| 621 | EmulationMenuSettings.dpadSlide = it.isChecked | 621 | BooleanSetting.DPAD_SLIDE.setBoolean(it.isChecked) |
| 622 | true | 622 | true |
| 623 | } | 623 | } |
| 624 | 624 | ||
| 625 | R.id.menu_haptics -> { | 625 | R.id.menu_haptics -> { |
| 626 | it.isChecked = !it.isChecked | 626 | it.isChecked = !it.isChecked |
| 627 | EmulationMenuSettings.hapticFeedback = it.isChecked | 627 | BooleanSetting.HAPTIC_FEEDBACK.setBoolean(it.isChecked) |
| 628 | true | 628 | true |
| 629 | } | 629 | } |
| 630 | 630 | ||
| @@ -667,6 +667,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 667 | it.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED | 667 | it.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED |
| 668 | } | 668 | } |
| 669 | } | 669 | } |
| 670 | NativeConfig.saveGlobalConfig() | ||
| 670 | } | 671 | } |
| 671 | 672 | ||
| 672 | @SuppressLint("SetTextI18n") | 673 | @SuppressLint("SetTextI18n") |
| @@ -675,7 +676,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 675 | adjustBinding.apply { | 676 | adjustBinding.apply { |
| 676 | inputScaleSlider.apply { | 677 | inputScaleSlider.apply { |
| 677 | valueTo = 150F | 678 | valueTo = 150F |
| 678 | value = preferences.getInt(Settings.PREF_CONTROL_SCALE, 50).toFloat() | 679 | value = IntSetting.OVERLAY_SCALE.getInt().toFloat() |
| 679 | addOnChangeListener( | 680 | addOnChangeListener( |
| 680 | Slider.OnChangeListener { _, value, _ -> | 681 | Slider.OnChangeListener { _, value, _ -> |
| 681 | inputScaleValue.text = "${value.toInt()}%" | 682 | inputScaleValue.text = "${value.toInt()}%" |
| @@ -685,7 +686,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 685 | } | 686 | } |
| 686 | inputOpacitySlider.apply { | 687 | inputOpacitySlider.apply { |
| 687 | valueTo = 100F | 688 | valueTo = 100F |
| 688 | value = preferences.getInt(Settings.PREF_CONTROL_OPACITY, 100).toFloat() | 689 | value = IntSetting.OVERLAY_OPACITY.getInt().toFloat() |
| 689 | addOnChangeListener( | 690 | addOnChangeListener( |
| 690 | Slider.OnChangeListener { _, value, _ -> | 691 | Slider.OnChangeListener { _, value, _ -> |
| 691 | inputOpacityValue.text = "${value.toInt()}%" | 692 | inputOpacityValue.text = "${value.toInt()}%" |
| @@ -709,16 +710,12 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback { | |||
| 709 | } | 710 | } |
| 710 | 711 | ||
| 711 | private fun setControlScale(scale: Int) { | 712 | private fun setControlScale(scale: Int) { |
| 712 | preferences.edit() | 713 | IntSetting.OVERLAY_SCALE.setInt(scale) |
| 713 | .putInt(Settings.PREF_CONTROL_SCALE, scale) | ||
| 714 | .apply() | ||
| 715 | binding.surfaceInputOverlay.refreshControls() | 714 | binding.surfaceInputOverlay.refreshControls() |
| 716 | } | 715 | } |
| 717 | 716 | ||
| 718 | private fun setControlOpacity(opacity: Int) { | 717 | private fun setControlOpacity(opacity: Int) { |
| 719 | preferences.edit() | 718 | IntSetting.OVERLAY_OPACITY.setInt(opacity) |
| 720 | .putInt(Settings.PREF_CONTROL_OPACITY, opacity) | ||
| 721 | .apply() | ||
| 722 | binding.surfaceInputOverlay.refreshControls() | 719 | binding.surfaceInputOverlay.refreshControls() |
| 723 | } | 720 | } |
| 724 | 721 | ||
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 a13faf3c7..bb69b8bd5 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 | |||
| @@ -21,7 +21,6 @@ import android.view.View | |||
| 21 | import android.view.View.OnTouchListener | 21 | import android.view.View.OnTouchListener |
| 22 | import android.view.WindowInsets | 22 | import android.view.WindowInsets |
| 23 | import androidx.core.content.ContextCompat | 23 | import androidx.core.content.ContextCompat |
| 24 | import androidx.preference.PreferenceManager | ||
| 25 | import androidx.window.layout.WindowMetricsCalculator | 24 | import androidx.window.layout.WindowMetricsCalculator |
| 26 | import kotlin.math.max | 25 | import kotlin.math.max |
| 27 | import kotlin.math.min | 26 | import kotlin.math.min |
| @@ -29,9 +28,13 @@ import org.yuzu.yuzu_emu.NativeLibrary | |||
| 29 | import org.yuzu.yuzu_emu.NativeLibrary.ButtonType | 28 | import org.yuzu.yuzu_emu.NativeLibrary.ButtonType |
| 30 | import org.yuzu.yuzu_emu.NativeLibrary.StickType | 29 | import org.yuzu.yuzu_emu.NativeLibrary.StickType |
| 31 | import org.yuzu.yuzu_emu.R | 30 | import org.yuzu.yuzu_emu.R |
| 32 | import org.yuzu.yuzu_emu.YuzuApplication | 31 | import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting |
| 32 | import org.yuzu.yuzu_emu.features.settings.model.IntSetting | ||
| 33 | import org.yuzu.yuzu_emu.features.settings.model.Settings | 33 | import org.yuzu.yuzu_emu.features.settings.model.Settings |
| 34 | import org.yuzu.yuzu_emu.utils.EmulationMenuSettings | 34 | import org.yuzu.yuzu_emu.overlay.model.OverlayControl |
| 35 | import org.yuzu.yuzu_emu.overlay.model.OverlayControlData | ||
| 36 | import org.yuzu.yuzu_emu.overlay.model.OverlayLayout | ||
| 37 | import org.yuzu.yuzu_emu.utils.NativeConfig | ||
| 35 | 38 | ||
| 36 | /** | 39 | /** |
| 37 | * Draws the interactive input overlay on top of the | 40 | * Draws the interactive input overlay on top of the |
| @@ -51,23 +54,18 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 51 | 54 | ||
| 52 | private lateinit var windowInsets: WindowInsets | 55 | private lateinit var windowInsets: WindowInsets |
| 53 | 56 | ||
| 54 | var layout = LANDSCAPE | 57 | var layout = OverlayLayout.Landscape |
| 55 | 58 | ||
| 56 | override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { | 59 | override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { |
| 57 | super.onLayout(changed, left, top, right, bottom) | 60 | super.onLayout(changed, left, top, right, bottom) |
| 58 | 61 | ||
| 59 | windowInsets = rootWindowInsets | 62 | windowInsets = rootWindowInsets |
| 60 | 63 | ||
| 61 | val overlayVersion = preferences.getInt(Settings.PREF_OVERLAY_VERSION, 0) | 64 | val overlayControlData = NativeConfig.getOverlayControlData() |
| 62 | if (overlayVersion != OVERLAY_VERSION) { | 65 | if (overlayControlData.isEmpty()) { |
| 63 | resetAllLayouts() | 66 | populateDefaultConfig() |
| 64 | } else { | 67 | } else { |
| 65 | val layoutIndex = overlayLayouts.indexOf(layout) | 68 | checkForNewControls(overlayControlData) |
| 66 | val currentLayoutVersion = | ||
| 67 | preferences.getInt(Settings.overlayLayoutPrefs[layoutIndex], 0) | ||
| 68 | if (currentLayoutVersion != overlayLayoutVersions[layoutIndex]) { | ||
| 69 | resetCurrentLayout() | ||
| 70 | } | ||
| 71 | } | 69 | } |
| 72 | 70 | ||
| 73 | // Load the controls. | 71 | // Load the controls. |
| @@ -123,7 +121,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 123 | } | 121 | } |
| 124 | 122 | ||
| 125 | for (dpad in overlayDpads) { | 123 | for (dpad in overlayDpads) { |
| 126 | if (!dpad.updateStatus(event, EmulationMenuSettings.dpadSlide)) { | 124 | if (!dpad.updateStatus(event, BooleanSetting.DPAD_SLIDE.getBoolean())) { |
| 127 | continue | 125 | continue |
| 128 | } | 126 | } |
| 129 | NativeLibrary.onGamePadButtonEvent( | 127 | NativeLibrary.onGamePadButtonEvent( |
| @@ -174,7 +172,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 174 | invalidate() | 172 | invalidate() |
| 175 | } | 173 | } |
| 176 | 174 | ||
| 177 | if (!preferences.getBoolean(Settings.PREF_TOUCH_ENABLED, true)) { | 175 | if (!BooleanSetting.TOUCHSCREEN.getBoolean()) { |
| 178 | return true | 176 | return true |
| 179 | } | 177 | } |
| 180 | 178 | ||
| @@ -211,7 +209,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 211 | } | 209 | } |
| 212 | 210 | ||
| 213 | private fun playHaptics(event: MotionEvent) { | 211 | private fun playHaptics(event: MotionEvent) { |
| 214 | if (EmulationMenuSettings.hapticFeedback) { | 212 | if (BooleanSetting.HAPTIC_FEEDBACK.getBoolean()) { |
| 215 | when (event.actionMasked) { | 213 | when (event.actionMasked) { |
| 216 | MotionEvent.ACTION_DOWN, | 214 | MotionEvent.ACTION_DOWN, |
| 217 | MotionEvent.ACTION_POINTER_DOWN -> | 215 | MotionEvent.ACTION_POINTER_DOWN -> |
| @@ -255,10 +253,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 255 | MotionEvent.ACTION_POINTER_DOWN -> | 253 | MotionEvent.ACTION_POINTER_DOWN -> |
| 256 | // If no button is being moved now, remember the currently touched button to move. | 254 | // If no button is being moved now, remember the currently touched button to move. |
| 257 | if (buttonBeingConfigured == null && | 255 | if (buttonBeingConfigured == null && |
| 258 | button.bounds.contains( | 256 | button.bounds.contains(fingerPositionX, fingerPositionY) |
| 259 | fingerPositionX, | ||
| 260 | fingerPositionY | ||
| 261 | ) | ||
| 262 | ) { | 257 | ) { |
| 263 | buttonBeingConfigured = button | 258 | buttonBeingConfigured = button |
| 264 | buttonBeingConfigured!!.onConfigureTouch(event) | 259 | buttonBeingConfigured!!.onConfigureTouch(event) |
| @@ -274,7 +269,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 274 | MotionEvent.ACTION_POINTER_UP -> if (buttonBeingConfigured === button) { | 269 | MotionEvent.ACTION_POINTER_UP -> if (buttonBeingConfigured === button) { |
| 275 | // Persist button position by saving new place. | 270 | // Persist button position by saving new place. |
| 276 | saveControlPosition( | 271 | saveControlPosition( |
| 277 | buttonBeingConfigured!!.prefId, | 272 | buttonBeingConfigured!!.overlayControlData.id, |
| 278 | buttonBeingConfigured!!.bounds.centerX(), | 273 | buttonBeingConfigured!!.bounds.centerX(), |
| 279 | buttonBeingConfigured!!.bounds.centerY(), | 274 | buttonBeingConfigured!!.bounds.centerY(), |
| 280 | layout | 275 | layout |
| @@ -321,10 +316,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 321 | when (event.action) { | 316 | when (event.action) { |
| 322 | MotionEvent.ACTION_DOWN, | 317 | MotionEvent.ACTION_DOWN, |
| 323 | MotionEvent.ACTION_POINTER_DOWN -> if (joystickBeingConfigured == null && | 318 | MotionEvent.ACTION_POINTER_DOWN -> if (joystickBeingConfigured == null && |
| 324 | joystick.bounds.contains( | 319 | joystick.bounds.contains(fingerPositionX, fingerPositionY) |
| 325 | fingerPositionX, | ||
| 326 | fingerPositionY | ||
| 327 | ) | ||
| 328 | ) { | 320 | ) { |
| 329 | joystickBeingConfigured = joystick | 321 | joystickBeingConfigured = joystick |
| 330 | joystickBeingConfigured!!.onConfigureTouch(event) | 322 | joystickBeingConfigured!!.onConfigureTouch(event) |
| @@ -351,231 +343,257 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 351 | return true | 343 | return true |
| 352 | } | 344 | } |
| 353 | 345 | ||
| 354 | private fun addOverlayControls(layout: String) { | 346 | private fun addOverlayControls(layout: OverlayLayout) { |
| 355 | val windowSize = getSafeScreenSize(context, Pair(measuredWidth, measuredHeight)) | 347 | val windowSize = getSafeScreenSize(context, Pair(measuredWidth, measuredHeight)) |
| 356 | if (preferences.getBoolean(Settings.PREF_BUTTON_A, true)) { | 348 | val overlayControlData = NativeConfig.getOverlayControlData() |
| 357 | overlayButtons.add( | 349 | for (data in overlayControlData) { |
| 358 | initializeOverlayButton( | 350 | if (!data.enabled) { |
| 359 | context, | 351 | continue |
| 360 | windowSize, | 352 | } |
| 361 | R.drawable.facebutton_a, | 353 | |
| 362 | R.drawable.facebutton_a_depressed, | 354 | val position = data.positionFromLayout(layout) |
| 363 | ButtonType.BUTTON_A, | 355 | when (data.id) { |
| 364 | Settings.PREF_BUTTON_A, | 356 | OverlayControl.BUTTON_A.id -> { |
| 365 | layout | 357 | overlayButtons.add( |
| 366 | ) | 358 | initializeOverlayButton( |
| 367 | ) | 359 | context, |
| 368 | } | 360 | windowSize, |
| 369 | if (preferences.getBoolean(Settings.PREF_BUTTON_B, true)) { | 361 | R.drawable.facebutton_a, |
| 370 | overlayButtons.add( | 362 | R.drawable.facebutton_a_depressed, |
| 371 | initializeOverlayButton( | 363 | ButtonType.BUTTON_A, |
| 372 | context, | 364 | data, |
| 373 | windowSize, | 365 | position |
| 374 | R.drawable.facebutton_b, | 366 | ) |
| 375 | R.drawable.facebutton_b_depressed, | 367 | ) |
| 376 | ButtonType.BUTTON_B, | 368 | } |
| 377 | Settings.PREF_BUTTON_B, | 369 | |
| 378 | layout | 370 | OverlayControl.BUTTON_B.id -> { |
| 379 | ) | 371 | overlayButtons.add( |
| 380 | ) | 372 | initializeOverlayButton( |
| 381 | } | 373 | context, |
| 382 | if (preferences.getBoolean(Settings.PREF_BUTTON_X, true)) { | 374 | windowSize, |
| 383 | overlayButtons.add( | 375 | R.drawable.facebutton_b, |
| 384 | initializeOverlayButton( | 376 | R.drawable.facebutton_b_depressed, |
| 385 | context, | 377 | ButtonType.BUTTON_B, |
| 386 | windowSize, | 378 | data, |
| 387 | R.drawable.facebutton_x, | 379 | position |
| 388 | R.drawable.facebutton_x_depressed, | 380 | ) |
| 389 | ButtonType.BUTTON_X, | 381 | ) |
| 390 | Settings.PREF_BUTTON_X, | 382 | } |
| 391 | layout | 383 | |
| 392 | ) | 384 | OverlayControl.BUTTON_X.id -> { |
| 393 | ) | 385 | overlayButtons.add( |
| 394 | } | 386 | initializeOverlayButton( |
| 395 | if (preferences.getBoolean(Settings.PREF_BUTTON_Y, true)) { | 387 | context, |
| 396 | overlayButtons.add( | 388 | windowSize, |
| 397 | initializeOverlayButton( | 389 | R.drawable.facebutton_x, |
| 398 | context, | 390 | R.drawable.facebutton_x_depressed, |
| 399 | windowSize, | 391 | ButtonType.BUTTON_X, |
| 400 | R.drawable.facebutton_y, | 392 | data, |
| 401 | R.drawable.facebutton_y_depressed, | 393 | position |
| 402 | ButtonType.BUTTON_Y, | 394 | ) |
| 403 | Settings.PREF_BUTTON_Y, | 395 | ) |
| 404 | layout | 396 | } |
| 405 | ) | 397 | |
| 406 | ) | 398 | OverlayControl.BUTTON_Y.id -> { |
| 407 | } | 399 | overlayButtons.add( |
| 408 | if (preferences.getBoolean(Settings.PREF_BUTTON_L, true)) { | 400 | initializeOverlayButton( |
| 409 | overlayButtons.add( | 401 | context, |
| 410 | initializeOverlayButton( | 402 | windowSize, |
| 411 | context, | 403 | R.drawable.facebutton_y, |
| 412 | windowSize, | 404 | R.drawable.facebutton_y_depressed, |
| 413 | R.drawable.l_shoulder, | 405 | ButtonType.BUTTON_Y, |
| 414 | R.drawable.l_shoulder_depressed, | 406 | data, |
| 415 | ButtonType.TRIGGER_L, | 407 | position |
| 416 | Settings.PREF_BUTTON_L, | 408 | ) |
| 417 | layout | 409 | ) |
| 418 | ) | 410 | } |
| 419 | ) | 411 | |
| 420 | } | 412 | OverlayControl.BUTTON_PLUS.id -> { |
| 421 | if (preferences.getBoolean(Settings.PREF_BUTTON_R, true)) { | 413 | overlayButtons.add( |
| 422 | overlayButtons.add( | 414 | initializeOverlayButton( |
| 423 | initializeOverlayButton( | 415 | context, |
| 424 | context, | 416 | windowSize, |
| 425 | windowSize, | 417 | R.drawable.facebutton_plus, |
| 426 | R.drawable.r_shoulder, | 418 | R.drawable.facebutton_plus_depressed, |
| 427 | R.drawable.r_shoulder_depressed, | 419 | ButtonType.BUTTON_PLUS, |
| 428 | ButtonType.TRIGGER_R, | 420 | data, |
| 429 | Settings.PREF_BUTTON_R, | 421 | position |
| 430 | layout | 422 | ) |
| 431 | ) | 423 | ) |
| 432 | ) | 424 | } |
| 433 | } | 425 | |
| 434 | if (preferences.getBoolean(Settings.PREF_BUTTON_ZL, true)) { | 426 | OverlayControl.BUTTON_MINUS.id -> { |
| 435 | overlayButtons.add( | 427 | overlayButtons.add( |
| 436 | initializeOverlayButton( | 428 | initializeOverlayButton( |
| 437 | context, | 429 | context, |
| 438 | windowSize, | 430 | windowSize, |
| 439 | R.drawable.zl_trigger, | 431 | R.drawable.facebutton_minus, |
| 440 | R.drawable.zl_trigger_depressed, | 432 | R.drawable.facebutton_minus_depressed, |
| 441 | ButtonType.TRIGGER_ZL, | 433 | ButtonType.BUTTON_MINUS, |
| 442 | Settings.PREF_BUTTON_ZL, | 434 | data, |
| 443 | layout | 435 | position |
| 444 | ) | 436 | ) |
| 445 | ) | 437 | ) |
| 446 | } | 438 | } |
| 447 | if (preferences.getBoolean(Settings.PREF_BUTTON_ZR, true)) { | 439 | |
| 448 | overlayButtons.add( | 440 | OverlayControl.BUTTON_HOME.id -> { |
| 449 | initializeOverlayButton( | 441 | overlayButtons.add( |
| 450 | context, | 442 | initializeOverlayButton( |
| 451 | windowSize, | 443 | context, |
| 452 | R.drawable.zr_trigger, | 444 | windowSize, |
| 453 | R.drawable.zr_trigger_depressed, | 445 | R.drawable.facebutton_home, |
| 454 | ButtonType.TRIGGER_ZR, | 446 | R.drawable.facebutton_home_depressed, |
| 455 | Settings.PREF_BUTTON_ZR, | 447 | ButtonType.BUTTON_HOME, |
| 456 | layout | 448 | data, |
| 457 | ) | 449 | position |
| 458 | ) | 450 | ) |
| 459 | } | 451 | ) |
| 460 | if (preferences.getBoolean(Settings.PREF_BUTTON_PLUS, true)) { | 452 | } |
| 461 | overlayButtons.add( | 453 | |
| 462 | initializeOverlayButton( | 454 | OverlayControl.BUTTON_CAPTURE.id -> { |
| 463 | context, | 455 | overlayButtons.add( |
| 464 | windowSize, | 456 | initializeOverlayButton( |
| 465 | R.drawable.facebutton_plus, | 457 | context, |
| 466 | R.drawable.facebutton_plus_depressed, | 458 | windowSize, |
| 467 | ButtonType.BUTTON_PLUS, | 459 | R.drawable.facebutton_screenshot, |
| 468 | Settings.PREF_BUTTON_PLUS, | 460 | R.drawable.facebutton_screenshot_depressed, |
| 469 | layout | 461 | ButtonType.BUTTON_CAPTURE, |
| 470 | ) | 462 | data, |
| 471 | ) | 463 | position |
| 472 | } | 464 | ) |
| 473 | if (preferences.getBoolean(Settings.PREF_BUTTON_MINUS, true)) { | 465 | ) |
| 474 | overlayButtons.add( | 466 | } |
| 475 | initializeOverlayButton( | 467 | |
| 476 | context, | 468 | OverlayControl.BUTTON_L.id -> { |
| 477 | windowSize, | 469 | overlayButtons.add( |
| 478 | R.drawable.facebutton_minus, | 470 | initializeOverlayButton( |
| 479 | R.drawable.facebutton_minus_depressed, | 471 | context, |
| 480 | ButtonType.BUTTON_MINUS, | 472 | windowSize, |
| 481 | Settings.PREF_BUTTON_MINUS, | 473 | R.drawable.l_shoulder, |
| 482 | layout | 474 | R.drawable.l_shoulder_depressed, |
| 483 | ) | 475 | ButtonType.TRIGGER_L, |
| 484 | ) | 476 | data, |
| 485 | } | 477 | position |
| 486 | if (preferences.getBoolean(Settings.PREF_BUTTON_DPAD, true)) { | 478 | ) |
| 487 | overlayDpads.add( | 479 | ) |
| 488 | initializeOverlayDpad( | 480 | } |
| 489 | context, | 481 | |
| 490 | windowSize, | 482 | OverlayControl.BUTTON_R.id -> { |
| 491 | R.drawable.dpad_standard, | 483 | overlayButtons.add( |
| 492 | R.drawable.dpad_standard_cardinal_depressed, | 484 | initializeOverlayButton( |
| 493 | R.drawable.dpad_standard_diagonal_depressed, | 485 | context, |
| 494 | layout | 486 | windowSize, |
| 495 | ) | 487 | R.drawable.r_shoulder, |
| 496 | ) | 488 | R.drawable.r_shoulder_depressed, |
| 497 | } | 489 | ButtonType.TRIGGER_R, |
| 498 | if (preferences.getBoolean(Settings.PREF_STICK_L, true)) { | 490 | data, |
| 499 | overlayJoysticks.add( | 491 | position |
| 500 | initializeOverlayJoystick( | 492 | ) |
| 501 | context, | 493 | ) |
| 502 | windowSize, | 494 | } |
| 503 | R.drawable.joystick_range, | 495 | |
| 504 | R.drawable.joystick, | 496 | OverlayControl.BUTTON_ZL.id -> { |
| 505 | R.drawable.joystick_depressed, | 497 | overlayButtons.add( |
| 506 | StickType.STICK_L, | 498 | initializeOverlayButton( |
| 507 | ButtonType.STICK_L, | 499 | context, |
| 508 | Settings.PREF_STICK_L, | 500 | windowSize, |
| 509 | layout | 501 | R.drawable.zl_trigger, |
| 510 | ) | 502 | R.drawable.zl_trigger_depressed, |
| 511 | ) | 503 | ButtonType.TRIGGER_ZL, |
| 512 | } | 504 | data, |
| 513 | if (preferences.getBoolean(Settings.PREF_STICK_R, true)) { | 505 | position |
| 514 | overlayJoysticks.add( | 506 | ) |
| 515 | initializeOverlayJoystick( | 507 | ) |
| 516 | context, | 508 | } |
| 517 | windowSize, | 509 | |
| 518 | R.drawable.joystick_range, | 510 | OverlayControl.BUTTON_ZR.id -> { |
| 519 | R.drawable.joystick, | 511 | overlayButtons.add( |
| 520 | R.drawable.joystick_depressed, | 512 | initializeOverlayButton( |
| 521 | StickType.STICK_R, | 513 | context, |
| 522 | ButtonType.STICK_R, | 514 | windowSize, |
| 523 | Settings.PREF_STICK_R, | 515 | R.drawable.zr_trigger, |
| 524 | layout | 516 | R.drawable.zr_trigger_depressed, |
| 525 | ) | 517 | ButtonType.TRIGGER_ZR, |
| 526 | ) | 518 | data, |
| 527 | } | 519 | position |
| 528 | if (preferences.getBoolean(Settings.PREF_BUTTON_HOME, false)) { | 520 | ) |
| 529 | overlayButtons.add( | 521 | ) |
| 530 | initializeOverlayButton( | 522 | } |
| 531 | context, | 523 | |
| 532 | windowSize, | 524 | OverlayControl.BUTTON_STICK_L.id -> { |
| 533 | R.drawable.facebutton_home, | 525 | overlayButtons.add( |
| 534 | R.drawable.facebutton_home_depressed, | 526 | initializeOverlayButton( |
| 535 | ButtonType.BUTTON_HOME, | 527 | context, |
| 536 | Settings.PREF_BUTTON_HOME, | 528 | windowSize, |
| 537 | layout | 529 | R.drawable.button_l3, |
| 538 | ) | 530 | R.drawable.button_l3_depressed, |
| 539 | ) | 531 | ButtonType.STICK_L, |
| 540 | } | 532 | data, |
| 541 | if (preferences.getBoolean(Settings.PREF_BUTTON_SCREENSHOT, false)) { | 533 | position |
| 542 | overlayButtons.add( | 534 | ) |
| 543 | initializeOverlayButton( | 535 | ) |
| 544 | context, | 536 | } |
| 545 | windowSize, | 537 | |
| 546 | R.drawable.facebutton_screenshot, | 538 | OverlayControl.BUTTON_STICK_R.id -> { |
| 547 | R.drawable.facebutton_screenshot_depressed, | 539 | overlayButtons.add( |
| 548 | ButtonType.BUTTON_CAPTURE, | 540 | initializeOverlayButton( |
| 549 | Settings.PREF_BUTTON_SCREENSHOT, | 541 | context, |
| 550 | layout | 542 | windowSize, |
| 551 | ) | 543 | R.drawable.button_r3, |
| 552 | ) | 544 | R.drawable.button_r3_depressed, |
| 553 | } | 545 | ButtonType.STICK_R, |
| 554 | if (preferences.getBoolean(Settings.PREF_BUTTON_STICK_L, true)) { | 546 | data, |
| 555 | overlayButtons.add( | 547 | position |
| 556 | initializeOverlayButton( | 548 | ) |
| 557 | context, | 549 | ) |
| 558 | windowSize, | 550 | } |
| 559 | R.drawable.button_l3, | 551 | |
| 560 | R.drawable.button_l3_depressed, | 552 | OverlayControl.STICK_L.id -> { |
| 561 | ButtonType.STICK_L, | 553 | overlayJoysticks.add( |
| 562 | Settings.PREF_BUTTON_STICK_L, | 554 | initializeOverlayJoystick( |
| 563 | layout | 555 | context, |
| 564 | ) | 556 | windowSize, |
| 565 | ) | 557 | R.drawable.joystick_range, |
| 566 | } | 558 | R.drawable.joystick, |
| 567 | if (preferences.getBoolean(Settings.PREF_BUTTON_STICK_R, true)) { | 559 | R.drawable.joystick_depressed, |
| 568 | overlayButtons.add( | 560 | StickType.STICK_L, |
| 569 | initializeOverlayButton( | 561 | ButtonType.STICK_L, |
| 570 | context, | 562 | data, |
| 571 | windowSize, | 563 | position |
| 572 | R.drawable.button_r3, | 564 | ) |
| 573 | R.drawable.button_r3_depressed, | 565 | ) |
| 574 | ButtonType.STICK_R, | 566 | } |
| 575 | Settings.PREF_BUTTON_STICK_R, | 567 | |
| 576 | layout | 568 | OverlayControl.STICK_R.id -> { |
| 577 | ) | 569 | overlayJoysticks.add( |
| 578 | ) | 570 | initializeOverlayJoystick( |
| 571 | context, | ||
| 572 | windowSize, | ||
| 573 | R.drawable.joystick_range, | ||
| 574 | R.drawable.joystick, | ||
| 575 | R.drawable.joystick_depressed, | ||
| 576 | StickType.STICK_R, | ||
| 577 | ButtonType.STICK_R, | ||
| 578 | data, | ||
| 579 | position | ||
| 580 | ) | ||
| 581 | ) | ||
| 582 | } | ||
| 583 | |||
| 584 | OverlayControl.COMBINED_DPAD.id -> { | ||
| 585 | overlayDpads.add( | ||
| 586 | initializeOverlayDpad( | ||
| 587 | context, | ||
| 588 | windowSize, | ||
| 589 | R.drawable.dpad_standard, | ||
| 590 | R.drawable.dpad_standard_cardinal_depressed, | ||
| 591 | R.drawable.dpad_standard_diagonal_depressed, | ||
| 592 | position | ||
| 593 | ) | ||
| 594 | ) | ||
| 595 | } | ||
| 596 | } | ||
| 579 | } | 597 | } |
| 580 | } | 598 | } |
| 581 | 599 | ||
| @@ -586,313 +604,87 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 586 | overlayJoysticks.clear() | 604 | overlayJoysticks.clear() |
| 587 | 605 | ||
| 588 | // Add all the enabled overlay items back to the HashSet. | 606 | // Add all the enabled overlay items back to the HashSet. |
| 589 | if (EmulationMenuSettings.showOverlay) { | 607 | if (BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean()) { |
| 590 | addOverlayControls(layout) | 608 | addOverlayControls(layout) |
| 591 | } | 609 | } |
| 592 | invalidate() | 610 | invalidate() |
| 593 | } | 611 | } |
| 594 | 612 | ||
| 595 | private fun saveControlPosition(prefId: String, x: Int, y: Int, layout: String) { | 613 | private fun saveControlPosition(id: String, x: Int, y: Int, layout: OverlayLayout) { |
| 596 | val windowSize = getSafeScreenSize(context, Pair(measuredWidth, measuredHeight)) | 614 | val windowSize = getSafeScreenSize(context, Pair(measuredWidth, measuredHeight)) |
| 597 | val min = windowSize.first | 615 | val min = windowSize.first |
| 598 | val max = windowSize.second | 616 | val max = windowSize.second |
| 599 | PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext).edit() | 617 | val overlayControlData = NativeConfig.getOverlayControlData() |
| 600 | .putFloat("$prefId-X$layout", (x - min.x).toFloat() / max.x) | 618 | val data = overlayControlData.firstOrNull { it.id == id } |
| 601 | .putFloat("$prefId-Y$layout", (y - min.y).toFloat() / max.y) | 619 | val newPosition = Pair((x - min.x).toDouble() / max.x, (y - min.y).toDouble() / max.y) |
| 602 | .apply() | 620 | when (layout) { |
| 621 | OverlayLayout.Landscape -> data?.landscapePosition = newPosition | ||
| 622 | OverlayLayout.Portrait -> data?.portraitPosition = newPosition | ||
| 623 | OverlayLayout.Foldable -> data?.foldablePosition = newPosition | ||
| 624 | } | ||
| 625 | NativeConfig.setOverlayControlData(overlayControlData) | ||
| 603 | } | 626 | } |
| 604 | 627 | ||
| 605 | fun setIsInEditMode(editMode: Boolean) { | 628 | fun setIsInEditMode(editMode: Boolean) { |
| 606 | inEditMode = editMode | 629 | inEditMode = editMode |
| 607 | } | 630 | } |
| 608 | 631 | ||
| 609 | private fun resetCurrentLayout() { | 632 | /** |
| 610 | defaultOverlayByLayout(layout) | 633 | * Applies and saves all default values for the overlay |
| 611 | val layoutIndex = overlayLayouts.indexOf(layout) | 634 | */ |
| 612 | preferences.edit() | 635 | private fun populateDefaultConfig() { |
| 613 | .putInt(Settings.overlayLayoutPrefs[layoutIndex], overlayLayoutVersions[layoutIndex]) | 636 | val newConfig = OverlayControl.entries.map { it.toOverlayControlData() } |
| 614 | .apply() | 637 | NativeConfig.setOverlayControlData(newConfig.toTypedArray()) |
| 638 | NativeConfig.saveGlobalConfig() | ||
| 615 | } | 639 | } |
| 616 | 640 | ||
| 617 | private fun resetAllLayouts() { | 641 | /** |
| 618 | val editor = preferences.edit() | 642 | * Checks if any new controls were added to OverlayControl that do not exist within deserialized |
| 619 | overlayLayouts.forEachIndexed { i, layout -> | 643 | * config and adds / saves them if necessary |
| 620 | defaultOverlayByLayout(layout) | 644 | * |
| 621 | editor.putInt(Settings.overlayLayoutPrefs[i], overlayLayoutVersions[i]) | 645 | * @param overlayControlData Overlay control data from [NativeConfig.getOverlayControlData] |
| 646 | */ | ||
| 647 | private fun checkForNewControls(overlayControlData: Array<OverlayControlData>) { | ||
| 648 | val missingControls = mutableListOf<OverlayControlData>() | ||
| 649 | OverlayControl.entries.forEach { defaultControl -> | ||
| 650 | val controlData = overlayControlData.firstOrNull { it.id == defaultControl.id } | ||
| 651 | if (controlData == null) { | ||
| 652 | missingControls.add(defaultControl.toOverlayControlData()) | ||
| 653 | } | ||
| 654 | } | ||
| 655 | |||
| 656 | if (missingControls.isNotEmpty()) { | ||
| 657 | NativeConfig.setOverlayControlData( | ||
| 658 | arrayOf(*overlayControlData, *(missingControls.toTypedArray())) | ||
| 659 | ) | ||
| 660 | NativeConfig.saveGlobalConfig() | ||
| 622 | } | 661 | } |
| 623 | editor.putInt(Settings.PREF_OVERLAY_VERSION, OVERLAY_VERSION) | ||
| 624 | editor.apply() | ||
| 625 | } | 662 | } |
| 626 | 663 | ||
| 627 | fun resetLayoutVisibilityAndPlacement() { | 664 | fun resetLayoutVisibilityAndPlacement() { |
| 628 | defaultOverlayByLayout(layout) | 665 | defaultOverlayPositionByLayout(layout) |
| 629 | val editor = preferences.edit() | 666 | |
| 630 | Settings.overlayPreferences.forEachIndexed { _, pref -> | 667 | val overlayControlData = NativeConfig.getOverlayControlData() |
| 631 | editor.remove(pref) | 668 | overlayControlData.forEach { |
| 669 | it.enabled = OverlayControl.from(it.id)?.defaultVisibility == false | ||
| 632 | } | 670 | } |
| 633 | editor.apply() | 671 | NativeConfig.setOverlayControlData(overlayControlData) |
| 672 | |||
| 634 | refreshControls() | 673 | refreshControls() |
| 635 | } | 674 | } |
| 636 | 675 | ||
| 637 | private val landscapeResources = arrayOf( | 676 | private fun defaultOverlayPositionByLayout(layout: OverlayLayout) { |
| 638 | R.integer.SWITCH_BUTTON_A_X, | 677 | val overlayControlData = NativeConfig.getOverlayControlData() |
| 639 | R.integer.SWITCH_BUTTON_A_Y, | 678 | for (data in overlayControlData) { |
| 640 | R.integer.SWITCH_BUTTON_B_X, | 679 | val defaultControlData = OverlayControl.from(data.id) ?: continue |
| 641 | R.integer.SWITCH_BUTTON_B_Y, | 680 | val position = defaultControlData.getDefaultPositionForLayout(layout) |
| 642 | R.integer.SWITCH_BUTTON_X_X, | 681 | when (layout) { |
| 643 | R.integer.SWITCH_BUTTON_X_Y, | 682 | OverlayLayout.Landscape -> data.landscapePosition = position |
| 644 | R.integer.SWITCH_BUTTON_Y_X, | 683 | OverlayLayout.Portrait -> data.portraitPosition = position |
| 645 | R.integer.SWITCH_BUTTON_Y_Y, | 684 | OverlayLayout.Foldable -> data.foldablePosition = position |
| 646 | R.integer.SWITCH_TRIGGER_ZL_X, | 685 | } |
| 647 | R.integer.SWITCH_TRIGGER_ZL_Y, | ||
| 648 | R.integer.SWITCH_TRIGGER_ZR_X, | ||
| 649 | R.integer.SWITCH_TRIGGER_ZR_Y, | ||
| 650 | R.integer.SWITCH_BUTTON_DPAD_X, | ||
| 651 | R.integer.SWITCH_BUTTON_DPAD_Y, | ||
| 652 | R.integer.SWITCH_TRIGGER_L_X, | ||
| 653 | R.integer.SWITCH_TRIGGER_L_Y, | ||
| 654 | R.integer.SWITCH_TRIGGER_R_X, | ||
| 655 | R.integer.SWITCH_TRIGGER_R_Y, | ||
| 656 | R.integer.SWITCH_BUTTON_PLUS_X, | ||
| 657 | R.integer.SWITCH_BUTTON_PLUS_Y, | ||
| 658 | R.integer.SWITCH_BUTTON_MINUS_X, | ||
| 659 | R.integer.SWITCH_BUTTON_MINUS_Y, | ||
| 660 | R.integer.SWITCH_BUTTON_HOME_X, | ||
| 661 | R.integer.SWITCH_BUTTON_HOME_Y, | ||
| 662 | R.integer.SWITCH_BUTTON_CAPTURE_X, | ||
| 663 | R.integer.SWITCH_BUTTON_CAPTURE_Y, | ||
| 664 | R.integer.SWITCH_STICK_R_X, | ||
| 665 | R.integer.SWITCH_STICK_R_Y, | ||
| 666 | R.integer.SWITCH_STICK_L_X, | ||
| 667 | R.integer.SWITCH_STICK_L_Y, | ||
| 668 | R.integer.SWITCH_BUTTON_STICK_L_X, | ||
| 669 | R.integer.SWITCH_BUTTON_STICK_L_Y, | ||
| 670 | R.integer.SWITCH_BUTTON_STICK_R_X, | ||
| 671 | R.integer.SWITCH_BUTTON_STICK_R_Y | ||
| 672 | ) | ||
| 673 | |||
| 674 | private val portraitResources = arrayOf( | ||
| 675 | R.integer.SWITCH_BUTTON_A_X_PORTRAIT, | ||
| 676 | R.integer.SWITCH_BUTTON_A_Y_PORTRAIT, | ||
| 677 | R.integer.SWITCH_BUTTON_B_X_PORTRAIT, | ||
| 678 | R.integer.SWITCH_BUTTON_B_Y_PORTRAIT, | ||
| 679 | R.integer.SWITCH_BUTTON_X_X_PORTRAIT, | ||
| 680 | R.integer.SWITCH_BUTTON_X_Y_PORTRAIT, | ||
| 681 | R.integer.SWITCH_BUTTON_Y_X_PORTRAIT, | ||
| 682 | R.integer.SWITCH_BUTTON_Y_Y_PORTRAIT, | ||
| 683 | R.integer.SWITCH_TRIGGER_ZL_X_PORTRAIT, | ||
| 684 | R.integer.SWITCH_TRIGGER_ZL_Y_PORTRAIT, | ||
| 685 | R.integer.SWITCH_TRIGGER_ZR_X_PORTRAIT, | ||
| 686 | R.integer.SWITCH_TRIGGER_ZR_Y_PORTRAIT, | ||
| 687 | R.integer.SWITCH_BUTTON_DPAD_X_PORTRAIT, | ||
| 688 | R.integer.SWITCH_BUTTON_DPAD_Y_PORTRAIT, | ||
| 689 | R.integer.SWITCH_TRIGGER_L_X_PORTRAIT, | ||
| 690 | R.integer.SWITCH_TRIGGER_L_Y_PORTRAIT, | ||
| 691 | R.integer.SWITCH_TRIGGER_R_X_PORTRAIT, | ||
| 692 | R.integer.SWITCH_TRIGGER_R_Y_PORTRAIT, | ||
| 693 | R.integer.SWITCH_BUTTON_PLUS_X_PORTRAIT, | ||
| 694 | R.integer.SWITCH_BUTTON_PLUS_Y_PORTRAIT, | ||
| 695 | R.integer.SWITCH_BUTTON_MINUS_X_PORTRAIT, | ||
| 696 | R.integer.SWITCH_BUTTON_MINUS_Y_PORTRAIT, | ||
| 697 | R.integer.SWITCH_BUTTON_HOME_X_PORTRAIT, | ||
| 698 | R.integer.SWITCH_BUTTON_HOME_Y_PORTRAIT, | ||
| 699 | R.integer.SWITCH_BUTTON_CAPTURE_X_PORTRAIT, | ||
| 700 | R.integer.SWITCH_BUTTON_CAPTURE_Y_PORTRAIT, | ||
| 701 | R.integer.SWITCH_STICK_R_X_PORTRAIT, | ||
| 702 | R.integer.SWITCH_STICK_R_Y_PORTRAIT, | ||
| 703 | R.integer.SWITCH_STICK_L_X_PORTRAIT, | ||
| 704 | R.integer.SWITCH_STICK_L_Y_PORTRAIT, | ||
| 705 | R.integer.SWITCH_BUTTON_STICK_L_X_PORTRAIT, | ||
| 706 | R.integer.SWITCH_BUTTON_STICK_L_Y_PORTRAIT, | ||
| 707 | R.integer.SWITCH_BUTTON_STICK_R_X_PORTRAIT, | ||
| 708 | R.integer.SWITCH_BUTTON_STICK_R_Y_PORTRAIT | ||
| 709 | ) | ||
| 710 | |||
| 711 | private val foldableResources = arrayOf( | ||
| 712 | R.integer.SWITCH_BUTTON_A_X_FOLDABLE, | ||
| 713 | R.integer.SWITCH_BUTTON_A_Y_FOLDABLE, | ||
| 714 | R.integer.SWITCH_BUTTON_B_X_FOLDABLE, | ||
| 715 | R.integer.SWITCH_BUTTON_B_Y_FOLDABLE, | ||
| 716 | R.integer.SWITCH_BUTTON_X_X_FOLDABLE, | ||
| 717 | R.integer.SWITCH_BUTTON_X_Y_FOLDABLE, | ||
| 718 | R.integer.SWITCH_BUTTON_Y_X_FOLDABLE, | ||
| 719 | R.integer.SWITCH_BUTTON_Y_Y_FOLDABLE, | ||
| 720 | R.integer.SWITCH_TRIGGER_ZL_X_FOLDABLE, | ||
| 721 | R.integer.SWITCH_TRIGGER_ZL_Y_FOLDABLE, | ||
| 722 | R.integer.SWITCH_TRIGGER_ZR_X_FOLDABLE, | ||
| 723 | R.integer.SWITCH_TRIGGER_ZR_Y_FOLDABLE, | ||
| 724 | R.integer.SWITCH_BUTTON_DPAD_X_FOLDABLE, | ||
| 725 | R.integer.SWITCH_BUTTON_DPAD_Y_FOLDABLE, | ||
| 726 | R.integer.SWITCH_TRIGGER_L_X_FOLDABLE, | ||
| 727 | R.integer.SWITCH_TRIGGER_L_Y_FOLDABLE, | ||
| 728 | R.integer.SWITCH_TRIGGER_R_X_FOLDABLE, | ||
| 729 | R.integer.SWITCH_TRIGGER_R_Y_FOLDABLE, | ||
| 730 | R.integer.SWITCH_BUTTON_PLUS_X_FOLDABLE, | ||
| 731 | R.integer.SWITCH_BUTTON_PLUS_Y_FOLDABLE, | ||
| 732 | R.integer.SWITCH_BUTTON_MINUS_X_FOLDABLE, | ||
| 733 | R.integer.SWITCH_BUTTON_MINUS_Y_FOLDABLE, | ||
| 734 | R.integer.SWITCH_BUTTON_HOME_X_FOLDABLE, | ||
| 735 | R.integer.SWITCH_BUTTON_HOME_Y_FOLDABLE, | ||
| 736 | R.integer.SWITCH_BUTTON_CAPTURE_X_FOLDABLE, | ||
| 737 | R.integer.SWITCH_BUTTON_CAPTURE_Y_FOLDABLE, | ||
| 738 | R.integer.SWITCH_STICK_R_X_FOLDABLE, | ||
| 739 | R.integer.SWITCH_STICK_R_Y_FOLDABLE, | ||
| 740 | R.integer.SWITCH_STICK_L_X_FOLDABLE, | ||
| 741 | R.integer.SWITCH_STICK_L_Y_FOLDABLE, | ||
| 742 | R.integer.SWITCH_BUTTON_STICK_L_X_FOLDABLE, | ||
| 743 | R.integer.SWITCH_BUTTON_STICK_L_Y_FOLDABLE, | ||
| 744 | R.integer.SWITCH_BUTTON_STICK_R_X_FOLDABLE, | ||
| 745 | R.integer.SWITCH_BUTTON_STICK_R_Y_FOLDABLE | ||
| 746 | ) | ||
| 747 | |||
| 748 | private fun getResourceValue(layout: String, position: Int): Float { | ||
| 749 | return when (layout) { | ||
| 750 | PORTRAIT -> resources.getInteger(portraitResources[position]).toFloat() / 1000 | ||
| 751 | FOLDABLE -> resources.getInteger(foldableResources[position]).toFloat() / 1000 | ||
| 752 | else -> resources.getInteger(landscapeResources[position]).toFloat() / 1000 | ||
| 753 | } | 686 | } |
| 754 | } | 687 | NativeConfig.setOverlayControlData(overlayControlData) |
| 755 | |||
| 756 | private fun defaultOverlayByLayout(layout: String) { | ||
| 757 | // Each value represents the position of the button in relation to the screen size without insets. | ||
| 758 | preferences.edit() | ||
| 759 | .putFloat( | ||
| 760 | "${Settings.PREF_BUTTON_A}-X$layout", | ||
| 761 | getResourceValue(layout, 0) | ||
| 762 | ) | ||
| 763 | .putFloat( | ||
| 764 | "${Settings.PREF_BUTTON_A}-Y$layout", | ||
| 765 | getResourceValue(layout, 1) | ||
| 766 | ) | ||
| 767 | .putFloat( | ||
| 768 | "${Settings.PREF_BUTTON_B}-X$layout", | ||
| 769 | getResourceValue(layout, 2) | ||
| 770 | ) | ||
| 771 | .putFloat( | ||
| 772 | "${Settings.PREF_BUTTON_B}-Y$layout", | ||
| 773 | getResourceValue(layout, 3) | ||
| 774 | ) | ||
| 775 | .putFloat( | ||
| 776 | "${Settings.PREF_BUTTON_X}-X$layout", | ||
| 777 | getResourceValue(layout, 4) | ||
| 778 | ) | ||
| 779 | .putFloat( | ||
| 780 | "${Settings.PREF_BUTTON_X}-Y$layout", | ||
| 781 | getResourceValue(layout, 5) | ||
| 782 | ) | ||
| 783 | .putFloat( | ||
| 784 | "${Settings.PREF_BUTTON_Y}-X$layout", | ||
| 785 | getResourceValue(layout, 6) | ||
| 786 | ) | ||
| 787 | .putFloat( | ||
| 788 | "${Settings.PREF_BUTTON_Y}-Y$layout", | ||
| 789 | getResourceValue(layout, 7) | ||
| 790 | ) | ||
| 791 | .putFloat( | ||
| 792 | "${Settings.PREF_BUTTON_ZL}-X$layout", | ||
| 793 | getResourceValue(layout, 8) | ||
| 794 | ) | ||
| 795 | .putFloat( | ||
| 796 | "${Settings.PREF_BUTTON_ZL}-Y$layout", | ||
| 797 | getResourceValue(layout, 9) | ||
| 798 | ) | ||
| 799 | .putFloat( | ||
| 800 | "${Settings.PREF_BUTTON_ZR}-X$layout", | ||
| 801 | getResourceValue(layout, 10) | ||
| 802 | ) | ||
| 803 | .putFloat( | ||
| 804 | "${Settings.PREF_BUTTON_ZR}-Y$layout", | ||
| 805 | getResourceValue(layout, 11) | ||
| 806 | ) | ||
| 807 | .putFloat( | ||
| 808 | "${Settings.PREF_BUTTON_DPAD}-X$layout", | ||
| 809 | getResourceValue(layout, 12) | ||
| 810 | ) | ||
| 811 | .putFloat( | ||
| 812 | "${Settings.PREF_BUTTON_DPAD}-Y$layout", | ||
| 813 | getResourceValue(layout, 13) | ||
| 814 | ) | ||
| 815 | .putFloat( | ||
| 816 | "${Settings.PREF_BUTTON_L}-X$layout", | ||
| 817 | getResourceValue(layout, 14) | ||
| 818 | ) | ||
| 819 | .putFloat( | ||
| 820 | "${Settings.PREF_BUTTON_L}-Y$layout", | ||
| 821 | getResourceValue(layout, 15) | ||
| 822 | ) | ||
| 823 | .putFloat( | ||
| 824 | "${Settings.PREF_BUTTON_R}-X$layout", | ||
| 825 | getResourceValue(layout, 16) | ||
| 826 | ) | ||
| 827 | .putFloat( | ||
| 828 | "${Settings.PREF_BUTTON_R}-Y$layout", | ||
| 829 | getResourceValue(layout, 17) | ||
| 830 | ) | ||
| 831 | .putFloat( | ||
| 832 | "${Settings.PREF_BUTTON_PLUS}-X$layout", | ||
| 833 | getResourceValue(layout, 18) | ||
| 834 | ) | ||
| 835 | .putFloat( | ||
| 836 | "${Settings.PREF_BUTTON_PLUS}-Y$layout", | ||
| 837 | getResourceValue(layout, 19) | ||
| 838 | ) | ||
| 839 | .putFloat( | ||
| 840 | "${Settings.PREF_BUTTON_MINUS}-X$layout", | ||
| 841 | getResourceValue(layout, 20) | ||
| 842 | ) | ||
| 843 | .putFloat( | ||
| 844 | "${Settings.PREF_BUTTON_MINUS}-Y$layout", | ||
| 845 | getResourceValue(layout, 21) | ||
| 846 | ) | ||
| 847 | .putFloat( | ||
| 848 | "${Settings.PREF_BUTTON_HOME}-X$layout", | ||
| 849 | getResourceValue(layout, 22) | ||
| 850 | ) | ||
| 851 | .putFloat( | ||
| 852 | "${Settings.PREF_BUTTON_HOME}-Y$layout", | ||
| 853 | getResourceValue(layout, 23) | ||
| 854 | ) | ||
| 855 | .putFloat( | ||
| 856 | "${Settings.PREF_BUTTON_SCREENSHOT}-X$layout", | ||
| 857 | getResourceValue(layout, 24) | ||
| 858 | ) | ||
| 859 | .putFloat( | ||
| 860 | "${Settings.PREF_BUTTON_SCREENSHOT}-Y$layout", | ||
| 861 | getResourceValue(layout, 25) | ||
| 862 | ) | ||
| 863 | .putFloat( | ||
| 864 | "${Settings.PREF_STICK_R}-X$layout", | ||
| 865 | getResourceValue(layout, 26) | ||
| 866 | ) | ||
| 867 | .putFloat( | ||
| 868 | "${Settings.PREF_STICK_R}-Y$layout", | ||
| 869 | getResourceValue(layout, 27) | ||
| 870 | ) | ||
| 871 | .putFloat( | ||
| 872 | "${Settings.PREF_STICK_L}-X$layout", | ||
| 873 | getResourceValue(layout, 28) | ||
| 874 | ) | ||
| 875 | .putFloat( | ||
| 876 | "${Settings.PREF_STICK_L}-Y$layout", | ||
| 877 | getResourceValue(layout, 29) | ||
| 878 | ) | ||
| 879 | .putFloat( | ||
| 880 | "${Settings.PREF_BUTTON_STICK_L}-X$layout", | ||
| 881 | getResourceValue(layout, 30) | ||
| 882 | ) | ||
| 883 | .putFloat( | ||
| 884 | "${Settings.PREF_BUTTON_STICK_L}-Y$layout", | ||
| 885 | getResourceValue(layout, 31) | ||
| 886 | ) | ||
| 887 | .putFloat( | ||
| 888 | "${Settings.PREF_BUTTON_STICK_R}-X$layout", | ||
| 889 | getResourceValue(layout, 32) | ||
| 890 | ) | ||
| 891 | .putFloat( | ||
| 892 | "${Settings.PREF_BUTTON_STICK_R}-Y$layout", | ||
| 893 | getResourceValue(layout, 33) | ||
| 894 | ) | ||
| 895 | .apply() | ||
| 896 | } | 688 | } |
| 897 | 689 | ||
| 898 | override fun isInEditMode(): Boolean { | 690 | override fun isInEditMode(): Boolean { |
| @@ -913,18 +705,6 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 913 | FOLDABLE_OVERLAY_VERSION | 705 | FOLDABLE_OVERLAY_VERSION |
| 914 | ) | 706 | ) |
| 915 | 707 | ||
| 916 | private val preferences: SharedPreferences = | ||
| 917 | PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) | ||
| 918 | |||
| 919 | const val LANDSCAPE = "_Landscape" | ||
| 920 | const val PORTRAIT = "_Portrait" | ||
| 921 | const val FOLDABLE = "_Foldable" | ||
| 922 | val overlayLayouts = listOf( | ||
| 923 | LANDSCAPE, | ||
| 924 | PORTRAIT, | ||
| 925 | FOLDABLE | ||
| 926 | ) | ||
| 927 | |||
| 928 | /** | 708 | /** |
| 929 | * Resizes a [Bitmap] by a given scale factor | 709 | * Resizes a [Bitmap] by a given scale factor |
| 930 | * | 710 | * |
| @@ -1036,29 +816,19 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 1036 | * In the input overlay configuration menu, | 816 | * In the input overlay configuration menu, |
| 1037 | * once a touch event begins and then ends (ie. Organizing the buttons to one's own liking for the overlay). | 817 | * once a touch event begins and then ends (ie. Organizing the buttons to one's own liking for the overlay). |
| 1038 | * the X and Y coordinates of the button at the END of its touch event | 818 | * the X and Y coordinates of the button at the END of its touch event |
| 1039 | * (when you remove your finger/stylus from the touchscreen) are then stored | 819 | * (when you remove your finger/stylus from the touchscreen) are then stored in a native . |
| 1040 | * within a SharedPreferences instance so that those values can be retrieved here. | ||
| 1041 | * | ||
| 1042 | * | ||
| 1043 | * This has a few benefits over the conventional way of storing the values | ||
| 1044 | * (ie. within the yuzu ini file). | ||
| 1045 | * | ||
| 1046 | * * No native calls | ||
| 1047 | * * Keeps Android-only values inside the Android environment | ||
| 1048 | * | ||
| 1049 | * | ||
| 1050 | * | 820 | * |
| 1051 | * Technically no modifications should need to be performed on the returned | 821 | * Technically no modifications should need to be performed on the returned |
| 1052 | * InputOverlayDrawableButton. Simply add it to the HashSet of overlay items and wait | 822 | * InputOverlayDrawableButton. Simply add it to the HashSet of overlay items and wait |
| 1053 | * for Android to call the onDraw method. | 823 | * for Android to call the onDraw method. |
| 1054 | * | 824 | * |
| 1055 | * @param context The current [Context]. | 825 | * @param context The current [Context]. |
| 1056 | * @param windowSize The size of the window to draw the overlay on. | 826 | * @param windowSize The size of the window to draw the overlay on. |
| 1057 | * @param defaultResId The resource ID of the [Drawable] to get the [Bitmap] of (Default State). | 827 | * @param defaultResId The resource ID of the [Drawable] to get the [Bitmap] of (Default State). |
| 1058 | * @param pressedResId The resource ID of the [Drawable] to get the [Bitmap] of (Pressed State). | 828 | * @param pressedResId The resource ID of the [Drawable] to get the [Bitmap] of (Pressed State). |
| 1059 | * @param buttonId Identifier for determining what type of button the initialized InputOverlayDrawableButton represents. | 829 | * @param buttonId Identifier for determining what type of button the initialized InputOverlayDrawableButton represents. |
| 1060 | * @param prefId Identifier for determining where a button appears on screen. | 830 | * @param overlayControlData Identifier for determining where a button appears on screen. |
| 1061 | * @param layout The current screen layout as determined by [LANDSCAPE], [PORTRAIT], or [FOLDABLE]. | 831 | * @param position The position on screen as represented by an x and y value between 0 and 1. |
| 1062 | * @return An [InputOverlayDrawableButton] with the correct drawing bounds set. | 832 | * @return An [InputOverlayDrawableButton] with the correct drawing bounds set. |
| 1063 | */ | 833 | */ |
| 1064 | private fun initializeOverlayButton( | 834 | private fun initializeOverlayButton( |
| @@ -1067,33 +837,30 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 1067 | defaultResId: Int, | 837 | defaultResId: Int, |
| 1068 | pressedResId: Int, | 838 | pressedResId: Int, |
| 1069 | buttonId: Int, | 839 | buttonId: Int, |
| 1070 | prefId: String, | 840 | overlayControlData: OverlayControlData, |
| 1071 | layout: String | 841 | position: Pair<Double, Double> |
| 1072 | ): InputOverlayDrawableButton { | 842 | ): InputOverlayDrawableButton { |
| 1073 | // Resources handle for fetching the initial Drawable resource. | 843 | // Resources handle for fetching the initial Drawable resource. |
| 1074 | val res = context.resources | 844 | val res = context.resources |
| 1075 | 845 | ||
| 1076 | // SharedPreference to retrieve the X and Y coordinates for the InputOverlayDrawableButton. | ||
| 1077 | val sPrefs = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) | ||
| 1078 | |||
| 1079 | // Decide scale based on button preference ID and user preference | 846 | // Decide scale based on button preference ID and user preference |
| 1080 | var scale: Float = when (prefId) { | 847 | var scale: Float = when (overlayControlData.id) { |
| 1081 | Settings.PREF_BUTTON_HOME, | 848 | OverlayControl.BUTTON_HOME.id, |
| 1082 | Settings.PREF_BUTTON_SCREENSHOT, | 849 | OverlayControl.BUTTON_CAPTURE.id, |
| 1083 | Settings.PREF_BUTTON_PLUS, | 850 | OverlayControl.BUTTON_PLUS.id, |
| 1084 | Settings.PREF_BUTTON_MINUS -> 0.07f | 851 | OverlayControl.BUTTON_MINUS.id -> 0.07f |
| 1085 | 852 | ||
| 1086 | Settings.PREF_BUTTON_L, | 853 | OverlayControl.BUTTON_L.id, |
| 1087 | Settings.PREF_BUTTON_R, | 854 | OverlayControl.BUTTON_R.id, |
| 1088 | Settings.PREF_BUTTON_ZL, | 855 | OverlayControl.BUTTON_ZL.id, |
| 1089 | Settings.PREF_BUTTON_ZR -> 0.26f | 856 | OverlayControl.BUTTON_ZR.id -> 0.26f |
| 1090 | 857 | ||
| 1091 | Settings.PREF_BUTTON_STICK_L, | 858 | OverlayControl.BUTTON_STICK_L.id, |
| 1092 | Settings.PREF_BUTTON_STICK_R -> 0.155f | 859 | OverlayControl.BUTTON_STICK_R.id -> 0.155f |
| 1093 | 860 | ||
| 1094 | else -> 0.11f | 861 | else -> 0.11f |
| 1095 | } | 862 | } |
| 1096 | scale *= (sPrefs.getInt(Settings.PREF_CONTROL_SCALE, 50) + 50).toFloat() | 863 | scale *= (IntSetting.OVERLAY_SCALE.getInt() + 50).toFloat() |
| 1097 | scale /= 100f | 864 | scale /= 100f |
| 1098 | 865 | ||
| 1099 | // Initialize the InputOverlayDrawableButton. | 866 | // Initialize the InputOverlayDrawableButton. |
| @@ -1104,7 +871,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 1104 | defaultStateBitmap, | 871 | defaultStateBitmap, |
| 1105 | pressedStateBitmap, | 872 | pressedStateBitmap, |
| 1106 | buttonId, | 873 | buttonId, |
| 1107 | prefId | 874 | overlayControlData |
| 1108 | ) | 875 | ) |
| 1109 | 876 | ||
| 1110 | // Get the minimum and maximum coordinates of the screen where the button can be placed. | 877 | // Get the minimum and maximum coordinates of the screen where the button can be placed. |
| @@ -1113,12 +880,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 1113 | 880 | ||
| 1114 | // The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay. | 881 | // The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay. |
| 1115 | // These were set in the input overlay configuration menu. | 882 | // These were set in the input overlay configuration menu. |
| 1116 | val xKey = "$prefId-X$layout" | 883 | val drawableX = (position.first * max.x + min.x).toInt() |
| 1117 | val yKey = "$prefId-Y$layout" | 884 | val drawableY = (position.second * max.y + min.y).toInt() |
| 1118 | val drawableXPercent = sPrefs.getFloat(xKey, 0f) | ||
| 1119 | val drawableYPercent = sPrefs.getFloat(yKey, 0f) | ||
| 1120 | val drawableX = (drawableXPercent * max.x + min.x).toInt() | ||
| 1121 | val drawableY = (drawableYPercent * max.y + min.y).toInt() | ||
| 1122 | val width = overlayDrawable.width | 885 | val width = overlayDrawable.width |
| 1123 | val height = overlayDrawable.height | 886 | val height = overlayDrawable.height |
| 1124 | 887 | ||
| @@ -1136,8 +899,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 1136 | drawableX - (width / 2), | 899 | drawableX - (width / 2), |
| 1137 | drawableY - (height / 2) | 900 | drawableY - (height / 2) |
| 1138 | ) | 901 | ) |
| 1139 | val savedOpacity = preferences.getInt(Settings.PREF_CONTROL_OPACITY, 100) | 902 | overlayDrawable.setOpacity(IntSetting.OVERLAY_OPACITY.getInt() * 255 / 100) |
| 1140 | overlayDrawable.setOpacity(savedOpacity * 255 / 100) | ||
| 1141 | return overlayDrawable | 903 | return overlayDrawable |
| 1142 | } | 904 | } |
| 1143 | 905 | ||
| @@ -1149,7 +911,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 1149 | * @param defaultResId The [Bitmap] resource ID of the default state. | 911 | * @param defaultResId The [Bitmap] resource ID of the default state. |
| 1150 | * @param pressedOneDirectionResId The [Bitmap] resource ID of the pressed state in one direction. | 912 | * @param pressedOneDirectionResId The [Bitmap] resource ID of the pressed state in one direction. |
| 1151 | * @param pressedTwoDirectionsResId The [Bitmap] resource ID of the pressed state in two directions. | 913 | * @param pressedTwoDirectionsResId The [Bitmap] resource ID of the pressed state in two directions. |
| 1152 | * @param layout The current screen layout as determined by [LANDSCAPE], [PORTRAIT], or [FOLDABLE]. | 914 | * @param position The position on screen as represented by an x and y value between 0 and 1. |
| 1153 | * @return The initialized [InputOverlayDrawableDpad] | 915 | * @return The initialized [InputOverlayDrawableDpad] |
| 1154 | */ | 916 | */ |
| 1155 | private fun initializeOverlayDpad( | 917 | private fun initializeOverlayDpad( |
| @@ -1158,17 +920,14 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 1158 | defaultResId: Int, | 920 | defaultResId: Int, |
| 1159 | pressedOneDirectionResId: Int, | 921 | pressedOneDirectionResId: Int, |
| 1160 | pressedTwoDirectionsResId: Int, | 922 | pressedTwoDirectionsResId: Int, |
| 1161 | layout: String | 923 | position: Pair<Double, Double> |
| 1162 | ): InputOverlayDrawableDpad { | 924 | ): InputOverlayDrawableDpad { |
| 1163 | // Resources handle for fetching the initial Drawable resource. | 925 | // Resources handle for fetching the initial Drawable resource. |
| 1164 | val res = context.resources | 926 | val res = context.resources |
| 1165 | 927 | ||
| 1166 | // SharedPreference to retrieve the X and Y coordinates for the InputOverlayDrawableDpad. | ||
| 1167 | val sPrefs = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) | ||
| 1168 | |||
| 1169 | // Decide scale based on button ID and user preference | 928 | // Decide scale based on button ID and user preference |
| 1170 | var scale = 0.25f | 929 | var scale = 0.25f |
| 1171 | scale *= (sPrefs.getInt(Settings.PREF_CONTROL_SCALE, 50) + 50).toFloat() | 930 | scale *= (IntSetting.OVERLAY_SCALE.getInt() + 50).toFloat() |
| 1172 | scale /= 100f | 931 | scale /= 100f |
| 1173 | 932 | ||
| 1174 | // Initialize the InputOverlayDrawableDpad. | 933 | // Initialize the InputOverlayDrawableDpad. |
| @@ -1195,10 +954,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 1195 | 954 | ||
| 1196 | // The X and Y coordinates of the InputOverlayDrawableDpad on the InputOverlay. | 955 | // The X and Y coordinates of the InputOverlayDrawableDpad on the InputOverlay. |
| 1197 | // These were set in the input overlay configuration menu. | 956 | // These were set in the input overlay configuration menu. |
| 1198 | val drawableXPercent = sPrefs.getFloat("${Settings.PREF_BUTTON_DPAD}-X$layout", 0f) | 957 | val drawableX = (position.first * max.x + min.x).toInt() |
| 1199 | val drawableYPercent = sPrefs.getFloat("${Settings.PREF_BUTTON_DPAD}-Y$layout", 0f) | 958 | val drawableY = (position.second * max.y + min.y).toInt() |
| 1200 | val drawableX = (drawableXPercent * max.x + min.x).toInt() | ||
| 1201 | val drawableY = (drawableYPercent * max.y + min.y).toInt() | ||
| 1202 | val width = overlayDrawable.width | 959 | val width = overlayDrawable.width |
| 1203 | val height = overlayDrawable.height | 960 | val height = overlayDrawable.height |
| 1204 | 961 | ||
| @@ -1213,8 +970,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 1213 | 970 | ||
| 1214 | // Need to set the image's position | 971 | // Need to set the image's position |
| 1215 | overlayDrawable.setPosition(drawableX - (width / 2), drawableY - (height / 2)) | 972 | overlayDrawable.setPosition(drawableX - (width / 2), drawableY - (height / 2)) |
| 1216 | val savedOpacity = preferences.getInt(Settings.PREF_CONTROL_OPACITY, 100) | 973 | overlayDrawable.setOpacity(IntSetting.OVERLAY_OPACITY.getInt() * 255 / 100) |
| 1217 | overlayDrawable.setOpacity(savedOpacity * 255 / 100) | ||
| 1218 | return overlayDrawable | 974 | return overlayDrawable |
| 1219 | } | 975 | } |
| 1220 | 976 | ||
| @@ -1227,9 +983,9 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 1227 | * @param defaultResInner Resource ID for the default inner image of the joystick (the one you actually move around). | 983 | * @param defaultResInner Resource ID for the default inner image of the joystick (the one you actually move around). |
| 1228 | * @param pressedResInner Resource ID for the pressed inner image of the joystick. | 984 | * @param pressedResInner Resource ID for the pressed inner image of the joystick. |
| 1229 | * @param joystick Identifier for which joystick this is. | 985 | * @param joystick Identifier for which joystick this is. |
| 1230 | * @param button Identifier for which joystick button this is. | 986 | * @param buttonId Identifier for which joystick button this is. |
| 1231 | * @param prefId Identifier for determining where a button appears on screen. | 987 | * @param overlayControlData Identifier for determining where a button appears on screen. |
| 1232 | * @param layout The current screen layout as determined by [LANDSCAPE], [PORTRAIT], or [FOLDABLE]. | 988 | * @param position The position on screen as represented by an x and y value between 0 and 1. |
| 1233 | * @return The initialized [InputOverlayDrawableJoystick]. | 989 | * @return The initialized [InputOverlayDrawableJoystick]. |
| 1234 | */ | 990 | */ |
| 1235 | private fun initializeOverlayJoystick( | 991 | private fun initializeOverlayJoystick( |
| @@ -1239,19 +995,16 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 1239 | defaultResInner: Int, | 995 | defaultResInner: Int, |
| 1240 | pressedResInner: Int, | 996 | pressedResInner: Int, |
| 1241 | joystick: Int, | 997 | joystick: Int, |
| 1242 | button: Int, | 998 | buttonId: Int, |
| 1243 | prefId: String, | 999 | overlayControlData: OverlayControlData, |
| 1244 | layout: String | 1000 | position: Pair<Double, Double> |
| 1245 | ): InputOverlayDrawableJoystick { | 1001 | ): InputOverlayDrawableJoystick { |
| 1246 | // Resources handle for fetching the initial Drawable resource. | 1002 | // Resources handle for fetching the initial Drawable resource. |
| 1247 | val res = context.resources | 1003 | val res = context.resources |
| 1248 | 1004 | ||
| 1249 | // SharedPreference to retrieve the X and Y coordinates for the InputOverlayDrawableJoystick. | ||
| 1250 | val sPrefs = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) | ||
| 1251 | |||
| 1252 | // Decide scale based on user preference | 1005 | // Decide scale based on user preference |
| 1253 | var scale = 0.3f | 1006 | var scale = 0.3f |
| 1254 | scale *= (sPrefs.getInt(Settings.PREF_CONTROL_SCALE, 50) + 50).toFloat() | 1007 | scale *= (IntSetting.OVERLAY_SCALE.getInt() + 50).toFloat() |
| 1255 | scale /= 100f | 1008 | scale /= 100f |
| 1256 | 1009 | ||
| 1257 | // Initialize the InputOverlayDrawableJoystick. | 1010 | // Initialize the InputOverlayDrawableJoystick. |
| @@ -1265,10 +1018,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 1265 | 1018 | ||
| 1266 | // The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay. | 1019 | // The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay. |
| 1267 | // These were set in the input overlay configuration menu. | 1020 | // These were set in the input overlay configuration menu. |
| 1268 | val drawableXPercent = sPrefs.getFloat("$prefId-X$layout", 0f) | 1021 | val drawableX = (position.first * max.x + min.x).toInt() |
| 1269 | val drawableYPercent = sPrefs.getFloat("$prefId-Y$layout", 0f) | 1022 | val drawableY = (position.second * max.y + min.y).toInt() |
| 1270 | val drawableX = (drawableXPercent * max.x + min.x).toInt() | ||
| 1271 | val drawableY = (drawableYPercent * max.y + min.y).toInt() | ||
| 1272 | val outerScale = 1.66f | 1023 | val outerScale = 1.66f |
| 1273 | 1024 | ||
| 1274 | // Now set the bounds for the InputOverlayDrawableJoystick. | 1025 | // Now set the bounds for the InputOverlayDrawableJoystick. |
| @@ -1292,14 +1043,13 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : | |||
| 1292 | outerRect, | 1043 | outerRect, |
| 1293 | innerRect, | 1044 | innerRect, |
| 1294 | joystick, | 1045 | joystick, |
| 1295 | button, | 1046 | buttonId, |
| 1296 | prefId | 1047 | overlayControlData.id |
| 1297 | ) | 1048 | ) |
| 1298 | 1049 | ||
| 1299 | // Need to set the image's position | 1050 | // Need to set the image's position |
| 1300 | overlayDrawable.setPosition(drawableX, drawableY) | 1051 | overlayDrawable.setPosition(drawableX, drawableY) |
| 1301 | val savedOpacity = preferences.getInt(Settings.PREF_CONTROL_OPACITY, 100) | 1052 | overlayDrawable.setOpacity(IntSetting.OVERLAY_OPACITY.getInt() * 255 / 100) |
| 1302 | overlayDrawable.setOpacity(savedOpacity * 255 / 100) | ||
| 1303 | return overlayDrawable | 1053 | return overlayDrawable |
| 1304 | } | 1054 | } |
| 1305 | } | 1055 | } |
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 2c28dda88..b14a4f96e 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 | |||
| @@ -10,6 +10,7 @@ import android.graphics.Rect | |||
| 10 | import android.graphics.drawable.BitmapDrawable | 10 | import android.graphics.drawable.BitmapDrawable |
| 11 | import android.view.MotionEvent | 11 | import android.view.MotionEvent |
| 12 | import org.yuzu.yuzu_emu.NativeLibrary.ButtonState | 12 | import org.yuzu.yuzu_emu.NativeLibrary.ButtonState |
| 13 | import org.yuzu.yuzu_emu.overlay.model.OverlayControlData | ||
| 13 | 14 | ||
| 14 | /** | 15 | /** |
| 15 | * Custom [BitmapDrawable] that is capable | 16 | * Custom [BitmapDrawable] that is capable |
| @@ -25,7 +26,7 @@ class InputOverlayDrawableButton( | |||
| 25 | defaultStateBitmap: Bitmap, | 26 | defaultStateBitmap: Bitmap, |
| 26 | pressedStateBitmap: Bitmap, | 27 | pressedStateBitmap: Bitmap, |
| 27 | val buttonId: Int, | 28 | val buttonId: Int, |
| 28 | val prefId: String | 29 | val overlayControlData: OverlayControlData |
| 29 | ) { | 30 | ) { |
| 30 | // The ID value what motion event is tracking | 31 | // The ID value what motion event is tracking |
| 31 | var trackId: Int | 32 | var trackId: Int |
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 518b1e783..113bf7c24 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 | |||
| @@ -14,7 +14,7 @@ import kotlin.math.cos | |||
| 14 | import kotlin.math.sin | 14 | import kotlin.math.sin |
| 15 | import kotlin.math.sqrt | 15 | import kotlin.math.sqrt |
| 16 | import org.yuzu.yuzu_emu.NativeLibrary | 16 | import org.yuzu.yuzu_emu.NativeLibrary |
| 17 | import org.yuzu.yuzu_emu.utils.EmulationMenuSettings | 17 | import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting |
| 18 | 18 | ||
| 19 | /** | 19 | /** |
| 20 | * Custom [BitmapDrawable] that is capable | 20 | * Custom [BitmapDrawable] that is capable |
| @@ -125,7 +125,7 @@ class InputOverlayDrawableJoystick( | |||
| 125 | pressedState = true | 125 | pressedState = true |
| 126 | outerBitmap.alpha = 0 | 126 | outerBitmap.alpha = 0 |
| 127 | boundsBoxBitmap.alpha = opacity | 127 | boundsBoxBitmap.alpha = opacity |
| 128 | if (EmulationMenuSettings.joystickRelCenter) { | 128 | if (BooleanSetting.JOYSTICK_REL_CENTER.getBoolean()) { |
| 129 | virtBounds.offset( | 129 | virtBounds.offset( |
| 130 | xPosition - virtBounds.centerX(), | 130 | xPosition - virtBounds.centerX(), |
| 131 | yPosition - virtBounds.centerY() | 131 | yPosition - virtBounds.centerY() |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayControl.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayControl.kt new file mode 100644 index 000000000..a0eeadf4b --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayControl.kt | |||
| @@ -0,0 +1,188 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.overlay.model | ||
| 5 | |||
| 6 | import androidx.annotation.IntegerRes | ||
| 7 | import org.yuzu.yuzu_emu.R | ||
| 8 | import org.yuzu.yuzu_emu.YuzuApplication | ||
| 9 | |||
| 10 | enum class OverlayControl( | ||
| 11 | val id: String, | ||
| 12 | val defaultVisibility: Boolean, | ||
| 13 | @IntegerRes val defaultLandscapePositionResources: Pair<Int, Int>, | ||
| 14 | @IntegerRes val defaultPortraitPositionResources: Pair<Int, Int>, | ||
| 15 | @IntegerRes val defaultFoldablePositionResources: Pair<Int, Int> | ||
| 16 | ) { | ||
| 17 | BUTTON_A( | ||
| 18 | "button_a", | ||
| 19 | true, | ||
| 20 | Pair(R.integer.BUTTON_A_X, R.integer.BUTTON_A_Y), | ||
| 21 | Pair(R.integer.BUTTON_A_X_PORTRAIT, R.integer.BUTTON_A_Y_PORTRAIT), | ||
| 22 | Pair(R.integer.BUTTON_A_X_FOLDABLE, R.integer.BUTTON_A_Y_FOLDABLE) | ||
| 23 | ), | ||
| 24 | BUTTON_B( | ||
| 25 | "button_b", | ||
| 26 | true, | ||
| 27 | Pair(R.integer.BUTTON_B_X, R.integer.BUTTON_B_Y), | ||
| 28 | Pair(R.integer.BUTTON_B_X_PORTRAIT, R.integer.BUTTON_B_Y_PORTRAIT), | ||
| 29 | Pair(R.integer.BUTTON_B_X_FOLDABLE, R.integer.BUTTON_B_Y_FOLDABLE) | ||
| 30 | ), | ||
| 31 | BUTTON_X( | ||
| 32 | "button_x", | ||
| 33 | true, | ||
| 34 | Pair(R.integer.BUTTON_X_X, R.integer.BUTTON_X_Y), | ||
| 35 | Pair(R.integer.BUTTON_X_X_PORTRAIT, R.integer.BUTTON_X_Y_PORTRAIT), | ||
| 36 | Pair(R.integer.BUTTON_X_X_FOLDABLE, R.integer.BUTTON_X_Y_FOLDABLE) | ||
| 37 | ), | ||
| 38 | BUTTON_Y( | ||
| 39 | "button_y", | ||
| 40 | true, | ||
| 41 | Pair(R.integer.BUTTON_Y_X, R.integer.BUTTON_Y_Y), | ||
| 42 | Pair(R.integer.BUTTON_Y_X_PORTRAIT, R.integer.BUTTON_Y_Y_PORTRAIT), | ||
| 43 | Pair(R.integer.BUTTON_Y_X_FOLDABLE, R.integer.BUTTON_Y_Y_FOLDABLE) | ||
| 44 | ), | ||
| 45 | BUTTON_PLUS( | ||
| 46 | "button_plus", | ||
| 47 | true, | ||
| 48 | Pair(R.integer.BUTTON_PLUS_X, R.integer.BUTTON_PLUS_Y), | ||
| 49 | Pair(R.integer.BUTTON_PLUS_X_PORTRAIT, R.integer.BUTTON_PLUS_Y_PORTRAIT), | ||
| 50 | Pair(R.integer.BUTTON_PLUS_X_FOLDABLE, R.integer.BUTTON_PLUS_Y_FOLDABLE) | ||
| 51 | ), | ||
| 52 | BUTTON_MINUS( | ||
| 53 | "button_minus", | ||
| 54 | true, | ||
| 55 | Pair(R.integer.BUTTON_MINUS_X, R.integer.BUTTON_MINUS_Y), | ||
| 56 | Pair(R.integer.BUTTON_MINUS_X_PORTRAIT, R.integer.BUTTON_MINUS_Y_PORTRAIT), | ||
| 57 | Pair(R.integer.BUTTON_MINUS_X_FOLDABLE, R.integer.BUTTON_MINUS_Y_FOLDABLE) | ||
| 58 | ), | ||
| 59 | BUTTON_HOME( | ||
| 60 | "button_home", | ||
| 61 | false, | ||
| 62 | Pair(R.integer.BUTTON_HOME_X, R.integer.BUTTON_HOME_Y), | ||
| 63 | Pair(R.integer.BUTTON_HOME_X_PORTRAIT, R.integer.BUTTON_HOME_Y_PORTRAIT), | ||
| 64 | Pair(R.integer.BUTTON_HOME_X_FOLDABLE, R.integer.BUTTON_HOME_Y_FOLDABLE) | ||
| 65 | ), | ||
| 66 | BUTTON_CAPTURE( | ||
| 67 | "button_capture", | ||
| 68 | false, | ||
| 69 | Pair(R.integer.BUTTON_CAPTURE_X, R.integer.BUTTON_CAPTURE_Y), | ||
| 70 | Pair(R.integer.BUTTON_CAPTURE_X_PORTRAIT, R.integer.BUTTON_CAPTURE_Y_PORTRAIT), | ||
| 71 | Pair(R.integer.BUTTON_CAPTURE_X_FOLDABLE, R.integer.BUTTON_CAPTURE_Y_FOLDABLE) | ||
| 72 | ), | ||
| 73 | BUTTON_L( | ||
| 74 | "button_l", | ||
| 75 | true, | ||
| 76 | Pair(R.integer.BUTTON_L_X, R.integer.BUTTON_L_Y), | ||
| 77 | Pair(R.integer.BUTTON_L_X_PORTRAIT, R.integer.BUTTON_L_Y_PORTRAIT), | ||
| 78 | Pair(R.integer.BUTTON_L_X_FOLDABLE, R.integer.BUTTON_L_Y_FOLDABLE) | ||
| 79 | ), | ||
| 80 | BUTTON_R( | ||
| 81 | "button_r", | ||
| 82 | true, | ||
| 83 | Pair(R.integer.BUTTON_R_X, R.integer.BUTTON_R_Y), | ||
| 84 | Pair(R.integer.BUTTON_R_X_PORTRAIT, R.integer.BUTTON_R_Y_PORTRAIT), | ||
| 85 | Pair(R.integer.BUTTON_R_X_FOLDABLE, R.integer.BUTTON_R_Y_FOLDABLE) | ||
| 86 | ), | ||
| 87 | BUTTON_ZL( | ||
| 88 | "button_zl", | ||
| 89 | true, | ||
| 90 | Pair(R.integer.BUTTON_ZL_X, R.integer.BUTTON_ZL_Y), | ||
| 91 | Pair(R.integer.BUTTON_ZL_X_PORTRAIT, R.integer.BUTTON_ZL_Y_PORTRAIT), | ||
| 92 | Pair(R.integer.BUTTON_ZL_X_FOLDABLE, R.integer.BUTTON_ZL_Y_FOLDABLE) | ||
| 93 | ), | ||
| 94 | BUTTON_ZR( | ||
| 95 | "button_zr", | ||
| 96 | true, | ||
| 97 | Pair(R.integer.BUTTON_ZR_X, R.integer.BUTTON_ZR_Y), | ||
| 98 | Pair(R.integer.BUTTON_ZR_X_PORTRAIT, R.integer.BUTTON_ZR_Y_PORTRAIT), | ||
| 99 | Pair(R.integer.BUTTON_ZR_X_FOLDABLE, R.integer.BUTTON_ZR_Y_FOLDABLE) | ||
| 100 | ), | ||
| 101 | BUTTON_STICK_L( | ||
| 102 | "button_stick_l", | ||
| 103 | true, | ||
| 104 | Pair(R.integer.BUTTON_STICK_L_X, R.integer.BUTTON_STICK_L_Y), | ||
| 105 | Pair(R.integer.BUTTON_STICK_L_X_PORTRAIT, R.integer.BUTTON_STICK_L_Y_PORTRAIT), | ||
| 106 | Pair(R.integer.BUTTON_STICK_L_X_FOLDABLE, R.integer.BUTTON_STICK_L_Y_FOLDABLE) | ||
| 107 | ), | ||
| 108 | BUTTON_STICK_R( | ||
| 109 | "button_stick_r", | ||
| 110 | true, | ||
| 111 | Pair(R.integer.BUTTON_STICK_R_X, R.integer.BUTTON_STICK_R_Y), | ||
| 112 | Pair(R.integer.BUTTON_STICK_R_X_PORTRAIT, R.integer.BUTTON_STICK_R_Y_PORTRAIT), | ||
| 113 | Pair(R.integer.BUTTON_STICK_R_X_FOLDABLE, R.integer.BUTTON_STICK_R_Y_FOLDABLE) | ||
| 114 | ), | ||
| 115 | STICK_L( | ||
| 116 | "stick_l", | ||
| 117 | true, | ||
| 118 | Pair(R.integer.STICK_L_X, R.integer.STICK_L_Y), | ||
| 119 | Pair(R.integer.STICK_L_X_PORTRAIT, R.integer.STICK_L_Y_PORTRAIT), | ||
| 120 | Pair(R.integer.STICK_L_X_FOLDABLE, R.integer.STICK_L_Y_FOLDABLE) | ||
| 121 | ), | ||
| 122 | STICK_R( | ||
| 123 | "stick_r", | ||
| 124 | true, | ||
| 125 | Pair(R.integer.STICK_R_X, R.integer.STICK_R_Y), | ||
| 126 | Pair(R.integer.STICK_R_X_PORTRAIT, R.integer.STICK_R_Y_PORTRAIT), | ||
| 127 | Pair(R.integer.STICK_R_X_FOLDABLE, R.integer.STICK_R_Y_FOLDABLE) | ||
| 128 | ), | ||
| 129 | COMBINED_DPAD( | ||
| 130 | "combined_dpad", | ||
| 131 | true, | ||
| 132 | Pair(R.integer.COMBINED_DPAD_X, R.integer.COMBINED_DPAD_Y), | ||
| 133 | Pair(R.integer.COMBINED_DPAD_X_PORTRAIT, R.integer.COMBINED_DPAD_Y_PORTRAIT), | ||
| 134 | Pair(R.integer.COMBINED_DPAD_X_FOLDABLE, R.integer.COMBINED_DPAD_Y_FOLDABLE) | ||
| 135 | ); | ||
| 136 | |||
| 137 | fun getDefaultPositionForLayout(layout: OverlayLayout): Pair<Double, Double> { | ||
| 138 | val rawResourcePair: Pair<Int, Int> | ||
| 139 | YuzuApplication.appContext.resources.apply { | ||
| 140 | rawResourcePair = when (layout) { | ||
| 141 | OverlayLayout.Landscape -> { | ||
| 142 | Pair( | ||
| 143 | getInteger(this@OverlayControl.defaultLandscapePositionResources.first), | ||
| 144 | getInteger(this@OverlayControl.defaultLandscapePositionResources.second) | ||
| 145 | ) | ||
| 146 | } | ||
| 147 | |||
| 148 | OverlayLayout.Portrait -> { | ||
| 149 | Pair( | ||
| 150 | getInteger(this@OverlayControl.defaultPortraitPositionResources.first), | ||
| 151 | getInteger(this@OverlayControl.defaultPortraitPositionResources.second) | ||
| 152 | ) | ||
| 153 | } | ||
| 154 | |||
| 155 | OverlayLayout.Foldable -> { | ||
| 156 | Pair( | ||
| 157 | getInteger(this@OverlayControl.defaultFoldablePositionResources.first), | ||
| 158 | getInteger(this@OverlayControl.defaultFoldablePositionResources.second) | ||
| 159 | ) | ||
| 160 | } | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | return Pair( | ||
| 165 | rawResourcePair.first.toDouble() / 1000, | ||
| 166 | rawResourcePair.second.toDouble() / 1000 | ||
| 167 | ) | ||
| 168 | } | ||
| 169 | |||
| 170 | fun toOverlayControlData(): OverlayControlData = | ||
| 171 | OverlayControlData( | ||
| 172 | id, | ||
| 173 | defaultVisibility, | ||
| 174 | getDefaultPositionForLayout(OverlayLayout.Landscape), | ||
| 175 | getDefaultPositionForLayout(OverlayLayout.Portrait), | ||
| 176 | getDefaultPositionForLayout(OverlayLayout.Foldable) | ||
| 177 | ) | ||
| 178 | |||
| 179 | companion object { | ||
| 180 | val map: HashMap<String, OverlayControl> by lazy { | ||
| 181 | val hashMap = hashMapOf<String, OverlayControl>() | ||
| 182 | entries.forEach { hashMap[it.id] = it } | ||
| 183 | hashMap | ||
| 184 | } | ||
| 185 | |||
| 186 | fun from(id: String): OverlayControl? = map[id] | ||
| 187 | } | ||
| 188 | } | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayControlData.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayControlData.kt new file mode 100644 index 000000000..26cfeb1db --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayControlData.kt | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.overlay.model | ||
| 5 | |||
| 6 | data class OverlayControlData( | ||
| 7 | val id: String, | ||
| 8 | var enabled: Boolean, | ||
| 9 | var landscapePosition: Pair<Double, Double>, | ||
| 10 | var portraitPosition: Pair<Double, Double>, | ||
| 11 | var foldablePosition: Pair<Double, Double> | ||
| 12 | ) { | ||
| 13 | fun positionFromLayout(layout: OverlayLayout): Pair<Double, Double> = | ||
| 14 | when (layout) { | ||
| 15 | OverlayLayout.Landscape -> landscapePosition | ||
| 16 | OverlayLayout.Portrait -> portraitPosition | ||
| 17 | OverlayLayout.Foldable -> foldablePosition | ||
| 18 | } | ||
| 19 | } | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayControlDefault.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayControlDefault.kt new file mode 100644 index 000000000..6bd74c82f --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayControlDefault.kt | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.overlay.model | ||
| 5 | |||
| 6 | import androidx.annotation.IntegerRes | ||
| 7 | |||
| 8 | data class OverlayControlDefault( | ||
| 9 | val buttonId: String, | ||
| 10 | @IntegerRes val landscapePositionResource: Pair<Int, Int>, | ||
| 11 | @IntegerRes val portraitPositionResource: Pair<Int, Int>, | ||
| 12 | @IntegerRes val foldablePositionResource: Pair<Int, Int> | ||
| 13 | ) | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayLayout.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayLayout.kt new file mode 100644 index 000000000..d728164e5 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayLayout.kt | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.overlay.model | ||
| 5 | |||
| 6 | enum class OverlayLayout(val id: String) { | ||
| 7 | Landscape("Landscape"), | ||
| 8 | Portrait("Portrait"), | ||
| 9 | Foldable("Foldable") | ||
| 10 | } | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt index d4a9da06f..de0794a17 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt | |||
| @@ -10,6 +10,9 @@ import org.yuzu.yuzu_emu.YuzuApplication | |||
| 10 | import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting | 10 | import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting |
| 11 | import org.yuzu.yuzu_emu.features.settings.model.IntSetting | 11 | import org.yuzu.yuzu_emu.features.settings.model.IntSetting |
| 12 | import org.yuzu.yuzu_emu.features.settings.model.Settings | 12 | import org.yuzu.yuzu_emu.features.settings.model.Settings |
| 13 | import org.yuzu.yuzu_emu.overlay.model.OverlayControlData | ||
| 14 | import org.yuzu.yuzu_emu.overlay.model.OverlayControl | ||
| 15 | import org.yuzu.yuzu_emu.overlay.model.OverlayLayout | ||
| 13 | import org.yuzu.yuzu_emu.utils.PreferenceUtil.migratePreference | 16 | import org.yuzu.yuzu_emu.utils.PreferenceUtil.migratePreference |
| 14 | 17 | ||
| 15 | object DirectoryInitialization { | 18 | object DirectoryInitialization { |
| @@ -64,8 +67,147 @@ object DirectoryInitialization { | |||
| 64 | saveConfig = true | 67 | saveConfig = true |
| 65 | } | 68 | } |
| 66 | 69 | ||
| 70 | val joystickRelCenter = | ||
| 71 | preferences.migratePreference<Boolean>(Settings.PREF_MENU_SETTINGS_JOYSTICK_REL_CENTER) | ||
| 72 | if (joystickRelCenter != null) { | ||
| 73 | BooleanSetting.JOYSTICK_REL_CENTER.setBoolean(joystickRelCenter) | ||
| 74 | saveConfig = true | ||
| 75 | } | ||
| 76 | |||
| 77 | val dpadSlide = | ||
| 78 | preferences.migratePreference<Boolean>(Settings.PREF_MENU_SETTINGS_DPAD_SLIDE) | ||
| 79 | if (dpadSlide != null) { | ||
| 80 | BooleanSetting.DPAD_SLIDE.setBoolean(dpadSlide) | ||
| 81 | saveConfig = true | ||
| 82 | } | ||
| 83 | |||
| 84 | val hapticFeedback = | ||
| 85 | preferences.migratePreference<Boolean>(Settings.PREF_MENU_SETTINGS_HAPTICS) | ||
| 86 | if (hapticFeedback != null) { | ||
| 87 | BooleanSetting.HAPTIC_FEEDBACK.setBoolean(hapticFeedback) | ||
| 88 | saveConfig = true | ||
| 89 | } | ||
| 90 | |||
| 91 | val showPerformanceOverlay = | ||
| 92 | preferences.migratePreference<Boolean>(Settings.PREF_MENU_SETTINGS_SHOW_FPS) | ||
| 93 | if (showPerformanceOverlay != null) { | ||
| 94 | BooleanSetting.SHOW_PERFORMANCE_OVERLAY.setBoolean(showPerformanceOverlay) | ||
| 95 | saveConfig = true | ||
| 96 | } | ||
| 97 | |||
| 98 | val showInputOverlay = | ||
| 99 | preferences.migratePreference<Boolean>(Settings.PREF_MENU_SETTINGS_SHOW_OVERLAY) | ||
| 100 | if (showInputOverlay != null) { | ||
| 101 | BooleanSetting.SHOW_INPUT_OVERLAY.setBoolean(showInputOverlay) | ||
| 102 | saveConfig = true | ||
| 103 | } | ||
| 104 | |||
| 105 | val overlayOpacity = preferences.migratePreference<Int>(Settings.PREF_CONTROL_OPACITY) | ||
| 106 | if (overlayOpacity != null) { | ||
| 107 | IntSetting.OVERLAY_OPACITY.setInt(overlayOpacity) | ||
| 108 | saveConfig = true | ||
| 109 | } | ||
| 110 | |||
| 111 | val overlayScale = preferences.migratePreference<Int>(Settings.PREF_CONTROL_SCALE) | ||
| 112 | if (overlayScale != null) { | ||
| 113 | IntSetting.OVERLAY_SCALE.setInt(overlayScale) | ||
| 114 | saveConfig = true | ||
| 115 | } | ||
| 116 | |||
| 117 | var setOverlayData = false | ||
| 118 | val overlayControlData = NativeConfig.getOverlayControlData() | ||
| 119 | if (overlayControlData.isEmpty()) { | ||
| 120 | val overlayControlDataMap = | ||
| 121 | NativeConfig.getOverlayControlData().associateBy { it.id }.toMutableMap() | ||
| 122 | for (button in Settings.overlayPreferences) { | ||
| 123 | val buttonId = convertButtonId(button) | ||
| 124 | var buttonEnabled = preferences.migratePreference<Boolean>(button) | ||
| 125 | if (buttonEnabled == null) { | ||
| 126 | buttonEnabled = OverlayControl.map[buttonId]?.defaultVisibility == true | ||
| 127 | } | ||
| 128 | |||
| 129 | var landscapeXPosition = preferences.migratePreference<Float>( | ||
| 130 | "$button-X${Settings.PREF_LANDSCAPE_SUFFIX}" | ||
| 131 | )?.toDouble() | ||
| 132 | var landscapeYPosition = preferences.migratePreference<Float>( | ||
| 133 | "$button-Y${Settings.PREF_LANDSCAPE_SUFFIX}" | ||
| 134 | )?.toDouble() | ||
| 135 | if (landscapeXPosition == null || landscapeYPosition == null) { | ||
| 136 | val landscapePosition = OverlayControl.map[buttonId] | ||
| 137 | ?.getDefaultPositionForLayout(OverlayLayout.Landscape) ?: Pair(0.0, 0.0) | ||
| 138 | landscapeXPosition = landscapePosition.first | ||
| 139 | landscapeYPosition = landscapePosition.second | ||
| 140 | } | ||
| 141 | |||
| 142 | var portraitXPosition = preferences.migratePreference<Float>( | ||
| 143 | "$button-X${Settings.PREF_PORTRAIT_SUFFIX}" | ||
| 144 | )?.toDouble() | ||
| 145 | var portraitYPosition = preferences.migratePreference<Float>( | ||
| 146 | "$button-Y${Settings.PREF_PORTRAIT_SUFFIX}" | ||
| 147 | )?.toDouble() | ||
| 148 | if (portraitXPosition == null || portraitYPosition == null) { | ||
| 149 | val portraitPosition = OverlayControl.map[buttonId] | ||
| 150 | ?.getDefaultPositionForLayout(OverlayLayout.Portrait) ?: Pair(0.0, 0.0) | ||
| 151 | portraitXPosition = portraitPosition.first | ||
| 152 | portraitYPosition = portraitPosition.second | ||
| 153 | } | ||
| 154 | |||
| 155 | var foldableXPosition = preferences.migratePreference<Float>( | ||
| 156 | "$button-X${Settings.PREF_FOLDABLE_SUFFIX}" | ||
| 157 | )?.toDouble() | ||
| 158 | var foldableYPosition = preferences.migratePreference<Float>( | ||
| 159 | "$button-Y${Settings.PREF_FOLDABLE_SUFFIX}" | ||
| 160 | )?.toDouble() | ||
| 161 | if (foldableXPosition == null || foldableYPosition == null) { | ||
| 162 | val foldablePosition = OverlayControl.map[buttonId] | ||
| 163 | ?.getDefaultPositionForLayout(OverlayLayout.Foldable) ?: Pair(0.0, 0.0) | ||
| 164 | foldableXPosition = foldablePosition.first | ||
| 165 | foldableYPosition = foldablePosition.second | ||
| 166 | } | ||
| 167 | |||
| 168 | val controlData = OverlayControlData( | ||
| 169 | buttonId, | ||
| 170 | buttonEnabled, | ||
| 171 | Pair(landscapeXPosition, landscapeYPosition), | ||
| 172 | Pair(portraitXPosition, portraitYPosition), | ||
| 173 | Pair(foldableXPosition, foldableYPosition) | ||
| 174 | ) | ||
| 175 | overlayControlDataMap[buttonId] = controlData | ||
| 176 | setOverlayData = true | ||
| 177 | } | ||
| 178 | |||
| 179 | if (setOverlayData) { | ||
| 180 | NativeConfig.setOverlayControlData( | ||
| 181 | overlayControlDataMap.map { it.value }.toTypedArray() | ||
| 182 | ) | ||
| 183 | saveConfig = true | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 67 | if (saveConfig) { | 187 | if (saveConfig) { |
| 68 | NativeConfig.saveGlobalConfig() | 188 | NativeConfig.saveGlobalConfig() |
| 69 | } | 189 | } |
| 70 | } | 190 | } |
| 191 | |||
| 192 | private fun convertButtonId(buttonId: String): String = | ||
| 193 | when (buttonId) { | ||
| 194 | Settings.PREF_BUTTON_A -> OverlayControl.BUTTON_A.id | ||
| 195 | Settings.PREF_BUTTON_B -> OverlayControl.BUTTON_B.id | ||
| 196 | Settings.PREF_BUTTON_X -> OverlayControl.BUTTON_X.id | ||
| 197 | Settings.PREF_BUTTON_Y -> OverlayControl.BUTTON_Y.id | ||
| 198 | Settings.PREF_BUTTON_L -> OverlayControl.BUTTON_L.id | ||
| 199 | Settings.PREF_BUTTON_R -> OverlayControl.BUTTON_R.id | ||
| 200 | Settings.PREF_BUTTON_ZL -> OverlayControl.BUTTON_ZL.id | ||
| 201 | Settings.PREF_BUTTON_ZR -> OverlayControl.BUTTON_ZR.id | ||
| 202 | Settings.PREF_BUTTON_PLUS -> OverlayControl.BUTTON_PLUS.id | ||
| 203 | Settings.PREF_BUTTON_MINUS -> OverlayControl.BUTTON_MINUS.id | ||
| 204 | Settings.PREF_BUTTON_DPAD -> OverlayControl.COMBINED_DPAD.id | ||
| 205 | Settings.PREF_STICK_L -> OverlayControl.STICK_L.id | ||
| 206 | Settings.PREF_STICK_R -> OverlayControl.STICK_R.id | ||
| 207 | Settings.PREF_BUTTON_HOME -> OverlayControl.BUTTON_HOME.id | ||
| 208 | Settings.PREF_BUTTON_SCREENSHOT -> OverlayControl.BUTTON_CAPTURE.id | ||
| 209 | Settings.PREF_BUTTON_STICK_L -> OverlayControl.BUTTON_STICK_L.id | ||
| 210 | Settings.PREF_BUTTON_STICK_R -> OverlayControl.BUTTON_STICK_R.id | ||
| 211 | else -> "" | ||
| 212 | } | ||
| 71 | } | 213 | } |
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 deleted file mode 100644 index 7e8f058c1..000000000 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/EmulationMenuSettings.kt +++ /dev/null | |||
| @@ -1,50 +0,0 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | package org.yuzu.yuzu_emu.utils | ||
| 5 | |||
| 6 | import androidx.preference.PreferenceManager | ||
| 7 | import org.yuzu.yuzu_emu.YuzuApplication | ||
| 8 | import org.yuzu.yuzu_emu.features.settings.model.Settings | ||
| 9 | |||
| 10 | object EmulationMenuSettings { | ||
| 11 | private val preferences = | ||
| 12 | PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) | ||
| 13 | |||
| 14 | var joystickRelCenter: Boolean | ||
| 15 | get() = preferences.getBoolean(Settings.PREF_MENU_SETTINGS_JOYSTICK_REL_CENTER, true) | ||
| 16 | set(value) { | ||
| 17 | preferences.edit() | ||
| 18 | .putBoolean(Settings.PREF_MENU_SETTINGS_JOYSTICK_REL_CENTER, value) | ||
| 19 | .apply() | ||
| 20 | } | ||
| 21 | var dpadSlide: Boolean | ||
| 22 | get() = preferences.getBoolean(Settings.PREF_MENU_SETTINGS_DPAD_SLIDE, true) | ||
| 23 | set(value) { | ||
| 24 | preferences.edit() | ||
| 25 | .putBoolean(Settings.PREF_MENU_SETTINGS_DPAD_SLIDE, value) | ||
| 26 | .apply() | ||
| 27 | } | ||
| 28 | var hapticFeedback: Boolean | ||
| 29 | get() = preferences.getBoolean(Settings.PREF_MENU_SETTINGS_HAPTICS, false) | ||
| 30 | set(value) { | ||
| 31 | preferences.edit() | ||
| 32 | .putBoolean(Settings.PREF_MENU_SETTINGS_HAPTICS, value) | ||
| 33 | .apply() | ||
| 34 | } | ||
| 35 | |||
| 36 | var showFps: Boolean | ||
| 37 | get() = preferences.getBoolean(Settings.PREF_MENU_SETTINGS_SHOW_FPS, false) | ||
| 38 | set(value) { | ||
| 39 | preferences.edit() | ||
| 40 | .putBoolean(Settings.PREF_MENU_SETTINGS_SHOW_FPS, value) | ||
| 41 | .apply() | ||
| 42 | } | ||
| 43 | var showOverlay: Boolean | ||
| 44 | get() = preferences.getBoolean(Settings.PREF_MENU_SETTINGS_SHOW_OVERLAY, true) | ||
| 45 | set(value) { | ||
| 46 | preferences.edit() | ||
| 47 | .putBoolean(Settings.PREF_MENU_SETTINGS_SHOW_OVERLAY, value) | ||
| 48 | .apply() | ||
| 49 | } | ||
| 50 | } | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/NativeConfig.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/NativeConfig.kt index 7512d5eed..a4c14b3a7 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/NativeConfig.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/NativeConfig.kt | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | package org.yuzu.yuzu_emu.utils | 4 | package org.yuzu.yuzu_emu.utils |
| 5 | 5 | ||
| 6 | import org.yuzu.yuzu_emu.model.GameDir | 6 | import org.yuzu.yuzu_emu.model.GameDir |
| 7 | import org.yuzu.yuzu_emu.overlay.model.OverlayControlData | ||
| 7 | 8 | ||
| 8 | object NativeConfig { | 9 | object NativeConfig { |
| 9 | /** | 10 | /** |
| @@ -150,4 +151,21 @@ object NativeConfig { | |||
| 150 | */ | 151 | */ |
| 151 | @Synchronized | 152 | @Synchronized |
| 152 | external fun setDisabledAddons(programId: String, disabledAddons: Array<String>) | 153 | external fun setDisabledAddons(programId: String, disabledAddons: Array<String>) |
| 154 | |||
| 155 | /** | ||
| 156 | * Gets an array of [OverlayControlData] from settings | ||
| 157 | * | ||
| 158 | * @return An array of [OverlayControlData] | ||
| 159 | */ | ||
| 160 | @Synchronized | ||
| 161 | external fun getOverlayControlData(): Array<OverlayControlData> | ||
| 162 | |||
| 163 | /** | ||
| 164 | * Clears the AndroidSettings::values.overlay_control_data array and replaces its values | ||
| 165 | * with [overlayControlData] | ||
| 166 | * | ||
| 167 | * @param overlayControlData Replacement array of [OverlayControlData] | ||
| 168 | */ | ||
| 169 | @Synchronized | ||
| 170 | external fun setOverlayControlData(overlayControlData: Array<OverlayControlData>) | ||
| 153 | } | 171 | } |
diff --git a/src/android/app/src/main/jni/android_common/android_common.cpp b/src/android/app/src/main/jni/android_common/android_common.cpp index 52d8ecfeb..1e884ffdd 100644 --- a/src/android/app/src/main/jni/android_common/android_common.cpp +++ b/src/android/app/src/main/jni/android_common/android_common.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include <jni.h> | 9 | #include <jni.h> |
| 10 | 10 | ||
| 11 | #include "common/string_util.h" | 11 | #include "common/string_util.h" |
| 12 | #include "jni/id_cache.h" | ||
| 12 | 13 | ||
| 13 | std::string GetJString(JNIEnv* env, jstring jstr) { | 14 | std::string GetJString(JNIEnv* env, jstring jstr) { |
| 14 | if (!jstr) { | 15 | if (!jstr) { |
| @@ -33,3 +34,11 @@ jstring ToJString(JNIEnv* env, std::string_view str) { | |||
| 33 | jstring ToJString(JNIEnv* env, std::u16string_view str) { | 34 | jstring ToJString(JNIEnv* env, std::u16string_view str) { |
| 34 | return ToJString(env, Common::UTF16ToUTF8(str)); | 35 | return ToJString(env, Common::UTF16ToUTF8(str)); |
| 35 | } | 36 | } |
| 37 | |||
| 38 | double GetJDouble(JNIEnv* env, jobject jdouble) { | ||
| 39 | return env->GetDoubleField(jdouble, IDCache::GetDoubleValueField()); | ||
| 40 | } | ||
| 41 | |||
| 42 | jobject ToJDouble(JNIEnv* env, double value) { | ||
| 43 | return env->NewObject(IDCache::GetDoubleClass(), IDCache::GetDoubleConstructor(), value); | ||
| 44 | } | ||
diff --git a/src/android/app/src/main/jni/android_common/android_common.h b/src/android/app/src/main/jni/android_common/android_common.h index ccb0c06f7..8eb803e1b 100644 --- a/src/android/app/src/main/jni/android_common/android_common.h +++ b/src/android/app/src/main/jni/android_common/android_common.h | |||
| @@ -10,3 +10,6 @@ | |||
| 10 | std::string GetJString(JNIEnv* env, jstring jstr); | 10 | std::string GetJString(JNIEnv* env, jstring jstr); |
| 11 | jstring ToJString(JNIEnv* env, std::string_view str); | 11 | jstring ToJString(JNIEnv* env, std::string_view str); |
| 12 | jstring ToJString(JNIEnv* env, std::u16string_view str); | 12 | jstring ToJString(JNIEnv* env, std::u16string_view str); |
| 13 | |||
| 14 | double GetJDouble(JNIEnv* env, jobject jdouble); | ||
| 15 | jobject ToJDouble(JNIEnv* env, double value); | ||
diff --git a/src/android/app/src/main/jni/android_config.cpp b/src/android/app/src/main/jni/android_config.cpp index fb17ab6f6..c86aa1c39 100644 --- a/src/android/app/src/main/jni/android_config.cpp +++ b/src/android/app/src/main/jni/android_config.cpp | |||
| @@ -35,6 +35,7 @@ void AndroidConfig::ReadAndroidValues() { | |||
| 35 | if (global) { | 35 | if (global) { |
| 36 | ReadAndroidUIValues(); | 36 | ReadAndroidUIValues(); |
| 37 | ReadUIValues(); | 37 | ReadUIValues(); |
| 38 | ReadOverlayValues(); | ||
| 38 | } | 39 | } |
| 39 | ReadDriverValues(); | 40 | ReadDriverValues(); |
| 40 | } | 41 | } |
| @@ -81,10 +82,42 @@ void AndroidConfig::ReadDriverValues() { | |||
| 81 | EndGroup(); | 82 | EndGroup(); |
| 82 | } | 83 | } |
| 83 | 84 | ||
| 85 | void AndroidConfig::ReadOverlayValues() { | ||
| 86 | BeginGroup(Settings::TranslateCategory(Settings::Category::Overlay)); | ||
| 87 | |||
| 88 | ReadCategory(Settings::Category::Overlay); | ||
| 89 | |||
| 90 | AndroidSettings::values.overlay_control_data.clear(); | ||
| 91 | const int control_data_size = BeginArray("control_data"); | ||
| 92 | for (int i = 0; i < control_data_size; ++i) { | ||
| 93 | SetArrayIndex(i); | ||
| 94 | AndroidSettings::OverlayControlData control_data; | ||
| 95 | control_data.id = ReadStringSetting(std::string("id")); | ||
| 96 | control_data.enabled = ReadBooleanSetting(std::string("enabled")); | ||
| 97 | control_data.landscape_position.first = | ||
| 98 | ReadDoubleSetting(std::string("landscape\\x_position")); | ||
| 99 | control_data.landscape_position.second = | ||
| 100 | ReadDoubleSetting(std::string("landscape\\y_position")); | ||
| 101 | control_data.portrait_position.first = | ||
| 102 | ReadDoubleSetting(std::string("portrait\\x_position")); | ||
| 103 | control_data.portrait_position.second = | ||
| 104 | ReadDoubleSetting(std::string("portrait\\y_position")); | ||
| 105 | control_data.foldable_position.first = | ||
| 106 | ReadDoubleSetting(std::string("foldable\\x_position")); | ||
| 107 | control_data.foldable_position.second = | ||
| 108 | ReadDoubleSetting(std::string("foldable\\y_position")); | ||
| 109 | AndroidSettings::values.overlay_control_data.push_back(control_data); | ||
| 110 | } | ||
| 111 | EndArray(); | ||
| 112 | |||
| 113 | EndGroup(); | ||
| 114 | } | ||
| 115 | |||
| 84 | void AndroidConfig::SaveAndroidValues() { | 116 | void AndroidConfig::SaveAndroidValues() { |
| 85 | if (global) { | 117 | if (global) { |
| 86 | SaveAndroidUIValues(); | 118 | SaveAndroidUIValues(); |
| 87 | SaveUIValues(); | 119 | SaveUIValues(); |
| 120 | SaveOverlayValues(); | ||
| 88 | } | 121 | } |
| 89 | SaveDriverValues(); | 122 | SaveDriverValues(); |
| 90 | 123 | ||
| @@ -131,6 +164,35 @@ void AndroidConfig::SaveDriverValues() { | |||
| 131 | EndGroup(); | 164 | EndGroup(); |
| 132 | } | 165 | } |
| 133 | 166 | ||
| 167 | void AndroidConfig::SaveOverlayValues() { | ||
| 168 | BeginGroup(Settings::TranslateCategory(Settings::Category::Overlay)); | ||
| 169 | |||
| 170 | WriteCategory(Settings::Category::Overlay); | ||
| 171 | |||
| 172 | BeginArray("control_data"); | ||
| 173 | for (size_t i = 0; i < AndroidSettings::values.overlay_control_data.size(); ++i) { | ||
| 174 | SetArrayIndex(i); | ||
| 175 | const auto& control_data = AndroidSettings::values.overlay_control_data[i]; | ||
| 176 | WriteStringSetting(std::string("id"), control_data.id); | ||
| 177 | WriteBooleanSetting(std::string("enabled"), control_data.enabled); | ||
| 178 | WriteDoubleSetting(std::string("landscape\\x_position"), | ||
| 179 | control_data.landscape_position.first); | ||
| 180 | WriteDoubleSetting(std::string("landscape\\y_position"), | ||
| 181 | control_data.landscape_position.second); | ||
| 182 | WriteDoubleSetting(std::string("portrait\\x_position"), | ||
| 183 | control_data.portrait_position.first); | ||
| 184 | WriteDoubleSetting(std::string("portrait\\y_position"), | ||
| 185 | control_data.portrait_position.second); | ||
| 186 | WriteDoubleSetting(std::string("foldable\\x_position"), | ||
| 187 | control_data.foldable_position.first); | ||
| 188 | WriteDoubleSetting(std::string("foldable\\y_position"), | ||
| 189 | control_data.foldable_position.second); | ||
| 190 | } | ||
| 191 | EndArray(); | ||
| 192 | |||
| 193 | EndGroup(); | ||
| 194 | } | ||
| 195 | |||
| 134 | std::vector<Settings::BasicSetting*>& AndroidConfig::FindRelevantList(Settings::Category category) { | 196 | std::vector<Settings::BasicSetting*>& AndroidConfig::FindRelevantList(Settings::Category category) { |
| 135 | auto& map = Settings::values.linkage.by_category; | 197 | auto& map = Settings::values.linkage.by_category; |
| 136 | if (map.contains(category)) { | 198 | if (map.contains(category)) { |
diff --git a/src/android/app/src/main/jni/android_config.h b/src/android/app/src/main/jni/android_config.h index 2c12874e1..d83852de9 100644 --- a/src/android/app/src/main/jni/android_config.h +++ b/src/android/app/src/main/jni/android_config.h | |||
| @@ -18,6 +18,7 @@ protected: | |||
| 18 | void ReadAndroidValues(); | 18 | void ReadAndroidValues(); |
| 19 | void ReadAndroidUIValues(); | 19 | void ReadAndroidUIValues(); |
| 20 | void ReadDriverValues(); | 20 | void ReadDriverValues(); |
| 21 | void ReadOverlayValues(); | ||
| 21 | void ReadHidbusValues() override {} | 22 | void ReadHidbusValues() override {} |
| 22 | void ReadDebugControlValues() override {} | 23 | void ReadDebugControlValues() override {} |
| 23 | void ReadPathValues() override; | 24 | void ReadPathValues() override; |
| @@ -30,6 +31,7 @@ protected: | |||
| 30 | void SaveAndroidValues(); | 31 | void SaveAndroidValues(); |
| 31 | void SaveAndroidUIValues(); | 32 | void SaveAndroidUIValues(); |
| 32 | void SaveDriverValues(); | 33 | void SaveDriverValues(); |
| 34 | void SaveOverlayValues(); | ||
| 33 | void SaveHidbusValues() override {} | 35 | void SaveHidbusValues() override {} |
| 34 | void SaveDebugControlValues() override {} | 36 | void SaveDebugControlValues() override {} |
| 35 | void SavePathValues() override; | 37 | void SavePathValues() override; |
diff --git a/src/android/app/src/main/jni/android_settings.h b/src/android/app/src/main/jni/android_settings.h index 1e4906b9a..559ae83eb 100644 --- a/src/android/app/src/main/jni/android_settings.h +++ b/src/android/app/src/main/jni/android_settings.h | |||
| @@ -14,6 +14,14 @@ struct GameDir { | |||
| 14 | bool deep_scan = false; | 14 | bool deep_scan = false; |
| 15 | }; | 15 | }; |
| 16 | 16 | ||
| 17 | struct OverlayControlData { | ||
| 18 | std::string id; | ||
| 19 | bool enabled; | ||
| 20 | std::pair<double, double> landscape_position; | ||
| 21 | std::pair<double, double> portrait_position; | ||
| 22 | std::pair<double, double> foldable_position; | ||
| 23 | }; | ||
| 24 | |||
| 17 | struct Values { | 25 | struct Values { |
| 18 | Settings::Linkage linkage; | 26 | Settings::Linkage linkage; |
| 19 | 27 | ||
| @@ -38,6 +46,23 @@ struct Values { | |||
| 38 | Settings::Setting<s32> theme_mode{linkage, -1, "theme_mode", Settings::Category::Android}; | 46 | Settings::Setting<s32> theme_mode{linkage, -1, "theme_mode", Settings::Category::Android}; |
| 39 | Settings::Setting<bool> black_backgrounds{linkage, false, "black_backgrounds", | 47 | Settings::Setting<bool> black_backgrounds{linkage, false, "black_backgrounds", |
| 40 | Settings::Category::Android}; | 48 | Settings::Category::Android}; |
| 49 | |||
| 50 | // Input/performance overlay settings | ||
| 51 | std::vector<OverlayControlData> overlay_control_data; | ||
| 52 | Settings::Setting<s32> overlay_scale{linkage, 50, "control_scale", Settings::Category::Overlay}; | ||
| 53 | Settings::Setting<s32> overlay_opacity{linkage, 100, "control_opacity", | ||
| 54 | Settings::Category::Overlay}; | ||
| 55 | |||
| 56 | Settings::Setting<bool> joystick_rel_center{linkage, true, "joystick_rel_center", | ||
| 57 | Settings::Category::Overlay}; | ||
| 58 | Settings::Setting<bool> dpad_slide{linkage, true, "dpad_slide", Settings::Category::Overlay}; | ||
| 59 | Settings::Setting<bool> haptic_feedback{linkage, true, "haptic_feedback", | ||
| 60 | Settings::Category::Overlay}; | ||
| 61 | Settings::Setting<bool> show_performance_overlay{linkage, true, "show_performance_overlay", | ||
| 62 | Settings::Category::Overlay}; | ||
| 63 | Settings::Setting<bool> show_input_overlay{linkage, true, "show_input_overlay", | ||
| 64 | Settings::Category::Overlay}; | ||
| 65 | Settings::Setting<bool> touchscreen{linkage, true, "touchscreen", Settings::Category::Overlay}; | ||
| 41 | }; | 66 | }; |
| 42 | 67 | ||
| 43 | extern Values values; | 68 | extern Values values; |
diff --git a/src/android/app/src/main/jni/id_cache.cpp b/src/android/app/src/main/jni/id_cache.cpp index e7a86d3fd..c79ad7d76 100644 --- a/src/android/app/src/main/jni/id_cache.cpp +++ b/src/android/app/src/main/jni/id_cache.cpp | |||
| @@ -35,6 +35,18 @@ static jmethodID s_pair_constructor; | |||
| 35 | static jfieldID s_pair_first_field; | 35 | static jfieldID s_pair_first_field; |
| 36 | static jfieldID s_pair_second_field; | 36 | static jfieldID s_pair_second_field; |
| 37 | 37 | ||
| 38 | static jclass s_overlay_control_data_class; | ||
| 39 | static jmethodID s_overlay_control_data_constructor; | ||
| 40 | static jfieldID s_overlay_control_data_id_field; | ||
| 41 | static jfieldID s_overlay_control_data_enabled_field; | ||
| 42 | static jfieldID s_overlay_control_data_landscape_position_field; | ||
| 43 | static jfieldID s_overlay_control_data_portrait_position_field; | ||
| 44 | static jfieldID s_overlay_control_data_foldable_position_field; | ||
| 45 | |||
| 46 | static jclass s_double_class; | ||
| 47 | static jmethodID s_double_constructor; | ||
| 48 | static jfieldID s_double_value_field; | ||
| 49 | |||
| 38 | static constexpr jint JNI_VERSION = JNI_VERSION_1_6; | 50 | static constexpr jint JNI_VERSION = JNI_VERSION_1_6; |
| 39 | 51 | ||
| 40 | namespace IDCache { | 52 | namespace IDCache { |
| @@ -146,6 +158,46 @@ jfieldID GetPairSecondField() { | |||
| 146 | return s_pair_second_field; | 158 | return s_pair_second_field; |
| 147 | } | 159 | } |
| 148 | 160 | ||
| 161 | jclass GetOverlayControlDataClass() { | ||
| 162 | return s_overlay_control_data_class; | ||
| 163 | } | ||
| 164 | |||
| 165 | jmethodID GetOverlayControlDataConstructor() { | ||
| 166 | return s_overlay_control_data_constructor; | ||
| 167 | } | ||
| 168 | |||
| 169 | jfieldID GetOverlayControlDataIdField() { | ||
| 170 | return s_overlay_control_data_id_field; | ||
| 171 | } | ||
| 172 | |||
| 173 | jfieldID GetOverlayControlDataEnabledField() { | ||
| 174 | return s_overlay_control_data_enabled_field; | ||
| 175 | } | ||
| 176 | |||
| 177 | jfieldID GetOverlayControlDataLandscapePositionField() { | ||
| 178 | return s_overlay_control_data_landscape_position_field; | ||
| 179 | } | ||
| 180 | |||
| 181 | jfieldID GetOverlayControlDataPortraitPositionField() { | ||
| 182 | return s_overlay_control_data_portrait_position_field; | ||
| 183 | } | ||
| 184 | |||
| 185 | jfieldID GetOverlayControlDataFoldablePositionField() { | ||
| 186 | return s_overlay_control_data_foldable_position_field; | ||
| 187 | } | ||
| 188 | |||
| 189 | jclass GetDoubleClass() { | ||
| 190 | return s_double_class; | ||
| 191 | } | ||
| 192 | |||
| 193 | jmethodID GetDoubleConstructor() { | ||
| 194 | return s_double_constructor; | ||
| 195 | } | ||
| 196 | |||
| 197 | jfieldID GetDoubleValueField() { | ||
| 198 | return s_double_value_field; | ||
| 199 | } | ||
| 200 | |||
| 149 | } // namespace IDCache | 201 | } // namespace IDCache |
| 150 | 202 | ||
| 151 | #ifdef __cplusplus | 203 | #ifdef __cplusplus |
| @@ -207,6 +259,31 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) { | |||
| 207 | s_pair_second_field = env->GetFieldID(pair_class, "second", "Ljava/lang/Object;"); | 259 | s_pair_second_field = env->GetFieldID(pair_class, "second", "Ljava/lang/Object;"); |
| 208 | env->DeleteLocalRef(pair_class); | 260 | env->DeleteLocalRef(pair_class); |
| 209 | 261 | ||
| 262 | const jclass overlay_control_data_class = | ||
| 263 | env->FindClass("org/yuzu/yuzu_emu/overlay/model/OverlayControlData"); | ||
| 264 | s_overlay_control_data_class = | ||
| 265 | reinterpret_cast<jclass>(env->NewGlobalRef(overlay_control_data_class)); | ||
| 266 | s_overlay_control_data_constructor = | ||
| 267 | env->GetMethodID(overlay_control_data_class, "<init>", | ||
| 268 | "(Ljava/lang/String;ZLkotlin/Pair;Lkotlin/Pair;Lkotlin/Pair;)V"); | ||
| 269 | s_overlay_control_data_id_field = | ||
| 270 | env->GetFieldID(overlay_control_data_class, "id", "Ljava/lang/String;"); | ||
| 271 | s_overlay_control_data_enabled_field = | ||
| 272 | env->GetFieldID(overlay_control_data_class, "enabled", "Z"); | ||
| 273 | s_overlay_control_data_landscape_position_field = | ||
| 274 | env->GetFieldID(overlay_control_data_class, "landscapePosition", "Lkotlin/Pair;"); | ||
| 275 | s_overlay_control_data_portrait_position_field = | ||
| 276 | env->GetFieldID(overlay_control_data_class, "portraitPosition", "Lkotlin/Pair;"); | ||
| 277 | s_overlay_control_data_foldable_position_field = | ||
| 278 | env->GetFieldID(overlay_control_data_class, "foldablePosition", "Lkotlin/Pair;"); | ||
| 279 | env->DeleteLocalRef(overlay_control_data_class); | ||
| 280 | |||
| 281 | const jclass double_class = env->FindClass("java/lang/Double"); | ||
| 282 | s_double_class = reinterpret_cast<jclass>(env->NewGlobalRef(double_class)); | ||
| 283 | s_double_constructor = env->GetMethodID(double_class, "<init>", "(D)V"); | ||
| 284 | s_double_value_field = env->GetFieldID(double_class, "value", "D"); | ||
| 285 | env->DeleteLocalRef(double_class); | ||
| 286 | |||
| 210 | // Initialize Android Storage | 287 | // Initialize Android Storage |
| 211 | Common::FS::Android::RegisterCallbacks(env, s_native_library_class); | 288 | Common::FS::Android::RegisterCallbacks(env, s_native_library_class); |
| 212 | 289 | ||
| @@ -231,6 +308,8 @@ void JNI_OnUnload(JavaVM* vm, void* reserved) { | |||
| 231 | env->DeleteGlobalRef(s_game_class); | 308 | env->DeleteGlobalRef(s_game_class); |
| 232 | env->DeleteGlobalRef(s_string_class); | 309 | env->DeleteGlobalRef(s_string_class); |
| 233 | env->DeleteGlobalRef(s_pair_class); | 310 | env->DeleteGlobalRef(s_pair_class); |
| 311 | env->DeleteGlobalRef(s_overlay_control_data_class); | ||
| 312 | env->DeleteGlobalRef(s_double_class); | ||
| 234 | 313 | ||
| 235 | // UnInitialize applets | 314 | // UnInitialize applets |
| 236 | SoftwareKeyboard::CleanupJNI(env); | 315 | SoftwareKeyboard::CleanupJNI(env); |
diff --git a/src/android/app/src/main/jni/id_cache.h b/src/android/app/src/main/jni/id_cache.h index 24030be42..784d1412f 100644 --- a/src/android/app/src/main/jni/id_cache.h +++ b/src/android/app/src/main/jni/id_cache.h | |||
| @@ -35,4 +35,16 @@ jmethodID GetPairConstructor(); | |||
| 35 | jfieldID GetPairFirstField(); | 35 | jfieldID GetPairFirstField(); |
| 36 | jfieldID GetPairSecondField(); | 36 | jfieldID GetPairSecondField(); |
| 37 | 37 | ||
| 38 | jclass GetOverlayControlDataClass(); | ||
| 39 | jmethodID GetOverlayControlDataConstructor(); | ||
| 40 | jfieldID GetOverlayControlDataIdField(); | ||
| 41 | jfieldID GetOverlayControlDataEnabledField(); | ||
| 42 | jfieldID GetOverlayControlDataLandscapePositionField(); | ||
| 43 | jfieldID GetOverlayControlDataPortraitPositionField(); | ||
| 44 | jfieldID GetOverlayControlDataFoldablePositionField(); | ||
| 45 | |||
| 46 | jclass GetDoubleClass(); | ||
| 47 | jmethodID GetDoubleConstructor(); | ||
| 48 | jfieldID GetDoubleValueField(); | ||
| 49 | |||
| 38 | } // namespace IDCache | 50 | } // namespace IDCache |
diff --git a/src/android/app/src/main/jni/native_config.cpp b/src/android/app/src/main/jni/native_config.cpp index 324d9e9cd..535902483 100644 --- a/src/android/app/src/main/jni/native_config.cpp +++ b/src/android/app/src/main/jni/native_config.cpp | |||
| @@ -344,4 +344,74 @@ void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setDisabledAddons(JNIEnv* env, j | |||
| 344 | Settings::values.disabled_addons[program_id] = disabled_addons; | 344 | Settings::values.disabled_addons[program_id] = disabled_addons; |
| 345 | } | 345 | } |
| 346 | 346 | ||
| 347 | jobjectArray Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getOverlayControlData(JNIEnv* env, | ||
| 348 | jobject obj) { | ||
| 349 | jobjectArray joverlayControlDataArray = | ||
| 350 | env->NewObjectArray(AndroidSettings::values.overlay_control_data.size(), | ||
| 351 | IDCache::GetOverlayControlDataClass(), nullptr); | ||
| 352 | for (size_t i = 0; i < AndroidSettings::values.overlay_control_data.size(); ++i) { | ||
| 353 | const auto& control_data = AndroidSettings::values.overlay_control_data[i]; | ||
| 354 | jobject jlandscapePosition = | ||
| 355 | env->NewObject(IDCache::GetPairClass(), IDCache::GetPairConstructor(), | ||
| 356 | ToJDouble(env, control_data.landscape_position.first), | ||
| 357 | ToJDouble(env, control_data.landscape_position.second)); | ||
| 358 | jobject jportraitPosition = | ||
| 359 | env->NewObject(IDCache::GetPairClass(), IDCache::GetPairConstructor(), | ||
| 360 | ToJDouble(env, control_data.portrait_position.first), | ||
| 361 | ToJDouble(env, control_data.portrait_position.second)); | ||
| 362 | jobject jfoldablePosition = | ||
| 363 | env->NewObject(IDCache::GetPairClass(), IDCache::GetPairConstructor(), | ||
| 364 | ToJDouble(env, control_data.foldable_position.first), | ||
| 365 | ToJDouble(env, control_data.foldable_position.second)); | ||
| 366 | |||
| 367 | jobject jcontrolData = env->NewObject( | ||
| 368 | IDCache::GetOverlayControlDataClass(), IDCache::GetOverlayControlDataConstructor(), | ||
| 369 | ToJString(env, control_data.id), control_data.enabled, jlandscapePosition, | ||
| 370 | jportraitPosition, jfoldablePosition); | ||
| 371 | env->SetObjectArrayElement(joverlayControlDataArray, i, jcontrolData); | ||
| 372 | } | ||
| 373 | return joverlayControlDataArray; | ||
| 374 | } | ||
| 375 | |||
| 376 | void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setOverlayControlData( | ||
| 377 | JNIEnv* env, jobject obj, jobjectArray joverlayControlDataArray) { | ||
| 378 | AndroidSettings::values.overlay_control_data.clear(); | ||
| 379 | int size = env->GetArrayLength(joverlayControlDataArray); | ||
| 380 | |||
| 381 | if (size == 0) { | ||
| 382 | return; | ||
| 383 | } | ||
| 384 | |||
| 385 | for (int i = 0; i < size; ++i) { | ||
| 386 | jobject joverlayControlData = env->GetObjectArrayElement(joverlayControlDataArray, i); | ||
| 387 | jstring jidString = static_cast<jstring>( | ||
| 388 | env->GetObjectField(joverlayControlData, IDCache::GetOverlayControlDataIdField())); | ||
| 389 | bool enabled = static_cast<bool>(env->GetBooleanField( | ||
| 390 | joverlayControlData, IDCache::GetOverlayControlDataEnabledField())); | ||
| 391 | |||
| 392 | jobject jlandscapePosition = env->GetObjectField( | ||
| 393 | joverlayControlData, IDCache::GetOverlayControlDataLandscapePositionField()); | ||
| 394 | std::pair<double, double> landscape_position = std::make_pair( | ||
| 395 | GetJDouble(env, env->GetObjectField(jlandscapePosition, IDCache::GetPairFirstField())), | ||
| 396 | GetJDouble(env, | ||
| 397 | env->GetObjectField(jlandscapePosition, IDCache::GetPairSecondField()))); | ||
| 398 | |||
| 399 | jobject jportraitPosition = env->GetObjectField( | ||
| 400 | joverlayControlData, IDCache::GetOverlayControlDataPortraitPositionField()); | ||
| 401 | std::pair<double, double> portrait_position = std::make_pair( | ||
| 402 | GetJDouble(env, env->GetObjectField(jportraitPosition, IDCache::GetPairFirstField())), | ||
| 403 | GetJDouble(env, env->GetObjectField(jportraitPosition, IDCache::GetPairSecondField()))); | ||
| 404 | |||
| 405 | jobject jfoldablePosition = env->GetObjectField( | ||
| 406 | joverlayControlData, IDCache::GetOverlayControlDataFoldablePositionField()); | ||
| 407 | std::pair<double, double> foldable_position = std::make_pair( | ||
| 408 | GetJDouble(env, env->GetObjectField(jfoldablePosition, IDCache::GetPairFirstField())), | ||
| 409 | GetJDouble(env, env->GetObjectField(jfoldablePosition, IDCache::GetPairSecondField()))); | ||
| 410 | |||
| 411 | AndroidSettings::values.overlay_control_data.push_back(AndroidSettings::OverlayControlData{ | ||
| 412 | GetJString(env, jidString), enabled, landscape_position, portrait_position, | ||
| 413 | foldable_position}); | ||
| 414 | } | ||
| 415 | } | ||
| 416 | |||
| 347 | } // extern "C" | 417 | } // extern "C" |
diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index c882a8e62..45d57c3ea 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml | |||
| @@ -212,19 +212,19 @@ | |||
| 212 | <item>B</item> | 212 | <item>B</item> |
| 213 | <item>X</item> | 213 | <item>X</item> |
| 214 | <item>Y</item> | 214 | <item>Y</item> |
| 215 | <item>+</item> | ||
| 216 | <item>-</item> | ||
| 217 | <item>@string/gamepad_home</item> | ||
| 218 | <item>@string/gamepad_screenshot</item> | ||
| 215 | <item>L</item> | 219 | <item>L</item> |
| 216 | <item>R</item> | 220 | <item>R</item> |
| 217 | <item>ZL</item> | 221 | <item>ZL</item> |
| 218 | <item>ZR</item> | 222 | <item>ZR</item> |
| 219 | <item>+</item> | ||
| 220 | <item>-</item> | ||
| 221 | <item>@string/gamepad_d_pad</item> | ||
| 222 | <item>@string/gamepad_left_stick</item> | 223 | <item>@string/gamepad_left_stick</item> |
| 223 | <item>@string/gamepad_right_stick</item> | 224 | <item>@string/gamepad_right_stick</item> |
| 224 | <item>L3</item> | 225 | <item>L3</item> |
| 225 | <item>R3</item> | 226 | <item>R3</item> |
| 226 | <item>@string/gamepad_home</item> | 227 | <item>@string/gamepad_d_pad</item> |
| 227 | <item>@string/gamepad_screenshot</item> | ||
| 228 | </string-array> | 228 | </string-array> |
| 229 | 229 | ||
| 230 | <string-array name="themeEntries"> | 230 | <string-array name="themeEntries"> |
diff --git a/src/android/app/src/main/res/values/integers.xml b/src/android/app/src/main/res/values/integers.xml index dc527965c..1c6f5db93 100644 --- a/src/android/app/src/main/res/values/integers.xml +++ b/src/android/app/src/main/res/values/integers.xml | |||
| @@ -3,111 +3,111 @@ | |||
| 3 | <integer name="grid_columns">1</integer> | 3 | <integer name="grid_columns">1</integer> |
| 4 | 4 | ||
| 5 | <!-- Default SWITCH landscape layout --> | 5 | <!-- Default SWITCH landscape layout --> |
| 6 | <integer name="SWITCH_BUTTON_A_X">760</integer> | 6 | <integer name="BUTTON_A_X">760</integer> |
| 7 | <integer name="SWITCH_BUTTON_A_Y">790</integer> | 7 | <integer name="BUTTON_A_Y">790</integer> |
| 8 | <integer name="SWITCH_BUTTON_B_X">710</integer> | 8 | <integer name="BUTTON_B_X">710</integer> |
| 9 | <integer name="SWITCH_BUTTON_B_Y">900</integer> | 9 | <integer name="BUTTON_B_Y">900</integer> |
| 10 | <integer name="SWITCH_BUTTON_X_X">710</integer> | 10 | <integer name="BUTTON_X_X">710</integer> |
| 11 | <integer name="SWITCH_BUTTON_X_Y">680</integer> | 11 | <integer name="BUTTON_X_Y">680</integer> |
| 12 | <integer name="SWITCH_BUTTON_Y_X">660</integer> | 12 | <integer name="BUTTON_Y_X">660</integer> |
| 13 | <integer name="SWITCH_BUTTON_Y_Y">790</integer> | 13 | <integer name="BUTTON_Y_Y">790</integer> |
| 14 | <integer name="SWITCH_STICK_L_X">100</integer> | 14 | <integer name="BUTTON_PLUS_X">540</integer> |
| 15 | <integer name="SWITCH_STICK_L_Y">670</integer> | 15 | <integer name="BUTTON_PLUS_Y">950</integer> |
| 16 | <integer name="SWITCH_STICK_R_X">900</integer> | 16 | <integer name="BUTTON_MINUS_X">460</integer> |
| 17 | <integer name="SWITCH_STICK_R_Y">670</integer> | 17 | <integer name="BUTTON_MINUS_Y">950</integer> |
| 18 | <integer name="SWITCH_TRIGGER_L_X">70</integer> | 18 | <integer name="BUTTON_HOME_X">600</integer> |
| 19 | <integer name="SWITCH_TRIGGER_L_Y">220</integer> | 19 | <integer name="BUTTON_HOME_Y">950</integer> |
| 20 | <integer name="SWITCH_TRIGGER_R_X">930</integer> | 20 | <integer name="BUTTON_CAPTURE_X">400</integer> |
| 21 | <integer name="SWITCH_TRIGGER_R_Y">220</integer> | 21 | <integer name="BUTTON_CAPTURE_Y">950</integer> |
| 22 | <integer name="SWITCH_TRIGGER_ZL_X">70</integer> | 22 | <integer name="BUTTON_L_X">70</integer> |
| 23 | <integer name="SWITCH_TRIGGER_ZL_Y">90</integer> | 23 | <integer name="BUTTON_L_Y">220</integer> |
| 24 | <integer name="SWITCH_TRIGGER_ZR_X">930</integer> | 24 | <integer name="BUTTON_R_X">930</integer> |
| 25 | <integer name="SWITCH_TRIGGER_ZR_Y">90</integer> | 25 | <integer name="BUTTON_R_Y">220</integer> |
| 26 | <integer name="SWITCH_BUTTON_MINUS_X">460</integer> | 26 | <integer name="BUTTON_ZL_X">70</integer> |
| 27 | <integer name="SWITCH_BUTTON_MINUS_Y">950</integer> | 27 | <integer name="BUTTON_ZL_Y">90</integer> |
| 28 | <integer name="SWITCH_BUTTON_PLUS_X">540</integer> | 28 | <integer name="BUTTON_ZR_X">930</integer> |
| 29 | <integer name="SWITCH_BUTTON_PLUS_Y">950</integer> | 29 | <integer name="BUTTON_ZR_Y">90</integer> |
| 30 | <integer name="SWITCH_BUTTON_HOME_X">600</integer> | 30 | <integer name="BUTTON_STICK_L_X">870</integer> |
| 31 | <integer name="SWITCH_BUTTON_HOME_Y">950</integer> | 31 | <integer name="BUTTON_STICK_L_Y">400</integer> |
| 32 | <integer name="SWITCH_BUTTON_CAPTURE_X">400</integer> | 32 | <integer name="BUTTON_STICK_R_X">960</integer> |
| 33 | <integer name="SWITCH_BUTTON_CAPTURE_Y">950</integer> | 33 | <integer name="BUTTON_STICK_R_Y">430</integer> |
| 34 | <integer name="SWITCH_BUTTON_DPAD_X">260</integer> | 34 | <integer name="STICK_L_X">100</integer> |
| 35 | <integer name="SWITCH_BUTTON_DPAD_Y">790</integer> | 35 | <integer name="STICK_L_Y">670</integer> |
| 36 | <integer name="SWITCH_BUTTON_STICK_L_X">870</integer> | 36 | <integer name="STICK_R_X">900</integer> |
| 37 | <integer name="SWITCH_BUTTON_STICK_L_Y">400</integer> | 37 | <integer name="STICK_R_Y">670</integer> |
| 38 | <integer name="SWITCH_BUTTON_STICK_R_X">960</integer> | 38 | <integer name="COMBINED_DPAD_X">260</integer> |
| 39 | <integer name="SWITCH_BUTTON_STICK_R_Y">430</integer> | 39 | <integer name="COMBINED_DPAD_Y">790</integer> |
| 40 | 40 | ||
| 41 | <!-- Default SWITCH portrait layout --> | 41 | <!-- Default SWITCH portrait layout --> |
| 42 | <integer name="SWITCH_BUTTON_A_X_PORTRAIT">840</integer> | 42 | <integer name="BUTTON_A_X_PORTRAIT">840</integer> |
| 43 | <integer name="SWITCH_BUTTON_A_Y_PORTRAIT">840</integer> | 43 | <integer name="BUTTON_A_Y_PORTRAIT">840</integer> |
| 44 | <integer name="SWITCH_BUTTON_B_X_PORTRAIT">740</integer> | 44 | <integer name="BUTTON_B_X_PORTRAIT">740</integer> |
| 45 | <integer name="SWITCH_BUTTON_B_Y_PORTRAIT">880</integer> | 45 | <integer name="BUTTON_B_Y_PORTRAIT">880</integer> |
| 46 | <integer name="SWITCH_BUTTON_X_X_PORTRAIT">740</integer> | 46 | <integer name="BUTTON_X_X_PORTRAIT">740</integer> |
| 47 | <integer name="SWITCH_BUTTON_X_Y_PORTRAIT">800</integer> | 47 | <integer name="BUTTON_X_Y_PORTRAIT">800</integer> |
| 48 | <integer name="SWITCH_BUTTON_Y_X_PORTRAIT">640</integer> | 48 | <integer name="BUTTON_Y_X_PORTRAIT">640</integer> |
| 49 | <integer name="SWITCH_BUTTON_Y_Y_PORTRAIT">840</integer> | 49 | <integer name="BUTTON_Y_Y_PORTRAIT">840</integer> |
| 50 | <integer name="SWITCH_STICK_L_X_PORTRAIT">180</integer> | 50 | <integer name="BUTTON_PLUS_Y_PORTRAIT">950</integer> |
| 51 | <integer name="SWITCH_STICK_L_Y_PORTRAIT">660</integer> | 51 | <integer name="BUTTON_MINUS_X_PORTRAIT">440</integer> |
| 52 | <integer name="SWITCH_STICK_R_X_PORTRAIT">820</integer> | 52 | <integer name="BUTTON_MINUS_Y_PORTRAIT">950</integer> |
| 53 | <integer name="SWITCH_STICK_R_Y_PORTRAIT">660</integer> | 53 | <integer name="BUTTON_HOME_X_PORTRAIT">680</integer> |
| 54 | <integer name="SWITCH_TRIGGER_L_X_PORTRAIT">140</integer> | 54 | <integer name="BUTTON_HOME_Y_PORTRAIT">950</integer> |
| 55 | <integer name="SWITCH_TRIGGER_L_Y_PORTRAIT">260</integer> | 55 | <integer name="BUTTON_CAPTURE_X_PORTRAIT">320</integer> |
| 56 | <integer name="SWITCH_TRIGGER_R_X_PORTRAIT">860</integer> | 56 | <integer name="BUTTON_CAPTURE_Y_PORTRAIT">950</integer> |
| 57 | <integer name="SWITCH_TRIGGER_R_Y_PORTRAIT">260</integer> | 57 | <integer name="BUTTON_L_X_PORTRAIT">140</integer> |
| 58 | <integer name="SWITCH_TRIGGER_ZL_X_PORTRAIT">140</integer> | 58 | <integer name="BUTTON_L_Y_PORTRAIT">260</integer> |
| 59 | <integer name="SWITCH_TRIGGER_ZL_Y_PORTRAIT">200</integer> | 59 | <integer name="BUTTON_R_X_PORTRAIT">860</integer> |
| 60 | <integer name="SWITCH_TRIGGER_ZR_X_PORTRAIT">860</integer> | 60 | <integer name="BUTTON_R_Y_PORTRAIT">260</integer> |
| 61 | <integer name="SWITCH_TRIGGER_ZR_Y_PORTRAIT">200</integer> | 61 | <integer name="BUTTON_ZL_X_PORTRAIT">140</integer> |
| 62 | <integer name="SWITCH_BUTTON_MINUS_X_PORTRAIT">440</integer> | 62 | <integer name="BUTTON_ZL_Y_PORTRAIT">200</integer> |
| 63 | <integer name="SWITCH_BUTTON_MINUS_Y_PORTRAIT">950</integer> | 63 | <integer name="BUTTON_ZR_X_PORTRAIT">860</integer> |
| 64 | <integer name="SWITCH_BUTTON_PLUS_X_PORTRAIT">560</integer> | 64 | <integer name="BUTTON_ZR_Y_PORTRAIT">200</integer> |
| 65 | <integer name="SWITCH_BUTTON_PLUS_Y_PORTRAIT">950</integer> | 65 | <integer name="BUTTON_PLUS_X_PORTRAIT">560</integer> |
| 66 | <integer name="SWITCH_BUTTON_HOME_X_PORTRAIT">680</integer> | 66 | <integer name="BUTTON_STICK_L_X_PORTRAIT">730</integer> |
| 67 | <integer name="SWITCH_BUTTON_HOME_Y_PORTRAIT">950</integer> | 67 | <integer name="BUTTON_STICK_L_Y_PORTRAIT">510</integer> |
| 68 | <integer name="SWITCH_BUTTON_CAPTURE_X_PORTRAIT">320</integer> | 68 | <integer name="BUTTON_STICK_R_X_PORTRAIT">900</integer> |
| 69 | <integer name="SWITCH_BUTTON_CAPTURE_Y_PORTRAIT">950</integer> | 69 | <integer name="BUTTON_STICK_R_Y_PORTRAIT">540</integer> |
| 70 | <integer name="SWITCH_BUTTON_DPAD_X_PORTRAIT">240</integer> | 70 | <integer name="STICK_L_X_PORTRAIT">180</integer> |
| 71 | <integer name="SWITCH_BUTTON_DPAD_Y_PORTRAIT">840</integer> | 71 | <integer name="STICK_L_Y_PORTRAIT">660</integer> |
| 72 | <integer name="SWITCH_BUTTON_STICK_L_X_PORTRAIT">730</integer> | 72 | <integer name="STICK_R_X_PORTRAIT">820</integer> |
| 73 | <integer name="SWITCH_BUTTON_STICK_L_Y_PORTRAIT">510</integer> | 73 | <integer name="STICK_R_Y_PORTRAIT">660</integer> |
| 74 | <integer name="SWITCH_BUTTON_STICK_R_X_PORTRAIT">900</integer> | 74 | <integer name="COMBINED_DPAD_X_PORTRAIT">240</integer> |
| 75 | <integer name="SWITCH_BUTTON_STICK_R_Y_PORTRAIT">540</integer> | 75 | <integer name="COMBINED_DPAD_Y_PORTRAIT">840</integer> |
| 76 | 76 | ||
| 77 | <!-- Default SWITCH foldable layout --> | 77 | <!-- Default SWITCH foldable layout --> |
| 78 | <integer name="SWITCH_BUTTON_A_X_FOLDABLE">840</integer> | 78 | <integer name="BUTTON_A_X_FOLDABLE">840</integer> |
| 79 | <integer name="SWITCH_BUTTON_A_Y_FOLDABLE">390</integer> | 79 | <integer name="BUTTON_A_Y_FOLDABLE">390</integer> |
| 80 | <integer name="SWITCH_BUTTON_B_X_FOLDABLE">740</integer> | 80 | <integer name="BUTTON_B_X_FOLDABLE">740</integer> |
| 81 | <integer name="SWITCH_BUTTON_B_Y_FOLDABLE">430</integer> | 81 | <integer name="BUTTON_B_Y_FOLDABLE">430</integer> |
| 82 | <integer name="SWITCH_BUTTON_X_X_FOLDABLE">740</integer> | 82 | <integer name="BUTTON_X_X_FOLDABLE">740</integer> |
| 83 | <integer name="SWITCH_BUTTON_X_Y_FOLDABLE">350</integer> | 83 | <integer name="BUTTON_X_Y_FOLDABLE">350</integer> |
| 84 | <integer name="SWITCH_BUTTON_Y_X_FOLDABLE">640</integer> | 84 | <integer name="BUTTON_Y_X_FOLDABLE">640</integer> |
| 85 | <integer name="SWITCH_BUTTON_Y_Y_FOLDABLE">390</integer> | 85 | <integer name="BUTTON_Y_Y_FOLDABLE">390</integer> |
| 86 | <integer name="SWITCH_STICK_L_X_FOLDABLE">180</integer> | 86 | <integer name="BUTTON_PLUS_X_FOLDABLE">560</integer> |
| 87 | <integer name="SWITCH_STICK_L_Y_FOLDABLE">250</integer> | 87 | <integer name="BUTTON_PLUS_Y_FOLDABLE">470</integer> |
| 88 | <integer name="SWITCH_STICK_R_X_FOLDABLE">820</integer> | 88 | <integer name="BUTTON_MINUS_X_FOLDABLE">440</integer> |
| 89 | <integer name="SWITCH_STICK_R_Y_FOLDABLE">250</integer> | 89 | <integer name="BUTTON_MINUS_Y_FOLDABLE">470</integer> |
| 90 | <integer name="SWITCH_TRIGGER_L_X_FOLDABLE">140</integer> | 90 | <integer name="BUTTON_HOME_X_FOLDABLE">680</integer> |
| 91 | <integer name="SWITCH_TRIGGER_L_Y_FOLDABLE">130</integer> | 91 | <integer name="BUTTON_HOME_Y_FOLDABLE">470</integer> |
| 92 | <integer name="SWITCH_TRIGGER_R_X_FOLDABLE">860</integer> | 92 | <integer name="BUTTON_CAPTURE_X_FOLDABLE">320</integer> |
| 93 | <integer name="SWITCH_TRIGGER_R_Y_FOLDABLE">130</integer> | 93 | <integer name="BUTTON_CAPTURE_Y_FOLDABLE">470</integer> |
| 94 | <integer name="SWITCH_TRIGGER_ZL_X_FOLDABLE">140</integer> | 94 | <integer name="BUTTON_L_X_FOLDABLE">140</integer> |
| 95 | <integer name="SWITCH_TRIGGER_ZL_Y_FOLDABLE">70</integer> | 95 | <integer name="BUTTON_L_Y_FOLDABLE">130</integer> |
| 96 | <integer name="SWITCH_TRIGGER_ZR_X_FOLDABLE">860</integer> | 96 | <integer name="BUTTON_R_X_FOLDABLE">860</integer> |
| 97 | <integer name="SWITCH_TRIGGER_ZR_Y_FOLDABLE">70</integer> | 97 | <integer name="BUTTON_R_Y_FOLDABLE">130</integer> |
| 98 | <integer name="SWITCH_BUTTON_MINUS_X_FOLDABLE">440</integer> | 98 | <integer name="BUTTON_ZL_X_FOLDABLE">140</integer> |
| 99 | <integer name="SWITCH_BUTTON_MINUS_Y_FOLDABLE">470</integer> | 99 | <integer name="BUTTON_ZL_Y_FOLDABLE">70</integer> |
| 100 | <integer name="SWITCH_BUTTON_PLUS_X_FOLDABLE">560</integer> | 100 | <integer name="BUTTON_ZR_X_FOLDABLE">860</integer> |
| 101 | <integer name="SWITCH_BUTTON_PLUS_Y_FOLDABLE">470</integer> | 101 | <integer name="BUTTON_ZR_Y_FOLDABLE">70</integer> |
| 102 | <integer name="SWITCH_BUTTON_HOME_X_FOLDABLE">680</integer> | 102 | <integer name="BUTTON_STICK_L_X_FOLDABLE">550</integer> |
| 103 | <integer name="SWITCH_BUTTON_HOME_Y_FOLDABLE">470</integer> | 103 | <integer name="BUTTON_STICK_L_Y_FOLDABLE">210</integer> |
| 104 | <integer name="SWITCH_BUTTON_CAPTURE_X_FOLDABLE">320</integer> | 104 | <integer name="BUTTON_STICK_R_X_FOLDABLE">550</integer> |
| 105 | <integer name="SWITCH_BUTTON_CAPTURE_Y_FOLDABLE">470</integer> | 105 | <integer name="BUTTON_STICK_R_Y_FOLDABLE">280</integer> |
| 106 | <integer name="SWITCH_BUTTON_DPAD_X_FOLDABLE">240</integer> | 106 | <integer name="STICK_L_X_FOLDABLE">180</integer> |
| 107 | <integer name="SWITCH_BUTTON_DPAD_Y_FOLDABLE">390</integer> | 107 | <integer name="STICK_L_Y_FOLDABLE">250</integer> |
| 108 | <integer name="SWITCH_BUTTON_STICK_L_X_FOLDABLE">550</integer> | 108 | <integer name="STICK_R_X_FOLDABLE">820</integer> |
| 109 | <integer name="SWITCH_BUTTON_STICK_L_Y_FOLDABLE">210</integer> | 109 | <integer name="STICK_R_Y_FOLDABLE">250</integer> |
| 110 | <integer name="SWITCH_BUTTON_STICK_R_X_FOLDABLE">550</integer> | 110 | <integer name="COMBINED_DPAD_X_FOLDABLE">240</integer> |
| 111 | <integer name="SWITCH_BUTTON_STICK_R_Y_FOLDABLE">280</integer> | 111 | <integer name="COMBINED_DPAD_Y_FOLDABLE">390</integer> |
| 112 | 112 | ||
| 113 | </resources> | 113 | </resources> |
diff --git a/src/common/settings.cpp b/src/common/settings.cpp index ea52bbfa6..07709d4e5 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp | |||
| @@ -199,6 +199,8 @@ const char* TranslateCategory(Category category) { | |||
| 199 | case Category::CpuDebug: | 199 | case Category::CpuDebug: |
| 200 | case Category::CpuUnsafe: | 200 | case Category::CpuUnsafe: |
| 201 | return "Cpu"; | 201 | return "Cpu"; |
| 202 | case Category::Overlay: | ||
| 203 | return "Overlay"; | ||
| 202 | case Category::Renderer: | 204 | case Category::Renderer: |
| 203 | case Category::RendererAdvanced: | 205 | case Category::RendererAdvanced: |
| 204 | case Category::RendererDebug: | 206 | case Category::RendererDebug: |
diff --git a/src/common/settings_common.h b/src/common/settings_common.h index c82e17495..1a290ad77 100644 --- a/src/common/settings_common.h +++ b/src/common/settings_common.h | |||
| @@ -18,6 +18,7 @@ enum class Category : u32 { | |||
| 18 | Cpu, | 18 | Cpu, |
| 19 | CpuDebug, | 19 | CpuDebug, |
| 20 | CpuUnsafe, | 20 | CpuUnsafe, |
| 21 | Overlay, | ||
| 21 | Renderer, | 22 | Renderer, |
| 22 | RendererAdvanced, | 23 | RendererAdvanced, |
| 23 | RendererDebug, | 24 | RendererDebug, |