summaryrefslogtreecommitdiffstats
path: root/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
diff options
context:
space:
mode:
Diffstat (limited to 'src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt')
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt794
1 files changed, 741 insertions, 53 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
index db1a58147..e491c29a2 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
@@ -3,11 +3,17 @@
package org.yuzu.yuzu_emu.features.settings.ui
+import android.annotation.SuppressLint
import android.os.Build
import android.widget.Toast
import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication
+import org.yuzu.yuzu_emu.features.input.NativeInput
+import org.yuzu.yuzu_emu.features.input.model.AnalogDirection
+import org.yuzu.yuzu_emu.features.input.model.NativeAnalog
+import org.yuzu.yuzu_emu.features.input.model.NativeButton
+import org.yuzu.yuzu_emu.features.input.model.NpadStyleIndex
import org.yuzu.yuzu_emu.features.settings.model.AbstractBooleanSetting
import org.yuzu.yuzu_emu.features.settings.model.AbstractIntSetting
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
@@ -15,18 +21,21 @@ import org.yuzu.yuzu_emu.features.settings.model.ByteSetting
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
import org.yuzu.yuzu_emu.features.settings.model.LongSetting
import org.yuzu.yuzu_emu.features.settings.model.Settings
+import org.yuzu.yuzu_emu.features.settings.model.Settings.MenuTag
import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
import org.yuzu.yuzu_emu.features.settings.model.view.*
-import org.yuzu.yuzu_emu.model.SettingsViewModel
+import org.yuzu.yuzu_emu.utils.InputHandler
import org.yuzu.yuzu_emu.utils.NativeConfig
class SettingsFragmentPresenter(
private val settingsViewModel: SettingsViewModel,
private val adapter: SettingsAdapter,
- private var menuTag: Settings.MenuTag
+ private var menuTag: MenuTag
) {
private var settingsList = ArrayList<SettingsItem>()
+ private val context get() = YuzuApplication.appContext
+
// Extension for altering settings list based on each setting's properties
fun ArrayList<SettingsItem>.add(key: String) {
val item = SettingsItem.settingsItems[key]!!
@@ -53,73 +62,90 @@ class SettingsFragmentPresenter(
add(item)
}
+ // Allows you to show/hide abstract settings based on the paired setting key
+ fun ArrayList<SettingsItem>.addAbstract(item: SettingsItem) {
+ val pairedSettingKey = item.setting.pairedSettingKey
+ if (pairedSettingKey.isNotEmpty()) {
+ val pairedSettingsItem =
+ this.firstOrNull { it.setting.key == pairedSettingKey } ?: return
+ val pairedSetting = pairedSettingsItem.setting as AbstractBooleanSetting
+ if (!pairedSetting.getBoolean(!NativeConfig.isPerGameConfigLoaded())) return
+ }
+ add(item)
+ }
+
fun onViewCreated() {
loadSettingsList()
}
- fun loadSettingsList() {
+ @SuppressLint("NotifyDataSetChanged")
+ fun loadSettingsList(notifyDataSetChanged: Boolean = false) {
val sl = ArrayList<SettingsItem>()
when (menuTag) {
- Settings.MenuTag.SECTION_ROOT -> addConfigSettings(sl)
- Settings.MenuTag.SECTION_SYSTEM -> addSystemSettings(sl)
- Settings.MenuTag.SECTION_RENDERER -> addGraphicsSettings(sl)
- Settings.MenuTag.SECTION_AUDIO -> addAudioSettings(sl)
- Settings.MenuTag.SECTION_THEME -> addThemeSettings(sl)
- Settings.MenuTag.SECTION_DEBUG -> addDebugSettings(sl)
- else -> {
- val context = YuzuApplication.appContext
- Toast.makeText(
- context,
- context.getString(R.string.unimplemented_menu),
- Toast.LENGTH_SHORT
- ).show()
- return
- }
+ MenuTag.SECTION_ROOT -> addConfigSettings(sl)
+ MenuTag.SECTION_SYSTEM -> addSystemSettings(sl)
+ MenuTag.SECTION_RENDERER -> addGraphicsSettings(sl)
+ MenuTag.SECTION_AUDIO -> addAudioSettings(sl)
+ MenuTag.SECTION_INPUT -> addInputSettings(sl)
+ MenuTag.SECTION_INPUT_PLAYER_ONE -> addInputPlayer(sl, 0)
+ MenuTag.SECTION_INPUT_PLAYER_TWO -> addInputPlayer(sl, 1)
+ MenuTag.SECTION_INPUT_PLAYER_THREE -> addInputPlayer(sl, 2)
+ MenuTag.SECTION_INPUT_PLAYER_FOUR -> addInputPlayer(sl, 3)
+ MenuTag.SECTION_INPUT_PLAYER_FIVE -> addInputPlayer(sl, 4)
+ MenuTag.SECTION_INPUT_PLAYER_SIX -> addInputPlayer(sl, 5)
+ MenuTag.SECTION_INPUT_PLAYER_SEVEN -> addInputPlayer(sl, 6)
+ MenuTag.SECTION_INPUT_PLAYER_EIGHT -> addInputPlayer(sl, 7)
+ MenuTag.SECTION_THEME -> addThemeSettings(sl)
+ MenuTag.SECTION_DEBUG -> addDebugSettings(sl)
}
settingsList = sl
- adapter.submitList(settingsList)
+ adapter.submitList(settingsList) {
+ if (notifyDataSetChanged) {
+ adapter.notifyDataSetChanged()
+ }
+ }
}
private fun addConfigSettings(sl: ArrayList<SettingsItem>) {
sl.apply {
add(
SubmenuSetting(
- R.string.preferences_system,
- R.string.preferences_system_description,
- R.drawable.ic_system_settings,
- Settings.MenuTag.SECTION_SYSTEM
+ titleId = R.string.preferences_system,
+ descriptionId = R.string.preferences_system_description,
+ iconId = R.drawable.ic_system_settings,
+ menuKey = MenuTag.SECTION_SYSTEM
)
)
add(
SubmenuSetting(
- R.string.preferences_graphics,
- R.string.preferences_graphics_description,
- R.drawable.ic_graphics,
- Settings.MenuTag.SECTION_RENDERER
+ titleId = R.string.preferences_graphics,
+ descriptionId = R.string.preferences_graphics_description,
+ iconId = R.drawable.ic_graphics,
+ menuKey = MenuTag.SECTION_RENDERER
)
)
add(
SubmenuSetting(
- R.string.preferences_audio,
- R.string.preferences_audio_description,
- R.drawable.ic_audio,
- Settings.MenuTag.SECTION_AUDIO
+ titleId = R.string.preferences_audio,
+ descriptionId = R.string.preferences_audio_description,
+ iconId = R.drawable.ic_audio,
+ menuKey = MenuTag.SECTION_AUDIO
)
)
add(
SubmenuSetting(
- R.string.preferences_debug,
- R.string.preferences_debug_description,
- R.drawable.ic_code,
- Settings.MenuTag.SECTION_DEBUG
+ titleId = R.string.preferences_debug,
+ descriptionId = R.string.preferences_debug_description,
+ iconId = R.drawable.ic_code,
+ menuKey = MenuTag.SECTION_DEBUG
)
)
add(
RunnableSetting(
- R.string.reset_to_default,
- R.string.reset_to_default_description,
- false,
- R.drawable.ic_restore
+ titleId = R.string.reset_to_default,
+ descriptionId = R.string.reset_to_default_description,
+ isRunnable = !NativeLibrary.isRunning(),
+ iconId = R.drawable.ic_restore
) { settingsViewModel.setShouldShowResetSettingsDialog(true) }
)
}
@@ -164,6 +190,671 @@ class SettingsFragmentPresenter(
}
}
+ private fun addInputSettings(sl: ArrayList<SettingsItem>) {
+ settingsViewModel.currentDevice = 0
+
+ if (NativeConfig.isPerGameConfigLoaded()) {
+ NativeInput.loadInputProfiles()
+ val profiles = NativeInput.getInputProfileNames().toMutableList()
+ profiles.add(0, "")
+ val prettyProfiles = profiles.toTypedArray()
+ prettyProfiles[0] =
+ context.getString(R.string.use_global_input_configuration)
+ sl.apply {
+ for (i in 0 until 8) {
+ add(
+ IntSingleChoiceSetting(
+ getPerGameProfileSetting(profiles, i),
+ titleString = getPlayerProfileString(i + 1),
+ choices = prettyProfiles,
+ values = IntArray(profiles.size) { it }.toTypedArray()
+ )
+ )
+ }
+ }
+ return
+ }
+
+ val getConnectedIcon: (Int) -> Int = { playerIndex: Int ->
+ if (NativeInput.getIsConnected(playerIndex)) {
+ R.drawable.ic_controller
+ } else {
+ R.drawable.ic_controller_disconnected
+ }
+ }
+
+ val inputSettings = NativeConfig.getInputSettings(true)
+ sl.apply {
+ add(
+ SubmenuSetting(
+ titleString = Settings.getPlayerString(1),
+ descriptionString = inputSettings[0].profileName,
+ menuKey = MenuTag.SECTION_INPUT_PLAYER_ONE,
+ iconId = getConnectedIcon(0)
+ )
+ )
+ add(
+ SubmenuSetting(
+ titleString = Settings.getPlayerString(2),
+ descriptionString = inputSettings[1].profileName,
+ menuKey = MenuTag.SECTION_INPUT_PLAYER_TWO,
+ iconId = getConnectedIcon(1)
+ )
+ )
+ add(
+ SubmenuSetting(
+ titleString = Settings.getPlayerString(3),
+ descriptionString = inputSettings[2].profileName,
+ menuKey = MenuTag.SECTION_INPUT_PLAYER_THREE,
+ iconId = getConnectedIcon(2)
+ )
+ )
+ add(
+ SubmenuSetting(
+ titleString = Settings.getPlayerString(4),
+ descriptionString = inputSettings[3].profileName,
+ menuKey = MenuTag.SECTION_INPUT_PLAYER_FOUR,
+ iconId = getConnectedIcon(3)
+ )
+ )
+ add(
+ SubmenuSetting(
+ titleString = Settings.getPlayerString(5),
+ descriptionString = inputSettings[4].profileName,
+ menuKey = MenuTag.SECTION_INPUT_PLAYER_FIVE,
+ iconId = getConnectedIcon(4)
+ )
+ )
+ add(
+ SubmenuSetting(
+ titleString = Settings.getPlayerString(6),
+ descriptionString = inputSettings[5].profileName,
+ menuKey = MenuTag.SECTION_INPUT_PLAYER_SIX,
+ iconId = getConnectedIcon(5)
+ )
+ )
+ add(
+ SubmenuSetting(
+ titleString = Settings.getPlayerString(7),
+ descriptionString = inputSettings[6].profileName,
+ menuKey = MenuTag.SECTION_INPUT_PLAYER_SEVEN,
+ iconId = getConnectedIcon(6)
+ )
+ )
+ add(
+ SubmenuSetting(
+ titleString = Settings.getPlayerString(8),
+ descriptionString = inputSettings[7].profileName,
+ menuKey = MenuTag.SECTION_INPUT_PLAYER_EIGHT,
+ iconId = getConnectedIcon(7)
+ )
+ )
+ }
+ }
+
+ private fun getPlayerProfileString(player: Int): String =
+ context.getString(R.string.player_num_profile, player)
+
+ private fun getPerGameProfileSetting(
+ profiles: List<String>,
+ playerIndex: Int
+ ): AbstractIntSetting {
+ return object : AbstractIntSetting {
+ private val players
+ get() = NativeConfig.getInputSettings(false)
+
+ override val key = ""
+
+ override fun getInt(needsGlobal: Boolean): Int {
+ val currentProfile = players[playerIndex].profileName
+ profiles.forEachIndexed { i, profile ->
+ if (profile == currentProfile) {
+ return i
+ }
+ }
+ return 0
+ }
+
+ override fun setInt(value: Int) {
+ NativeInput.loadPerGameConfiguration(playerIndex, value, profiles[value])
+ NativeInput.connectControllers(playerIndex)
+ NativeConfig.saveControlPlayerValues()
+ }
+
+ override val defaultValue = 0
+
+ override fun getValueAsString(needsGlobal: Boolean): String = getInt().toString()
+
+ override fun reset() = setInt(defaultValue)
+
+ override var global = true
+
+ override val isRuntimeModifiable = true
+
+ override val isSaveable = true
+ }
+ }
+
+ private fun addInputPlayer(sl: ArrayList<SettingsItem>, playerIndex: Int) {
+ sl.apply {
+ val connectedSetting = object : AbstractBooleanSetting {
+ override val key = "connected"
+
+ override fun getBoolean(needsGlobal: Boolean): Boolean =
+ NativeInput.getIsConnected(playerIndex)
+
+ override fun setBoolean(value: Boolean) =
+ NativeInput.connectControllers(playerIndex, value)
+
+ override val defaultValue = playerIndex == 0
+
+ override fun getValueAsString(needsGlobal: Boolean): String =
+ getBoolean(needsGlobal).toString()
+
+ override fun reset() = setBoolean(defaultValue)
+ }
+ add(SwitchSetting(connectedSetting, R.string.connected))
+
+ val styleTags = NativeInput.getSupportedStyleTags(playerIndex)
+ val npadType = object : AbstractIntSetting {
+ override val key = "npad_type"
+ override fun getInt(needsGlobal: Boolean): Int {
+ val styleIndex = NativeInput.getStyleIndex(playerIndex)
+ return styleTags.indexOfFirst { it == styleIndex }
+ }
+
+ override fun setInt(value: Int) {
+ NativeInput.setStyleIndex(playerIndex, styleTags[value])
+ settingsViewModel.setReloadListAndNotifyDataset(true)
+ }
+
+ override val defaultValue = NpadStyleIndex.Fullkey.int
+ override fun getValueAsString(needsGlobal: Boolean): String = getInt().toString()
+ override fun reset() = setInt(defaultValue)
+ override val pairedSettingKey: String = "connected"
+ }
+ addAbstract(
+ IntSingleChoiceSetting(
+ npadType,
+ titleId = R.string.controller_type,
+ choices = styleTags.map { context.getString(it.nameId) }
+ .toTypedArray(),
+ values = IntArray(styleTags.size) { it }.toTypedArray()
+ )
+ )
+
+ InputHandler.updateControllerData()
+
+ val autoMappingSetting = object : AbstractIntSetting {
+ override val key = "auto_mapping_device"
+
+ override fun getInt(needsGlobal: Boolean): Int = -1
+
+ override fun setInt(value: Int) {
+ val registeredController = InputHandler.registeredControllers[value + 1]
+ val displayName = registeredController.get(
+ "display",
+ context.getString(R.string.unknown)
+ )
+ NativeInput.updateMappingsWithDefault(
+ playerIndex,
+ registeredController,
+ displayName
+ )
+ Toast.makeText(
+ context,
+ context.getString(R.string.attempted_auto_map, displayName),
+ Toast.LENGTH_SHORT
+ ).show()
+ settingsViewModel.setReloadListAndNotifyDataset(true)
+ }
+
+ override val defaultValue = -1
+
+ override fun getValueAsString(needsGlobal: Boolean) = getInt().toString()
+
+ override fun reset() = setInt(defaultValue)
+
+ override val isRuntimeModifiable: Boolean = true
+ }
+
+ val unknownString = context.getString(R.string.unknown)
+ val prettyAutoMappingControllerList = InputHandler.registeredControllers.mapNotNull {
+ val port = it.get("port", -1)
+ return@mapNotNull if (port == 100 || port == -1) {
+ null
+ } else {
+ it.get("display", unknownString)
+ }
+ }.toTypedArray()
+ add(
+ IntSingleChoiceSetting(
+ autoMappingSetting,
+ titleId = R.string.auto_map,
+ descriptionId = R.string.auto_map_description,
+ choices = prettyAutoMappingControllerList,
+ values = IntArray(prettyAutoMappingControllerList.size) { it }.toTypedArray()
+ )
+ )
+
+ val mappingFilterSetting = object : AbstractIntSetting {
+ override val key = "mapping_filter"
+
+ override fun getInt(needsGlobal: Boolean): Int = settingsViewModel.currentDevice
+
+ override fun setInt(value: Int) {
+ settingsViewModel.currentDevice = value
+ }
+
+ override val defaultValue = 0
+
+ override fun getValueAsString(needsGlobal: Boolean) = getInt().toString()
+
+ override fun reset() = setInt(defaultValue)
+
+ override val isRuntimeModifiable: Boolean = true
+ }
+
+ val prettyControllerList = InputHandler.registeredControllers.mapNotNull {
+ return@mapNotNull if (it.get("port", 0) == 100) {
+ null
+ } else {
+ it.get("display", unknownString)
+ }
+ }.toTypedArray()
+ add(
+ IntSingleChoiceSetting(
+ mappingFilterSetting,
+ titleId = R.string.input_mapping_filter,
+ descriptionId = R.string.input_mapping_filter_description,
+ choices = prettyControllerList,
+ values = IntArray(prettyControllerList.size) { it }.toTypedArray()
+ )
+ )
+
+ add(InputProfileSetting(playerIndex))
+ add(
+ RunnableSetting(titleId = R.string.reset_to_default, isRunnable = true) {
+ settingsViewModel.setShouldShowResetInputDialog(true)
+ }
+ )
+
+ val styleIndex = NativeInput.getStyleIndex(playerIndex)
+
+ // Buttons
+ when (styleIndex) {
+ NpadStyleIndex.Fullkey,
+ NpadStyleIndex.Handheld,
+ NpadStyleIndex.JoyconDual -> {
+ add(HeaderSetting(R.string.buttons))
+ add(ButtonInputSetting(playerIndex, NativeButton.A, R.string.button_a))
+ add(ButtonInputSetting(playerIndex, NativeButton.B, R.string.button_b))
+ add(ButtonInputSetting(playerIndex, NativeButton.X, R.string.button_x))
+ add(ButtonInputSetting(playerIndex, NativeButton.Y, R.string.button_y))
+ add(ButtonInputSetting(playerIndex, NativeButton.Plus, R.string.button_plus))
+ add(ButtonInputSetting(playerIndex, NativeButton.Minus, R.string.button_minus))
+ add(ButtonInputSetting(playerIndex, NativeButton.Home, R.string.button_home))
+ add(
+ ButtonInputSetting(
+ playerIndex,
+ NativeButton.Capture,
+ R.string.button_capture
+ )
+ )
+ }
+
+ NpadStyleIndex.JoyconLeft -> {
+ add(HeaderSetting(R.string.buttons))
+ add(ButtonInputSetting(playerIndex, NativeButton.Minus, R.string.button_minus))
+ add(
+ ButtonInputSetting(
+ playerIndex,
+ NativeButton.Capture,
+ R.string.button_capture
+ )
+ )
+ }
+
+ NpadStyleIndex.JoyconRight -> {
+ add(HeaderSetting(R.string.buttons))
+ add(ButtonInputSetting(playerIndex, NativeButton.A, R.string.button_a))
+ add(ButtonInputSetting(playerIndex, NativeButton.B, R.string.button_b))
+ add(ButtonInputSetting(playerIndex, NativeButton.X, R.string.button_x))
+ add(ButtonInputSetting(playerIndex, NativeButton.Y, R.string.button_y))
+ add(ButtonInputSetting(playerIndex, NativeButton.Plus, R.string.button_plus))
+ add(ButtonInputSetting(playerIndex, NativeButton.Home, R.string.button_home))
+ }
+
+ NpadStyleIndex.GameCube -> {
+ add(HeaderSetting(R.string.buttons))
+ add(ButtonInputSetting(playerIndex, NativeButton.A, R.string.button_a))
+ add(ButtonInputSetting(playerIndex, NativeButton.B, R.string.button_b))
+ add(ButtonInputSetting(playerIndex, NativeButton.X, R.string.button_x))
+ add(ButtonInputSetting(playerIndex, NativeButton.Y, R.string.button_y))
+ add(ButtonInputSetting(playerIndex, NativeButton.Plus, R.string.start_pause))
+ }
+
+ else -> {
+ // No-op
+ }
+ }
+
+ when (styleIndex) {
+ NpadStyleIndex.Fullkey,
+ NpadStyleIndex.Handheld,
+ NpadStyleIndex.JoyconDual,
+ NpadStyleIndex.JoyconLeft -> {
+ add(HeaderSetting(R.string.dpad))
+ add(ButtonInputSetting(playerIndex, NativeButton.DUp, R.string.up))
+ add(ButtonInputSetting(playerIndex, NativeButton.DDown, R.string.down))
+ add(ButtonInputSetting(playerIndex, NativeButton.DLeft, R.string.left))
+ add(ButtonInputSetting(playerIndex, NativeButton.DRight, R.string.right))
+ }
+
+ else -> {
+ // No-op
+ }
+ }
+
+ // Left stick
+ when (styleIndex) {
+ NpadStyleIndex.Fullkey,
+ NpadStyleIndex.Handheld,
+ NpadStyleIndex.JoyconDual,
+ NpadStyleIndex.JoyconLeft -> {
+ add(HeaderSetting(R.string.left_stick))
+ addAll(getStickDirections(playerIndex, NativeAnalog.LStick))
+ add(ButtonInputSetting(playerIndex, NativeButton.LStick, R.string.pressed))
+ addAll(getExtraStickSettings(playerIndex, NativeAnalog.LStick))
+ }
+
+ NpadStyleIndex.GameCube -> {
+ add(HeaderSetting(R.string.control_stick))
+ addAll(getStickDirections(playerIndex, NativeAnalog.LStick))
+ addAll(getExtraStickSettings(playerIndex, NativeAnalog.LStick))
+ }
+
+ else -> {
+ // No-op
+ }
+ }
+
+ // Right stick
+ when (styleIndex) {
+ NpadStyleIndex.Fullkey,
+ NpadStyleIndex.Handheld,
+ NpadStyleIndex.JoyconDual,
+ NpadStyleIndex.JoyconRight -> {
+ add(HeaderSetting(R.string.right_stick))
+ addAll(getStickDirections(playerIndex, NativeAnalog.RStick))
+ add(ButtonInputSetting(playerIndex, NativeButton.RStick, R.string.pressed))
+ addAll(getExtraStickSettings(playerIndex, NativeAnalog.RStick))
+ }
+
+ NpadStyleIndex.GameCube -> {
+ add(HeaderSetting(R.string.c_stick))
+ addAll(getStickDirections(playerIndex, NativeAnalog.RStick))
+ addAll(getExtraStickSettings(playerIndex, NativeAnalog.RStick))
+ }
+
+ else -> {
+ // No-op
+ }
+ }
+
+ // L/R, ZL/ZR, and SL/SR
+ when (styleIndex) {
+ NpadStyleIndex.Fullkey,
+ NpadStyleIndex.Handheld -> {
+ add(HeaderSetting(R.string.triggers))
+ add(ButtonInputSetting(playerIndex, NativeButton.L, R.string.button_l))
+ add(ButtonInputSetting(playerIndex, NativeButton.R, R.string.button_r))
+ add(ButtonInputSetting(playerIndex, NativeButton.ZL, R.string.button_zl))
+ add(ButtonInputSetting(playerIndex, NativeButton.ZR, R.string.button_zr))
+ }
+
+ NpadStyleIndex.JoyconDual -> {
+ add(HeaderSetting(R.string.triggers))
+ add(ButtonInputSetting(playerIndex, NativeButton.L, R.string.button_l))
+ add(ButtonInputSetting(playerIndex, NativeButton.R, R.string.button_r))
+ add(ButtonInputSetting(playerIndex, NativeButton.ZL, R.string.button_zl))
+ add(ButtonInputSetting(playerIndex, NativeButton.ZR, R.string.button_zr))
+ add(
+ ButtonInputSetting(
+ playerIndex,
+ NativeButton.SLLeft,
+ R.string.button_sl_left
+ )
+ )
+ add(
+ ButtonInputSetting(
+ playerIndex,
+ NativeButton.SRLeft,
+ R.string.button_sr_left
+ )
+ )
+ add(
+ ButtonInputSetting(
+ playerIndex,
+ NativeButton.SLRight,
+ R.string.button_sl_right
+ )
+ )
+ add(
+ ButtonInputSetting(
+ playerIndex,
+ NativeButton.SRRight,
+ R.string.button_sr_right
+ )
+ )
+ }
+
+ NpadStyleIndex.JoyconLeft -> {
+ add(HeaderSetting(R.string.triggers))
+ add(ButtonInputSetting(playerIndex, NativeButton.L, R.string.button_l))
+ add(ButtonInputSetting(playerIndex, NativeButton.ZL, R.string.button_zl))
+ add(
+ ButtonInputSetting(
+ playerIndex,
+ NativeButton.SLLeft,
+ R.string.button_sl_left
+ )
+ )
+ add(
+ ButtonInputSetting(
+ playerIndex,
+ NativeButton.SRLeft,
+ R.string.button_sr_left
+ )
+ )
+ }
+
+ NpadStyleIndex.JoyconRight -> {
+ add(HeaderSetting(R.string.triggers))
+ add(ButtonInputSetting(playerIndex, NativeButton.R, R.string.button_r))
+ add(ButtonInputSetting(playerIndex, NativeButton.ZR, R.string.button_zr))
+ add(
+ ButtonInputSetting(
+ playerIndex,
+ NativeButton.SLRight,
+ R.string.button_sl_right
+ )
+ )
+ add(
+ ButtonInputSetting(
+ playerIndex,
+ NativeButton.SRRight,
+ R.string.button_sr_right
+ )
+ )
+ }
+
+ NpadStyleIndex.GameCube -> {
+ add(HeaderSetting(R.string.triggers))
+ add(ButtonInputSetting(playerIndex, NativeButton.R, R.string.button_z))
+ add(ButtonInputSetting(playerIndex, NativeButton.ZL, R.string.button_l))
+ add(ButtonInputSetting(playerIndex, NativeButton.ZR, R.string.button_r))
+ }
+
+ else -> {
+ // No-op
+ }
+ }
+
+ add(HeaderSetting(R.string.vibration))
+ val vibrationEnabledSetting = object : AbstractBooleanSetting {
+ override val key = "vibration"
+
+ override fun getBoolean(needsGlobal: Boolean): Boolean =
+ NativeConfig.getInputSettings(true)[playerIndex].vibrationEnabled
+
+ override fun setBoolean(value: Boolean) {
+ val settings = NativeConfig.getInputSettings(true)
+ settings[playerIndex].vibrationEnabled = value
+ NativeConfig.setInputSettings(settings, true)
+ }
+
+ override val defaultValue = true
+
+ override fun getValueAsString(needsGlobal: Boolean): String =
+ getBoolean(needsGlobal).toString()
+
+ override fun reset() = setBoolean(defaultValue)
+ }
+ add(SwitchSetting(vibrationEnabledSetting, R.string.vibration))
+
+ val useSystemVibratorSetting = object : AbstractBooleanSetting {
+ override val key = ""
+
+ override fun getBoolean(needsGlobal: Boolean): Boolean =
+ NativeConfig.getInputSettings(true)[playerIndex].useSystemVibrator
+
+ override fun setBoolean(value: Boolean) {
+ val settings = NativeConfig.getInputSettings(true)
+ settings[playerIndex].useSystemVibrator = value
+ NativeConfig.setInputSettings(settings, true)
+ }
+
+ override val defaultValue = playerIndex == 0
+
+ override fun getValueAsString(needsGlobal: Boolean): String =
+ getBoolean(needsGlobal).toString()
+
+ override fun reset() = setBoolean(defaultValue)
+
+ override val pairedSettingKey: String = "vibration"
+ }
+ addAbstract(SwitchSetting(useSystemVibratorSetting, R.string.use_system_vibrator))
+
+ val vibrationStrengthSetting = object : AbstractIntSetting {
+ override val key = ""
+
+ override fun getInt(needsGlobal: Boolean): Int =
+ NativeConfig.getInputSettings(true)[playerIndex].vibrationStrength
+
+ override fun setInt(value: Int) {
+ val settings = NativeConfig.getInputSettings(true)
+ settings[playerIndex].vibrationStrength = value
+ NativeConfig.setInputSettings(settings, true)
+ }
+
+ override val defaultValue = 100
+
+ override fun getValueAsString(needsGlobal: Boolean): String =
+ getInt(needsGlobal).toString()
+
+ override fun reset() = setInt(defaultValue)
+
+ override val pairedSettingKey: String = "vibration"
+ }
+ addAbstract(
+ SliderSetting(vibrationStrengthSetting, R.string.vibration_strength, units = "%")
+ )
+ }
+ }
+
+ // Convenience function for creating AbstractIntSettings for modifier range/stick range/stick deadzones
+ private fun getStickIntSettingFromParam(
+ playerIndex: Int,
+ paramName: String,
+ stick: NativeAnalog,
+ defaultValue: Int
+ ): AbstractIntSetting =
+ object : AbstractIntSetting {
+ val params get() = NativeInput.getStickParam(playerIndex, stick)
+
+ override val key = ""
+
+ override fun getInt(needsGlobal: Boolean): Int =
+ (params.get(paramName, 0.15f) * 100).toInt()
+
+ override fun setInt(value: Int) {
+ val tempParams = params
+ tempParams.set(paramName, value.toFloat() / 100)
+ NativeInput.setStickParam(playerIndex, stick, tempParams)
+ }
+
+ override val defaultValue = defaultValue
+
+ override fun getValueAsString(needsGlobal: Boolean): String =
+ getInt(needsGlobal).toString()
+
+ override fun reset() = setInt(defaultValue)
+ }
+
+ private fun getExtraStickSettings(
+ playerIndex: Int,
+ nativeAnalog: NativeAnalog
+ ): List<SettingsItem> {
+ val stickIsController =
+ NativeInput.isController(NativeInput.getStickParam(playerIndex, nativeAnalog))
+ val modifierRangeSetting =
+ getStickIntSettingFromParam(playerIndex, "modifier_scale", nativeAnalog, 50)
+ val stickRangeSetting =
+ getStickIntSettingFromParam(playerIndex, "range", nativeAnalog, 95)
+ val stickDeadzoneSetting =
+ getStickIntSettingFromParam(playerIndex, "deadzone", nativeAnalog, 15)
+
+ val out = mutableListOf<SettingsItem>().apply {
+ if (stickIsController) {
+ add(SliderSetting(stickRangeSetting, titleId = R.string.range, min = 25, max = 150))
+ add(SliderSetting(stickDeadzoneSetting, R.string.deadzone))
+ } else {
+ add(ModifierInputSetting(playerIndex, NativeAnalog.LStick, R.string.modifier))
+ add(SliderSetting(modifierRangeSetting, R.string.modifier_range))
+ }
+ }
+ return out
+ }
+
+ private fun getStickDirections(player: Int, stick: NativeAnalog): List<AnalogInputSetting> =
+ listOf(
+ AnalogInputSetting(
+ player,
+ stick,
+ AnalogDirection.Up,
+ R.string.up
+ ),
+ AnalogInputSetting(
+ player,
+ stick,
+ AnalogDirection.Down,
+ R.string.down
+ ),
+ AnalogInputSetting(
+ player,
+ stick,
+ AnalogDirection.Left,
+ R.string.left
+ ),
+ AnalogInputSetting(
+ player,
+ stick,
+ AnalogDirection.Right,
+ R.string.right
+ )
+ )
+
private fun addThemeSettings(sl: ArrayList<SettingsItem>) {
sl.apply {
val theme: AbstractIntSetting = object : AbstractIntSetting {
@@ -186,20 +877,18 @@ class SettingsFragmentPresenter(
add(
SingleChoiceSetting(
theme,
- R.string.change_app_theme,
- 0,
- R.array.themeEntriesA12,
- R.array.themeValuesA12
+ titleId = R.string.change_app_theme,
+ choicesId = R.array.themeEntriesA12,
+ valuesId = R.array.themeValuesA12
)
)
} else {
add(
SingleChoiceSetting(
theme,
- R.string.change_app_theme,
- 0,
- R.array.themeEntries,
- R.array.themeValues
+ titleId = R.string.change_app_theme,
+ choicesId = R.array.themeEntries,
+ valuesId = R.array.themeValues
)
)
}
@@ -228,10 +917,9 @@ class SettingsFragmentPresenter(
add(
SingleChoiceSetting(
themeMode,
- R.string.change_theme_mode,
- 0,
- R.array.themeModeEntries,
- R.array.themeModeValues
+ titleId = R.string.change_theme_mode,
+ choicesId = R.array.themeModeEntries,
+ valuesId = R.array.themeModeValues
)
)
@@ -262,8 +950,8 @@ class SettingsFragmentPresenter(
add(
SwitchSetting(
blackBackgrounds,
- R.string.use_black_backgrounds,
- R.string.use_black_backgrounds_description
+ titleId = R.string.use_black_backgrounds,
+ descriptionId = R.string.use_black_backgrounds_description
)
)
}