summaryrefslogtreecommitdiff
path: root/Source/Android/app/src
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2023-03-19 17:15:22 +0100
committerGitHub <noreply@github.com>2023-03-19 17:15:22 +0100
commit002a96adb05366b12909d65023f74830bb6a082c (patch)
treed261603af41ca04021e03d9c59dfb245a509cdf9 /Source/Android/app/src
parenta4d3342419e32f35280feb7b79837e78225c683d (diff)
parent9020b6aeb929198f4aa3b11ab6c83d8d96753ad1 (diff)
Merge pull request #11662 from t895/kotlin-settings
Android: Convert Settings to Kotlin
Diffstat (limited to 'Source/Android/app/src')
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatsActivity.kt2
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/SettingDisabledWarningFragment.kt2
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/view/InputDeviceSetting.java4
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/ProfileDialog.kt8
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractBooleanSetting.java12
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractBooleanSetting.kt9
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractFloatSetting.java12
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractFloatSetting.kt9
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractIntSetting.java12
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractIntSetting.kt9
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractSetting.java14
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractSetting.kt10
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractStringSetting.java13
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractStringSetting.kt9
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AdHocBooleanSetting.java62
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AdHocBooleanSetting.kt36
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AdHocStringSetting.java61
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AdHocStringSetting.kt36
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.java371
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.kt747
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/FloatSetting.java73
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/FloatSetting.kt41
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/IntSetting.java196
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/IntSetting.kt219
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/NativeConfig.java51
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/NativeConfig.kt107
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/PostProcessing.java17
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/PostProcessing.kt17
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/ScaledIntSetting.kt15
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.java181
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.kt144
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.java113
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.kt104
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/DateTimeChoiceSetting.kt13
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FilePicker.java60
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FilePicker.kt26
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FloatSliderSetting.java44
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FloatSliderSetting.kt47
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/HeaderSetting.java32
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/HeaderSetting.kt20
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/HyperLinkHeaderSetting.java19
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/HyperLinkHeaderSetting.kt11
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InputStringSetting.java72
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InputStringSetting.kt29
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/IntSliderSetting.java37
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/IntSliderSetting.kt29
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InvertedSwitchSetting.java36
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InvertedSwitchSetting.kt25
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/LogSwitchSetting.java23
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/LogSwitchSetting.kt21
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/PercentSliderSetting.java36
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/PercentSliderSetting.kt27
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/RunRunnable.java59
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/RunRunnable.kt24
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SettingsItem.java107
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SettingsItem.kt89
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SingleChoiceSetting.java72
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SingleChoiceSetting.kt30
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SingleChoiceSettingDynamicDescriptions.java89
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SingleChoiceSettingDynamicDescriptions.kt27
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SliderSetting.java61
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SliderSetting.kt47
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/StringSingleChoiceSetting.java153
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/StringSingleChoiceSetting.kt110
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SubmenuSetting.java36
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SubmenuSetting.kt17
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SwitchSetting.java50
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SwitchSetting.kt41
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/MenuTag.java165
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/MenuTag.kt132
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.java401
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.kt323
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityPresenter.java197
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityPresenter.kt147
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityView.java137
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityView.kt135
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.java703
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.kt590
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.java295
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.kt242
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java1402
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt2329
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentView.java123
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentView.kt114
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsViewModel.java17
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsViewModel.kt10
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/DateTimeSettingViewHolder.kt25
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/FilePickerViewHolder.java99
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/FilePickerViewHolder.kt68
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/HeaderHyperLinkViewHolder.java36
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/HeaderHyperLinkViewHolder.kt27
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/HeaderViewHolder.java42
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/HeaderViewHolder.kt27
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/InputStringSettingViewHolder.java71
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/InputStringSettingViewHolder.kt49
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/RunRunnableViewHolder.java93
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/RunRunnableViewHolder.kt68
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SettingViewHolder.java111
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SettingViewHolder.kt98
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SingleChoiceViewHolder.java148
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt98
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SliderViewHolder.java74
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SliderViewHolder.kt51
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SubmenuViewHolder.java46
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SubmenuViewHolder.kt28
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SwitchSettingViewHolder.java106
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt82
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java131
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.kt107
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SerializableHelper.kt24
110 files changed, 6893 insertions, 6613 deletions
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatsActivity.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatsActivity.kt
index d22431752b..dd1226d3f2 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatsActivity.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/CheatsActivity.kt
@@ -160,7 +160,7 @@ class CheatsActivity : AppCompatActivity(), PanelSlideListener {
fun loadGameSpecificSettings(): Settings {
val settings = Settings()
- settings.loadSettings(gameId, revision, isWii)
+ settings.loadSettings(gameId!!, revision, isWii)
return settings
}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/SettingDisabledWarningFragment.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/SettingDisabledWarningFragment.kt
index 737a931a85..538f4144e8 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/SettingDisabledWarningFragment.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/cheats/ui/SettingDisabledWarningFragment.kt
@@ -43,7 +43,7 @@ abstract class SettingDisabledWarningFragment(
super.onResume()
val activity = requireActivity() as CheatsActivity
activity.loadGameSpecificSettings().use {
- val cheatsEnabled = setting.getBoolean()
+ val cheatsEnabled = setting.boolean
requireView().visibility = if (cheatsEnabled) View.GONE else View.VISIBLE
}
}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/view/InputDeviceSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/view/InputDeviceSetting.java
index 3ee7112007..f02de2e3f3 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/view/InputDeviceSetting.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/model/view/InputDeviceSetting.java
@@ -46,8 +46,8 @@ public class InputDeviceSetting extends StringSingleChoiceSetting
{
String[] devices = ControllerInterface.getAllDeviceStrings();
- mChoices = devices;
- mValues = devices;
+ setChoices(devices);
+ setValues(devices);
}
@Override
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/ProfileDialog.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/ProfileDialog.kt
index 2779ee7473..acc3f605a9 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/ProfileDialog.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/input/ui/ProfileDialog.kt
@@ -2,7 +2,6 @@
package org.dolphinemu.dolphinemu.features.input.ui
-import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@@ -14,6 +13,7 @@ import com.google.android.material.divider.MaterialDividerItemDecoration
import org.dolphinemu.dolphinemu.R
import org.dolphinemu.dolphinemu.databinding.DialogInputProfilesBinding
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag
+import org.dolphinemu.dolphinemu.utils.SerializableHelper.serializable
class ProfileDialog : BottomSheetDialogFragment() {
private var presenter: ProfileDialogPresenter? = null
@@ -22,11 +22,7 @@ class ProfileDialog : BottomSheetDialogFragment() {
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
- val menuTag: MenuTag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- requireArguments().getSerializable(KEY_MENU_TAG, MenuTag::class.java) as MenuTag
- } else {
- requireArguments().getSerializable(KEY_MENU_TAG) as MenuTag
- }
+ val menuTag = requireArguments().serializable<MenuTag>(KEY_MENU_TAG)
presenter = ProfileDialogPresenter(this, menuTag)
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractBooleanSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractBooleanSetting.java
deleted file mode 100644
index 22d757d4c6..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractBooleanSetting.java
+++ /dev/null
@@ -1,12 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model;
-
-import androidx.annotation.NonNull;
-
-public interface AbstractBooleanSetting extends AbstractSetting
-{
- boolean getBoolean();
-
- void setBoolean(@NonNull Settings settings, boolean newValue);
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractBooleanSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractBooleanSetting.kt
new file mode 100644
index 0000000000..6196597dac
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractBooleanSetting.kt
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model
+
+interface AbstractBooleanSetting : AbstractSetting {
+ val boolean: Boolean
+
+ fun setBoolean(settings: Settings, newValue: Boolean)
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractFloatSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractFloatSetting.java
deleted file mode 100644
index a432c7139b..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractFloatSetting.java
+++ /dev/null
@@ -1,12 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model;
-
-import androidx.annotation.NonNull;
-
-public interface AbstractFloatSetting extends AbstractSetting
-{
- float getFloat();
-
- void setFloat(@NonNull Settings settings, float newValue);
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractFloatSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractFloatSetting.kt
new file mode 100644
index 0000000000..7dd4c82c0c
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractFloatSetting.kt
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model
+
+interface AbstractFloatSetting : AbstractSetting {
+ val float: Float
+
+ fun setFloat(settings: Settings, newValue: Float)
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractIntSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractIntSetting.java
deleted file mode 100644
index dc868d55d9..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractIntSetting.java
+++ /dev/null
@@ -1,12 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model;
-
-import androidx.annotation.NonNull;
-
-public interface AbstractIntSetting extends AbstractSetting
-{
- int getInt();
-
- void setInt(@NonNull Settings settings, int newValue);
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractIntSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractIntSetting.kt
new file mode 100644
index 0000000000..f22077dd6a
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractIntSetting.kt
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model
+
+interface AbstractIntSetting : AbstractSetting {
+ val int: Int
+
+ fun setInt(settings: Settings, newValue: Int)
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractSetting.java
deleted file mode 100644
index 9ffaf20544..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractSetting.java
+++ /dev/null
@@ -1,14 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model;
-
-import androidx.annotation.NonNull;
-
-public interface AbstractSetting
-{
- boolean isOverridden();
-
- boolean isRuntimeEditable();
-
- boolean delete(@NonNull Settings settings);
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractSetting.kt
new file mode 100644
index 0000000000..6afcfab2e4
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractSetting.kt
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model
+
+interface AbstractSetting {
+ val isOverridden: Boolean
+ val isRuntimeEditable: Boolean
+
+ fun delete(settings: Settings): Boolean
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractStringSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractStringSetting.java
deleted file mode 100644
index 9dd9384090..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractStringSetting.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model;
-
-import androidx.annotation.NonNull;
-
-public interface AbstractStringSetting extends AbstractSetting
-{
- @NonNull
- String getString();
-
- void setString(@NonNull Settings settings, @NonNull String newValue);
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractStringSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractStringSetting.kt
new file mode 100644
index 0000000000..7828dbd552
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AbstractStringSetting.kt
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model
+
+interface AbstractStringSetting : AbstractSetting {
+ val string: String
+
+ fun setString(settings: Settings, newValue: String)
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AdHocBooleanSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AdHocBooleanSetting.java
deleted file mode 100644
index c12bc51ca0..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AdHocBooleanSetting.java
+++ /dev/null
@@ -1,62 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model;
-
-import androidx.annotation.NonNull;
-
-public class AdHocBooleanSetting implements AbstractBooleanSetting
-{
- private final String mFile;
- private final String mSection;
- private final String mKey;
- private final boolean mDefaultValue;
-
- public AdHocBooleanSetting(String file, String section, String key, boolean defaultValue)
- {
- mFile = file;
- mSection = section;
- mKey = key;
- mDefaultValue = defaultValue;
-
- if (!NativeConfig.isSettingSaveable(file, section, key))
- {
- throw new IllegalArgumentException("File/section/key is unknown or legacy");
- }
- }
-
- @Override
- public boolean isOverridden()
- {
- return NativeConfig.isOverridden(mFile, mSection, mKey);
- }
-
- @Override
- public boolean isRuntimeEditable()
- {
- return true;
- }
-
- @Override
- public boolean delete(@NonNull Settings settings)
- {
- return NativeConfig.deleteKey(settings.getWriteLayer(), mFile, mSection, mKey);
- }
-
- @Override
- public boolean getBoolean()
- {
- return NativeConfig.getBoolean(NativeConfig.LAYER_ACTIVE, mFile, mSection, mKey, mDefaultValue);
- }
-
- @Override
- public void setBoolean(@NonNull Settings settings, boolean newValue)
- {
- NativeConfig.setBoolean(settings.getWriteLayer(), mFile, mSection, mKey, newValue);
- }
-
- public static boolean getBooleanGlobal(String file, String section, String key,
- boolean defaultValue)
- {
- return NativeConfig.getBoolean(NativeConfig.LAYER_ACTIVE, file, section, key, defaultValue);
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AdHocBooleanSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AdHocBooleanSetting.kt
new file mode 100644
index 0000000000..f62ead3251
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AdHocBooleanSetting.kt
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model
+
+class AdHocBooleanSetting(
+ private val file: String,
+ private val section: String,
+ private val key: String,
+ private val defaultValue: Boolean
+) : AbstractBooleanSetting {
+ init {
+ require(
+ NativeConfig.isSettingSaveable(
+ file,
+ section,
+ key
+ )
+ ) { "File/section/key is unknown or legacy" }
+ }
+
+ override val isOverridden: Boolean
+ get() = NativeConfig.isOverridden(file, section, key)
+
+ override val isRuntimeEditable: Boolean = true
+
+ override fun delete(settings: Settings): Boolean {
+ return NativeConfig.deleteKey(settings.writeLayer, file, section, key)
+ }
+
+ override val boolean: Boolean
+ get() = NativeConfig.getBoolean(NativeConfig.LAYER_ACTIVE, file, section, key, defaultValue)
+
+ override fun setBoolean(settings: Settings, newValue: Boolean) {
+ NativeConfig.setBoolean(settings.writeLayer, file, section, key, newValue)
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AdHocStringSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AdHocStringSetting.java
deleted file mode 100644
index fdba08af71..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AdHocStringSetting.java
+++ /dev/null
@@ -1,61 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model;
-
-import androidx.annotation.NonNull;
-
-public class AdHocStringSetting implements AbstractStringSetting
-{
- private final String mFile;
- private final String mSection;
- private final String mKey;
- private final String mDefaultValue;
-
- public AdHocStringSetting(String file, String section, String key, String defaultValue)
- {
- mFile = file;
- mSection = section;
- mKey = key;
- mDefaultValue = defaultValue;
-
- if (!NativeConfig.isSettingSaveable(file, section, key))
- {
- throw new IllegalArgumentException("File/section/key is unknown or legacy");
- }
- }
-
- @Override
- public boolean isOverridden()
- {
- return NativeConfig.isOverridden(mFile, mSection, mKey);
- }
-
- @Override
- public boolean isRuntimeEditable()
- {
- return true;
- }
-
- @Override
- public boolean delete(@NonNull Settings settings)
- {
- return NativeConfig.deleteKey(settings.getWriteLayer(), mFile, mSection, mKey);
- }
-
- @NonNull @Override
- public String getString()
- {
- return NativeConfig.getString(NativeConfig.LAYER_ACTIVE, mFile, mSection, mKey, mDefaultValue);
- }
-
- @Override
- public void setString(@NonNull Settings settings, @NonNull String newValue)
- {
- NativeConfig.setString(settings.getWriteLayer(), mFile, mSection, mKey, newValue);
- }
-
- public static String getStringGlobal(String file, String section, String key, String defaultValue)
- {
- return NativeConfig.getString(NativeConfig.LAYER_ACTIVE, file, section, key, defaultValue);
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AdHocStringSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AdHocStringSetting.kt
new file mode 100644
index 0000000000..fd416d8905
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AdHocStringSetting.kt
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model
+
+class AdHocStringSetting(
+ private val file: String,
+ private val section: String,
+ private val key: String,
+ private val defaultValue: String
+) : AbstractStringSetting {
+ init {
+ require(
+ NativeConfig.isSettingSaveable(
+ file,
+ section,
+ key
+ )
+ ) { "File/section/key is unknown or legacy" }
+ }
+
+ override val isOverridden: Boolean
+ get() = NativeConfig.isOverridden(file, section, key)
+
+ override val isRuntimeEditable: Boolean = true
+
+ override fun delete(settings: Settings): Boolean {
+ return NativeConfig.deleteKey(settings.writeLayer, file, section, key)
+ }
+
+ override val string: String
+ get() = NativeConfig.getString(NativeConfig.LAYER_ACTIVE, file, section, key, defaultValue)
+
+ override fun setString(settings: Settings, newValue: String) {
+ NativeConfig.setString(settings.writeLayer, file, section, key, newValue)
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.java
deleted file mode 100644
index 581a7a9aab..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.java
+++ /dev/null
@@ -1,371 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model;
-
-import androidx.annotation.NonNull;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
-public enum BooleanSetting implements AbstractBooleanSetting
-{
- // These entries have the same names and order as in C++, just for consistency.
-
- MAIN_SKIP_IPL(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SkipIPL", true),
- MAIN_DSP_HLE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "DSPHLE", true),
- MAIN_FASTMEM(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "Fastmem", true),
- MAIN_CPU_THREAD(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "CPUThread", true),
- MAIN_SYNC_ON_SKIP_IDLE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SyncOnSkipIdle", true),
- MAIN_ENABLE_CHEATS(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "EnableCheats", false),
- MAIN_OVERRIDE_REGION_SETTINGS(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE,
- "OverrideRegionSettings", false),
- MAIN_AUDIO_STRETCH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AudioStretch", false),
- MAIN_BBA_XLINK_CHAT_OSD(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "BBA_XLINK_CHAT_OSD",
- false),
- MAIN_ADAPTER_RUMBLE_0(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AdapterRumble0", true),
- MAIN_ADAPTER_RUMBLE_1(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AdapterRumble1", true),
- MAIN_ADAPTER_RUMBLE_2(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AdapterRumble2", true),
- MAIN_ADAPTER_RUMBLE_3(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AdapterRumble3", true),
- MAIN_SIMULATE_KONGA_0(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SimulateKonga0", false),
- MAIN_SIMULATE_KONGA_1(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SimulateKonga1", false),
- MAIN_SIMULATE_KONGA_2(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SimulateKonga2", false),
- MAIN_SIMULATE_KONGA_3(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SimulateKonga3", false),
- MAIN_WII_SD_CARD(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "WiiSDCard", true),
- MAIN_WII_SD_CARD_ENABLE_FOLDER_SYNC(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE,
- "WiiSDCardEnableFolderSync", false),
- MAIN_WIIMOTE_CONTINUOUS_SCANNING(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE,
- "WiimoteContinuousScanning", false),
- MAIN_WIIMOTE_ENABLE_SPEAKER(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE,
- "WiimoteEnableSpeaker", false),
- MAIN_MMU(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "MMU", false),
- MAIN_PAUSE_ON_PANIC(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "PauseOnPanic", false),
- MAIN_ACCURATE_CPU_CACHE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AccurateCPUCache",
- false),
- MAIN_SYNC_GPU(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SyncGPU", false),
- MAIN_FAST_DISC_SPEED(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "FastDiscSpeed",
- false),
- MAIN_OVERCLOCK_ENABLE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "OverclockEnable", false),
- MAIN_RAM_OVERRIDE_ENABLE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "RAMOverrideEnable",
- false),
- MAIN_CUSTOM_RTC_ENABLE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "EnableCustomRTC",
- false),
- MAIN_AUTO_DISC_CHANGE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AutoDiscChange", false),
- MAIN_ALLOW_SD_WRITES(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "WiiSDCardAllowWrites",
- true),
- MAIN_ENABLE_SAVESTATES(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "EnableSaveStates",
- false),
-
- MAIN_DSP_JIT(Settings.FILE_DOLPHIN, Settings.SECTION_INI_DSP, "EnableJIT", true),
-
- MAIN_EXPAND_TO_CUTOUT_AREA(Settings.FILE_DOLPHIN, Settings.SECTION_INI_INTERFACE,
- "ExpandToCutoutArea", false),
- MAIN_USE_PANIC_HANDLERS(Settings.FILE_DOLPHIN, Settings.SECTION_INI_INTERFACE,
- "UsePanicHandlers", true),
- MAIN_OSD_MESSAGES(Settings.FILE_DOLPHIN, Settings.SECTION_INI_INTERFACE,
- "OnScreenDisplayMessages", true),
-
- MAIN_ANALYTICS_ENABLED(Settings.FILE_DOLPHIN, Settings.SECTION_ANALYTICS, "Enabled", false),
- MAIN_ANALYTICS_PERMISSION_ASKED(Settings.FILE_DOLPHIN, Settings.SECTION_ANALYTICS,
- "PermissionAsked", false),
-
- MAIN_RECURSIVE_ISO_PATHS(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL,
- "RecursiveISOPaths", false),
- MAIN_USE_GAME_COVERS(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL,
- "UseGameCovers", true),
-
- MAIN_DEBUG_JIT_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG, "JitOff", false),
- MAIN_DEBUG_JIT_LOAD_STORE_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG, "JitLoadStoreOff",
- false),
- MAIN_DEBUG_JIT_LOAD_STORE_FLOATING_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG,
- "JitLoadStoreFloatingOff", false),
- MAIN_DEBUG_JIT_LOAD_STORE_PAIRED_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG,
- "JitLoadStorePairedOff", false),
- MAIN_DEBUG_JIT_FLOATING_POINT_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG,
- "JitFloatingPointOff", false),
- MAIN_DEBUG_JIT_INTEGER_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG, "JitIntegerOff", false),
- MAIN_DEBUG_JIT_PAIRED_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG, "JitPairedOff", false),
- MAIN_DEBUG_JIT_SYSTEM_REGISTERS_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG,
- "JitSystemRegistersOff", false),
- MAIN_DEBUG_JIT_BRANCH_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG, "JitBranchOff", false),
- MAIN_DEBUG_JIT_REGISTER_CACHE_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG,
- "JitRegisterCacheOff", false),
-
- MAIN_EMULATE_SKYLANDER_PORTAL(Settings.FILE_DOLPHIN, Settings.SECTION_EMULATED_USB_DEVICES,
- "EmulateSkylanderPortal", false),
-
- MAIN_SHOW_GAME_TITLES(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID,
- "ShowGameTitles", true),
- MAIN_USE_BLACK_BACKGROUNDS(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID,
- "UseBlackBackgrounds", false),
- MAIN_JOYSTICK_REL_CENTER(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID,
- "JoystickRelCenter", true),
- MAIN_SHOW_INPUT_OVERLAY(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID,
- "ShowInputOverlay", true),
- MAIN_IR_ALWAYS_RECENTER(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID,
- "IRAlwaysRecenter", false),
-
- MAIN_BUTTON_TOGGLE_GC_0(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleGCButtonA", true),
- MAIN_BUTTON_TOGGLE_GC_1(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleGCButtonB", true),
- MAIN_BUTTON_TOGGLE_GC_2(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleGCButtonX", true),
- MAIN_BUTTON_TOGGLE_GC_3(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleGCButtonY", true),
- MAIN_BUTTON_TOGGLE_GC_4(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleGCButtonZ", true),
- MAIN_BUTTON_TOGGLE_GC_5(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleGCButtonStart", true),
- MAIN_BUTTON_TOGGLE_GC_6(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleGCTriggerL", true),
- MAIN_BUTTON_TOGGLE_GC_7(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleGCTriggerR", true),
- MAIN_BUTTON_TOGGLE_GC_8(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleGCDPad", true),
- MAIN_BUTTON_TOGGLE_GC_9(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleGCStickMain", true),
- MAIN_BUTTON_TOGGLE_GC_10(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleGCStickC", true),
- MAIN_BUTTON_TOGGLE_CLASSIC_0(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleClassicButtonA", true),
- MAIN_BUTTON_TOGGLE_CLASSIC_1(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleClassicButtonB", true),
- MAIN_BUTTON_TOGGLE_CLASSIC_2(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleClassicButtonX", true),
- MAIN_BUTTON_TOGGLE_CLASSIC_3(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleClassicButtonY", true),
- MAIN_BUTTON_TOGGLE_CLASSIC_4(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleClassicButtonPlus", true),
- MAIN_BUTTON_TOGGLE_CLASSIC_5(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleClassicButtonMinus", true),
- MAIN_BUTTON_TOGGLE_CLASSIC_6(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleClassicButtonHome", true),
- MAIN_BUTTON_TOGGLE_CLASSIC_7(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleClassicTriggerL", true),
- MAIN_BUTTON_TOGGLE_CLASSIC_8(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleClassicTriggerR", true),
- MAIN_BUTTON_TOGGLE_CLASSIC_9(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleClassicButtonZL", true),
- MAIN_BUTTON_TOGGLE_CLASSIC_10(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleClassicButtonZR", true),
- MAIN_BUTTON_TOGGLE_CLASSIC_11(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleClassicDPad", true),
- MAIN_BUTTON_TOGGLE_CLASSIC_12(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleClassicStickLeft", true),
- MAIN_BUTTON_TOGGLE_CLASSIC_13(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleClassicStickRight", true),
- MAIN_BUTTON_TOGGLE_WII_0(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleWiimoteButtonA", true),
- MAIN_BUTTON_TOGGLE_WII_1(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleWiimoteButtonB", true),
- MAIN_BUTTON_TOGGLE_WII_2(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleWiimoteButton1", true),
- MAIN_BUTTON_TOGGLE_WII_3(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleWiimoteButton2", true),
- MAIN_BUTTON_TOGGLE_WII_4(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleWiimoteButtonPlus", true),
- MAIN_BUTTON_TOGGLE_WII_5(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleWiimoteButtonMinus", true),
- MAIN_BUTTON_TOGGLE_WII_6(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleWiimoteButtonHome", true),
- MAIN_BUTTON_TOGGLE_WII_7(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleWiimoteDPad", true),
- MAIN_BUTTON_TOGGLE_WII_8(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleNunchukC", true),
- MAIN_BUTTON_TOGGLE_WII_9(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleNunchukZ", true),
- MAIN_BUTTON_TOGGLE_WII_10(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "ButtonToggleNunchukStick", true),
-
- SYSCONF_SCREENSAVER(Settings.FILE_SYSCONF, "IPL", "SSV", false),
- SYSCONF_WIDESCREEN(Settings.FILE_SYSCONF, "IPL", "AR", true),
- SYSCONF_PROGRESSIVE_SCAN(Settings.FILE_SYSCONF, "IPL", "PGS", true),
- SYSCONF_PAL60(Settings.FILE_SYSCONF, "IPL", "E60", true),
-
- SYSCONF_WIIMOTE_MOTOR(Settings.FILE_SYSCONF, "BT", "MOT", true),
-
- GFX_WIDESCREEN_HACK(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "wideScreenHack", false),
- GFX_CROP(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "Crop", false),
- GFX_SHOW_FPS(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowFPS", false),
- GFX_SHOW_FTIMES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowFTimes", false),
- GFX_SHOW_VPS(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowVPS", false),
- GFX_SHOW_VTIMES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowVTimes", false),
- GFX_SHOW_GRAPHS(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowGraphs", false),
- GFX_SHOW_SPEED(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowSpeed", false),
- GFX_SHOW_SPEED_COLORS(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowSpeedColors", true),
- GFX_LOG_RENDER_TIME_TO_FILE(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
- "LogRenderTimeToFile", false),
- GFX_OVERLAY_STATS(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "OverlayStats", false),
- GFX_DUMP_TEXTURES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "DumpTextures", false),
- GFX_DUMP_MIP_TEXTURES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "DumpMipTextures", false),
- GFX_DUMP_BASE_TEXTURES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "DumpBaseTextures",
- false),
- GFX_HIRES_TEXTURES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "HiresTextures", false),
- GFX_CACHE_HIRES_TEXTURES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "CacheHiresTextures",
- false),
- GFX_DUMP_EFB_TARGET(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "DumpEFBTarget", false),
- GFX_DUMP_XFB_TARGET(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "DumpXFBTarget", false),
- GFX_INTERNAL_RESOLUTION_FRAME_DUMPS(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
- "InternalResolutionFrameDumps", false),
- GFX_ENABLE_GPU_TEXTURE_DECODING(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
- "EnableGPUTextureDecoding", false),
- GFX_ENABLE_PIXEL_LIGHTING(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
- "EnablePixelLighting", false),
- GFX_FAST_DEPTH_CALC(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "FastDepthCalc", true),
- GFX_TEXFMT_OVERLAY_ENABLE(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "TexFmtOverlayEnable",
- false),
- GFX_ENABLE_WIREFRAME(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "WireFrame", false),
- GFX_DISABLE_FOG(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "DisableFog", false),
- GFX_ENABLE_VALIDATION_LAYER(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
- "EnableValidationLayer", false),
- GFX_BACKEND_MULTITHREADING(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
- "BackendMultithreading", true),
- GFX_WAIT_FOR_SHADERS_BEFORE_STARTING(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
- "WaitForShadersBeforeStarting", false),
- GFX_SAVE_TEXTURE_CACHE_TO_STATE(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
- "SaveTextureCacheToState", true),
- GFX_PREFER_VS_FOR_LINE_POINT_EXPANSION(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
- "PreferVSForLinePointExpansion", false),
- GFX_CPU_CULL(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "CPUCull", false),
- GFX_MODS_ENABLE(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "EnableMods", false),
-
- GFX_ENHANCE_FORCE_TRUE_COLOR(Settings.FILE_GFX, Settings.SECTION_GFX_ENHANCEMENTS,
- "ForceTrueColor", true),
- GFX_ENHANCE_DISABLE_COPY_FILTER(Settings.FILE_GFX, Settings.SECTION_GFX_ENHANCEMENTS,
- "DisableCopyFilter", true),
- GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION(Settings.FILE_GFX, Settings.SECTION_GFX_ENHANCEMENTS,
- "ArbitraryMipmapDetection", true),
-
- GFX_STEREO_SWAP_EYES(Settings.FILE_GFX, Settings.SECTION_STEREOSCOPY, "StereoSwapEyes", false),
-
- GFX_HACK_EFB_ACCESS_ENABLE(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "EFBAccessEnable",
- true),
- GFX_HACK_EFB_DEFER_INVALIDATION(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS,
- "EFBAccessDeferInvalidation", false),
- GFX_HACK_BBOX_ENABLE(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "BBoxEnable", false),
- GFX_HACK_SKIP_EFB_COPY_TO_RAM(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS,
- "EFBToTextureEnable", true),
- GFX_HACK_SKIP_XFB_COPY_TO_RAM(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS,
- "XFBToTextureEnable", true),
- GFX_HACK_DISABLE_COPY_TO_VRAM(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "DisableCopyToVRAM",
- false),
- GFX_HACK_DEFER_EFB_COPIES(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "DeferEFBCopies", true),
- GFX_HACK_IMMEDIATE_XFB(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "ImmediateXFBEnable",
- false),
- GFX_HACK_SKIP_DUPLICATE_XFBS(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "SkipDuplicateXFBs",
- true),
- GFX_HACK_COPY_EFB_SCALED(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "EFBScaledCopy", true),
- GFX_HACK_EFB_EMULATE_FORMAT_CHANGES(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS,
- "EFBEmulateFormatChanges", false),
- GFX_HACK_VERTEX_ROUNDING(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "VertexRounding", false),
- GFX_HACK_VI_SKIP(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "VISkip", false),
- GFX_HACK_FAST_TEXTURE_SAMPLING(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS,
- "FastTextureSampling", true),
-
- LOGGER_WRITE_TO_FILE(Settings.FILE_LOGGER, Settings.SECTION_LOGGER_OPTIONS, "WriteToFile", false);
-
- private static final BooleanSetting[] NOT_RUNTIME_EDITABLE_ARRAY = new BooleanSetting[]{
- MAIN_DSP_HLE,
- MAIN_CPU_THREAD,
- MAIN_ENABLE_CHEATS,
- MAIN_OVERRIDE_REGION_SETTINGS,
- MAIN_MMU,
- MAIN_PAUSE_ON_PANIC,
- MAIN_ACCURATE_CPU_CACHE,
- MAIN_RAM_OVERRIDE_ENABLE,
- MAIN_CUSTOM_RTC_ENABLE,
- MAIN_DSP_JIT,
- MAIN_EMULATE_SKYLANDER_PORTAL,
- };
-
- private static final Set<BooleanSetting> NOT_RUNTIME_EDITABLE =
- new HashSet<>(Arrays.asList(NOT_RUNTIME_EDITABLE_ARRAY));
-
- private final String mFile;
- private final String mSection;
- private final String mKey;
- private final boolean mDefaultValue;
-
- BooleanSetting(String file, String section, String key, boolean defaultValue)
- {
- mFile = file;
- mSection = section;
- mKey = key;
- mDefaultValue = defaultValue;
- }
-
- @Override
- public boolean isOverridden()
- {
- return NativeConfig.isOverridden(mFile, mSection, mKey);
- }
-
- @Override
- public boolean isRuntimeEditable()
- {
- if (mFile.equals(Settings.FILE_SYSCONF))
- return false;
-
- for (BooleanSetting setting : NOT_RUNTIME_EDITABLE)
- {
- if (setting == this)
- return false;
- }
-
- return NativeConfig.isSettingSaveable(mFile, mSection, mKey);
- }
-
- @Override
- public boolean delete(@NonNull Settings settings)
- {
- if (!NativeConfig.isSettingSaveable(mFile, mSection, mKey))
- {
- throw new UnsupportedOperationException(
- "Unsupported setting: " + mFile + ", " + mSection + ", " + mKey);
- }
-
- return NativeConfig.deleteKey(settings.getWriteLayer(), mFile, mSection, mKey);
- }
-
- @Override
- public boolean getBoolean()
- {
- return NativeConfig.getBoolean(NativeConfig.LAYER_ACTIVE, mFile, mSection, mKey, mDefaultValue);
- }
-
- @Override
- public void setBoolean(@NonNull Settings settings, boolean newValue)
- {
- if (!NativeConfig.isSettingSaveable(mFile, mSection, mKey))
- {
- throw new UnsupportedOperationException(
- "Unsupported setting: " + mFile + ", " + mSection + ", " + mKey);
- }
-
- NativeConfig.setBoolean(settings.getWriteLayer(), mFile, mSection, mKey, newValue);
- }
-
- public void setBoolean(int layer, boolean newValue)
- {
- if (!NativeConfig.isSettingSaveable(mFile, mSection, mKey))
- {
- throw new UnsupportedOperationException(
- "Unsupported setting: " + mFile + ", " + mSection + ", " + mKey);
- }
-
- NativeConfig.setBoolean(layer, mFile, mSection, mKey, newValue);
- }
-
- public static BooleanSetting getSettingForAdapterRumble(int channel)
- {
- return new BooleanSetting[]{MAIN_ADAPTER_RUMBLE_0, MAIN_ADAPTER_RUMBLE_1, MAIN_ADAPTER_RUMBLE_2,
- MAIN_ADAPTER_RUMBLE_3}[channel];
- }
-
- public static BooleanSetting getSettingForSimulateKonga(int channel)
- {
- return new BooleanSetting[]{MAIN_SIMULATE_KONGA_0, MAIN_SIMULATE_KONGA_1, MAIN_SIMULATE_KONGA_2,
- MAIN_SIMULATE_KONGA_3}[channel];
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.kt
new file mode 100644
index 0000000000..e59cb8a097
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.kt
@@ -0,0 +1,747 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model
+
+import java.util.*
+
+enum class BooleanSetting(
+ private val file: String,
+ private val section: String,
+ private val key: String,
+ private val defaultValue: Boolean
+) : AbstractBooleanSetting {
+ // These entries have the same names and order as in C++, just for consistency.
+ MAIN_SKIP_IPL(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SkipIPL", true),
+ MAIN_DSP_HLE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "DSPHLE", true),
+ MAIN_FASTMEM(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "Fastmem", true),
+ MAIN_CPU_THREAD(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "CPUThread", true),
+ MAIN_SYNC_ON_SKIP_IDLE(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "SyncOnSkipIdle",
+ true
+ ),
+ MAIN_ENABLE_CHEATS(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "EnableCheats", false),
+ MAIN_OVERRIDE_REGION_SETTINGS(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "OverrideRegionSettings",
+ false
+ ),
+ MAIN_AUDIO_STRETCH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AudioStretch", false),
+ MAIN_BBA_XLINK_CHAT_OSD(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "BBA_XLINK_CHAT_OSD",
+ false
+ ),
+ MAIN_ADAPTER_RUMBLE_0(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AdapterRumble0", true),
+ MAIN_ADAPTER_RUMBLE_1(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AdapterRumble1", true),
+ MAIN_ADAPTER_RUMBLE_2(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AdapterRumble2", true),
+ MAIN_ADAPTER_RUMBLE_3(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "AdapterRumble3", true),
+ MAIN_SIMULATE_KONGA_0(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "SimulateKonga0",
+ false
+ ),
+ MAIN_SIMULATE_KONGA_1(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "SimulateKonga1",
+ false
+ ),
+ MAIN_SIMULATE_KONGA_2(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "SimulateKonga2",
+ false
+ ),
+ MAIN_SIMULATE_KONGA_3(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "SimulateKonga3",
+ false
+ ),
+ MAIN_WII_SD_CARD(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "WiiSDCard", true),
+ MAIN_WII_SD_CARD_ENABLE_FOLDER_SYNC(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "WiiSDCardEnableFolderSync",
+ false
+ ),
+ MAIN_WIIMOTE_CONTINUOUS_SCANNING(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "WiimoteContinuousScanning",
+ false
+ ),
+ MAIN_WIIMOTE_ENABLE_SPEAKER(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "WiimoteEnableSpeaker",
+ false
+ ),
+ MAIN_MMU(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "MMU", false),
+ MAIN_PAUSE_ON_PANIC(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "PauseOnPanic", false),
+ MAIN_ACCURATE_CPU_CACHE(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "AccurateCPUCache",
+ false
+ ),
+ MAIN_SYNC_GPU(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SyncGPU", false),
+ MAIN_FAST_DISC_SPEED(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "FastDiscSpeed", false),
+ MAIN_OVERCLOCK_ENABLE(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "OverclockEnable",
+ false
+ ),
+ MAIN_RAM_OVERRIDE_ENABLE(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "RAMOverrideEnable",
+ false
+ ),
+ MAIN_CUSTOM_RTC_ENABLE(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "EnableCustomRTC",
+ false
+ ),
+ MAIN_AUTO_DISC_CHANGE(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "AutoDiscChange",
+ false
+ ),
+ MAIN_ALLOW_SD_WRITES(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "WiiSDCardAllowWrites",
+ true
+ ),
+ MAIN_ENABLE_SAVESTATES(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "EnableSaveStates",
+ false
+ ),
+ MAIN_DSP_JIT(Settings.FILE_DOLPHIN, Settings.SECTION_INI_DSP, "EnableJIT", true),
+ MAIN_EXPAND_TO_CUTOUT_AREA(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_INTERFACE,
+ "ExpandToCutoutArea",
+ false
+ ),
+ MAIN_USE_PANIC_HANDLERS(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_INTERFACE,
+ "UsePanicHandlers",
+ true
+ ),
+ MAIN_OSD_MESSAGES(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_INTERFACE,
+ "OnScreenDisplayMessages",
+ true
+ ),
+ MAIN_ANALYTICS_ENABLED(Settings.FILE_DOLPHIN, Settings.SECTION_ANALYTICS, "Enabled", false),
+ MAIN_ANALYTICS_PERMISSION_ASKED(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_ANALYTICS,
+ "PermissionAsked",
+ false
+ ),
+ MAIN_RECURSIVE_ISO_PATHS(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_GENERAL,
+ "RecursiveISOPaths",
+ false
+ ),
+ MAIN_USE_GAME_COVERS(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_GENERAL,
+ "UseGameCovers",
+ true
+ ),
+ MAIN_DEBUG_JIT_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG, "JitOff", false),
+ MAIN_DEBUG_JIT_LOAD_STORE_OFF(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_DEBUG,
+ "JitLoadStoreOff",
+ false
+ ),
+ MAIN_DEBUG_JIT_LOAD_STORE_FLOATING_OFF(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_DEBUG,
+ "JitLoadStoreFloatingOff",
+ false
+ ),
+ MAIN_DEBUG_JIT_LOAD_STORE_PAIRED_OFF(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_DEBUG,
+ "JitLoadStorePairedOff",
+ false
+ ),
+ MAIN_DEBUG_JIT_FLOATING_POINT_OFF(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_DEBUG,
+ "JitFloatingPointOff",
+ false
+ ),
+ MAIN_DEBUG_JIT_INTEGER_OFF(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_DEBUG,
+ "JitIntegerOff",
+ false
+ ),
+ MAIN_DEBUG_JIT_PAIRED_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG, "JitPairedOff", false),
+ MAIN_DEBUG_JIT_SYSTEM_REGISTERS_OFF(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_DEBUG,
+ "JitSystemRegistersOff",
+ false
+ ),
+ MAIN_DEBUG_JIT_BRANCH_OFF(Settings.FILE_DOLPHIN, Settings.SECTION_DEBUG, "JitBranchOff", false),
+ MAIN_DEBUG_JIT_REGISTER_CACHE_OFF(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_DEBUG,
+ "JitRegisterCacheOff",
+ false
+ ),
+ MAIN_EMULATE_SKYLANDER_PORTAL(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_EMULATED_USB_DEVICES,
+ "EmulateSkylanderPortal",
+ false
+ ),
+ MAIN_SHOW_GAME_TITLES(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID,
+ "ShowGameTitles",
+ true
+ ),
+ MAIN_USE_BLACK_BACKGROUNDS(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID,
+ "UseBlackBackgrounds",
+ false
+ ),
+ MAIN_JOYSTICK_REL_CENTER(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID,
+ "JoystickRelCenter",
+ true
+ ),
+ MAIN_SHOW_INPUT_OVERLAY(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID,
+ "ShowInputOverlay",
+ true
+ ),
+ MAIN_IR_ALWAYS_RECENTER(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID,
+ "IRAlwaysRecenter",
+ false
+ ),
+ MAIN_BUTTON_TOGGLE_GC_0(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleGCButtonA",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_GC_1(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleGCButtonB",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_GC_2(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleGCButtonX",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_GC_3(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleGCButtonY",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_GC_4(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleGCButtonZ",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_GC_5(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleGCButtonStart",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_GC_6(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleGCTriggerL",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_GC_7(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleGCTriggerR",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_GC_8(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleGCDPad",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_GC_9(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleGCStickMain",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_GC_10(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleGCStickC",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_CLASSIC_0(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleClassicButtonA",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_CLASSIC_1(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleClassicButtonB",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_CLASSIC_2(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleClassicButtonX",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_CLASSIC_3(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleClassicButtonY",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_CLASSIC_4(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleClassicButtonPlus",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_CLASSIC_5(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleClassicButtonMinus",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_CLASSIC_6(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleClassicButtonHome",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_CLASSIC_7(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleClassicTriggerL",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_CLASSIC_8(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleClassicTriggerR",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_CLASSIC_9(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleClassicButtonZL",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_CLASSIC_10(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleClassicButtonZR",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_CLASSIC_11(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleClassicDPad",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_CLASSIC_12(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleClassicStickLeft",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_CLASSIC_13(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleClassicStickRight",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_WII_0(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleWiimoteButtonA",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_WII_1(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleWiimoteButtonB",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_WII_2(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleWiimoteButton1",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_WII_3(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleWiimoteButton2",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_WII_4(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleWiimoteButtonPlus",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_WII_5(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleWiimoteButtonMinus",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_WII_6(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleWiimoteButtonHome",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_WII_7(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleWiimoteDPad",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_WII_8(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleNunchukC",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_WII_9(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleNunchukZ",
+ true
+ ),
+ MAIN_BUTTON_TOGGLE_WII_10(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "ButtonToggleNunchukStick",
+ true
+ ),
+ SYSCONF_SCREENSAVER(Settings.FILE_SYSCONF, "IPL", "SSV", false),
+ SYSCONF_WIDESCREEN(Settings.FILE_SYSCONF, "IPL", "AR", true),
+ SYSCONF_PROGRESSIVE_SCAN(Settings.FILE_SYSCONF, "IPL", "PGS", true),
+ SYSCONF_PAL60(Settings.FILE_SYSCONF, "IPL", "E60", true),
+ SYSCONF_WIIMOTE_MOTOR(Settings.FILE_SYSCONF, "BT", "MOT", true),
+ GFX_WIDESCREEN_HACK(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "wideScreenHack", false),
+ GFX_CROP(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "Crop", false),
+ GFX_SHOW_FPS(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowFPS", false),
+ GFX_SHOW_FTIMES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowFTimes", false),
+ GFX_SHOW_VPS(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowVPS", false),
+ GFX_SHOW_VTIMES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowVTimes", false),
+ GFX_SHOW_GRAPHS(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowGraphs", false),
+ GFX_SHOW_SPEED(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "ShowSpeed", false),
+ GFX_SHOW_SPEED_COLORS(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_SETTINGS,
+ "ShowSpeedColors",
+ true
+ ),
+ GFX_LOG_RENDER_TIME_TO_FILE(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_SETTINGS,
+ "LogRenderTimeToFile",
+ false
+ ),
+ GFX_OVERLAY_STATS(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "OverlayStats", false),
+ GFX_DUMP_TEXTURES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "DumpTextures", false),
+ GFX_DUMP_MIP_TEXTURES(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_SETTINGS,
+ "DumpMipTextures",
+ false
+ ),
+ GFX_DUMP_BASE_TEXTURES(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_SETTINGS,
+ "DumpBaseTextures",
+ false
+ ),
+ GFX_HIRES_TEXTURES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "HiresTextures", false),
+ GFX_CACHE_HIRES_TEXTURES(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_SETTINGS,
+ "CacheHiresTextures",
+ false
+ ),
+ GFX_DUMP_EFB_TARGET(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "DumpEFBTarget", false),
+ GFX_DUMP_XFB_TARGET(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "DumpXFBTarget", false),
+ GFX_INTERNAL_RESOLUTION_FRAME_DUMPS(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_SETTINGS,
+ "InternalResolutionFrameDumps",
+ false
+ ),
+ GFX_ENABLE_GPU_TEXTURE_DECODING(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_SETTINGS,
+ "EnableGPUTextureDecoding",
+ false
+ ),
+ GFX_ENABLE_PIXEL_LIGHTING(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_SETTINGS,
+ "EnablePixelLighting",
+ false
+ ),
+ GFX_FAST_DEPTH_CALC(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "FastDepthCalc", true),
+ GFX_TEXFMT_OVERLAY_ENABLE(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_SETTINGS,
+ "TexFmtOverlayEnable",
+ false
+ ),
+ GFX_ENABLE_WIREFRAME(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "WireFrame", false),
+ GFX_DISABLE_FOG(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "DisableFog", false),
+ GFX_ENABLE_VALIDATION_LAYER(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_SETTINGS,
+ "EnableValidationLayer",
+ false
+ ),
+ GFX_BACKEND_MULTITHREADING(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_SETTINGS,
+ "BackendMultithreading",
+ true
+ ),
+ GFX_WAIT_FOR_SHADERS_BEFORE_STARTING(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_SETTINGS,
+ "WaitForShadersBeforeStarting",
+ false
+ ),
+ GFX_SAVE_TEXTURE_CACHE_TO_STATE(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_SETTINGS,
+ "SaveTextureCacheToState",
+ true
+ ),
+ GFX_PREFER_VS_FOR_LINE_POINT_EXPANSION(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_SETTINGS,
+ "PreferVSForLinePointExpansion",
+ false
+ ),
+ GFX_CPU_CULL(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "CPUCull", false),
+ GFX_MODS_ENABLE(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "EnableMods", false),
+ GFX_ENHANCE_FORCE_TRUE_COLOR(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_ENHANCEMENTS,
+ "ForceTrueColor",
+ true
+ ),
+ GFX_ENHANCE_DISABLE_COPY_FILTER(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_ENHANCEMENTS,
+ "DisableCopyFilter",
+ true
+ ),
+ GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_ENHANCEMENTS,
+ "ArbitraryMipmapDetection",
+ true
+ ),
+ GFX_STEREO_SWAP_EYES(Settings.FILE_GFX, Settings.SECTION_STEREOSCOPY, "StereoSwapEyes", false),
+ GFX_HACK_EFB_ACCESS_ENABLE(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_HACKS,
+ "EFBAccessEnable",
+ true
+ ),
+ GFX_HACK_EFB_DEFER_INVALIDATION(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_HACKS,
+ "EFBAccessDeferInvalidation",
+ false
+ ),
+ GFX_HACK_BBOX_ENABLE(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "BBoxEnable", false),
+ GFX_HACK_SKIP_EFB_COPY_TO_RAM(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_HACKS,
+ "EFBToTextureEnable",
+ true
+ ),
+ GFX_HACK_SKIP_XFB_COPY_TO_RAM(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_HACKS,
+ "XFBToTextureEnable",
+ true
+ ),
+ GFX_HACK_DISABLE_COPY_TO_VRAM(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_HACKS,
+ "DisableCopyToVRAM",
+ false
+ ),
+ GFX_HACK_DEFER_EFB_COPIES(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_HACKS,
+ "DeferEFBCopies",
+ true
+ ),
+ GFX_HACK_IMMEDIATE_XFB(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_HACKS,
+ "ImmediateXFBEnable",
+ false
+ ),
+ GFX_HACK_SKIP_DUPLICATE_XFBS(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_HACKS,
+ "SkipDuplicateXFBs",
+ true
+ ),
+ GFX_HACK_COPY_EFB_SCALED(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "EFBScaledCopy", true),
+ GFX_HACK_EFB_EMULATE_FORMAT_CHANGES(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_HACKS,
+ "EFBEmulateFormatChanges",
+ false
+ ),
+ GFX_HACK_VERTEX_ROUNDING(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_HACKS,
+ "VertexRounding",
+ false
+ ),
+ GFX_HACK_VI_SKIP(Settings.FILE_GFX, Settings.SECTION_GFX_HACKS, "VISkip", false),
+ GFX_HACK_FAST_TEXTURE_SAMPLING(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_HACKS,
+ "FastTextureSampling",
+ true
+ ),
+ LOGGER_WRITE_TO_FILE(
+ Settings.FILE_LOGGER,
+ Settings.SECTION_LOGGER_OPTIONS,
+ "WriteToFile",
+ false
+ );
+
+ override val isOverridden: Boolean
+ get() = NativeConfig.isOverridden(file, section, key)
+
+ override val isRuntimeEditable: Boolean
+ get() {
+ if (file == Settings.FILE_SYSCONF) return false
+ for (setting in NOT_RUNTIME_EDITABLE) {
+ if (setting == this) return false
+ }
+ return NativeConfig.isSettingSaveable(file, section, key)
+ }
+
+ override fun delete(settings: Settings): Boolean {
+ if (!NativeConfig.isSettingSaveable(file, section, key)) {
+ throw UnsupportedOperationException("Unsupported setting: $file, $section, $key")
+ }
+ return NativeConfig.deleteKey(settings.writeLayer, file, section, key)
+ }
+
+ override val boolean: Boolean
+ get() = NativeConfig.getBoolean(
+ NativeConfig.LAYER_ACTIVE,
+ file,
+ section,
+ key,
+ defaultValue
+ )
+
+ override fun setBoolean(settings: Settings, newValue: Boolean) {
+ if (!NativeConfig.isSettingSaveable(file, section, key)) {
+ throw UnsupportedOperationException("Unsupported setting: $file, $section, $key")
+ }
+ NativeConfig.setBoolean(settings.writeLayer, file, section, key, newValue)
+ }
+
+ fun setBoolean(layer: Int, newValue: Boolean) {
+ if (!NativeConfig.isSettingSaveable(file, section, key)) {
+ throw UnsupportedOperationException("Unsupported setting: $file, $section, $key")
+ }
+ NativeConfig.setBoolean(layer, file, section, key, newValue)
+ }
+
+ companion object {
+ private val NOT_RUNTIME_EDITABLE_ARRAY = arrayOf(
+ MAIN_DSP_HLE,
+ MAIN_CPU_THREAD,
+ MAIN_ENABLE_CHEATS,
+ MAIN_OVERRIDE_REGION_SETTINGS,
+ MAIN_MMU,
+ MAIN_PAUSE_ON_PANIC,
+ MAIN_ACCURATE_CPU_CACHE,
+ MAIN_RAM_OVERRIDE_ENABLE,
+ MAIN_CUSTOM_RTC_ENABLE,
+ MAIN_DSP_JIT,
+ MAIN_EMULATE_SKYLANDER_PORTAL
+ )
+ private val NOT_RUNTIME_EDITABLE: Set<BooleanSetting> =
+ HashSet(listOf(*NOT_RUNTIME_EDITABLE_ARRAY))
+
+ @JvmStatic
+ fun getSettingForAdapterRumble(channel: Int): BooleanSetting {
+ return arrayOf(
+ MAIN_ADAPTER_RUMBLE_0,
+ MAIN_ADAPTER_RUMBLE_1,
+ MAIN_ADAPTER_RUMBLE_2,
+ MAIN_ADAPTER_RUMBLE_3
+ )[channel]
+ }
+
+ @JvmStatic
+ fun getSettingForSimulateKonga(channel: Int): BooleanSetting {
+ return arrayOf(
+ MAIN_SIMULATE_KONGA_0,
+ MAIN_SIMULATE_KONGA_1,
+ MAIN_SIMULATE_KONGA_2,
+ MAIN_SIMULATE_KONGA_3
+ )[channel]
+ }
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/FloatSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/FloatSetting.java
deleted file mode 100644
index 99d15957c4..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/FloatSetting.java
+++ /dev/null
@@ -1,73 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model;
-
-import androidx.annotation.NonNull;
-
-public enum FloatSetting implements AbstractFloatSetting
-{
- // These entries have the same names and order as in C++, just for consistency.
-
- MAIN_EMULATION_SPEED(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "EmulationSpeed", 1.0f),
- MAIN_OVERCLOCK(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "Overclock", 1.0f);
-
- private final String mFile;
- private final String mSection;
- private final String mKey;
- private final float mDefaultValue;
-
- FloatSetting(String file, String section, String key, float defaultValue)
- {
- mFile = file;
- mSection = section;
- mKey = key;
- mDefaultValue = defaultValue;
- }
-
- @Override
- public boolean isOverridden()
- {
- return NativeConfig.isOverridden(mFile, mSection, mKey);
- }
-
- @Override
- public boolean isRuntimeEditable()
- {
- return NativeConfig.isSettingSaveable(mFile, mSection, mKey);
- }
-
- @Override
- public boolean delete(@NonNull Settings settings)
- {
- if (!NativeConfig.isSettingSaveable(mFile, mSection, mKey))
- {
- throw new UnsupportedOperationException(
- "Unsupported setting: " + mFile + ", " + mSection + ", " + mKey);
- }
-
- return NativeConfig.deleteKey(settings.getWriteLayer(), mFile, mSection, mKey);
- }
-
- @Override
- public float getFloat()
- {
- return NativeConfig.getFloat(NativeConfig.LAYER_ACTIVE, mFile, mSection, mKey, mDefaultValue);
- }
-
- @Override
- public void setFloat(@NonNull Settings settings, float newValue)
- {
- if (!NativeConfig.isSettingSaveable(mFile, mSection, mKey))
- {
- throw new UnsupportedOperationException(
- "Unsupported setting: " + mFile + ", " + mSection + ", " + mKey);
- }
-
- NativeConfig.setFloat(settings.getWriteLayer(), mFile, mSection, mKey, newValue);
- }
-
- public void setFloat(int layer, float newValue)
- {
- NativeConfig.setFloat(layer, mFile, mSection, mKey, newValue);
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/FloatSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/FloatSetting.kt
new file mode 100644
index 0000000000..99b73251e7
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/FloatSetting.kt
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model
+
+enum class FloatSetting(
+ private val file: String,
+ private val section: String,
+ private val key: String,
+ private val defaultValue: Float
+) : AbstractFloatSetting {
+ // These entries have the same names and order as in C++, just for consistency.
+ MAIN_EMULATION_SPEED(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "EmulationSpeed", 1.0f),
+ MAIN_OVERCLOCK(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "Overclock", 1.0f);
+
+ override val isOverridden: Boolean
+ get() = NativeConfig.isOverridden(file, section, key)
+
+ override val isRuntimeEditable: Boolean
+ get() = NativeConfig.isSettingSaveable(file, section, key)
+
+ override fun delete(settings: Settings): Boolean {
+ if (!NativeConfig.isSettingSaveable(file, section, key)) {
+ throw UnsupportedOperationException("Unsupported setting: $file, $section, $key")
+ }
+ return NativeConfig.deleteKey(settings.writeLayer, file, section, key)
+ }
+
+ override val float: Float
+ get() = NativeConfig.getFloat(NativeConfig.LAYER_ACTIVE, file, section, key, defaultValue)
+
+ override fun setFloat(settings: Settings, newValue: Float) {
+ if (!NativeConfig.isSettingSaveable(file, section, key)) {
+ throw UnsupportedOperationException("Unsupported setting: $file, $section, $key")
+ }
+ NativeConfig.setFloat(settings.writeLayer, file, section, key, newValue)
+ }
+
+ fun setFloat(layer: Int, newValue: Float) {
+ NativeConfig.setFloat(layer, file, section, key, newValue)
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/IntSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/IntSetting.java
deleted file mode 100644
index df562c6998..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/IntSetting.java
+++ /dev/null
@@ -1,196 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model;
-
-import android.content.pm.ActivityInfo;
-
-import androidx.annotation.NonNull;
-
-import org.dolphinemu.dolphinemu.NativeLibrary;
-import org.dolphinemu.dolphinemu.overlay.InputOverlayPointer;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
-public enum IntSetting implements AbstractIntSetting
-{
- // These entries have the same names and order as in C++, just for consistency.
-
- MAIN_CPU_CORE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "CPUCore",
- NativeLibrary.DefaultCPUCore()),
- MAIN_GC_LANGUAGE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SelectedLanguage", 0),
- MAIN_MEM1_SIZE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "MEM1Size", 0x01800000),
- MAIN_MEM2_SIZE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "MEM2Size", 0x04000000),
- MAIN_SLOT_A(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SlotA", 8),
- MAIN_SLOT_B(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SlotB", 255),
- MAIN_SERIAL_PORT_1(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SerialPort1", 255),
- MAIN_FALLBACK_REGION(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "FallbackRegion", 2),
- MAIN_SI_DEVICE_0(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SIDevice0", 6),
- MAIN_SI_DEVICE_1(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SIDevice1", 0),
- MAIN_SI_DEVICE_2(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SIDevice2", 0),
- MAIN_SI_DEVICE_3(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SIDevice3", 0),
-
- MAIN_AUDIO_VOLUME(Settings.FILE_DOLPHIN, Settings.SECTION_INI_DSP, "Volume", 100),
-
- MAIN_OVERLAY_GC_CONTROLLER(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID,
- "OverlayGCController", 0), // Defaults to GameCube controller 1
- MAIN_OVERLAY_WII_CONTROLLER(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID,
- "OverlayWiiController", 4), // Defaults to Wii Remote 1
- MAIN_CONTROL_SCALE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "ControlScale", 50),
- MAIN_CONTROL_OPACITY(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "ControlOpacity", 65),
- MAIN_EMULATION_ORIENTATION(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID,
- "EmulationOrientation", ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE),
- MAIN_INTERFACE_THEME(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "InterfaceTheme", 0),
- MAIN_INTERFACE_THEME_MODE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID,
- "InterfaceThemeMode", -1),
- MAIN_LAST_PLATFORM_TAB(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "LastPlatformTab", 0),
- MAIN_IR_MODE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "IRMode",
- InputOverlayPointer.MODE_FOLLOW),
-
- MAIN_DOUBLE_TAP_BUTTON(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
- "DoubleTapButton", NativeLibrary.ButtonType.WIIMOTE_BUTTON_A),
-
- SYSCONF_LANGUAGE(Settings.FILE_SYSCONF, "IPL", "LNG", 0x01),
- SYSCONF_SOUND_MODE(Settings.FILE_SYSCONF, "IPL", "SND", 0x01),
-
- SYSCONF_SENSOR_BAR_POSITION(Settings.FILE_SYSCONF, "BT", "BAR", 0x01),
- SYSCONF_SENSOR_BAR_SENSITIVITY(Settings.FILE_SYSCONF, "BT", "SENS", 0x03),
- SYSCONF_SPEAKER_VOLUME(Settings.FILE_SYSCONF, "BT", "SPKV", 0x58),
-
- GFX_ASPECT_RATIO(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "AspectRatio", 0),
- GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
- "SafeTextureCacheColorSamples", 128),
- GFX_PNG_COMPRESSION_LEVEL(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "PNGCompressionLevel",
- 6),
- GFX_MSAA(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "MSAA", 1),
- GFX_EFB_SCALE(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "InternalResolution", 1),
- GFX_SHADER_COMPILATION_MODE(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS,
- "ShaderCompilationMode", 0),
-
- GFX_ENHANCE_FORCE_TEXTURE_FILTERING(Settings.FILE_GFX, Settings.SECTION_GFX_ENHANCEMENTS,
- "ForceTextureFiltering", 0),
-
- GFX_ENHANCE_MAX_ANISOTROPY(Settings.FILE_GFX, Settings.SECTION_GFX_ENHANCEMENTS, "MaxAnisotropy",
- 0),
-
- GFX_STEREO_MODE(Settings.FILE_GFX, Settings.SECTION_STEREOSCOPY, "StereoMode", 0),
- GFX_STEREO_DEPTH(Settings.FILE_GFX, Settings.SECTION_STEREOSCOPY, "StereoDepth", 20),
- GFX_STEREO_CONVERGENCE_PERCENTAGE(Settings.FILE_GFX, Settings.SECTION_STEREOSCOPY,
- "StereoConvergencePercentage", 100),
-
- GFX_PERF_SAMP_WINDOW(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "PerfSampWindowMS", 1000),
-
- LOGGER_VERBOSITY(Settings.FILE_LOGGER, Settings.SECTION_LOGGER_OPTIONS, "Verbosity", 1),
-
- WIIMOTE_1_SOURCE(Settings.FILE_WIIMOTE, "Wiimote1", "Source", 1),
- WIIMOTE_2_SOURCE(Settings.FILE_WIIMOTE, "Wiimote2", "Source", 0),
- WIIMOTE_3_SOURCE(Settings.FILE_WIIMOTE, "Wiimote3", "Source", 0),
- WIIMOTE_4_SOURCE(Settings.FILE_WIIMOTE, "Wiimote4", "Source", 0),
- WIIMOTE_BB_SOURCE(Settings.FILE_WIIMOTE, "BalanceBoard", "Source", 0);
-
- private static final IntSetting[] NOT_RUNTIME_EDITABLE_ARRAY = new IntSetting[]{
- MAIN_CPU_CORE,
- MAIN_GC_LANGUAGE,
- MAIN_MEM1_SIZE,
- MAIN_MEM2_SIZE,
- MAIN_SLOT_A, // Can actually be changed, but specific code is required
- MAIN_SLOT_B, // Can actually be changed, but specific code is required
- MAIN_SERIAL_PORT_1,
- MAIN_FALLBACK_REGION,
- MAIN_SI_DEVICE_0, // Can actually be changed, but specific code is required
- MAIN_SI_DEVICE_1, // Can actually be changed, but specific code is required
- MAIN_SI_DEVICE_2, // Can actually be changed, but specific code is required
- MAIN_SI_DEVICE_3, // Can actually be changed, but specific code is required
- };
-
- private static final Set<IntSetting> NOT_RUNTIME_EDITABLE =
- new HashSet<>(Arrays.asList(NOT_RUNTIME_EDITABLE_ARRAY));
-
- private final String mFile;
- private final String mSection;
- private final String mKey;
- private final int mDefaultValue;
-
- IntSetting(String file, String section, String key, int defaultValue)
- {
- mFile = file;
- mSection = section;
- mKey = key;
- mDefaultValue = defaultValue;
- }
-
- @Override
- public boolean isOverridden()
- {
- return NativeConfig.isOverridden(mFile, mSection, mKey);
- }
-
- @Override
- public boolean isRuntimeEditable()
- {
- if (mFile.equals(Settings.FILE_SYSCONF))
- return false;
-
- for (IntSetting setting : NOT_RUNTIME_EDITABLE)
- {
- if (setting == this)
- return false;
- }
-
- return NativeConfig.isSettingSaveable(mFile, mSection, mKey);
- }
-
- @Override
- public boolean delete(@NonNull Settings settings)
- {
- if (!NativeConfig.isSettingSaveable(mFile, mSection, mKey))
- {
- throw new UnsupportedOperationException(
- "Unsupported setting: " + mFile + ", " + mSection + ", " + mKey);
- }
-
- return NativeConfig.deleteKey(settings.getWriteLayer(), mFile, mSection, mKey);
- }
-
- @Override
- public int getInt()
- {
- return NativeConfig.getInt(NativeConfig.LAYER_ACTIVE, mFile, mSection, mKey, mDefaultValue);
- }
-
- @Override
- public void setInt(@NonNull Settings settings, int newValue)
- {
- if (!NativeConfig.isSettingSaveable(mFile, mSection, mKey))
- {
- throw new UnsupportedOperationException(
- "Unsupported setting: " + mFile + ", " + mSection + ", " + mKey);
- }
-
- NativeConfig.setInt(settings.getWriteLayer(), mFile, mSection, mKey, newValue);
- }
-
- public void setInt(int layer, int newValue)
- {
- if (!NativeConfig.isSettingSaveable(mFile, mSection, mKey))
- {
- throw new UnsupportedOperationException(
- "Unsupported setting: " + mFile + ", " + mSection + ", " + mKey);
- }
-
- NativeConfig.setInt(layer, mFile, mSection, mKey, newValue);
- }
-
- public static IntSetting getSettingForSIDevice(int channel)
- {
- return new IntSetting[]{MAIN_SI_DEVICE_0, MAIN_SI_DEVICE_1, MAIN_SI_DEVICE_2, MAIN_SI_DEVICE_3}
- [channel];
- }
-
- public static IntSetting getSettingForWiimoteSource(int index)
- {
- return new IntSetting[]{WIIMOTE_1_SOURCE, WIIMOTE_2_SOURCE, WIIMOTE_3_SOURCE, WIIMOTE_4_SOURCE,
- WIIMOTE_BB_SOURCE}[index];
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/IntSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/IntSetting.kt
new file mode 100644
index 0000000000..256e68007e
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/IntSetting.kt
@@ -0,0 +1,219 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model
+
+import android.content.pm.ActivityInfo
+import org.dolphinemu.dolphinemu.NativeLibrary
+import org.dolphinemu.dolphinemu.overlay.InputOverlayPointer
+import java.util.*
+
+enum class IntSetting(
+ private val file: String,
+ private val section: String,
+ private val key: String,
+ private val defaultValue: Int
+) : AbstractIntSetting {
+ // These entries have the same names and order as in C++, just for consistency.
+ MAIN_CPU_CORE(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "CPUCore",
+ NativeLibrary.DefaultCPUCore()
+ ),
+ MAIN_GC_LANGUAGE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SelectedLanguage", 0),
+ MAIN_MEM1_SIZE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "MEM1Size", 0x01800000),
+ MAIN_MEM2_SIZE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "MEM2Size", 0x04000000),
+ MAIN_SLOT_A(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SlotA", 8),
+ MAIN_SLOT_B(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SlotB", 255),
+ MAIN_SERIAL_PORT_1(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SerialPort1", 255),
+ MAIN_FALLBACK_REGION(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "FallbackRegion", 2),
+ MAIN_SI_DEVICE_0(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SIDevice0", 6),
+ MAIN_SI_DEVICE_1(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SIDevice1", 0),
+ MAIN_SI_DEVICE_2(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SIDevice2", 0),
+ MAIN_SI_DEVICE_3(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "SIDevice3", 0),
+ MAIN_AUDIO_VOLUME(Settings.FILE_DOLPHIN, Settings.SECTION_INI_DSP, "Volume", 100),
+ MAIN_OVERLAY_GC_CONTROLLER(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID,
+ "OverlayGCController",
+ 0
+ ),
+
+ // Defaults to GameCube controller 1
+ MAIN_OVERLAY_WII_CONTROLLER(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID,
+ "OverlayWiiController",
+ 4
+ ),
+
+ // Defaults to Wii Remote 1
+ MAIN_CONTROL_SCALE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "ControlScale", 50),
+ MAIN_CONTROL_OPACITY(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "ControlOpacity", 65),
+ MAIN_EMULATION_ORIENTATION(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID,
+ "EmulationOrientation",
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
+ ),
+ MAIN_INTERFACE_THEME(Settings.FILE_DOLPHIN, Settings.SECTION_INI_ANDROID, "InterfaceTheme", 0),
+ MAIN_INTERFACE_THEME_MODE(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID,
+ "InterfaceThemeMode",
+ -1
+ ),
+ MAIN_LAST_PLATFORM_TAB(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID,
+ "LastPlatformTab",
+ 0
+ ),
+ MAIN_IR_MODE(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID,
+ "IRMode",
+ InputOverlayPointer.MODE_FOLLOW
+ ),
+ MAIN_DOUBLE_TAP_BUTTON(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_ANDROID_OVERLAY_BUTTONS,
+ "DoubleTapButton",
+ NativeLibrary.ButtonType.WIIMOTE_BUTTON_A
+ ),
+ SYSCONF_LANGUAGE(Settings.FILE_SYSCONF, "IPL", "LNG", 0x01),
+ SYSCONF_SOUND_MODE(Settings.FILE_SYSCONF, "IPL", "SND", 0x01),
+ SYSCONF_SENSOR_BAR_POSITION(Settings.FILE_SYSCONF, "BT", "BAR", 0x01),
+ SYSCONF_SENSOR_BAR_SENSITIVITY(Settings.FILE_SYSCONF, "BT", "SENS", 0x03),
+ SYSCONF_SPEAKER_VOLUME(Settings.FILE_SYSCONF, "BT", "SPKV", 0x58),
+ GFX_ASPECT_RATIO(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "AspectRatio", 0),
+ GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_SETTINGS,
+ "SafeTextureCacheColorSamples",
+ 128
+ ),
+ GFX_PNG_COMPRESSION_LEVEL(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_SETTINGS,
+ "PNGCompressionLevel",
+ 6
+ ),
+ GFX_MSAA(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "MSAA", 1),
+ GFX_EFB_SCALE(Settings.FILE_GFX, Settings.SECTION_GFX_SETTINGS, "InternalResolution", 1),
+ GFX_SHADER_COMPILATION_MODE(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_SETTINGS,
+ "ShaderCompilationMode",
+ 0
+ ),
+ GFX_ENHANCE_FORCE_TEXTURE_FILTERING(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_ENHANCEMENTS,
+ "ForceTextureFiltering",
+ 0
+ ),
+ GFX_ENHANCE_MAX_ANISOTROPY(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_ENHANCEMENTS,
+ "MaxAnisotropy",
+ 0
+ ),
+ GFX_STEREO_MODE(Settings.FILE_GFX, Settings.SECTION_STEREOSCOPY, "StereoMode", 0),
+ GFX_STEREO_DEPTH(Settings.FILE_GFX, Settings.SECTION_STEREOSCOPY, "StereoDepth", 20),
+ GFX_STEREO_CONVERGENCE_PERCENTAGE(
+ Settings.FILE_GFX,
+ Settings.SECTION_STEREOSCOPY,
+ "StereoConvergencePercentage",
+ 100
+ ),
+ GFX_PERF_SAMP_WINDOW(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_SETTINGS,
+ "PerfSampWindowMS",
+ 1000
+ ),
+ LOGGER_VERBOSITY(Settings.FILE_LOGGER, Settings.SECTION_LOGGER_OPTIONS, "Verbosity", 1),
+ WIIMOTE_1_SOURCE(Settings.FILE_WIIMOTE, "Wiimote1", "Source", 1),
+ WIIMOTE_2_SOURCE(Settings.FILE_WIIMOTE, "Wiimote2", "Source", 0),
+ WIIMOTE_3_SOURCE(Settings.FILE_WIIMOTE, "Wiimote3", "Source", 0),
+ WIIMOTE_4_SOURCE(Settings.FILE_WIIMOTE, "Wiimote4", "Source", 0),
+ WIIMOTE_BB_SOURCE(Settings.FILE_WIIMOTE, "BalanceBoard", "Source", 0);
+
+ override val isOverridden: Boolean
+ get() = NativeConfig.isOverridden(file, section, key)
+
+ override val isRuntimeEditable: Boolean
+ get() {
+ if (file == Settings.FILE_SYSCONF) return false
+ for (setting in NOT_RUNTIME_EDITABLE) {
+ if (setting == this) return false
+ }
+ return NativeConfig.isSettingSaveable(file, section, key)
+ }
+
+ override fun delete(settings: Settings): Boolean {
+ if (!NativeConfig.isSettingSaveable(file, section, key)) {
+ throw UnsupportedOperationException("Unsupported setting: $file, $section, $key")
+ }
+ return NativeConfig.deleteKey(settings.writeLayer, file, section, key)
+ }
+
+ override val int: Int
+ get() = NativeConfig.getInt(NativeConfig.LAYER_ACTIVE, file, section, key, defaultValue)
+
+ override fun setInt(settings: Settings, newValue: Int) {
+ if (!NativeConfig.isSettingSaveable(file, section, key)) {
+ throw UnsupportedOperationException("Unsupported setting: $file, $section, $key")
+ }
+ NativeConfig.setInt(settings.writeLayer, file, section, key, newValue)
+ }
+
+ fun setInt(layer: Int, newValue: Int) {
+ if (!NativeConfig.isSettingSaveable(file, section, key)) {
+ throw UnsupportedOperationException("Unsupported setting: $file, $section, $key")
+ }
+ NativeConfig.setInt(layer, file, section, key, newValue)
+ }
+
+ companion object {
+ private val NOT_RUNTIME_EDITABLE_ARRAY = arrayOf(
+ MAIN_CPU_CORE,
+ MAIN_GC_LANGUAGE,
+ MAIN_MEM1_SIZE,
+ MAIN_MEM2_SIZE,
+ MAIN_SLOT_A,
+ MAIN_SLOT_B,
+ MAIN_SERIAL_PORT_1,
+ MAIN_FALLBACK_REGION,
+ MAIN_SI_DEVICE_0,
+ MAIN_SI_DEVICE_1,
+ MAIN_SI_DEVICE_2,
+ MAIN_SI_DEVICE_3
+ )
+
+ private val NOT_RUNTIME_EDITABLE: Set<IntSetting> =
+ HashSet(listOf(*NOT_RUNTIME_EDITABLE_ARRAY))
+
+ @JvmStatic
+ fun getSettingForSIDevice(channel: Int): IntSetting {
+ return arrayOf(
+ MAIN_SI_DEVICE_0,
+ MAIN_SI_DEVICE_1,
+ MAIN_SI_DEVICE_2,
+ MAIN_SI_DEVICE_3
+ )[channel]
+ }
+
+ @JvmStatic
+ fun getSettingForWiimoteSource(index: Int): IntSetting {
+ return arrayOf(
+ WIIMOTE_1_SOURCE,
+ WIIMOTE_2_SOURCE,
+ WIIMOTE_3_SOURCE,
+ WIIMOTE_4_SOURCE,
+ WIIMOTE_BB_SOURCE
+ )[index]
+ }
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/NativeConfig.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/NativeConfig.java
deleted file mode 100644
index 7fbe96f95e..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/NativeConfig.java
+++ /dev/null
@@ -1,51 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model;
-
-public class NativeConfig
-{
- public static final int LAYER_BASE_OR_CURRENT = 0;
- public static final int LAYER_BASE = 1;
- public static final int LAYER_LOCAL_GAME = 2;
- public static final int LAYER_ACTIVE = 3;
- public static final int LAYER_CURRENT = 4;
-
- public static native boolean isSettingSaveable(String file, String section, String key);
-
- public static native void loadGameInis(String gameId, int revision);
-
- public static native void unloadGameInis();
-
- public static native void save(int layer);
-
- public static native void deleteAllKeys(int layer);
-
- public static native boolean isOverridden(String file, String section, String key);
-
- public static native boolean deleteKey(int layer, String file, String section, String key);
-
- public static native boolean exists(int layer, String file, String section, String key);
-
- public static native String getString(int layer, String file, String section, String key,
- String defaultValue);
-
- public static native boolean getBoolean(int layer, String file, String section, String key,
- boolean defaultValue);
-
- public static native int getInt(int layer, String file, String section, String key,
- int defaultValue);
-
- public static native float getFloat(int layer, String file, String section, String key,
- float defaultValue);
-
- public static native void setString(int layer, String file, String section, String key,
- String value);
-
- public static native void setBoolean(int layer, String file, String section, String key,
- boolean value);
-
- public static native void setInt(int layer, String file, String section, String key, int value);
-
- public static native void setFloat(int layer, String file, String section, String key,
- float value);
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/NativeConfig.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/NativeConfig.kt
new file mode 100644
index 0000000000..c49667574e
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/NativeConfig.kt
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model
+
+object NativeConfig {
+ const val LAYER_BASE_OR_CURRENT = 0
+ const val LAYER_BASE = 1
+ const val LAYER_LOCAL_GAME = 2
+ const val LAYER_ACTIVE = 3
+ const val LAYER_CURRENT = 4
+
+ @JvmStatic
+ external fun isSettingSaveable(file: String, section: String, key: String): Boolean
+
+ @JvmStatic
+ external fun loadGameInis(gameId: String, revision: Int)
+
+ @JvmStatic
+ external fun unloadGameInis()
+
+ @JvmStatic
+ external fun save(layer: Int)
+
+ @JvmStatic
+ external fun deleteAllKeys(layer: Int)
+
+ @JvmStatic
+ external fun isOverridden(file: String, section: String, key: String): Boolean
+
+ @JvmStatic
+ external fun deleteKey(layer: Int, file: String, section: String, key: String): Boolean
+
+ @JvmStatic
+ external fun exists(layer: Int, file: String, section: String, key: String): Boolean
+
+ @JvmStatic
+ external fun getString(
+ layer: Int,
+ file: String,
+ section: String,
+ key: String,
+ defaultValue: String
+ ): String
+
+ @JvmStatic
+ external fun getBoolean(
+ layer: Int,
+ file: String,
+ section: String,
+ key: String,
+ defaultValue: Boolean
+ ): Boolean
+
+ @JvmStatic
+ external fun getInt(
+ layer: Int,
+ file: String,
+ section: String,
+ key: String,
+ defaultValue: Int
+ ): Int
+
+ @JvmStatic
+ external fun getFloat(
+ layer: Int,
+ file: String,
+ section: String,
+ key: String,
+ defaultValue: Float
+ ): Float
+
+ @JvmStatic
+ external fun setString(
+ layer: Int,
+ file: String,
+ section: String,
+ key: String,
+ value: String?
+ )
+
+ @JvmStatic
+ external fun setBoolean(
+ layer: Int,
+ file: String,
+ section: String,
+ key: String,
+ value: Boolean
+ )
+
+ @JvmStatic
+ external fun setInt(
+ layer: Int,
+ file: String,
+ section: String,
+ key: String,
+ value: Int
+ )
+
+ @JvmStatic
+ external fun setFloat(
+ layer: Int,
+ file: String,
+ section: String,
+ key: String,
+ value: Float
+ )
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/PostProcessing.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/PostProcessing.java
deleted file mode 100644
index 8cd86caeb4..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/PostProcessing.java
+++ /dev/null
@@ -1,17 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model;
-
-import androidx.annotation.NonNull;
-
-public class PostProcessing
-{
- @NonNull
- public static native String[] getShaderList();
-
- @NonNull
- public static native String[] getAnaglyphShaderList();
-
- @NonNull
- public static native String[] getPassiveShaderList();
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/PostProcessing.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/PostProcessing.kt
new file mode 100644
index 0000000000..1bb1aa04d7
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/PostProcessing.kt
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model
+
+object PostProcessing {
+ @JvmStatic
+ val shaderList: Array<String?>
+ external get
+
+ @JvmStatic
+ val anaglyphShaderList: Array<String?>
+ external get
+
+ @JvmStatic
+ val passiveShaderList: Array<String?>
+ external get
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/ScaledIntSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/ScaledIntSetting.kt
index 91b69b8fc3..4eef9ed6cf 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/ScaledIntSetting.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/ScaledIntSetting.kt
@@ -6,21 +6,18 @@ class ScaledIntSetting(
private val scale: Int,
private val setting: AbstractIntSetting
) : AbstractIntSetting {
- override fun isOverridden(): Boolean {
- return setting.isOverridden()
- }
+ override val isOverridden: Boolean
+ get() = setting.isOverridden
- override fun isRuntimeEditable(): Boolean {
- return setting.isRuntimeEditable
- }
+ override val isRuntimeEditable: Boolean
+ get() = setting.isRuntimeEditable
override fun delete(settings: Settings): Boolean {
return setting.delete(settings)
}
- override fun getInt(): Int {
- return setting.getInt() / scale
- }
+ override val int: Int
+ get() = setting.int / scale
override fun setInt(settings: Settings, newValue: Int) {
return setting.setInt(settings, newValue * scale)
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.java
deleted file mode 100644
index 0bb935f3df..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.java
+++ /dev/null
@@ -1,181 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model;
-
-import android.content.Context;
-import android.text.TextUtils;
-import android.widget.Toast;
-
-import org.dolphinemu.dolphinemu.NativeLibrary;
-import org.dolphinemu.dolphinemu.R;
-import org.dolphinemu.dolphinemu.features.input.model.MappingCommon;
-import org.dolphinemu.dolphinemu.services.GameFileCacheManager;
-
-import java.io.Closeable;
-
-public class Settings implements Closeable
-{
- public static final String FILE_DOLPHIN = "Dolphin";
- public static final String FILE_SYSCONF = "SYSCONF";
- public static final String FILE_GFX = "GFX";
- public static final String FILE_LOGGER = "Logger";
- public static final String FILE_WIIMOTE = "WiimoteNew";
- public static final String FILE_GAME_SETTINGS_ONLY = "GameSettingsOnly";
-
- public static final String SECTION_INI_ANDROID = "Android";
- public static final String SECTION_INI_ANDROID_OVERLAY_BUTTONS = "AndroidOverlayButtons";
- public static final String SECTION_INI_GENERAL = "General";
- public static final String SECTION_INI_CORE = "Core";
- public static final String SECTION_INI_INTERFACE = "Interface";
- public static final String SECTION_INI_DSP = "DSP";
-
- public static final String SECTION_LOGGER_LOGS = "Logs";
- public static final String SECTION_LOGGER_OPTIONS = "Options";
-
- public static final String SECTION_GFX_SETTINGS = "Settings";
- public static final String SECTION_GFX_ENHANCEMENTS = "Enhancements";
- public static final String SECTION_GFX_HACKS = "Hacks";
-
- public static final String SECTION_DEBUG = "Debug";
- public static final String SECTION_EMULATED_USB_DEVICES = "EmulatedUSBDevices";
-
- public static final String SECTION_STEREOSCOPY = "Stereoscopy";
-
- public static final String SECTION_BINDINGS = "Android";
- public static final String SECTION_PROFILE = "Profile";
-
- public static final String SECTION_ANALYTICS = "Analytics";
-
- private String mGameId;
- private int mRevision;
- private boolean mIsWii;
-
- private boolean mSettingsLoaded = false;
-
- private boolean mLoadedRecursiveIsoPathsValue = false;
-
- public boolean isGameSpecific()
- {
- return !TextUtils.isEmpty(mGameId);
- }
-
- public boolean isWii()
- {
- return mIsWii;
- }
-
- public int getWriteLayer()
- {
- return isGameSpecific() ? NativeConfig.LAYER_LOCAL_GAME : NativeConfig.LAYER_BASE_OR_CURRENT;
- }
-
- public boolean areSettingsLoaded()
- {
- return mSettingsLoaded;
- }
-
- public void loadSettings()
- {
- // The value of isWii doesn't matter if we don't have any SettingsActivity
- loadSettings(true);
- }
-
- public void loadSettings(boolean isWii)
- {
- mIsWii = isWii;
- mSettingsLoaded = true;
-
- if (isGameSpecific())
- {
- // Loading game INIs while the core is running will mess with the game INIs loaded by the core
- if (NativeLibrary.IsRunning())
- throw new IllegalStateException("Attempted to load game INI while emulating");
-
- NativeConfig.loadGameInis(mGameId, mRevision);
- }
-
- mLoadedRecursiveIsoPathsValue = BooleanSetting.MAIN_RECURSIVE_ISO_PATHS.getBoolean();
- }
-
- public void loadSettings(String gameId, int revision, boolean isWii)
- {
- mGameId = gameId;
- mRevision = revision;
- loadSettings(isWii);
- }
-
- public void saveSettings(Context context)
- {
- if (!isGameSpecific())
- {
- if (context != null)
- Toast.makeText(context, R.string.settings_saved, Toast.LENGTH_SHORT).show();
-
- MappingCommon.save();
-
- NativeConfig.save(NativeConfig.LAYER_BASE);
-
- NativeLibrary.ReloadLoggerConfig();
- NativeLibrary.UpdateGCAdapterScanThread();
-
- if (mLoadedRecursiveIsoPathsValue != BooleanSetting.MAIN_RECURSIVE_ISO_PATHS.getBoolean())
- {
- // Refresh game library
- GameFileCacheManager.startRescan();
- }
- }
- else
- {
- // custom game settings
-
- if (context != null)
- {
- Toast.makeText(context, context.getString(R.string.settings_saved_game_specific, mGameId),
- Toast.LENGTH_SHORT).show();
- }
-
- NativeConfig.save(NativeConfig.LAYER_LOCAL_GAME);
- }
- }
-
- public void clearGameSettings()
- {
- NativeConfig.deleteAllKeys(NativeConfig.LAYER_LOCAL_GAME);
- }
-
- public boolean gameIniContainsJunk()
- {
- // Older versions of Android Dolphin would copy the entire contents of most of the global INIs
- // into any game INI that got saved (with some of the sections renamed to match the game INI
- // section names). The problems with this are twofold:
- //
- // 1. The user game INIs will contain entries that Dolphin doesn't support reading from
- // game INIs. This is annoying when editing game INIs manually but shouldn't really be
- // a problem for those who only use the GUI.
- //
- // 2. Global settings will stick around in user game INIs. For instance, if someone wants to
- // change the texture cache accuracy to safe for all games, they have to edit not only the
- // global settings but also every single game INI they have created, since the old value of
- // the texture cache accuracy setting has been copied into every user game INI.
- //
- // These problems are serious enough that we should detect and delete such INI files.
- // Problem 1 is easy to detect, but due to the nature of problem 2, it's unfortunately not
- // possible to know which lines were added intentionally by the user and which lines were added
- // unintentionally, which is why we have to delete the whole file in order to fix everything.
-
- if (!isGameSpecific())
- return false;
-
- return NativeConfig.exists(NativeConfig.LAYER_LOCAL_GAME, FILE_DOLPHIN, SECTION_INI_INTERFACE,
- "ThemeName");
- }
-
- @Override
- public void close()
- {
- if (isGameSpecific())
- {
- NativeConfig.unloadGameInis();
- }
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.kt
new file mode 100644
index 0000000000..b363104703
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.kt
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model
+
+import android.content.Context
+import android.text.TextUtils
+import android.widget.Toast
+import org.dolphinemu.dolphinemu.NativeLibrary
+import org.dolphinemu.dolphinemu.R
+import org.dolphinemu.dolphinemu.features.input.model.MappingCommon
+import org.dolphinemu.dolphinemu.services.GameFileCacheManager
+import java.io.Closeable
+
+class Settings : Closeable {
+ private var gameId: String = ""
+ private var revision = 0
+
+ var isWii = false
+ private set
+
+ private var settingsLoaded = false
+ private var loadedRecursiveIsoPathsValue = false
+
+ private val isGameSpecific: Boolean
+ get() = !TextUtils.isEmpty(gameId)
+
+ val writeLayer: Int
+ get() = if (isGameSpecific) NativeConfig.LAYER_LOCAL_GAME else NativeConfig.LAYER_BASE_OR_CURRENT
+
+ fun areSettingsLoaded(): Boolean {
+ return settingsLoaded
+ }
+
+ @JvmOverloads
+ fun loadSettings(isWii: Boolean = true) {
+ this.isWii = isWii
+ settingsLoaded = true
+
+ if (isGameSpecific) {
+ // Loading game INIs while the core is running will mess with the game INIs loaded by the core
+ check(!NativeLibrary.IsRunning()) { "Attempted to load game INI while emulating" }
+ NativeConfig.loadGameInis(gameId, revision)
+ }
+
+ loadedRecursiveIsoPathsValue = BooleanSetting.MAIN_RECURSIVE_ISO_PATHS.boolean
+ }
+
+ fun loadSettings(gameId: String, revision: Int, isWii: Boolean) {
+ this.gameId = gameId
+ this.revision = revision
+ loadSettings(isWii)
+ }
+
+ fun saveSettings(context: Context?) {
+ if (!isGameSpecific) {
+ if (context != null) Toast.makeText(
+ context,
+ R.string.settings_saved,
+ Toast.LENGTH_SHORT
+ ).show()
+
+ MappingCommon.save()
+
+ NativeConfig.save(NativeConfig.LAYER_BASE)
+
+ NativeLibrary.ReloadLoggerConfig()
+ NativeLibrary.UpdateGCAdapterScanThread()
+
+ if (loadedRecursiveIsoPathsValue != BooleanSetting.MAIN_RECURSIVE_ISO_PATHS.boolean) {
+ // Refresh game library
+ GameFileCacheManager.startRescan()
+ }
+ } else {
+ // custom game settings
+ if (context != null) {
+ Toast.makeText(
+ context, context.getString(R.string.settings_saved_game_specific, gameId),
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+ NativeConfig.save(NativeConfig.LAYER_LOCAL_GAME)
+ }
+ }
+
+ fun clearGameSettings() {
+ NativeConfig.deleteAllKeys(NativeConfig.LAYER_LOCAL_GAME)
+ }
+
+ fun gameIniContainsJunk(): Boolean {
+ // Older versions of Android Dolphin would copy the entire contents of most of the global INIs
+ // into any game INI that got saved (with some of the sections renamed to match the game INI
+ // section names). The problems with this are twofold:
+ //
+ // 1. The user game INIs will contain entries that Dolphin doesn't support reading from
+ // game INIs. This is annoying when editing game INIs manually but shouldn't really be
+ // a problem for those who only use the GUI.
+ //
+ // 2. Global settings will stick around in user game INIs. For instance, if someone wants to
+ // change the texture cache accuracy to safe for all games, they have to edit not only the
+ // global settings but also every single game INI they have created, since the old value of
+ // the texture cache accuracy Setting has been copied into every user game INI.
+ //
+ // These problems are serious enough that we should detect and delete such INI files.
+ // Problem 1 is easy to detect, but due to the nature of problem 2, it's unfortunately not
+ // possible to know which lines were added intentionally by the user and which lines were added
+ // unintentionally, which is why we have to delete the whole file in order to fix everything.
+ return if (!isGameSpecific) false else NativeConfig.exists(
+ NativeConfig.LAYER_LOCAL_GAME,
+ FILE_DOLPHIN,
+ SECTION_INI_INTERFACE,
+ "ThemeName"
+ )
+ }
+
+ override fun close() {
+ if (isGameSpecific) {
+ NativeConfig.unloadGameInis()
+ }
+ }
+
+ companion object {
+ const val FILE_DOLPHIN = "Dolphin"
+ const val FILE_SYSCONF = "SYSCONF"
+ const val FILE_GFX = "GFX"
+ const val FILE_LOGGER = "Logger"
+ const val FILE_WIIMOTE = "WiimoteNew"
+ const val FILE_GAME_SETTINGS_ONLY = "GameSettingsOnly"
+ const val SECTION_INI_ANDROID = "Android"
+ const val SECTION_INI_ANDROID_OVERLAY_BUTTONS = "AndroidOverlayButtons"
+ const val SECTION_INI_GENERAL = "General"
+ const val SECTION_INI_CORE = "Core"
+ const val SECTION_INI_INTERFACE = "Interface"
+ const val SECTION_INI_DSP = "DSP"
+ const val SECTION_LOGGER_LOGS = "Logs"
+ const val SECTION_LOGGER_OPTIONS = "Options"
+ const val SECTION_GFX_SETTINGS = "Settings"
+ const val SECTION_GFX_ENHANCEMENTS = "Enhancements"
+ const val SECTION_GFX_HACKS = "Hacks"
+ const val SECTION_DEBUG = "Debug"
+ const val SECTION_EMULATED_USB_DEVICES = "EmulatedUSBDevices"
+ const val SECTION_STEREOSCOPY = "Stereoscopy"
+ const val SECTION_ANALYTICS = "Analytics"
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.java
deleted file mode 100644
index c72f26aa0f..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.java
+++ /dev/null
@@ -1,113 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model;
-
-import androidx.annotation.NonNull;
-
-import org.dolphinemu.dolphinemu.NativeLibrary;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
-public enum StringSetting implements AbstractStringSetting
-{
- // These entries have the same names and order as in C++, just for consistency.
-
- MAIN_DEFAULT_ISO(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "DefaultISO", ""),
-
- MAIN_BBA_MAC(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "BBA_MAC", ""),
- MAIN_BBA_XLINK_IP(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "BBA_XLINK_IP", ""),
-
- // Schthack PSO Server - https://schtserv.com/
- MAIN_BBA_BUILTIN_DNS(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "BBA_BUILTIN_DNS",
- "149.56.167.128"),
-
- MAIN_CUSTOM_RTC_VALUE(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "CustomRTCValue",
- "0x386d4380"),
-
- MAIN_GFX_BACKEND(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "GFXBackend",
- NativeLibrary.GetDefaultGraphicsBackendName()),
-
- MAIN_DUMP_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "DumpPath", ""),
- MAIN_LOAD_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "LoadPath", ""),
- MAIN_RESOURCEPACK_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "ResourcePackPath",
- ""),
- MAIN_FS_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "NANDRootPath", ""),
- MAIN_WII_SD_CARD_IMAGE_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "WiiSDCardPath",
- ""),
- MAIN_WII_SD_CARD_SYNC_FOLDER_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL,
- "WiiSDCardSyncFolder", ""),
- MAIN_WFS_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "WFSPath", ""),
-
- GFX_ENHANCE_POST_SHADER(Settings.FILE_GFX, Settings.SECTION_GFX_ENHANCEMENTS,
- "PostProcessingShader", "");
-
- private static final StringSetting[] NOT_RUNTIME_EDITABLE_ARRAY = new StringSetting[]{
- MAIN_CUSTOM_RTC_VALUE,
- MAIN_GFX_BACKEND,
- };
-
- private static final Set<StringSetting> NOT_RUNTIME_EDITABLE =
- new HashSet<>(Arrays.asList(NOT_RUNTIME_EDITABLE_ARRAY));
-
- private final String mFile;
- private final String mSection;
- private final String mKey;
- private final String mDefaultValue;
-
- StringSetting(String file, String section, String key, String defaultValue)
- {
- mFile = file;
- mSection = section;
- mKey = key;
- mDefaultValue = defaultValue;
- }
-
- @Override
- public boolean isOverridden()
- {
- return NativeConfig.isOverridden(mFile, mSection, mKey);
- }
-
- @Override
- public boolean isRuntimeEditable()
- {
- for (StringSetting setting : NOT_RUNTIME_EDITABLE)
- {
- if (setting == this)
- return false;
- }
-
- return NativeConfig.isSettingSaveable(mFile, mSection, mKey);
- }
-
- @Override
- public boolean delete(@NonNull Settings settings)
- {
- return NativeConfig.deleteKey(settings.getWriteLayer(), mFile, mSection, mKey);
- }
-
- @NonNull @Override
- public String getString()
- {
- if (!NativeConfig.isSettingSaveable(mFile, mSection, mKey))
- {
- throw new UnsupportedOperationException(
- "Unsupported setting: " + mFile + ", " + mSection + ", " + mKey);
- }
-
- return NativeConfig.getString(NativeConfig.LAYER_ACTIVE, mFile, mSection, mKey, mDefaultValue);
- }
-
- @Override
- public void setString(@NonNull Settings settings, @NonNull String newValue)
- {
- NativeConfig.setString(settings.getWriteLayer(), mFile, mSection, mKey, newValue);
- }
-
- public void setString(int layer, String newValue)
- {
- NativeConfig.setString(layer, mFile, mSection, mKey, newValue);
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.kt
new file mode 100644
index 0000000000..bb479267c9
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.kt
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model
+
+import org.dolphinemu.dolphinemu.NativeLibrary
+import java.util.*
+
+enum class StringSetting(
+ private val file: String,
+ private val section: String,
+ private val key: String,
+ private val defaultValue: String
+) : AbstractStringSetting {
+ // These entries have the same names and order as in C++, just for consistency.
+ MAIN_DEFAULT_ISO(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "DefaultISO", ""),
+ MAIN_BBA_MAC(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "BBA_MAC", ""),
+ MAIN_BBA_XLINK_IP(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "BBA_XLINK_IP", ""),
+
+ // Schthack PSO Server - https://schtserv.com/
+ MAIN_BBA_BUILTIN_DNS(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "BBA_BUILTIN_DNS",
+ "149.56.167.128"
+ ),
+ MAIN_CUSTOM_RTC_VALUE(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "CustomRTCValue",
+ "0x386d4380"
+ ),
+ MAIN_GFX_BACKEND(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_CORE,
+ "GFXBackend",
+ NativeLibrary.GetDefaultGraphicsBackendName()
+ ),
+ MAIN_DUMP_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "DumpPath", ""),
+ MAIN_LOAD_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "LoadPath", ""),
+ MAIN_RESOURCEPACK_PATH(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_GENERAL,
+ "ResourcePackPath",
+ ""
+ ),
+ MAIN_FS_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "NANDRootPath", ""),
+ MAIN_WII_SD_CARD_IMAGE_PATH(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_GENERAL,
+ "WiiSDCardPath",
+ ""
+ ),
+ MAIN_WII_SD_CARD_SYNC_FOLDER_PATH(
+ Settings.FILE_DOLPHIN,
+ Settings.SECTION_INI_GENERAL,
+ "WiiSDCardSyncFolder",
+ ""
+ ),
+ MAIN_WFS_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "WFSPath", ""),
+ GFX_ENHANCE_POST_SHADER(
+ Settings.FILE_GFX,
+ Settings.SECTION_GFX_ENHANCEMENTS,
+ "PostProcessingShader",
+ ""
+ );
+
+ override val isOverridden: Boolean
+ get() = NativeConfig.isOverridden(file, section, key)
+
+ override val isRuntimeEditable: Boolean
+ get() {
+ for (setting in NOT_RUNTIME_EDITABLE) {
+ if (setting == this) return false
+ }
+ return NativeConfig.isSettingSaveable(file, section, key)
+ }
+
+ override fun delete(settings: Settings): Boolean {
+ return NativeConfig.deleteKey(settings.writeLayer, file, section, key)
+ }
+
+ override val string: String
+ get() = if (!NativeConfig.isSettingSaveable(file, section, key)) {
+ throw UnsupportedOperationException("Unsupported setting: $file, $section, $key")
+ } else NativeConfig.getString(NativeConfig.LAYER_ACTIVE, file, section, key, defaultValue)
+
+ override fun setString(settings: Settings, newValue: String) {
+ NativeConfig.setString(settings.writeLayer, file, section, key, newValue)
+ }
+
+ fun setString(layer: Int, newValue: String?) {
+ NativeConfig.setString(layer, file, section, key, newValue)
+ }
+
+ companion object {
+ private val NOT_RUNTIME_EDITABLE_ARRAY = arrayOf(
+ MAIN_CUSTOM_RTC_VALUE,
+ MAIN_GFX_BACKEND
+ )
+
+ private val NOT_RUNTIME_EDITABLE: Set<StringSetting> =
+ HashSet(listOf(*NOT_RUNTIME_EDITABLE_ARRAY))
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/DateTimeChoiceSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/DateTimeChoiceSetting.kt
index d1d411f80e..1cd15b50ee 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/DateTimeChoiceSetting.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/DateTimeChoiceSetting.kt
@@ -3,29 +3,22 @@
package org.dolphinemu.dolphinemu.features.settings.model.view
import android.content.Context
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
import org.dolphinemu.dolphinemu.features.settings.model.AbstractStringSetting
import org.dolphinemu.dolphinemu.features.settings.model.Settings
class DateTimeChoiceSetting(
context: Context,
- private val setting: AbstractStringSetting,
+ override val setting: AbstractStringSetting,
nameId: Int,
descriptionId: Int
) : SettingsItem(context, nameId, descriptionId) {
- override fun getType(): Int {
- return TYPE_DATETIME_CHOICE
- }
-
- override fun getSetting(): AbstractSetting {
- return setting
- }
+ override val type: Int = TYPE_DATETIME_CHOICE
fun setSelectedValue(settings: Settings, selection: String) {
setting.setString(settings, selection)
}
fun getSelectedValue(): String {
- return setting.getString()
+ return setting.string
}
}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FilePicker.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FilePicker.java
deleted file mode 100644
index 4b0ae749a9..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FilePicker.java
+++ /dev/null
@@ -1,60 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model.view;
-
-import android.content.Context;
-
-import androidx.annotation.Nullable;
-
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractStringSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-
-public final class FilePicker extends SettingsItem
-{
- private AbstractStringSetting mSetting;
- private int mRequestType;
- private String mDefaultPathRelativeToUserDirectory;
-
- public FilePicker(Context context, AbstractStringSetting setting, int titleId, int descriptionId,
- int requestType, @Nullable String defaultPathRelativeToUserDirectory)
- {
- super(context, titleId, descriptionId);
- mSetting = setting;
- mRequestType = requestType;
- mDefaultPathRelativeToUserDirectory = defaultPathRelativeToUserDirectory;
- }
-
- public String getSelectedValue()
- {
- return mSetting.getString();
- }
-
- public void setSelectedValue(Settings settings, String selection)
- {
- mSetting.setString(settings, selection);
- }
-
- public int getRequestType()
- {
- return mRequestType;
- }
-
- @Nullable
- public String getDefaultPathRelativeToUserDirectory()
- {
- return mDefaultPathRelativeToUserDirectory;
- }
-
- @Override
- public int getType()
- {
- return TYPE_FILE_PICKER;
- }
-
- @Override
- public AbstractSetting getSetting()
- {
- return mSetting;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FilePicker.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FilePicker.kt
new file mode 100644
index 0000000000..2b5bd70162
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FilePicker.kt
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model.view
+
+import android.content.Context
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractStringSetting
+import org.dolphinemu.dolphinemu.features.settings.model.Settings
+
+class FilePicker(
+ context: Context,
+ override var setting: AbstractStringSetting,
+ titleId: Int,
+ descriptionId: Int,
+ val requestType: Int,
+ val defaultPathRelativeToUserDirectory: String?
+) : SettingsItem(context, titleId, descriptionId) {
+ override val type: Int = TYPE_FILE_PICKER
+
+ fun getSelectedValue() : String {
+ return setting.string
+ }
+
+ fun setSelectedValue(settings: Settings, selection: String) {
+ setting.setString(settings, selection)
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FloatSliderSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FloatSliderSetting.java
deleted file mode 100644
index 29432aaaa7..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FloatSliderSetting.java
+++ /dev/null
@@ -1,44 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model.view;
-
-import android.content.Context;
-
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractFloatSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-
-public class FloatSliderSetting extends SliderSetting
-{
- protected AbstractFloatSetting mSetting;
-
- public FloatSliderSetting(Context context, AbstractFloatSetting setting, int titleId,
- int descriptionId, int min, int max, String units, int stepSize)
- {
- super(context, titleId, descriptionId, min, max, units, stepSize);
- mSetting = setting;
- }
-
- public FloatSliderSetting(AbstractFloatSetting setting, CharSequence name,
- CharSequence description, int min, int max, String units)
- {
- super(name, description, min, max, units);
- mSetting = setting;
- }
-
- public int getSelectedValue()
- {
- return Math.round(mSetting.getFloat());
- }
-
- public void setSelectedValue(Settings settings, float selection)
- {
- mSetting.setFloat(settings, selection);
- }
-
- @Override
- public AbstractSetting getSetting()
- {
- return mSetting;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FloatSliderSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FloatSliderSetting.kt
new file mode 100644
index 0000000000..5b2ee40fe7
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/FloatSliderSetting.kt
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model.view
+
+import android.content.Context
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractFloatSetting
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
+import org.dolphinemu.dolphinemu.features.settings.model.Settings
+import kotlin.math.roundToInt
+
+open class FloatSliderSetting : SliderSetting {
+ var floatSetting: AbstractFloatSetting
+
+ override val setting: AbstractSetting
+ get() = floatSetting
+
+ constructor(
+ context: Context,
+ setting: AbstractFloatSetting,
+ titleId: Int,
+ descriptionId: Int,
+ min: Int,
+ max: Int,
+ units: String?,
+ stepSize: Int
+ ) : super(context, titleId, descriptionId, min, max, units, stepSize) {
+ floatSetting = setting
+ }
+
+ constructor(
+ setting: AbstractFloatSetting,
+ name: CharSequence,
+ description: CharSequence?,
+ min: Int,
+ max: Int,
+ units: String?
+ ) : super(name, description, min, max, units) {
+ floatSetting = setting
+ }
+
+ override val selectedValue: Int
+ get() = floatSetting.float.roundToInt()
+
+ open fun setSelectedValue(settings: Settings?, selection: Float) {
+ floatSetting.setFloat(settings!!, selection)
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/HeaderSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/HeaderSetting.java
deleted file mode 100644
index b65f45837b..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/HeaderSetting.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model.view;
-
-import android.content.Context;
-
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
-
-public class HeaderSetting extends SettingsItem
-{
- public HeaderSetting(Context context, int titleId, int descriptionId)
- {
- super(context, titleId, descriptionId);
- }
-
- public HeaderSetting(CharSequence title, CharSequence description)
- {
- super(title, description);
- }
-
- @Override
- public int getType()
- {
- return SettingsItem.TYPE_HEADER;
- }
-
- @Override
- public AbstractSetting getSetting()
- {
- return null;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/HeaderSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/HeaderSetting.kt
new file mode 100644
index 0000000000..3a166ddddf
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/HeaderSetting.kt
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model.view
+
+import android.content.Context
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
+
+open class HeaderSetting : SettingsItem {
+ override val setting: AbstractSetting? = null
+
+ constructor(
+ context: Context,
+ titleId: Int,
+ descriptionId: Int
+ ) : super(context, titleId, descriptionId)
+
+ constructor(title: CharSequence, description: CharSequence?) : super(title, description)
+
+ override val type: Int = TYPE_HEADER
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/HyperLinkHeaderSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/HyperLinkHeaderSetting.java
deleted file mode 100644
index 785e6cd6f6..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/HyperLinkHeaderSetting.java
+++ /dev/null
@@ -1,19 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model.view;
-
-import android.content.Context;
-
-public final class HyperLinkHeaderSetting extends HeaderSetting
-{
- public HyperLinkHeaderSetting(Context context, int titleId, int descriptionId)
- {
- super(context, titleId, descriptionId);
- }
-
- @Override
- public int getType()
- {
- return SettingsItem.TYPE_HYPERLINK_HEADER;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/HyperLinkHeaderSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/HyperLinkHeaderSetting.kt
new file mode 100644
index 0000000000..bc1595528b
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/HyperLinkHeaderSetting.kt
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model.view
+
+import android.content.Context
+
+class HyperLinkHeaderSetting(
+ context: Context,
+ titleId: Int,
+ descriptionId: Int
+) : HeaderSetting(context, titleId, descriptionId)
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InputStringSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InputStringSetting.java
deleted file mode 100644
index 9cd811b82d..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InputStringSetting.java
+++ /dev/null
@@ -1,72 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model.view;
-
-import android.content.Context;
-
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractStringSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
-
-public class InputStringSetting extends SettingsItem
-{
- private AbstractStringSetting mSetting;
-
- private MenuTag mMenuTag;
-
- public InputStringSetting(Context context, AbstractStringSetting setting, int titleId,
- int descriptionId, MenuTag menuTag)
- {
- super(context, titleId, descriptionId);
- mSetting = setting;
- mMenuTag = menuTag;
- }
-
- public InputStringSetting(Context context, AbstractStringSetting setting, int titleId,
- int descriptionId)
- {
- this(context, setting, titleId, descriptionId, null);
- }
-
- public InputStringSetting(Context context, AbstractStringSetting setting, int titleId,
- int descriptionId, int choicesId, int valuesId, MenuTag menuTag)
- {
- super(context, titleId, descriptionId);
- mSetting = setting;
- mMenuTag = menuTag;
- }
-
- public InputStringSetting(Context context, AbstractStringSetting setting, int titleId,
- int descriptionId, int choicesId, int valuesId)
- {
- this(context, setting, titleId, descriptionId, choicesId, valuesId, null);
- }
-
- public String getSelectedValue()
- {
- return mSetting.getString();
- }
-
- public MenuTag getMenuTag()
- {
- return mMenuTag;
- }
-
- public void setSelectedValue(Settings settings, String selection)
- {
- mSetting.setString(settings, selection);
- }
-
- @Override
- public int getType()
- {
- return TYPE_STRING;
- }
-
- @Override
- public AbstractSetting getSetting()
- {
- return mSetting;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InputStringSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InputStringSetting.kt
new file mode 100644
index 0000000000..69bb842be0
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InputStringSetting.kt
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model.view
+
+import android.content.Context
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractStringSetting
+import org.dolphinemu.dolphinemu.features.settings.model.Settings
+
+class InputStringSetting(
+ context: Context,
+ setting: AbstractStringSetting,
+ titleId: Int,
+ descriptionId: Int,
+) : SettingsItem(context, titleId, descriptionId) {
+ override val type: Int = TYPE_STRING
+
+ private var stringSetting: AbstractStringSetting = setting
+
+ override val setting: AbstractSetting
+ get() = stringSetting
+
+ val selectedValue: String
+ get() = stringSetting.string
+
+ fun setSelectedValue(settings: Settings, selection: String) {
+ stringSetting.setString(settings, selection)
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/IntSliderSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/IntSliderSetting.java
deleted file mode 100644
index e8d19f9059..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/IntSliderSetting.java
+++ /dev/null
@@ -1,37 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model.view;
-
-import android.content.Context;
-
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractIntSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-
-public final class IntSliderSetting extends SliderSetting
-{
- private AbstractIntSetting mSetting;
-
- public IntSliderSetting(Context context, AbstractIntSetting setting, int titleId,
- int descriptionId, int min, int max, String units, int stepSize)
- {
- super(context, titleId, descriptionId, min, max, units, stepSize);
- mSetting = setting;
- }
-
- public int getSelectedValue()
- {
- return mSetting.getInt();
- }
-
- public void setSelectedValue(Settings settings, int selection)
- {
- mSetting.setInt(settings, selection);
- }
-
- @Override
- public AbstractSetting getSetting()
- {
- return mSetting;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/IntSliderSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/IntSliderSetting.kt
new file mode 100644
index 0000000000..23bcd49317
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/IntSliderSetting.kt
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model.view
+
+import android.content.Context
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractIntSetting
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
+import org.dolphinemu.dolphinemu.features.settings.model.Settings
+
+class IntSliderSetting(
+ context: Context,
+ private val intSetting: AbstractIntSetting,
+ titleId: Int,
+ descriptionId: Int,
+ min: Int,
+ max: Int,
+ units: String?,
+ stepSize: Int
+) : SliderSetting(context, titleId, descriptionId, min, max, units, stepSize) {
+ override val setting: AbstractSetting
+ get() = intSetting
+
+ override val selectedValue: Int
+ get() = intSetting.int
+
+ fun setSelectedValue(settings: Settings?, selection: Int) {
+ intSetting.setInt(settings!!, selection)
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InvertedSwitchSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InvertedSwitchSetting.java
deleted file mode 100644
index 621530e980..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InvertedSwitchSetting.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model.view;
-
-import android.content.Context;
-
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractBooleanSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-
-public final class InvertedSwitchSetting extends SwitchSetting
-{
- public InvertedSwitchSetting(Context context, AbstractBooleanSetting setting, int titleId,
- int descriptionId)
- {
- super(context, setting, titleId, descriptionId);
- }
-
- @Override
- public boolean isChecked()
- {
- return !mSetting.getBoolean();
- }
-
- @Override
- public void setChecked(Settings settings, boolean checked)
- {
- mSetting.setBoolean(settings, !checked);
- }
-
- @Override
- public AbstractSetting getSetting()
- {
- return mSetting;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InvertedSwitchSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InvertedSwitchSetting.kt
new file mode 100644
index 0000000000..1a423c62f5
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/InvertedSwitchSetting.kt
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model.view
+
+import android.content.Context
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractBooleanSetting
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
+import org.dolphinemu.dolphinemu.features.settings.model.Settings
+
+class InvertedSwitchSetting(
+ context: Context,
+ setting: AbstractBooleanSetting,
+ titleId: Int,
+ descriptionId: Int
+) : SwitchSetting(context, setting, titleId, descriptionId) {
+ override val setting: AbstractSetting
+ get() = booleanSetting
+
+ override val isChecked: Boolean
+ get() = !booleanSetting.boolean
+
+ override fun setChecked(settings: Settings?, checked: Boolean) {
+ booleanSetting.setBoolean(settings!!, !checked)
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/LogSwitchSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/LogSwitchSetting.java
deleted file mode 100644
index 910c8fb171..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/LogSwitchSetting.java
+++ /dev/null
@@ -1,23 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model.view;
-
-import org.dolphinemu.dolphinemu.features.settings.model.AdHocBooleanSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-
-public class LogSwitchSetting extends SwitchSetting
-{
- String mKey;
-
- public LogSwitchSetting(String key, CharSequence title, CharSequence description)
- {
- super(new AdHocBooleanSetting(Settings.FILE_LOGGER, Settings.SECTION_LOGGER_LOGS, key, false),
- title, description);
- mKey = key;
- }
-
- public String getKey()
- {
- return mKey;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/LogSwitchSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/LogSwitchSetting.kt
new file mode 100644
index 0000000000..1bad7bff9f
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/LogSwitchSetting.kt
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model.view
+
+import org.dolphinemu.dolphinemu.features.settings.model.AdHocBooleanSetting
+import org.dolphinemu.dolphinemu.features.settings.model.Settings
+
+class LogSwitchSetting(
+ var key: String,
+ title: CharSequence?,
+ description: CharSequence?
+) : SwitchSetting(
+ AdHocBooleanSetting(
+ Settings.FILE_LOGGER,
+ Settings.SECTION_LOGGER_LOGS,
+ key,
+ false
+ ),
+ title,
+ description
+)
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/PercentSliderSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/PercentSliderSetting.java
deleted file mode 100644
index 834b10e077..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/PercentSliderSetting.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model.view;
-
-import android.content.Context;
-
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractFloatSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-
-public final class PercentSliderSetting extends FloatSliderSetting
-{
- public PercentSliderSetting(Context context, AbstractFloatSetting setting, int titleId,
- int descriptionId, int min, int max, String units, int stepSize)
- {
- super(context, setting, titleId, descriptionId, min, max, units, stepSize);
- }
-
- @Override
- public int getSelectedValue()
- {
- return Math.round(mSetting.getFloat() * 100);
- }
-
- @Override
- public void setSelectedValue(Settings settings, float selection)
- {
- mSetting.setFloat(settings, selection / 100);
- }
-
- @Override
- public AbstractSetting getSetting()
- {
- return mSetting;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/PercentSliderSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/PercentSliderSetting.kt
new file mode 100644
index 0000000000..db6454b0c5
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/PercentSliderSetting.kt
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model.view
+
+import android.content.Context
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractFloatSetting
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
+import org.dolphinemu.dolphinemu.features.settings.model.Settings
+import kotlin.math.roundToInt
+
+class PercentSliderSetting(
+ context: Context,
+ override val setting: AbstractFloatSetting,
+ titleId: Int,
+ descriptionId: Int,
+ min: Int,
+ max: Int,
+ units: String?,
+ stepSize: Int
+) : FloatSliderSetting(context, setting, titleId, descriptionId, min, max, units, stepSize) {
+ override val selectedValue: Int
+ get() = (floatSetting.float * 100).roundToInt()
+
+ override fun setSelectedValue(settings: Settings?, selection: Float) {
+ floatSetting.setFloat(settings!!, selection / 100)
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/RunRunnable.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/RunRunnable.java
deleted file mode 100644
index c83d4e292e..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/RunRunnable.java
+++ /dev/null
@@ -1,59 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model.view;
-
-import android.content.Context;
-
-import org.dolphinemu.dolphinemu.NativeLibrary;
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
-
-public final class RunRunnable extends SettingsItem
-{
- private final int mAlertText;
- private final int mToastTextAfterRun;
- private final boolean mWorksDuringEmulation;
- private final Runnable mRunnable;
-
- public RunRunnable(Context context, int titleId, int descriptionId, int alertText,
- int toastTextAfterRun, boolean worksDuringEmulation, Runnable runnable)
- {
- super(context, titleId, descriptionId);
- mAlertText = alertText;
- mToastTextAfterRun = toastTextAfterRun;
- mWorksDuringEmulation = worksDuringEmulation;
- mRunnable = runnable;
- }
-
- public int getAlertText()
- {
- return mAlertText;
- }
-
- public int getToastTextAfterRun()
- {
- return mToastTextAfterRun;
- }
-
- public Runnable getRunnable()
- {
- return mRunnable;
- }
-
- @Override
- public int getType()
- {
- return TYPE_RUN_RUNNABLE;
- }
-
- @Override
- public AbstractSetting getSetting()
- {
- return null;
- }
-
- @Override
- public boolean isEditable()
- {
- return mWorksDuringEmulation || !NativeLibrary.IsRunning();
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/RunRunnable.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/RunRunnable.kt
new file mode 100644
index 0000000000..f9d5786e22
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/RunRunnable.kt
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model.view
+
+import android.content.Context
+import org.dolphinemu.dolphinemu.NativeLibrary
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
+
+class RunRunnable(
+ context: Context,
+ titleId: Int,
+ descriptionId: Int,
+ val alertText: Int,
+ val toastTextAfterRun: Int,
+ private val worksDuringEmulation: Boolean,
+ val runnable: Runnable
+) : SettingsItem(context, titleId, descriptionId) {
+ override val type: Int = TYPE_RUN_RUNNABLE
+
+ override val setting: AbstractSetting? = null
+
+ override val isEditable: Boolean
+ get() = worksDuringEmulation || !NativeLibrary.IsRunning()
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SettingsItem.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SettingsItem.java
deleted file mode 100644
index 7d757c3e69..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SettingsItem.java
+++ /dev/null
@@ -1,107 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model.view;
-
-import android.content.Context;
-
-import org.dolphinemu.dolphinemu.NativeLibrary;
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
-
-/**
- * ViewModel abstraction for an Item in the RecyclerView powering SettingsFragments.
- * Most of them correspond to a single line in an INI file, but there are a few with multiple
- * analogues and a few with none (Headers, for example, do not correspond to anything on disk.)
- */
-public abstract class SettingsItem
-{
- public static final int TYPE_HEADER = 0;
- public static final int TYPE_SWITCH = 1;
- public static final int TYPE_SINGLE_CHOICE = 2;
- public static final int TYPE_SLIDER = 3;
- public static final int TYPE_SUBMENU = 4;
- public static final int TYPE_INPUT_MAPPING_CONTROL = 5;
- public static final int TYPE_STRING_SINGLE_CHOICE = 6;
- public static final int TYPE_SINGLE_CHOICE_DYNAMIC_DESCRIPTIONS = 8;
- public static final int TYPE_FILE_PICKER = 9;
- public static final int TYPE_RUN_RUNNABLE = 10;
- public static final int TYPE_STRING = 11;
- public static final int TYPE_HYPERLINK_HEADER = 12;
- public static final int TYPE_DATETIME_CHOICE = 13;
-
- private final CharSequence mName;
- private final CharSequence mDescription;
-
- /**
- * Base constructor.
- *
- * @param name A text string to be displayed as this setting's name.
- * @param description A text string to be displayed as this setting's description.
- */
- public SettingsItem(CharSequence name, CharSequence description)
- {
- mName = name;
- mDescription = description;
- }
-
- /**
- * @param nameId Resource ID for a text string to be displayed as this setting's name.
- * @param descriptionId Resource ID for a text string to be displayed as this setting's description.
- */
- public SettingsItem(Context context, int nameId, int descriptionId)
- {
- mName = nameId == 0 ? "" : context.getText(nameId);
- mDescription = descriptionId == 0 ? "" : context.getText(descriptionId);
- }
-
- public CharSequence getName()
- {
- return mName;
- }
-
- public CharSequence getDescription()
- {
- return mDescription;
- }
-
- /**
- * Used by {@link SettingsAdapter}'s onCreateViewHolder()
- * method to determine which type of ViewHolder should be created.
- *
- * @return An integer (ideally, one of the constants defined in this file)
- */
- public abstract int getType();
-
- protected abstract AbstractSetting getSetting();
-
- public boolean isOverridden()
- {
- AbstractSetting setting = getSetting();
- return setting != null && setting.isOverridden();
- }
-
- public boolean isEditable()
- {
- if (!NativeLibrary.IsRunning())
- return true;
-
- AbstractSetting setting = getSetting();
- return setting != null && setting.isRuntimeEditable();
- }
-
- public boolean hasSetting()
- {
- return getSetting() != null;
- }
-
- public boolean canClear()
- {
- return hasSetting();
- }
-
- public void clear(Settings settings)
- {
- getSetting().delete(settings);
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SettingsItem.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SettingsItem.kt
new file mode 100644
index 0000000000..2180cbe029
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SettingsItem.kt
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model.view
+
+import android.content.Context
+import org.dolphinemu.dolphinemu.NativeLibrary
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
+import org.dolphinemu.dolphinemu.features.settings.model.Settings
+
+/**
+ * ViewModel abstraction for an Item in the RecyclerView powering SettingsFragments.
+ * Most of them correspond to a single line in an INI file, but there are a few with multiple
+ * analogues and a few with none (Headers, for example, do not correspond to anything on disk.)
+ */
+abstract class SettingsItem {
+ val name: CharSequence
+ val description: CharSequence?
+
+ /**
+ * Base constructor.
+ *
+ * @param name A text string to be displayed as this Setting's name.
+ * @param description A text string to be displayed as this Setting's description.
+ */
+ constructor(name: CharSequence, description: CharSequence?) {
+ this.name = name
+ this.description = description
+ }
+
+ /**
+ * @param nameId Resource ID for a text string to be displayed as this Setting's name.
+ * @param descriptionId Resource ID for a text string to be displayed as this Setting's description.
+ */
+ constructor(context: Context, nameId: Int, descriptionId: Int) {
+ name = if (nameId == 0) "" else context.getText(nameId)
+ description = if (descriptionId == 0) "" else context.getText(descriptionId)
+ }
+
+ /**
+ * Used by [SettingsAdapter]'s onCreateViewHolder()
+ * method to determine which type of ViewHolder should be created.
+ *
+ * @return An integer (ideally, one of the constants defined in this file)
+ */
+ abstract val type: Int
+
+ abstract val setting: AbstractSetting?
+
+ val isOverridden: Boolean
+ get() {
+ val setting = setting
+ return setting != null && setting.isOverridden
+ }
+
+ open val isEditable: Boolean
+ get() {
+ if (!NativeLibrary.IsRunning()) return true
+ val setting = setting
+ return setting != null && setting.isRuntimeEditable
+ }
+
+ private fun hasSetting(): Boolean {
+ return setting != null
+ }
+
+ open fun canClear(): Boolean {
+ return hasSetting()
+ }
+
+ open fun clear(settings: Settings) {
+ setting!!.delete(settings)
+ }
+
+ companion object {
+ const val TYPE_HEADER = 0
+ const val TYPE_SWITCH = 1
+ const val TYPE_SINGLE_CHOICE = 2
+ const val TYPE_SLIDER = 3
+ const val TYPE_SUBMENU = 4
+ const val TYPE_INPUT_MAPPING_CONTROL = 5
+ const val TYPE_STRING_SINGLE_CHOICE = 6
+ const val TYPE_SINGLE_CHOICE_DYNAMIC_DESCRIPTIONS = 8
+ const val TYPE_FILE_PICKER = 9
+ const val TYPE_RUN_RUNNABLE = 10
+ const val TYPE_STRING = 11
+ const val TYPE_HYPERLINK_HEADER = 12
+ const val TYPE_DATETIME_CHOICE = 13
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SingleChoiceSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SingleChoiceSetting.java
deleted file mode 100644
index 1569785cd3..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SingleChoiceSetting.java
+++ /dev/null
@@ -1,72 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model.view;
-
-import android.content.Context;
-
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractIntSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
-
-public final class SingleChoiceSetting extends SettingsItem
-{
- private AbstractIntSetting mSetting;
-
- private int mChoicesId;
- private int mValuesId;
- private MenuTag menuTag;
-
- public SingleChoiceSetting(Context context, AbstractIntSetting setting, int titleId,
- int descriptionId, int choicesId, int valuesId, MenuTag menuTag)
- {
- super(context, titleId, descriptionId);
- mSetting = setting;
- mValuesId = valuesId;
- mChoicesId = choicesId;
- this.menuTag = menuTag;
- }
-
- public SingleChoiceSetting(Context context, AbstractIntSetting setting, int titleId,
- int descriptionId, int choicesId, int valuesId)
- {
- this(context, setting, titleId, descriptionId, choicesId, valuesId, null);
- }
-
- public int getChoicesId()
- {
- return mChoicesId;
- }
-
- public int getValuesId()
- {
- return mValuesId;
- }
-
- public int getSelectedValue()
- {
- return mSetting.getInt();
- }
-
- public MenuTag getMenuTag()
- {
- return menuTag;
- }
-
- public void setSelectedValue(Settings settings, int selection)
- {
- mSetting.setInt(settings, selection);
- }
-
- @Override
- public int getType()
- {
- return TYPE_SINGLE_CHOICE;
- }
-
- @Override
- public AbstractSetting getSetting()
- {
- return mSetting;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SingleChoiceSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SingleChoiceSetting.kt
new file mode 100644
index 0000000000..cd9f3ddb64
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SingleChoiceSetting.kt
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+package org.dolphinemu.dolphinemu.features.settings.model.view
+
+import android.content.Context
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractIntSetting
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
+import org.dolphinemu.dolphinemu.features.settings.model.Settings
+import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag
+
+class SingleChoiceSetting(
+ context: Context,
+ private val intSetting: AbstractIntSetting,
+ titleId: Int,
+ descriptionId: Int,
+ val choicesId: Int,
+ val valuesId: Int,
+ val menuTag: MenuTag? = null
+) : SettingsItem(context, titleId, descriptionId) {
+ override val type: Int = TYPE_SINGLE_CHOICE
+
+ override val setting: AbstractSetting
+ get() = intSetting
+
+ val selectedValue: Int
+ get() = intSetting.int
+
+ fun setSelectedValue(settings: Settings?, selection: Int) {
+ intSetting.setInt(settings!!, selection)
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SingleChoiceSettingDynamicDescriptions.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SingleChoiceSettingDynamicDescriptions.java
deleted file mode 100644
index b59e535f87..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SingleChoiceSettingDynamicDescriptions.java
+++ /dev/null
@@ -1,89 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model.view;
-
-import android.content.Context;
-
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractIntSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
-
-public final class SingleChoiceSettingDynamicDescriptions extends SettingsItem
-{
- private AbstractIntSetting mSetting;
-
- private int mChoicesId;
- private int mValuesId;
- private int mDescriptionChoicesId;
- private int mDescriptionValuesId;
- private MenuTag menuTag;
-
- public SingleChoiceSettingDynamicDescriptions(Context context, AbstractIntSetting setting,
- int titleId, int descriptionId, int choicesId, int valuesId, int descriptionChoicesId,
- int descriptionValuesId, MenuTag menuTag)
- {
- super(context, titleId, descriptionId);
- mSetting = setting;
- mValuesId = valuesId;
- mChoicesId = choicesId;
- mDescriptionChoicesId = descriptionChoicesId;
- mDescriptionValuesId = descriptionValuesId;
- this.menuTag = menuTag;
- }
-
- public SingleChoiceSettingDynamicDescriptions(Context context, AbstractIntSetting setting,
- int titleId, int descriptionId, int choicesId, int valuesId, int descriptionChoicesId,
- int descriptionValuesId)
- {
- this(context, setting, titleId, descriptionId, choicesId, valuesId, descriptionChoicesId,
- descriptionValuesId, null);
- }
-
- public int getChoicesId()
- {
- return mChoicesId;
- }
-
- public int getValuesId()
- {
- return mValuesId;
- }
-
- public int getDescriptionChoicesId()
- {
- return mDescriptionChoicesId;
- }
-
- public int getDescriptionValuesId()
- {
- return mDescriptionValuesId;
- }
-
- public int getSelectedValue()
- {
- return mSetting.getInt();
- }
-
- public MenuTag getMenuTag()
- {
- return menuTag;
- }
-
- public void setSelectedValue(Settings settings, int selection)
- {
- mSetting.setInt(settings, selection);
- }
-
- @Override
- public int getType()
- {
- return TYPE_SINGLE_CHOICE_DYNAMIC_DESCRIPTIONS;
- }
-
- @Override
- public AbstractSetting getSetting()
- {
- return mSetting;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SingleChoiceSettingDynamicDescriptions.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SingleChoiceSettingDynamicDescriptions.kt
new file mode 100644
index 0000000000..e24b2f4b08
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SingleChoiceSettingDynamicDescriptions.kt
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model.view
+
+import android.content.Context
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractIntSetting
+import org.dolphinemu.dolphinemu.features.settings.model.Settings
+
+class SingleChoiceSettingDynamicDescriptions(
+ context: Context,
+ override val setting: AbstractIntSetting,
+ titleId: Int,
+ descriptionId: Int,
+ val choicesId: Int,
+ val valuesId: Int,
+ val descriptionChoicesId: Int,
+ val descriptionValuesId: Int,
+) : SettingsItem(context, titleId, descriptionId) {
+ override val type: Int = TYPE_SINGLE_CHOICE_DYNAMIC_DESCRIPTIONS
+
+ val selectedValue: Int
+ get() = setting.int
+
+ fun setSelectedValue(settings: Settings, selection: Int) {
+ setting.setInt(settings, selection)
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SliderSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SliderSetting.java
deleted file mode 100644
index fccbe0a0b1..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SliderSetting.java
+++ /dev/null
@@ -1,61 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model.view;
-
-import android.content.Context;
-
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-
-public abstract class SliderSetting extends SettingsItem
-{
- private int mMin;
- private int mMax;
- private String mUnits;
- private int mStepSize;
-
- public SliderSetting(Context context, int nameId, int descriptionId, int min, int max,
- String units, int stepSize)
- {
- super(context, nameId, descriptionId);
- mMin = min;
- mMax = max;
- mUnits = units;
- mStepSize = stepSize;
- }
-
- public SliderSetting(CharSequence name, CharSequence description, int min, int max, String units)
- {
- super(name, description);
- mMin = min;
- mMax = max;
- mUnits = units;
- }
-
- public abstract int getSelectedValue();
-
- public int getMin()
- {
- return mMin;
- }
-
- public int getMax()
- {
- return mMax;
- }
-
- public String getUnits()
- {
- return mUnits;
- }
-
- public int getStepSize()
- {
- return mStepSize;
- }
-
- @Override
- public int getType()
- {
- return TYPE_SLIDER;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SliderSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SliderSetting.kt
new file mode 100644
index 0000000000..f595c4cea3
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SliderSetting.kt
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model.view
+
+import android.content.Context
+
+abstract class SliderSetting : SettingsItem {
+ override val type: Int = TYPE_SLIDER
+
+ var min: Int
+ private set
+ var max: Int
+ private set
+ var units: String?
+ private set
+ var stepSize = 0
+ private set
+
+ constructor(
+ context: Context,
+ nameId: Int,
+ descriptionId: Int,
+ min: Int,
+ max: Int,
+ units: String?,
+ stepSize: Int
+ ) : super(context, nameId, descriptionId) {
+ this.min = min
+ this.max = max
+ this.units = units
+ this.stepSize = stepSize
+ }
+
+ constructor(
+ name: CharSequence,
+ description: CharSequence?,
+ min: Int,
+ max: Int,
+ units: String?
+ ) : super(name, description) {
+ this.min = min
+ this.max = max
+ this.units = units
+ }
+
+ abstract val selectedValue: Int
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/StringSingleChoiceSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/StringSingleChoiceSetting.java
deleted file mode 100644
index e83fe913cd..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/StringSingleChoiceSetting.java
+++ /dev/null
@@ -1,153 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model.view;
-
-import android.content.Context;
-
-import org.dolphinemu.dolphinemu.DolphinApplication;
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractStringSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
-
-public class StringSingleChoiceSetting extends SettingsItem
-{
- private final AbstractStringSetting mSetting;
-
- protected String[] mChoices;
- protected String[] mValues;
- private final MenuTag mMenuTag;
- private int mNoChoicesAvailableString = 0;
-
- public StringSingleChoiceSetting(Context context, AbstractStringSetting setting, int titleId,
- int descriptionId, String[] choices, String[] values, MenuTag menuTag)
- {
- super(context, titleId, descriptionId);
- mSetting = setting;
- mChoices = choices;
- mValues = values;
- mMenuTag = menuTag;
- }
-
- public StringSingleChoiceSetting(Context context, AbstractStringSetting setting, int titleId,
- int descriptionId, String[] choices, String[] values)
- {
- this(context, setting, titleId, descriptionId, choices, values, null);
- }
-
- public StringSingleChoiceSetting(Context context, AbstractStringSetting setting, int titleId,
- int descriptionId, String[] choices, String[] values, int noChoicesAvailableString)
- {
- this(context, setting, titleId, descriptionId, choices, values, null);
- mNoChoicesAvailableString = noChoicesAvailableString;
- }
-
- public StringSingleChoiceSetting(Context context, AbstractStringSetting setting, int titleId,
- int descriptionId, int choicesId, int valuesId, MenuTag menuTag)
- {
- super(context, titleId, descriptionId);
- mSetting = setting;
- mChoices = DolphinApplication.getAppContext().getResources().getStringArray(choicesId);
- mValues = DolphinApplication.getAppContext().getResources().getStringArray(valuesId);
- mMenuTag = menuTag;
- }
-
- public StringSingleChoiceSetting(Context context, AbstractStringSetting setting, int titleId,
- int descriptionId, int choicesId, int valuesId)
- {
- this(context, setting, titleId, descriptionId, choicesId, valuesId, null);
- }
-
- public String[] getChoices()
- {
- return mChoices;
- }
-
- public String[] getValues()
- {
- return mValues;
- }
-
- public String getChoiceAt(int index)
- {
- if (mChoices == null)
- return null;
-
- if (index >= 0 && index < mChoices.length)
- {
- return mChoices[index];
- }
-
- return "";
- }
-
- public String getValueAt(int index)
- {
- if (mValues == null)
- return null;
-
- if (index >= 0 && index < mValues.length)
- {
- return mValues[index];
- }
-
- return "";
- }
-
- public String getSelectedChoice()
- {
- return getChoiceAt(getSelectedValueIndex());
- }
-
- public String getSelectedValue()
- {
- return mSetting.getString();
- }
-
- public int getSelectedValueIndex()
- {
- String selectedValue = getSelectedValue();
- for (int i = 0; i < mValues.length; i++)
- {
- if (mValues[i].equals(selectedValue))
- {
- return i;
- }
- }
-
- return -1;
- }
-
- public MenuTag getMenuTag()
- {
- return mMenuTag;
- }
-
- public int getNoChoicesAvailableString()
- {
- return mNoChoicesAvailableString;
- }
-
- public void setSelectedValue(Settings settings, String selection)
- {
- mSetting.setString(settings, selection);
- }
-
- public void refreshChoicesAndValues()
- {
- }
-
- @Override
- public int getType()
- {
- return TYPE_STRING_SINGLE_CHOICE;
- }
-
- @Override
- public AbstractSetting getSetting()
- {
- return mSetting;
- }
-}
-
-
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/StringSingleChoiceSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/StringSingleChoiceSetting.kt
new file mode 100644
index 0000000000..62301e23ef
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/StringSingleChoiceSetting.kt
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model.view
+
+import android.content.Context
+import org.dolphinemu.dolphinemu.DolphinApplication
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractStringSetting
+import org.dolphinemu.dolphinemu.features.settings.model.Settings
+import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag
+
+open class StringSingleChoiceSetting : SettingsItem {
+ override val type: Int = TYPE_SINGLE_CHOICE
+
+ private val stringSetting: AbstractStringSetting?
+
+ override val setting: AbstractSetting?
+ get() = stringSetting
+
+ var choices: Array<String?>?
+ protected set
+ var values: Array<String?>?
+ protected set
+ val menuTag: MenuTag?
+ var noChoicesAvailableString = 0
+ private set
+
+ open val selectedChoice: String?
+ get() = getChoiceAt(selectedValueIndex)
+
+ open val selectedValue: String
+ get() = stringSetting!!.string
+
+ @JvmOverloads
+ constructor(
+ context: Context,
+ setting: AbstractStringSetting?,
+ titleId: Int,
+ descriptionId: Int,
+ choices: Array<String?>?,
+ values: Array<String?>?,
+ menuTag: MenuTag? = null
+ ) : super(context, titleId, descriptionId) {
+ stringSetting = setting
+ this.choices = choices
+ this.values = values
+ this.menuTag = menuTag
+ }
+
+ constructor(
+ context: Context,
+ setting: AbstractStringSetting,
+ titleId: Int,
+ descriptionId: Int,
+ choices: Array<String?>,
+ values: Array<String?>,
+ noChoicesAvailableString: Int
+ ) : this(context, setting, titleId, descriptionId, choices, values) {
+ this.noChoicesAvailableString = noChoicesAvailableString
+ }
+
+ @JvmOverloads
+ constructor(
+ context: Context,
+ setting: AbstractStringSetting,
+ titleId: Int,
+ descriptionId: Int,
+ choicesId: Int,
+ valuesId: Int,
+ menuTag: MenuTag? = null
+ ) : super(context, titleId, descriptionId) {
+ stringSetting = setting
+ choices = DolphinApplication.getAppContext().resources.getStringArray(choicesId)
+ values = DolphinApplication.getAppContext().resources.getStringArray(valuesId)
+ this.menuTag = menuTag
+ }
+
+ fun getChoiceAt(index: Int): String? {
+ if (choices == null) return null
+
+ return if (index >= 0 && index < choices!!.size) {
+ choices!![index]
+ } else ""
+ }
+
+ fun getValueAt(index: Int): String? {
+ if (values == null) return null
+
+ return if (index >= 0 && index < values!!.size) {
+ values!![index]
+ } else ""
+ }
+
+ val selectedValueIndex: Int
+ get() {
+ val selectedValue = selectedValue
+ for (i in values!!.indices) {
+ if (values!![i] == selectedValue) {
+ return i
+ }
+ }
+ return -1
+ }
+
+ open fun setSelectedValue(settings: Settings?, selection: String?) {
+ stringSetting!!.setString(settings!!, selection!!)
+ }
+
+ open fun refreshChoicesAndValues() {}
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SubmenuSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SubmenuSetting.java
deleted file mode 100644
index ddfb30bfc4..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SubmenuSetting.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model.view;
-
-import android.content.Context;
-
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
-import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
-
-public final class SubmenuSetting extends SettingsItem
-{
- private MenuTag mMenuKey;
-
- public SubmenuSetting(Context context, int titleId, MenuTag menuKey)
- {
- super(context, titleId, 0);
- mMenuKey = menuKey;
- }
-
- public MenuTag getMenuKey()
- {
- return mMenuKey;
- }
-
- @Override
- public int getType()
- {
- return TYPE_SUBMENU;
- }
-
- @Override
- public AbstractSetting getSetting()
- {
- return null;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SubmenuSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SubmenuSetting.kt
new file mode 100644
index 0000000000..6fe573d7d0
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SubmenuSetting.kt
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model.view
+
+import android.content.Context
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
+import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag
+
+class SubmenuSetting(
+ context: Context,
+ titleId: Int,
+ val menuKey: MenuTag
+) : SettingsItem(context, titleId, 0) {
+ override val type: Int = TYPE_SUBMENU
+
+ override val setting: AbstractSetting? = null
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SwitchSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SwitchSetting.java
deleted file mode 100644
index dc7fa44714..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SwitchSetting.java
+++ /dev/null
@@ -1,50 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.model.view;
-
-import android.content.Context;
-
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractBooleanSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-
-public class SwitchSetting extends SettingsItem
-{
- protected AbstractBooleanSetting mSetting;
-
- public SwitchSetting(Context context, AbstractBooleanSetting setting, int titleId,
- int descriptionId)
- {
- super(context, titleId, descriptionId);
- mSetting = setting;
- }
-
- public SwitchSetting(AbstractBooleanSetting setting, CharSequence title,
- CharSequence description)
- {
- super(title, description);
- mSetting = setting;
- }
-
- public boolean isChecked()
- {
- return mSetting.getBoolean();
- }
-
- public void setChecked(Settings settings, boolean checked)
- {
- mSetting.setBoolean(settings, checked);
- }
-
- @Override
- public int getType()
- {
- return TYPE_SWITCH;
- }
-
- @Override
- public AbstractSetting getSetting()
- {
- return mSetting;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SwitchSetting.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SwitchSetting.kt
new file mode 100644
index 0000000000..5f9d0cb218
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/SwitchSetting.kt
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.model.view
+
+import android.content.Context
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractBooleanSetting
+import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
+import org.dolphinemu.dolphinemu.features.settings.model.Settings
+
+open class SwitchSetting : SettingsItem {
+ override val type: Int = TYPE_SWITCH
+
+ protected var booleanSetting: AbstractBooleanSetting
+
+ override val setting: AbstractSetting
+ get() = booleanSetting
+
+ constructor(
+ context: Context,
+ setting: AbstractBooleanSetting,
+ titleId: Int,
+ descriptionId: Int
+ ) : super(context, titleId, descriptionId) {
+ booleanSetting = setting
+ }
+
+ constructor(
+ setting: AbstractBooleanSetting,
+ title: CharSequence?,
+ description: CharSequence?
+ ) : super(title!!, description) {
+ booleanSetting = setting
+ }
+
+ open val isChecked: Boolean
+ get() = booleanSetting.boolean
+
+ open fun setChecked(settings: Settings?, checked: Boolean) {
+ booleanSetting.setBoolean(settings!!, checked)
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/MenuTag.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/MenuTag.java
deleted file mode 100644
index a0a67dd838..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/MenuTag.java
+++ /dev/null
@@ -1,165 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.ui;
-
-import androidx.annotation.NonNull;
-
-import org.dolphinemu.dolphinemu.features.input.model.controlleremu.EmulatedController;
-
-public enum MenuTag
-{
- SETTINGS("settings"),
- CONFIG("config"),
- CONFIG_GENERAL("config_general"),
- CONFIG_INTERFACE("config_interface"),
- CONFIG_AUDIO("config_audio"),
- CONFIG_PATHS("config_paths"),
- CONFIG_GAME_CUBE("config_gamecube"),
- CONFIG_SERIALPORT1("config_serialport1"),
- CONFIG_WII("config_wii"),
- CONFIG_ADVANCED("config_advanced"),
- CONFIG_LOG("config_log"),
- DEBUG("debug"),
- GRAPHICS("graphics"),
- ENHANCEMENTS("enhancements"),
- STEREOSCOPY("stereoscopy"),
- HACKS("hacks"),
- STATISTICS("statistics"),
- ADVANCED_GRAPHICS("advanced_graphics"),
- GCPAD_TYPE("gc_pad_type"),
- WIIMOTE("wiimote"),
- WIIMOTE_EXTENSION("wiimote_extension"),
- GCPAD_1("gcpad", 0),
- GCPAD_2("gcpad", 1),
- GCPAD_3("gcpad", 2),
- GCPAD_4("gcpad", 3),
- WIIMOTE_1("wiimote", 0),
- WIIMOTE_2("wiimote", 1),
- WIIMOTE_3("wiimote", 2),
- WIIMOTE_4("wiimote", 3),
- WIIMOTE_EXTENSION_1("wiimote_extension", 0),
- WIIMOTE_EXTENSION_2("wiimote_extension", 1),
- WIIMOTE_EXTENSION_3("wiimote_extension", 2),
- WIIMOTE_EXTENSION_4("wiimote_extension", 3),
- WIIMOTE_GENERAL_1("wiimote_general", 0),
- WIIMOTE_GENERAL_2("wiimote_general", 1),
- WIIMOTE_GENERAL_3("wiimote_general", 2),
- WIIMOTE_GENERAL_4("wiimote_general", 3),
- WIIMOTE_MOTION_SIMULATION_1("wiimote_motion_simulation", 0),
- WIIMOTE_MOTION_SIMULATION_2("wiimote_motion_simulation", 1),
- WIIMOTE_MOTION_SIMULATION_3("wiimote_motion_simulation", 2),
- WIIMOTE_MOTION_SIMULATION_4("wiimote_motion_simulation", 3),
- WIIMOTE_MOTION_INPUT_1("wiimote_motion_input", 0),
- WIIMOTE_MOTION_INPUT_2("wiimote_motion_input", 1),
- WIIMOTE_MOTION_INPUT_3("wiimote_motion_input", 2),
- WIIMOTE_MOTION_INPUT_4("wiimote_motion_input", 3);
-
- private String tag;
- private int subType = -1;
-
- MenuTag(String tag)
- {
- this.tag = tag;
- }
-
- MenuTag(String tag, int subtype)
- {
- this.tag = tag;
- this.subType = subtype;
- }
-
- @NonNull
- @Override
- public String toString()
- {
- if (subType != -1)
- {
- return tag + subType;
- }
-
- return tag;
- }
-
- public String getTag()
- {
- return tag;
- }
-
- public int getSubType()
- {
- return subType;
- }
-
- public EmulatedController getCorrespondingEmulatedController()
- {
- if (isGCPadMenu())
- return EmulatedController.getGcPad(getSubType());
- else if (isWiimoteMenu())
- return EmulatedController.getWiimote(getSubType());
- else
- throw new UnsupportedOperationException();
- }
-
- public boolean isSerialPort1Menu()
- {
- return this == CONFIG_SERIALPORT1;
- }
-
- public boolean isGCPadMenu()
- {
- return this == GCPAD_1 || this == GCPAD_2 || this == GCPAD_3 || this == GCPAD_4;
- }
-
- public boolean isWiimoteMenu()
- {
- return this == WIIMOTE_1 || this == WIIMOTE_2 || this == WIIMOTE_3 || this == WIIMOTE_4;
- }
-
- public boolean isWiimoteExtensionMenu()
- {
- return this == WIIMOTE_EXTENSION_1 || this == WIIMOTE_EXTENSION_2
- || this == WIIMOTE_EXTENSION_3 || this == WIIMOTE_EXTENSION_4;
- }
-
- public static MenuTag getGCPadMenuTag(int subtype)
- {
- return getMenuTag("gcpad", subtype);
- }
-
- public static MenuTag getWiimoteMenuTag(int subtype)
- {
- return getMenuTag("wiimote", subtype);
- }
-
- public static MenuTag getWiimoteExtensionMenuTag(int subtype)
- {
- return getMenuTag("wiimote_extension", subtype);
- }
-
- public static MenuTag getWiimoteGeneralMenuTag(int subtype)
- {
- return getMenuTag("wiimote_general", subtype);
- }
-
- public static MenuTag getWiimoteMotionSimulationMenuTag(int subtype)
- {
- return getMenuTag("wiimote_motion_simulation", subtype);
- }
-
- public static MenuTag getWiimoteMotionInputMenuTag(int subtype)
- {
- return getMenuTag("wiimote_motion_input", subtype);
- }
-
- private static MenuTag getMenuTag(String tag, int subtype)
- {
- for (MenuTag menuTag : MenuTag.values())
- {
- if (menuTag.tag.equals(tag) && menuTag.subType == subtype)
- return menuTag;
- }
-
- throw new IllegalArgumentException("You are asking for a menu that is not available or " +
- "passing a wrong subtype");
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/MenuTag.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/MenuTag.kt
new file mode 100644
index 0000000000..38c162d6fd
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/MenuTag.kt
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.ui
+
+import org.dolphinemu.dolphinemu.features.input.model.controlleremu.EmulatedController
+
+enum class MenuTag {
+ SETTINGS("settings"),
+ CONFIG("config"),
+ CONFIG_GENERAL("config_general"),
+ CONFIG_INTERFACE("config_interface"),
+ CONFIG_AUDIO("config_audio"),
+ CONFIG_PATHS("config_paths"),
+ CONFIG_GAME_CUBE("config_gamecube"),
+ CONFIG_SERIALPORT1("config_serialport1"),
+ CONFIG_WII("config_wii"),
+ CONFIG_ADVANCED("config_advanced"),
+ CONFIG_LOG("config_log"),
+ DEBUG("debug"),
+ GRAPHICS("graphics"),
+ ENHANCEMENTS("enhancements"),
+ STEREOSCOPY("stereoscopy"),
+ HACKS("hacks"),
+ STATISTICS("statistics"),
+ ADVANCED_GRAPHICS("advanced_graphics"),
+ GCPAD_TYPE("gc_pad_type"),
+ WIIMOTE("wiimote"),
+ WIIMOTE_EXTENSION("wiimote_extension"),
+ GCPAD_1("gcpad", 0),
+ GCPAD_2("gcpad", 1),
+ GCPAD_3("gcpad", 2),
+ GCPAD_4("gcpad", 3),
+ WIIMOTE_1("wiimote", 0),
+ WIIMOTE_2("wiimote", 1),
+ WIIMOTE_3("wiimote", 2),
+ WIIMOTE_4("wiimote", 3),
+ WIIMOTE_EXTENSION_1("wiimote_extension", 0),
+ WIIMOTE_EXTENSION_2("wiimote_extension", 1),
+ WIIMOTE_EXTENSION_3("wiimote_extension", 2),
+ WIIMOTE_EXTENSION_4("wiimote_extension", 3),
+ WIIMOTE_GENERAL_1("wiimote_general", 0),
+ WIIMOTE_GENERAL_2("wiimote_general", 1),
+ WIIMOTE_GENERAL_3("wiimote_general", 2),
+ WIIMOTE_GENERAL_4("wiimote_general", 3),
+ WIIMOTE_MOTION_SIMULATION_1("wiimote_motion_simulation", 0),
+ WIIMOTE_MOTION_SIMULATION_2("wiimote_motion_simulation", 1),
+ WIIMOTE_MOTION_SIMULATION_3("wiimote_motion_simulation", 2),
+ WIIMOTE_MOTION_SIMULATION_4("wiimote_motion_simulation", 3),
+ WIIMOTE_MOTION_INPUT_1("wiimote_motion_input", 0),
+ WIIMOTE_MOTION_INPUT_2("wiimote_motion_input", 1),
+ WIIMOTE_MOTION_INPUT_3("wiimote_motion_input", 2),
+ WIIMOTE_MOTION_INPUT_4("wiimote_motion_input", 3);
+
+ var tag: String
+ private set
+ var subType = -1
+ private set
+
+ constructor(tag: String) {
+ this.tag = tag
+ }
+
+ constructor(tag: String, subtype: Int) {
+ this.tag = tag
+ subType = subtype
+ }
+
+ override fun toString(): String {
+ return if (subType != -1) {
+ tag + subType
+ } else tag
+ }
+
+ val correspondingEmulatedController: EmulatedController
+ get() = if (isGCPadMenu) EmulatedController.getGcPad(subType) else if (isWiimoteMenu) EmulatedController.getWiimote(
+ subType
+ ) else throw UnsupportedOperationException()
+
+ val isSerialPort1Menu: Boolean
+ get() = this == CONFIG_SERIALPORT1
+
+ val isGCPadMenu: Boolean
+ get() = this == GCPAD_1 || this == GCPAD_2 || this == GCPAD_3 || this == GCPAD_4
+
+ val isWiimoteMenu: Boolean
+ get() = this == WIIMOTE_1 || this == WIIMOTE_2 || this == WIIMOTE_3 || this == WIIMOTE_4
+
+ val isWiimoteExtensionMenu: Boolean
+ get() = this == WIIMOTE_EXTENSION_1 || this == WIIMOTE_EXTENSION_2 || this == WIIMOTE_EXTENSION_3 || this == WIIMOTE_EXTENSION_4
+
+ companion object {
+ @JvmStatic
+ fun getGCPadMenuTag(subtype: Int): MenuTag {
+ return getMenuTag("gcpad", subtype)
+ }
+
+ @JvmStatic
+ fun getWiimoteMenuTag(subtype: Int): MenuTag {
+ return getMenuTag("wiimote", subtype)
+ }
+
+ @JvmStatic
+ fun getWiimoteExtensionMenuTag(subtype: Int): MenuTag {
+ return getMenuTag("wiimote_extension", subtype)
+ }
+
+ @JvmStatic
+ fun getWiimoteGeneralMenuTag(subtype: Int): MenuTag {
+ return getMenuTag("wiimote_general", subtype)
+ }
+
+ @JvmStatic
+ fun getWiimoteMotionSimulationMenuTag(subtype: Int): MenuTag {
+ return getMenuTag("wiimote_motion_simulation", subtype)
+ }
+
+ @JvmStatic
+ fun getWiimoteMotionInputMenuTag(subtype: Int): MenuTag {
+ return getMenuTag("wiimote_motion_input", subtype)
+ }
+
+ private fun getMenuTag(tag: String, subtype: Int): MenuTag {
+ for (menuTag in values()) {
+ if (menuTag.tag == tag && menuTag.subType == subtype) return menuTag
+ }
+ throw IllegalArgumentException(
+ "You are asking for a menu that is not available or " +
+ "passing a wrong subtype"
+ )
+ }
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.java
deleted file mode 100644
index 4f1e4bdf45..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.java
+++ /dev/null
@@ -1,401 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.ui;
-
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.View;
-import android.widget.Toast;
-
-import androidx.annotation.NonNull;
-import androidx.appcompat.app.AlertDialog;
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.core.graphics.Insets;
-import androidx.core.view.ViewCompat;
-import androidx.core.view.WindowCompat;
-import androidx.core.view.WindowInsetsCompat;
-import androidx.fragment.app.DialogFragment;
-import androidx.fragment.app.FragmentTransaction;
-import androidx.lifecycle.ViewModelProvider;
-
-import com.google.android.material.appbar.CollapsingToolbarLayout;
-import com.google.android.material.color.MaterialColors;
-import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-
-import org.dolphinemu.dolphinemu.NativeLibrary;
-import org.dolphinemu.dolphinemu.R;
-import org.dolphinemu.dolphinemu.databinding.ActivitySettingsBinding;
-import org.dolphinemu.dolphinemu.ui.main.MainPresenter;
-import org.dolphinemu.dolphinemu.utils.FileBrowserHelper;
-import org.dolphinemu.dolphinemu.utils.InsetsHelper;
-import org.dolphinemu.dolphinemu.utils.ThemeHelper;
-
-import java.util.Set;
-
-public final class SettingsActivity extends AppCompatActivity implements SettingsActivityView
-{
- private static final String ARG_MENU_TAG = "menu_tag";
- private static final String ARG_GAME_ID = "game_id";
- private static final String ARG_REVISION = "revision";
- private static final String ARG_IS_WII = "is_wii";
- private static final String KEY_MAPPING_ALL_DEVICES = "all_devices";
- private static final String FRAGMENT_TAG = "settings";
- private static final String FRAGMENT_DIALOG_TAG = "settings_dialog";
-
- private SettingsActivityPresenter mPresenter;
- private AlertDialog dialog;
- private CollapsingToolbarLayout mToolbarLayout;
-
- private ActivitySettingsBinding mBinding;
-
- private boolean mMappingAllDevices = false;
-
- public static void launch(Context context, MenuTag menuTag, String gameId, int revision,
- boolean isWii)
- {
- Intent settings = new Intent(context, SettingsActivity.class);
- settings.putExtra(ARG_MENU_TAG, menuTag);
- settings.putExtra(ARG_GAME_ID, gameId);
- settings.putExtra(ARG_REVISION, revision);
- settings.putExtra(ARG_IS_WII, isWii);
- context.startActivity(settings);
- }
-
- public static void launch(Context context, MenuTag menuTag)
- {
- Intent settings = new Intent(context, SettingsActivity.class);
- settings.putExtra(ARG_MENU_TAG, menuTag);
- settings.putExtra(ARG_IS_WII, !NativeLibrary.IsRunning() || NativeLibrary.IsEmulatingWii());
- context.startActivity(settings);
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState)
- {
- ThemeHelper.setTheme(this);
-
- super.onCreate(savedInstanceState);
-
- // If we came here from the game list, we don't want to rescan when returning to the game list.
- // But if we came here after UserDataActivity restarted the app, we do want to rescan.
- if (savedInstanceState == null)
- {
- MainPresenter.skipRescanningLibrary();
- }
- else
- {
- mMappingAllDevices = savedInstanceState.getBoolean(KEY_MAPPING_ALL_DEVICES);
- }
-
- mBinding = ActivitySettingsBinding.inflate(getLayoutInflater());
- setContentView(mBinding.getRoot());
-
- WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
-
- Intent launcher = getIntent();
- String gameID = launcher.getStringExtra(ARG_GAME_ID);
- if (gameID == null)
- gameID = "";
- int revision = launcher.getIntExtra(ARG_REVISION, 0);
- boolean isWii = launcher.getBooleanExtra(ARG_IS_WII, true);
- MenuTag menuTag = (MenuTag) launcher.getSerializableExtra(ARG_MENU_TAG);
-
- mPresenter = new SettingsActivityPresenter(this, getSettings());
- mPresenter.onCreate(savedInstanceState, menuTag, gameID, revision, isWii, this);
-
- mToolbarLayout = mBinding.toolbarSettingsLayout;
- setSupportActionBar(mBinding.toolbarSettings);
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
-
- // TODO: Remove this when CollapsingToolbarLayouts are fixed by Google
- // https://github.com/material-components/material-components-android/issues/1310
- ViewCompat.setOnApplyWindowInsetsListener(mToolbarLayout, null);
-
- setInsets();
- ThemeHelper.enableScrollTint(this, mBinding.toolbarSettings, mBinding.appbarSettings);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu)
- {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.menu_settings, menu);
-
- return true;
- }
-
- @Override
- protected void onSaveInstanceState(@NonNull Bundle outState)
- {
- // Critical: If super method is not called, rotations will be busted.
- super.onSaveInstanceState(outState);
-
- mPresenter.saveState(outState);
-
- outState.putBoolean(KEY_MAPPING_ALL_DEVICES, mMappingAllDevices);
- }
-
- @Override
- protected void onStart()
- {
- super.onStart();
- mPresenter.onStart();
- }
-
- /**
- * If this is called, the user has left the settings screen (potentially through the
- * home button) and will expect their changes to be persisted.
- */
- @Override
- protected void onStop()
- {
- super.onStop();
- mPresenter.onStop(isFinishing());
- }
-
- @Override
- protected void onDestroy()
- {
- super.onDestroy();
- mPresenter.onDestroy();
- }
-
- @Override
- public void showSettingsFragment(MenuTag menuTag, Bundle extras, boolean addToStack,
- String gameID)
- {
- if (!addToStack && getFragment() != null)
- return;
-
- FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
-
- if (addToStack)
- {
- if (areSystemAnimationsEnabled())
- {
- transaction.setCustomAnimations(
- R.anim.anim_settings_fragment_in,
- R.anim.anim_settings_fragment_out,
- 0,
- R.anim.anim_pop_settings_fragment_out);
- }
-
- transaction.addToBackStack(null);
- }
- transaction.replace(R.id.frame_content_settings,
- SettingsFragment.newInstance(menuTag, gameID, extras), FRAGMENT_TAG);
-
- transaction.commit();
- }
-
- @Override
- public void showDialogFragment(DialogFragment fragment)
- {
- fragment.show(getSupportFragmentManager(), FRAGMENT_DIALOG_TAG);
- }
-
- private boolean areSystemAnimationsEnabled()
- {
- float duration = Settings.Global.getFloat(
- getContentResolver(),
- Settings.Global.ANIMATOR_DURATION_SCALE, 1);
- float transition = Settings.Global.getFloat(
- getContentResolver(),
- Settings.Global.TRANSITION_ANIMATION_SCALE, 1);
- return duration != 0 && transition != 0;
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent result)
- {
- super.onActivityResult(requestCode, resultCode, result);
-
- // If the user picked a file, as opposed to just backing out.
- if (resultCode == RESULT_OK)
- {
- if (requestCode != MainPresenter.REQUEST_DIRECTORY)
- {
- Uri uri = canonicalizeIfPossible(result.getData());
-
- Set<String> validExtensions = requestCode == MainPresenter.REQUEST_GAME_FILE ?
- FileBrowserHelper.GAME_EXTENSIONS : FileBrowserHelper.RAW_EXTENSION;
-
- int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION;
- if (requestCode != MainPresenter.REQUEST_GAME_FILE)
- flags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
- int takeFlags = flags & result.getFlags();
-
- FileBrowserHelper.runAfterExtensionCheck(this, uri, validExtensions, () ->
- {
- getContentResolver().takePersistableUriPermission(uri, takeFlags);
- getFragment().getAdapter().onFilePickerConfirmation(uri.toString());
- });
- }
- else
- {
- String path = FileBrowserHelper.getSelectedPath(result);
- getFragment().getAdapter().onFilePickerConfirmation(path);
- }
- }
- }
-
- @NonNull
- private Uri canonicalizeIfPossible(@NonNull Uri uri)
- {
- Uri canonicalizedUri = getContentResolver().canonicalize(uri);
- return canonicalizedUri != null ? canonicalizedUri : uri;
- }
-
- @Override
- public void showLoading()
- {
- if (dialog == null)
- {
- dialog = new MaterialAlertDialogBuilder(this)
- .setTitle(getString(R.string.load_settings))
- .setView(R.layout.dialog_indeterminate_progress)
- .create();
- }
- dialog.show();
- }
-
- @Override
- public void hideLoading()
- {
- dialog.dismiss();
- }
-
- @Override
- public void showGameIniJunkDeletionQuestion()
- {
- new MaterialAlertDialogBuilder(this)
- .setTitle(getString(R.string.game_ini_junk_title))
- .setMessage(getString(R.string.game_ini_junk_question))
- .setPositiveButton(R.string.yes, (dialogInterface, i) -> mPresenter.clearGameSettings())
- .setNegativeButton(R.string.no, null)
- .show();
- }
-
- @Override
- public org.dolphinemu.dolphinemu.features.settings.model.Settings getSettings()
- {
- return new ViewModelProvider(this).get(SettingsViewModel.class).getSettings();
- }
-
- @Override
- public void onSettingsFileLoaded(
- org.dolphinemu.dolphinemu.features.settings.model.Settings settings)
- {
- SettingsFragmentView fragment = getFragment();
-
- if (fragment != null)
- {
- fragment.onSettingsFileLoaded(settings);
- }
- }
-
- @Override
- public void onSettingsFileNotFound()
- {
- SettingsFragmentView fragment = getFragment();
-
- if (fragment != null)
- {
- fragment.loadDefaultSettings();
- }
- }
-
- @Override
- public void showToastMessage(String message)
- {
- Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
- }
-
- @Override
- public void onSettingChanged()
- {
- mPresenter.onSettingChanged();
- }
-
- @Override
- public void onControllerSettingsChanged()
- {
- getFragment().onControllerSettingsChanged();
- }
-
- @Override
- public void onMenuTagAction(@NonNull MenuTag menuTag, int value)
- {
- mPresenter.onMenuTagAction(menuTag, value);
- }
-
- @Override
- public boolean hasMenuTagActionForValue(@NonNull MenuTag menuTag, int value)
- {
- return mPresenter.hasMenuTagActionForValue(menuTag, value);
- }
-
- @Override
- public boolean onSupportNavigateUp()
- {
- onBackPressed();
- return true;
- }
-
- private SettingsFragment getFragment()
- {
- return (SettingsFragment) getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG);
- }
-
- public void setToolbarTitle(String title)
- {
- mBinding.toolbarSettingsLayout.setTitle(title);
- }
-
- @Override
- public void setMappingAllDevices(boolean allDevices)
- {
- mMappingAllDevices = allDevices;
- }
-
- @Override
- public boolean isMappingAllDevices()
- {
- return mMappingAllDevices;
- }
-
- @Override
- public int setOldControllerSettingsWarningVisibility(boolean visible)
- {
- // We use INVISIBLE instead of GONE to avoid getting a stale height for the return value
- mBinding.oldControllerSettingsWarning.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
- return visible ? mBinding.oldControllerSettingsWarning.getHeight() : 0;
- }
-
- private void setInsets()
- {
- ViewCompat.setOnApplyWindowInsetsListener(mBinding.appbarSettings, (v, windowInsets) ->
- {
- Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
-
- InsetsHelper.insetAppBar(insets, mBinding.appbarSettings);
-
- mBinding.frameContentSettings.setPadding(insets.left, 0, insets.right, 0);
-
- int textPadding = getResources().getDimensionPixelSize(R.dimen.spacing_large);
- mBinding.oldControllerSettingsWarning.setPadding(textPadding + insets.left, textPadding,
- textPadding + insets.right, textPadding + insets.bottom);
-
- InsetsHelper.applyNavbarWorkaround(insets.bottom, mBinding.workaroundView);
- ThemeHelper.setNavigationBarColor(this,
- MaterialColors.getColor(mBinding.appbarSettings, R.attr.colorSurface));
-
- return windowInsets;
- });
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.kt
new file mode 100644
index 0000000000..4d950d9933
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.kt
@@ -0,0 +1,323 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.ui
+
+import android.content.Context
+import android.content.DialogInterface
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import android.view.Menu
+import android.view.View
+import android.widget.Toast
+import androidx.appcompat.app.AlertDialog
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.fragment.app.DialogFragment
+import androidx.lifecycle.ViewModelProvider
+import com.google.android.material.appbar.CollapsingToolbarLayout
+import com.google.android.material.color.MaterialColors
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import org.dolphinemu.dolphinemu.NativeLibrary
+import org.dolphinemu.dolphinemu.R
+import org.dolphinemu.dolphinemu.databinding.ActivitySettingsBinding
+import org.dolphinemu.dolphinemu.features.settings.model.Settings
+import org.dolphinemu.dolphinemu.features.settings.ui.SettingsFragment.Companion.newInstance
+import org.dolphinemu.dolphinemu.ui.main.MainPresenter
+import org.dolphinemu.dolphinemu.utils.FileBrowserHelper
+import org.dolphinemu.dolphinemu.utils.InsetsHelper
+import org.dolphinemu.dolphinemu.utils.SerializableHelper.serializable
+import org.dolphinemu.dolphinemu.utils.ThemeHelper.enableScrollTint
+import org.dolphinemu.dolphinemu.utils.ThemeHelper.setNavigationBarColor
+import org.dolphinemu.dolphinemu.utils.ThemeHelper.setTheme
+
+class SettingsActivity : AppCompatActivity(), SettingsActivityView {
+ private var presenter: SettingsActivityPresenter? = null
+ private var dialog: AlertDialog? = null
+ private var toolbarLayout: CollapsingToolbarLayout? = null
+ private var binding: ActivitySettingsBinding? = null
+
+ override var isMappingAllDevices = false
+
+ override val settings: Settings
+ get() = ViewModelProvider(this)[SettingsViewModel::class.java].settings
+
+ private val fragment: SettingsFragment?
+ get() = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG) as SettingsFragment?
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ setTheme(this)
+
+ super.onCreate(savedInstanceState)
+
+ // If we came here from the game list, we don't want to rescan when returning to the game list.
+ // But if we came here after UserDataActivity restarted the app, we do want to rescan.
+ if (savedInstanceState == null) {
+ MainPresenter.skipRescanningLibrary()
+ } else {
+ isMappingAllDevices = savedInstanceState.getBoolean(KEY_MAPPING_ALL_DEVICES)
+ }
+
+ binding = ActivitySettingsBinding.inflate(layoutInflater)
+ setContentView(binding!!.root)
+
+ WindowCompat.setDecorFitsSystemWindows(window, false)
+
+ val launcher = intent
+ var gameID = launcher.getStringExtra(ARG_GAME_ID)
+ if (gameID == null) gameID = ""
+ val revision = launcher.getIntExtra(ARG_REVISION, 0)
+ val isWii = launcher.getBooleanExtra(ARG_IS_WII, true)
+ val menuTag = launcher.serializable<MenuTag>(ARG_MENU_TAG)
+
+ presenter = SettingsActivityPresenter(this, settings)
+ presenter!!.onCreate(savedInstanceState, menuTag, gameID, revision, isWii, this)
+ toolbarLayout = binding!!.toolbarSettingsLayout
+ setSupportActionBar(binding!!.toolbarSettings)
+ supportActionBar!!.setDisplayHomeAsUpEnabled(true)
+
+ // TODO: Remove this when CollapsingToolbarLayouts are fixed by Google
+ // https://github.com/material-components/material-components-android/issues/1310
+ ViewCompat.setOnApplyWindowInsetsListener(toolbarLayout!!, null)
+ setInsets()
+ enableScrollTint(this, binding!!.toolbarSettings, binding!!.appbarSettings)
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu): Boolean {
+ val inflater = menuInflater
+ inflater.inflate(R.menu.menu_settings, menu)
+ return true
+ }
+
+ override fun onSaveInstanceState(outState: Bundle) {
+ // Critical: If super method is not called, rotations will be busted.
+ super.onSaveInstanceState(outState)
+ presenter!!.saveState(outState)
+ outState.putBoolean(KEY_MAPPING_ALL_DEVICES, isMappingAllDevices)
+ }
+
+ override fun onStart() {
+ super.onStart()
+ presenter!!.onStart()
+ }
+
+ /**
+ * If this is called, the user has left the settings screen (potentially through the
+ * home button) and will expect their changes to be persisted.
+ */
+ override fun onStop() {
+ super.onStop()
+ presenter!!.onStop(isFinishing)
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ presenter!!.onDestroy()
+ }
+
+ override fun showSettingsFragment(
+ menuTag: MenuTag,
+ extras: Bundle?,
+ addToStack: Boolean,
+ gameId: String
+ ) {
+ if (!addToStack && fragment != null) return
+ val transaction = supportFragmentManager.beginTransaction()
+ if (addToStack) {
+ if (areSystemAnimationsEnabled()) {
+ transaction.setCustomAnimations(
+ R.anim.anim_settings_fragment_in,
+ R.anim.anim_settings_fragment_out,
+ 0,
+ R.anim.anim_pop_settings_fragment_out
+ )
+ }
+ transaction.addToBackStack(null)
+ }
+ transaction.replace(
+ R.id.frame_content_settings,
+ newInstance(menuTag, gameId, extras), FRAGMENT_TAG
+ )
+ transaction.commit()
+ }
+
+ override fun showDialogFragment(fragment: DialogFragment) {
+ fragment.show(supportFragmentManager, FRAGMENT_DIALOG_TAG)
+ }
+
+ private fun areSystemAnimationsEnabled(): Boolean {
+ val duration = android.provider.Settings.Global.getFloat(
+ contentResolver,
+ android.provider.Settings.Global.ANIMATOR_DURATION_SCALE,
+ 1f
+ )
+ val transition = android.provider.Settings.Global.getFloat(
+ contentResolver,
+ android.provider.Settings.Global.TRANSITION_ANIMATION_SCALE,
+ 1f
+ )
+ return duration != 0f && transition != 0f
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, result: Intent?) {
+ super.onActivityResult(requestCode, resultCode, result)
+
+ // If the user picked a file, as opposed to just backing out.
+ if (resultCode == RESULT_OK) {
+ if (requestCode != MainPresenter.REQUEST_DIRECTORY) {
+ val uri = canonicalizeIfPossible(result!!.data!!)
+ val validExtensions: Set<String> =
+ if (requestCode == MainPresenter.REQUEST_GAME_FILE) FileBrowserHelper.GAME_EXTENSIONS else FileBrowserHelper.RAW_EXTENSION
+ var flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
+ if (requestCode != MainPresenter.REQUEST_GAME_FILE) flags =
+ flags or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+ val takeFlags = flags and result.flags
+ FileBrowserHelper.runAfterExtensionCheck(this, uri, validExtensions) {
+ contentResolver.takePersistableUriPermission(uri, takeFlags)
+ fragment!!.adapter!!.onFilePickerConfirmation(uri.toString())
+ }
+ } else {
+ val path = FileBrowserHelper.getSelectedPath(result)
+ fragment!!.adapter!!.onFilePickerConfirmation(path!!)
+ }
+ }
+ }
+
+ private fun canonicalizeIfPossible(uri: Uri): Uri {
+ val canonicalizedUri = contentResolver.canonicalize(uri)
+ return canonicalizedUri ?: uri
+ }
+
+ override fun showLoading() {
+ if (dialog == null) {
+ dialog = MaterialAlertDialogBuilder(this)
+ .setTitle(getString(R.string.load_settings))
+ .setView(R.layout.dialog_indeterminate_progress)
+ .create()
+ }
+ dialog!!.show()
+ }
+
+ override fun hideLoading() {
+ dialog!!.dismiss()
+ }
+
+ override fun showGameIniJunkDeletionQuestion() {
+ MaterialAlertDialogBuilder(this)
+ .setTitle(getString(R.string.game_ini_junk_title))
+ .setMessage(getString(R.string.game_ini_junk_question))
+ .setPositiveButton(R.string.yes) { _: DialogInterface?, _: Int -> presenter!!.clearGameSettings() }
+ .setNegativeButton(R.string.no, null)
+ .show()
+ }
+
+ override fun onSettingsFileLoaded(settings: Settings) {
+ val fragment: SettingsFragmentView? = fragment
+ fragment?.onSettingsFileLoaded(settings)
+ }
+
+ override fun onSettingsFileNotFound() {
+ val fragment: SettingsFragmentView? = fragment
+ fragment?.loadDefaultSettings()
+ }
+
+ override fun showToastMessage(message: String) {
+ Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
+ }
+
+ override fun onSettingChanged() {
+ presenter!!.onSettingChanged()
+ }
+
+ override fun onControllerSettingsChanged() {
+ fragment!!.onControllerSettingsChanged()
+ }
+
+ override fun onMenuTagAction(menuTag: MenuTag, value: Int) {
+ presenter!!.onMenuTagAction(menuTag, value)
+ }
+
+ override fun hasMenuTagActionForValue(menuTag: MenuTag, value: Int): Boolean {
+ return presenter!!.hasMenuTagActionForValue(menuTag, value)
+ }
+
+ override fun onSupportNavigateUp(): Boolean {
+ onBackPressed()
+ return true
+ }
+
+ override fun setToolbarTitle(title: String) {
+ binding!!.toolbarSettingsLayout.title = title
+ }
+
+ override fun setOldControllerSettingsWarningVisibility(visible: Boolean): Int {
+ // We use INVISIBLE instead of GONE to avoid getting a stale height for the return value
+ binding!!.oldControllerSettingsWarning.visibility =
+ if (visible) View.VISIBLE else View.INVISIBLE
+ return if (visible) binding!!.oldControllerSettingsWarning.height else 0
+ }
+
+ private fun setInsets() {
+ ViewCompat.setOnApplyWindowInsetsListener(binding!!.appbarSettings) { _: View?, windowInsets: WindowInsetsCompat ->
+ val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+
+ InsetsHelper.insetAppBar(insets, binding!!.appbarSettings)
+
+ binding!!.frameContentSettings.setPadding(insets.left, 0, insets.right, 0)
+ val textPadding = resources.getDimensionPixelSize(R.dimen.spacing_large)
+ binding!!.oldControllerSettingsWarning.setPadding(
+ textPadding + insets.left,
+ textPadding,
+ textPadding + insets.right,
+ textPadding + insets.bottom
+ )
+
+ InsetsHelper.applyNavbarWorkaround(insets.bottom, binding!!.workaroundView)
+ setNavigationBarColor(
+ this,
+ MaterialColors.getColor(binding!!.appbarSettings, R.attr.colorSurface)
+ )
+
+ windowInsets
+ }
+ }
+
+ companion object {
+ private const val ARG_MENU_TAG = "menu_tag"
+ private const val ARG_GAME_ID = "game_id"
+ private const val ARG_REVISION = "revision"
+ private const val ARG_IS_WII = "is_wii"
+ private const val KEY_MAPPING_ALL_DEVICES = "all_devices"
+ private const val FRAGMENT_TAG = "settings"
+ private const val FRAGMENT_DIALOG_TAG = "settings_dialog"
+
+ @JvmStatic
+ fun launch(
+ context: Context,
+ menuTag: MenuTag?,
+ gameId: String?,
+ revision: Int,
+ isWii: Boolean
+ ) {
+ val settings = Intent(context, SettingsActivity::class.java)
+ settings.putExtra(ARG_MENU_TAG, menuTag)
+ settings.putExtra(ARG_GAME_ID, gameId)
+ settings.putExtra(ARG_REVISION, revision)
+ settings.putExtra(ARG_IS_WII, isWii)
+ context.startActivity(settings)
+ }
+
+ @JvmStatic
+ fun launch(context: Context, menuTag: MenuTag?) {
+ val settings = Intent(context, SettingsActivity::class.java)
+ settings.putExtra(ARG_MENU_TAG, menuTag)
+ settings.putExtra(
+ ARG_IS_WII,
+ !NativeLibrary.IsRunning() || NativeLibrary.IsEmulatingWii()
+ )
+ context.startActivity(settings)
+ }
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityPresenter.java
deleted file mode 100644
index 00561daffb..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityPresenter.java
+++ /dev/null
@@ -1,197 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.ui;
-
-import android.os.Bundle;
-import android.text.TextUtils;
-
-import androidx.annotation.NonNull;
-import androidx.core.app.ComponentActivity;
-
-import org.dolphinemu.dolphinemu.R;
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-import org.dolphinemu.dolphinemu.utils.AfterDirectoryInitializationRunner;
-import org.dolphinemu.dolphinemu.utils.DirectoryInitialization;
-import org.dolphinemu.dolphinemu.utils.Log;
-
-public final class SettingsActivityPresenter
-{
- private static final String KEY_SHOULD_SAVE = "should_save";
-
- private SettingsActivityView mView;
-
- private Settings mSettings;
-
- private boolean mShouldSave;
-
- private MenuTag mMenuTag;
- private String mGameId;
- private int mRevision;
- private boolean mIsWii;
- private ComponentActivity mActivity;
-
- SettingsActivityPresenter(SettingsActivityView view, Settings settings)
- {
- mView = view;
- mSettings = settings;
- }
-
- public void onCreate(Bundle savedInstanceState, MenuTag menuTag, String gameId, int revision,
- boolean isWii, ComponentActivity activity)
- {
- this.mMenuTag = menuTag;
- this.mGameId = gameId;
- this.mRevision = revision;
- this.mIsWii = isWii;
- this.mActivity = activity;
-
- mShouldSave = savedInstanceState != null && savedInstanceState.getBoolean(KEY_SHOULD_SAVE);
- }
-
- public void onDestroy()
- {
- if (mSettings != null)
- {
- mSettings.close();
- mSettings = null;
- }
- }
-
- public void onStart()
- {
- prepareDolphinDirectoriesIfNeeded();
- }
-
- private void loadSettingsUI()
- {
- mView.hideLoading();
-
- if (!mSettings.areSettingsLoaded())
- {
- if (!TextUtils.isEmpty(mGameId))
- {
- mSettings.loadSettings(mGameId, mRevision, mIsWii);
-
- if (mSettings.gameIniContainsJunk())
- {
- mView.showGameIniJunkDeletionQuestion();
- }
- }
- else
- {
- mSettings.loadSettings(mIsWii);
- }
- }
-
- mView.showSettingsFragment(mMenuTag, null, false, mGameId);
- mView.onSettingsFileLoaded(mSettings);
- }
-
- private void prepareDolphinDirectoriesIfNeeded()
- {
- mView.showLoading();
-
- new AfterDirectoryInitializationRunner().runWithLifecycle(mActivity, this::loadSettingsUI);
- }
-
- public Settings getSettings()
- {
- return mSettings;
- }
-
- public void clearGameSettings()
- {
- mSettings.clearGameSettings();
- onSettingChanged();
- }
-
- public void onStop(boolean finishing)
- {
- if (mSettings != null && finishing && mShouldSave)
- {
- Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...");
- mSettings.saveSettings(mActivity);
- }
- }
-
- public void onSettingChanged()
- {
- mShouldSave = true;
- }
-
- public void saveState(Bundle outState)
- {
- outState.putBoolean(KEY_SHOULD_SAVE, mShouldSave);
- }
-
- public boolean shouldSave()
- {
- return mShouldSave;
- }
-
- public void onMenuTagAction(@NonNull MenuTag menuTag, int value)
- {
- if (menuTag.isSerialPort1Menu())
- {
- if (value != 0 && value != 255) // Not disabled or dummy
- {
- Bundle bundle = new Bundle();
- bundle.putInt(SettingsFragmentPresenter.ARG_SERIALPORT1_TYPE, value);
- mView.showSettingsFragment(menuTag, bundle, true, mGameId);
- }
- }
-
- if (menuTag.isGCPadMenu())
- {
- if (value != 0) // Not disabled
- {
- Bundle bundle = new Bundle();
- bundle.putInt(SettingsFragmentPresenter.ARG_CONTROLLER_TYPE, value);
- mView.showSettingsFragment(menuTag, bundle, true, mGameId);
- }
- }
-
- if (menuTag.isWiimoteMenu())
- {
- if (value == 1) // Emulated Wii Remote
- {
- mView.showSettingsFragment(menuTag, null, true, mGameId);
- }
- }
-
- if (menuTag.isWiimoteExtensionMenu())
- {
- if (value != 0) // Not disabled
- {
- Bundle bundle = new Bundle();
- bundle.putInt(SettingsFragmentPresenter.ARG_CONTROLLER_TYPE, value);
- mView.showSettingsFragment(menuTag, bundle, true, mGameId);
- }
- }
- }
-
- public boolean hasMenuTagActionForValue(@NonNull MenuTag menuTag, int value)
- {
- if (menuTag.isSerialPort1Menu())
- {
- return (value != 0 && value != 255); // Not disabled or dummy
- }
-
- if (menuTag.isGCPadMenu())
- {
- return (value != 0); // Not disabled
- }
-
- if (menuTag.isWiimoteMenu())
- {
- return (value == 1); // Emulated Wii Remote
- }
-
- if (menuTag.isWiimoteExtensionMenu())
- {
- return (value != 0); // Not disabled
- }
-
- return false;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityPresenter.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityPresenter.kt
new file mode 100644
index 0000000000..eee800463b
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityPresenter.kt
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.ui
+
+import android.os.Bundle
+import android.text.TextUtils
+import androidx.appcompat.app.AppCompatActivity
+import org.dolphinemu.dolphinemu.features.settings.model.Settings
+import org.dolphinemu.dolphinemu.utils.AfterDirectoryInitializationRunner
+import org.dolphinemu.dolphinemu.utils.Log
+
+class SettingsActivityPresenter(
+ private val activityView: SettingsActivityView,
+ var settings: Settings?
+) {
+ private var shouldSave = false
+ private var menuTag: MenuTag? = null
+ private var gameId: String? = null
+ private var revision = 0
+ private var isWii = false
+ private lateinit var activity: AppCompatActivity
+
+ fun onCreate(
+ savedInstanceState: Bundle?,
+ menuTag: MenuTag?,
+ gameId: String?,
+ revision: Int,
+ isWii: Boolean,
+ activity: AppCompatActivity
+ ) {
+ this.menuTag = menuTag
+ this.gameId = gameId
+ this.revision = revision
+ this.isWii = isWii
+ this.activity = activity
+ shouldSave = savedInstanceState != null && savedInstanceState.getBoolean(KEY_SHOULD_SAVE)
+ }
+
+ fun onDestroy() {
+ if (settings != null) {
+ settings!!.close()
+ settings = null
+ }
+ }
+
+ fun onStart() {
+ prepareDolphinDirectoriesIfNeeded()
+ }
+
+ private fun loadSettingsUI() {
+ activityView.hideLoading()
+ if (!settings!!.areSettingsLoaded()) {
+ if (!TextUtils.isEmpty(gameId)) {
+ settings!!.loadSettings(gameId!!, revision, isWii)
+ if (settings!!.gameIniContainsJunk()) {
+ activityView.showGameIniJunkDeletionQuestion()
+ }
+ } else {
+ settings!!.loadSettings(isWii)
+ }
+ }
+ activityView.showSettingsFragment(menuTag!!, null, false, gameId!!)
+ activityView.onSettingsFileLoaded(settings!!)
+ }
+
+ private fun prepareDolphinDirectoriesIfNeeded() {
+ activityView.showLoading()
+ AfterDirectoryInitializationRunner().runWithLifecycle(activity) { loadSettingsUI() }
+ }
+
+ fun clearGameSettings() {
+ settings!!.clearGameSettings()
+ onSettingChanged()
+ }
+
+ fun onStop(finishing: Boolean) {
+ if (settings != null && finishing && shouldSave) {
+ Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...")
+ settings!!.saveSettings(activity)
+ }
+ }
+
+ fun onSettingChanged() {
+ shouldSave = true
+ }
+
+ fun saveState(outState: Bundle) {
+ outState.putBoolean(KEY_SHOULD_SAVE, shouldSave)
+ }
+
+ fun onMenuTagAction(menuTag: MenuTag, value: Int) {
+ if (menuTag.isSerialPort1Menu) {
+ // Not disabled or dummy
+ if (value != 0 && value != 255) {
+ val bundle = Bundle()
+ bundle.putInt(SettingsFragmentPresenter.ARG_SERIALPORT1_TYPE, value)
+ activityView.showSettingsFragment(menuTag, bundle, true, gameId!!)
+ }
+ }
+ if (menuTag.isGCPadMenu) {
+ // Not disabled
+ if (value != 0)
+ {
+ val bundle = Bundle()
+ bundle.putInt(SettingsFragmentPresenter.ARG_CONTROLLER_TYPE, value)
+ activityView.showSettingsFragment(menuTag, bundle, true, gameId!!)
+ }
+ }
+ if (menuTag.isWiimoteMenu) {
+ // Emulated Wii Remote
+ if (value == 1) {
+ activityView.showSettingsFragment(menuTag, null, true, gameId!!)
+ }
+ }
+ if (menuTag.isWiimoteExtensionMenu) {
+ // Not disabled
+ if (value != 0) {
+ val bundle = Bundle()
+ bundle.putInt(SettingsFragmentPresenter.ARG_CONTROLLER_TYPE, value)
+ activityView.showSettingsFragment(menuTag, bundle, true, gameId!!)
+ }
+ }
+ }
+
+ fun hasMenuTagActionForValue(menuTag: MenuTag, value: Int): Boolean {
+ if (menuTag.isSerialPort1Menu) {
+ // Not disabled or dummy
+ return value != 0 && value != 255
+ }
+ if (menuTag.isGCPadMenu) {
+ // Not disabled
+ return value != 0
+ }
+ if (menuTag.isWiimoteMenu) {
+ // Emulated Wii Remote
+ return value == 1
+ }
+ return if (menuTag.isWiimoteExtensionMenu) {
+ // Not disabled
+ value != 0
+ } else false
+ }
+
+ companion object {
+ private const val KEY_SHOULD_SAVE = "should_save"
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityView.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityView.java
deleted file mode 100644
index 464d0ea165..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityView.java
+++ /dev/null
@@ -1,137 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.ui;
-
-import android.os.Bundle;
-
-import androidx.annotation.NonNull;
-import androidx.fragment.app.DialogFragment;
-
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-
-/**
- * Abstraction for the Activity that manages SettingsFragments.
- */
-public interface SettingsActivityView
-{
- /**
- * Show a new SettingsFragment.
- *
- * @param menuTag Identifier for the settings group that should be displayed.
- * @param addToStack Whether or not this fragment should replace a previous one.
- */
- void showSettingsFragment(MenuTag menuTag, Bundle extras, boolean addToStack, String gameId);
-
- /**
- * Shows a DialogFragment.
- *
- * Only one can be shown at a time.
- */
- void showDialogFragment(DialogFragment fragment);
-
- /**
- * Called by a contained Fragment to get access to the Setting HashMap
- * loaded from disk, so that each Fragment doesn't need to perform its own
- * read operation.
- *
- * @return A possibly null HashMap of Settings.
- */
- Settings getSettings();
-
- /**
- * Called when an asynchronous load operation completes.
- *
- * @param settings The (possibly null) result of the ini load operation.
- */
- void onSettingsFileLoaded(Settings settings);
-
- /**
- * Called when an asynchronous load operation fails.
- */
- void onSettingsFileNotFound();
-
- /**
- * Display a popup text message on screen.
- *
- * @param message The contents of the onscreen message.
- */
- void showToastMessage(String message);
-
- /**
- * End the activity.
- */
- void finish();
-
- /**
- * Called by a containing Fragment to tell the Activity that a setting was changed;
- * unless this has been called, the Activity will not save to disk.
- */
- void onSettingChanged();
-
- /**
- * Refetches the values of all controller settings.
- *
- * To be used when loading an input profile or performing some other action that changes all
- * controller settings at once.
- */
- void onControllerSettingsChanged();
-
- /**
- * Called by a containing Fragment to tell the containing Activity that the user wants to open the
- * MenuTag associated with a setting.
- *
- * @param menuTag The MenuTag of the setting.
- * @param value The current value of the setting.
- */
- void onMenuTagAction(@NonNull MenuTag menuTag, int value);
-
- /**
- * Returns whether anything will happen when the user wants to open the MenuTag associated with a
- * setting, given the current value of the setting.
- *
- * @param menuTag The MenuTag of the setting.
- * @param value The current value of the setting.
- */
- boolean hasMenuTagActionForValue(@NonNull MenuTag menuTag, int value);
-
- /**
- * Show loading dialog while loading the settings
- */
- void showLoading();
-
- /**
- * Hide the loading dialog
- */
- void hideLoading();
-
- /**
- * Tell the user that there is junk in the game INI and ask if they want to delete the whole file.
- */
- void showGameIniJunkDeletionQuestion();
-
- /**
- * Accesses the material toolbar layout and changes the title
- */
- void setToolbarTitle(String title);
-
- /**
- * Sets whether the input mapping dialog should detect inputs from all devices,
- * not just the device configured for the controller.
- */
- void setMappingAllDevices(boolean allDevices);
-
- /**
- * Returns whether the input mapping dialog should detect inputs from all devices,
- * not just the device configured for the controller.
- */
- boolean isMappingAllDevices();
-
- /**
- * Shows or hides a warning telling the user that they're using incompatible controller settings.
- * The warning is hidden by default.
- *
- * @param visible Whether the warning should be visible.
- * @return The height of the warning view, or 0 if the view is now invisible.
- */
- int setOldControllerSettingsWarningVisibility(boolean visible);
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityView.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityView.kt
new file mode 100644
index 0000000000..435d23fad6
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityView.kt
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.ui
+
+import android.os.Bundle
+import androidx.fragment.app.DialogFragment
+import org.dolphinemu.dolphinemu.features.settings.model.Settings
+
+/**
+ * Abstraction for the Activity that manages SettingsFragments.
+ */
+interface SettingsActivityView {
+ /**
+ * Show a new SettingsFragment.
+ *
+ * @param menuTag Identifier for the settings group that should be displayed.
+ * @param addToStack Whether or not this fragment should replace a previous one.
+ */
+ fun showSettingsFragment(
+ menuTag: MenuTag,
+ extras: Bundle?,
+ addToStack: Boolean,
+ gameId: String
+ )
+
+ /**
+ * Shows a DialogFragment.
+ *
+ * Only one can be shown at a time.
+ */
+ fun showDialogFragment(fragment: DialogFragment)
+
+ /**
+ * Called by a contained Fragment to get access to the Setting HashMap
+ * loaded from disk, so that each Fragment doesn't need to perform its own
+ * read operation.
+ *
+ * @return A possibly null HashMap of Settings.
+ */
+ val settings: Settings
+
+ /**
+ * Called when an asynchronous load operation completes.
+ *
+ * @param settings The (possibly null) result of the ini load operation.
+ */
+ fun onSettingsFileLoaded(settings: Settings)
+
+ /**
+ * Called when an asynchronous load operation fails.
+ */
+ fun onSettingsFileNotFound()
+
+ /**
+ * Display a popup text message on screen.
+ *
+ * @param message The contents of the onscreen message.
+ */
+ fun showToastMessage(message: String)
+
+ /**
+ * End the activity.
+ */
+ fun finish()
+
+ /**
+ * Called by a containing Fragment to tell the Activity that a Setting was changed;
+ * unless this has been called, the Activity will not save to disk.
+ */
+ fun onSettingChanged()
+
+ /**
+ * Refetches the values of all controller settings.
+ *
+ * To be used when loading an input profile or performing some other action that changes all
+ * controller settings at once.
+ */
+ fun onControllerSettingsChanged()
+
+ /**
+ * Called by a containing Fragment to tell the containing Activity that the user wants to open the
+ * MenuTag associated with a Setting.
+ *
+ * @param menuTag The MenuTag of the Setting.
+ * @param value The current value of the Setting.
+ */
+ fun onMenuTagAction(menuTag: MenuTag, value: Int)
+
+ /**
+ * Returns whether anything will happen when the user wants to open the MenuTag associated with a
+ * Setting, given the current value of the Setting.
+ *
+ * @param menuTag The MenuTag of the Setting.
+ * @param value The current value of the Setting.
+ */
+ fun hasMenuTagActionForValue(menuTag: MenuTag, value: Int): Boolean
+
+ /**
+ * Show loading dialog while loading the settings
+ */
+ fun showLoading()
+
+ /**
+ * Hide the loading dialog
+ */
+ fun hideLoading()
+
+ /**
+ * Tell the user that there is junk in the game INI and ask if they want to delete the whole file.
+ */
+ fun showGameIniJunkDeletionQuestion()
+
+ /**
+ * Accesses the material toolbar layout and changes the title
+ */
+ fun setToolbarTitle(title: String)
+ /**
+ * Returns whether the input mapping dialog should detect inputs from all devices,
+ * not just the device configured for the controller.
+ */
+ /**
+ * Sets whether the input mapping dialog should detect inputs from all devices,
+ * not just the device configured for the controller.
+ */
+ var isMappingAllDevices: Boolean
+
+ /**
+ * Shows or hides a warning telling the user that they're using incompatible controller settings.
+ * The warning is hidden by default.
+ *
+ * @param visible Whether the warning should be visible.
+ * @return The height of the warning view, or 0 if the view is now invisible.
+ */
+ fun setOldControllerSettingsWarningVisibility(visible: Boolean): Int
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.java
deleted file mode 100644
index e062dd71b2..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.java
+++ /dev/null
@@ -1,703 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.ui;
-
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.graphics.PorterDuff;
-import android.graphics.drawable.Drawable;
-import android.os.Build;
-import android.provider.DocumentsContract;
-import android.text.format.DateFormat;
-import android.view.LayoutInflater;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-import androidx.annotation.ColorInt;
-import androidx.annotation.NonNull;
-import androidx.appcompat.app.AlertDialog;
-import androidx.core.content.ContextCompat;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.google.android.material.color.MaterialColors;
-import com.google.android.material.datepicker.CalendarConstraints;
-import com.google.android.material.datepicker.MaterialDatePicker;
-import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-import com.google.android.material.elevation.ElevationOverlayProvider;
-import com.google.android.material.slider.Slider;
-import com.google.android.material.textfield.TextInputEditText;
-import com.google.android.material.timepicker.MaterialTimePicker;
-import com.google.android.material.timepicker.TimeFormat;
-
-import org.dolphinemu.dolphinemu.R;
-import org.dolphinemu.dolphinemu.databinding.DialogAdvancedMappingBinding;
-import org.dolphinemu.dolphinemu.databinding.DialogInputStringBinding;
-import org.dolphinemu.dolphinemu.databinding.DialogSliderBinding;
-import org.dolphinemu.dolphinemu.databinding.ListItemHeaderBinding;
-import org.dolphinemu.dolphinemu.databinding.ListItemMappingBinding;
-import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding;
-import org.dolphinemu.dolphinemu.databinding.ListItemSettingSwitchBinding;
-import org.dolphinemu.dolphinemu.databinding.ListItemSubmenuBinding;
-import org.dolphinemu.dolphinemu.features.input.ui.AdvancedMappingDialog;
-import org.dolphinemu.dolphinemu.features.input.ui.MotionAlertDialog;
-import org.dolphinemu.dolphinemu.features.input.model.view.InputMappingControlSetting;
-import org.dolphinemu.dolphinemu.features.input.ui.viewholder.InputMappingControlSettingViewHolder;
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-import org.dolphinemu.dolphinemu.features.settings.model.view.DateTimeChoiceSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SwitchSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.FilePicker;
-import org.dolphinemu.dolphinemu.features.settings.model.view.FloatSliderSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.IntSliderSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SingleChoiceSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SingleChoiceSettingDynamicDescriptions;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SliderSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.InputStringSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.StringSingleChoiceSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SubmenuSetting;
-import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.DateTimeSettingViewHolder;
-import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.FilePickerViewHolder;
-import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.HeaderHyperLinkViewHolder;
-import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.HeaderViewHolder;
-import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.InputStringSettingViewHolder;
-import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.RunRunnableViewHolder;
-import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.SettingViewHolder;
-import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.SingleChoiceViewHolder;
-import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.SliderViewHolder;
-import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.SubmenuViewHolder;
-import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.SwitchSettingViewHolder;
-import org.dolphinemu.dolphinemu.utils.DirectoryInitialization;
-import org.dolphinemu.dolphinemu.utils.FileBrowserHelper;
-import org.dolphinemu.dolphinemu.utils.Log;
-import org.dolphinemu.dolphinemu.utils.PermissionsHandler;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.TimeZone;
-
-public final class SettingsAdapter extends RecyclerView.Adapter<SettingViewHolder>
- implements DialogInterface.OnClickListener, Slider.OnChangeListener
-{
- private final SettingsFragmentView mView;
- private final Context mContext;
- private ArrayList<SettingsItem> mSettings;
-
- private SettingsItem mClickedItem;
- private int mClickedPosition;
- private int mSeekbarProgress;
-
- private AlertDialog mDialog;
- private TextView mTextSliderValue;
-
- public SettingsAdapter(SettingsFragmentView view, Context context)
- {
- mView = view;
- mContext = context;
- mClickedPosition = -1;
- }
-
- @NonNull
- @Override
- public SettingViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
- {
- LayoutInflater inflater = LayoutInflater.from(parent.getContext());
- switch (viewType)
- {
- case SettingsItem.TYPE_HEADER:
- return new HeaderViewHolder(ListItemHeaderBinding.inflate(inflater), this);
-
- case SettingsItem.TYPE_SWITCH:
- return new SwitchSettingViewHolder(ListItemSettingSwitchBinding.inflate(inflater),
- this);
-
- case SettingsItem.TYPE_STRING_SINGLE_CHOICE:
- case SettingsItem.TYPE_SINGLE_CHOICE_DYNAMIC_DESCRIPTIONS:
- case SettingsItem.TYPE_SINGLE_CHOICE:
- return new SingleChoiceViewHolder(ListItemSettingBinding.inflate(inflater), this);
-
- case SettingsItem.TYPE_SLIDER:
- return new SliderViewHolder(ListItemSettingBinding.inflate(inflater), this, mContext);
-
- case SettingsItem.TYPE_SUBMENU:
- return new SubmenuViewHolder(ListItemSubmenuBinding.inflate(inflater), this);
-
- case SettingsItem.TYPE_INPUT_MAPPING_CONTROL:
- return new InputMappingControlSettingViewHolder(ListItemMappingBinding.inflate(inflater),
- this);
-
- case SettingsItem.TYPE_FILE_PICKER:
- return new FilePickerViewHolder(ListItemSettingBinding.inflate(inflater), this);
-
- case SettingsItem.TYPE_RUN_RUNNABLE:
- return new RunRunnableViewHolder(ListItemSettingBinding.inflate(inflater), this, mContext);
-
- case SettingsItem.TYPE_STRING:
- return new InputStringSettingViewHolder(ListItemSettingBinding.inflate(inflater), this);
-
- case SettingsItem.TYPE_HYPERLINK_HEADER:
- return new HeaderHyperLinkViewHolder(ListItemHeaderBinding.inflate(inflater), this);
-
- case SettingsItem.TYPE_DATETIME_CHOICE:
- return new DateTimeSettingViewHolder(ListItemSettingBinding.inflate(inflater), this);
-
- default:
- throw new IllegalArgumentException("Invalid view type: " + viewType);
- }
- }
-
- @Override
- public void onBindViewHolder(@NonNull SettingViewHolder holder, int position)
- {
- holder.bind(getItem(position));
- }
-
- private SettingsItem getItem(int position)
- {
- return mSettings.get(position);
- }
-
- @Override
- public int getItemCount()
- {
- if (mSettings != null)
- {
- return mSettings.size();
- }
- else
- {
- return 0;
- }
- }
-
- @Override
- public int getItemViewType(int position)
- {
- return getItem(position).getType();
- }
-
- public Settings getSettings()
- {
- return mView.getSettings();
- }
-
- public void setSettings(ArrayList<SettingsItem> settings)
- {
- mSettings = settings;
- notifyDataSetChanged();
- }
-
- public void clearSetting(SettingsItem item)
- {
- item.clear(getSettings());
-
- mView.onSettingChanged();
- }
-
- public void notifyAllSettingsChanged()
- {
- notifyItemRangeChanged(0, getItemCount());
-
- mView.onSettingChanged();
- }
-
- public void onBooleanClick(SwitchSetting item, boolean checked)
- {
- item.setChecked(getSettings(), checked);
-
- mView.onSettingChanged();
- }
-
- public void onInputStringClick(InputStringSetting item, int position)
- {
- LayoutInflater inflater = LayoutInflater.from(mContext);
-
- DialogInputStringBinding binding = DialogInputStringBinding.inflate(inflater);
- TextInputEditText input = binding.input;
- input.setText(item.getSelectedValue());
-
- mDialog = new MaterialAlertDialogBuilder(mView.getActivity())
- .setView(binding.getRoot())
- .setMessage(item.getDescription())
- .setPositiveButton(R.string.ok, (dialogInterface, i) ->
- {
- String editTextInput = input.getText().toString();
-
- if (!item.getSelectedValue().equals(editTextInput))
- {
- notifyItemChanged(position);
- mView.onSettingChanged();
- }
-
- item.setSelectedValue(mView.getSettings(), editTextInput);
- })
- .setNegativeButton(R.string.cancel, null)
- .show();
- }
-
- public void onSingleChoiceClick(SingleChoiceSetting item, int position)
- {
- mClickedItem = item;
- mClickedPosition = position;
-
- int value = getSelectionForSingleChoiceValue(item);
-
- mDialog = new MaterialAlertDialogBuilder(mView.getActivity())
- .setTitle(item.getName())
- .setSingleChoiceItems(item.getChoicesId(), value, this)
- .show();
- }
-
- public void onStringSingleChoiceClick(StringSingleChoiceSetting item, int position)
- {
- mClickedItem = item;
- mClickedPosition = position;
-
- item.refreshChoicesAndValues();
-
- String[] choices = item.getChoices();
- int noChoicesAvailableString = item.getNoChoicesAvailableString();
- if (noChoicesAvailableString != 0 && choices.length == 0)
- {
- mDialog = new MaterialAlertDialogBuilder(mView.getActivity())
- .setTitle(item.getName())
- .setMessage(noChoicesAvailableString)
- .setPositiveButton(R.string.ok, null)
- .show();
- }
- else
- {
- mDialog = new MaterialAlertDialogBuilder(mView.getActivity())
- .setTitle(item.getName())
- .setSingleChoiceItems(item.getChoices(), item.getSelectedValueIndex(),
- this)
- .show();
- }
- }
-
- public void onSingleChoiceDynamicDescriptionsClick(SingleChoiceSettingDynamicDescriptions item,
- int position)
- {
- mClickedItem = item;
- mClickedPosition = position;
-
- int value = getSelectionForSingleChoiceDynamicDescriptionsValue(item);
-
- mDialog = new MaterialAlertDialogBuilder(mView.getActivity())
- .setTitle(item.getName())
- .setSingleChoiceItems(item.getChoicesId(), value, this)
- .show();
- }
-
- public void onSliderClick(SliderSetting item, int position)
- {
- mClickedItem = item;
- mClickedPosition = position;
- mSeekbarProgress = item.getSelectedValue();
-
- LayoutInflater inflater = LayoutInflater.from(mView.getActivity());
- DialogSliderBinding binding = DialogSliderBinding.inflate(inflater);
-
- mTextSliderValue = binding.textValue;
- mTextSliderValue.setText(String.valueOf(mSeekbarProgress));
-
- binding.textUnits.setText(item.getUnits());
-
- Slider slider = binding.slider;
- slider.setValueFrom(item.getMin());
- slider.setValueTo(item.getMax());
- slider.setValue(mSeekbarProgress);
- slider.setStepSize(item.getStepSize());
-
- slider.addOnChangeListener(this);
-
- mDialog = new MaterialAlertDialogBuilder(mView.getActivity())
- .setTitle(item.getName())
- .setView(binding.getRoot())
- .setPositiveButton(R.string.ok, this)
- .show();
- }
-
- public void onSubmenuClick(SubmenuSetting item)
- {
- mView.loadSubMenu(item.getMenuKey());
- }
-
- public void onInputMappingClick(final InputMappingControlSetting item, final int position)
- {
- if (item.getController().getDefaultDevice().isEmpty() && !mView.isMappingAllDevices())
- {
- new MaterialAlertDialogBuilder(mView.getActivity())
- .setMessage(R.string.input_binding_no_device)
- .setPositiveButton(R.string.ok, this)
- .show();
- return;
- }
-
- final MotionAlertDialog dialog = new MotionAlertDialog(mView.getActivity(), item,
- mView.isMappingAllDevices());
-
- Drawable background = ContextCompat.getDrawable(mContext, R.drawable.dialog_round);
- @ColorInt int color = new ElevationOverlayProvider(dialog.getContext()).compositeOverlay(
- MaterialColors.getColor(dialog.getWindow().getDecorView(), R.attr.colorSurface),
- dialog.getWindow().getDecorView().getElevation());
- background.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
- dialog.getWindow().setBackgroundDrawable(background);
-
- dialog.setTitle(R.string.input_binding);
- dialog.setMessage(String.format(mContext.getString(R.string.input_binding_description),
- item.getName()));
- dialog.setButton(AlertDialog.BUTTON_NEGATIVE, mContext.getString(R.string.cancel), this);
- dialog.setButton(AlertDialog.BUTTON_NEUTRAL, mContext.getString(R.string.clear),
- (dialogInterface, i) -> item.clearValue());
- dialog.setOnDismissListener(dialog1 ->
- {
- notifyItemChanged(position);
- mView.onSettingChanged();
- });
- dialog.setCanceledOnTouchOutside(false);
- dialog.show();
- }
-
- public void onAdvancedInputMappingClick(final InputMappingControlSetting item, final int position)
- {
- LayoutInflater inflater = LayoutInflater.from(mContext);
-
- DialogAdvancedMappingBinding binding = DialogAdvancedMappingBinding.inflate(inflater);
-
- final AdvancedMappingDialog dialog = new AdvancedMappingDialog(mContext, binding,
- item.getControlReference(), item.getController());
-
- Drawable background = ContextCompat.getDrawable(mContext, R.drawable.dialog_round);
- @ColorInt int color = new ElevationOverlayProvider(dialog.getContext()).compositeOverlay(
- MaterialColors.getColor(dialog.getWindow().getDecorView(), R.attr.colorSurface),
- dialog.getWindow().getDecorView().getElevation());
- background.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
- dialog.getWindow().setBackgroundDrawable(background);
-
- dialog.setTitle(item.isInput() ?
- R.string.input_configure_input : R.string.input_configure_output);
- dialog.setView(binding.getRoot());
- dialog.setButton(AlertDialog.BUTTON_POSITIVE, mContext.getString(R.string.ok),
- (dialogInterface, i) ->
- {
- item.setValue(dialog.getExpression());
- notifyItemChanged(position);
- mView.onSettingChanged();
- });
- dialog.setButton(AlertDialog.BUTTON_NEGATIVE, mContext.getString(R.string.cancel), this);
- dialog.setButton(AlertDialog.BUTTON_NEUTRAL, mContext.getString(R.string.clear),
- (dialogInterface, i) ->
- {
- item.clearValue();
- notifyItemChanged(position);
- mView.onSettingChanged();
- });
- dialog.setCanceledOnTouchOutside(false);
- dialog.show();
- }
-
- public void onFilePickerDirectoryClick(SettingsItem item, int position)
- {
- mClickedItem = item;
- mClickedPosition = position;
-
- if (!PermissionsHandler.isExternalStorageLegacy())
- {
- new MaterialAlertDialogBuilder(mContext)
- .setMessage(R.string.path_not_changeable_scoped_storage)
- .setPositiveButton(R.string.ok, (dialog, i) -> dialog.dismiss())
- .show();
- }
- else
- {
- FileBrowserHelper.openDirectoryPicker(mView.getActivity(), FileBrowserHelper.GAME_EXTENSIONS);
- }
- }
-
- public void onFilePickerFileClick(SettingsItem item, int position)
- {
- mClickedItem = item;
- mClickedPosition = position;
- FilePicker filePicker = (FilePicker) item;
-
- Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- intent.setType("*/*");
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
- {
- intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, filePicker.getSelectedValue());
- }
-
- mView.getActivity().startActivityForResult(intent, filePicker.getRequestType());
- }
-
- public void onDateTimeClick(DateTimeChoiceSetting item, int position)
- {
- mClickedItem = item;
- mClickedPosition = position;
- long storedTime = Long.decode(item.getSelectedValue()) * 1000;
-
- // Helper to extract hour and minute from epoch time
- Calendar calendar = Calendar.getInstance();
- calendar.setTimeInMillis(storedTime);
- calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
-
- // Start and end epoch times available for the Wii's date picker
- CalendarConstraints calendarConstraints = new CalendarConstraints.Builder()
- .setStart(946684800000L)
- .setEnd(2082672000000L)
- .build();
-
- int timeFormat = TimeFormat.CLOCK_12H;
- if (DateFormat.is24HourFormat(mView.getActivity()))
- {
- timeFormat = TimeFormat.CLOCK_24H;
- }
-
- MaterialDatePicker<Long> datePicker = MaterialDatePicker.Builder.datePicker()
- .setSelection(storedTime)
- .setTitleText(R.string.select_rtc_date)
- .setCalendarConstraints(calendarConstraints)
- .build();
- MaterialTimePicker timePicker = new MaterialTimePicker.Builder()
- .setTimeFormat(timeFormat)
- .setHour(calendar.get(Calendar.HOUR_OF_DAY))
- .setMinute(calendar.get(Calendar.MINUTE))
- .setTitleText(R.string.select_rtc_time)
- .build();
-
- datePicker.addOnPositiveButtonClickListener(
- selection -> timePicker.show(mView.getActivity().getSupportFragmentManager(),
- "TimePicker"));
- timePicker.addOnPositiveButtonClickListener(selection ->
- {
- long epochTime = datePicker.getSelection() / 1000;
- epochTime += (long) timePicker.getHour() * 60 * 60;
- epochTime += (long) timePicker.getMinute() * 60;
- String rtcString = "0x" + Long.toHexString(epochTime);
- if (!item.getSelectedValue().equals(rtcString))
- {
- notifyItemChanged(mClickedPosition);
- mView.onSettingChanged();
- }
-
- item.setSelectedValue(mView.getSettings(), rtcString);
-
- mClickedItem = null;
- });
- datePicker.show(mView.getActivity().getSupportFragmentManager(), "DatePicker");
- }
-
- public void onFilePickerConfirmation(String selectedFile)
- {
- FilePicker filePicker = (FilePicker) mClickedItem;
-
- if (!filePicker.getSelectedValue().equals(selectedFile))
- {
- notifyItemChanged(mClickedPosition);
- mView.onSettingChanged();
- }
-
- filePicker.setSelectedValue(mView.getSettings(), selectedFile);
-
- mClickedItem = null;
- }
-
- public static void clearLog()
- {
- // Don't delete the log in case it is being monitored by another app.
- File log = new File(DirectoryInitialization.getUserDirectory() + "/Logs/dolphin.log");
-
- try
- {
- RandomAccessFile raf = new RandomAccessFile(log, "rw");
- raf.setLength(0);
- }
- catch (IOException e)
- {
- Log.error("[SettingsAdapter] Failed to clear log file: " + e.getMessage());
- }
- }
-
- public void onMenuTagAction(@NonNull MenuTag menuTag, int value)
- {
- mView.onMenuTagAction(menuTag, value);
- }
-
- public boolean hasMenuTagActionForValue(@NonNull MenuTag menuTag, int value)
- {
- return mView.hasMenuTagActionForValue(menuTag, value);
- }
-
- @Override
- public void onClick(DialogInterface dialog, int which)
- {
- if (mClickedItem instanceof SingleChoiceSetting)
- {
- SingleChoiceSetting scSetting = (SingleChoiceSetting) mClickedItem;
-
- int value = getValueForSingleChoiceSelection(scSetting, which);
- if (scSetting.getSelectedValue() != value)
- mView.onSettingChanged();
-
- scSetting.setSelectedValue(getSettings(), value);
-
- closeDialog();
- }
- else if (mClickedItem instanceof SingleChoiceSettingDynamicDescriptions)
- {
- SingleChoiceSettingDynamicDescriptions scSetting =
- (SingleChoiceSettingDynamicDescriptions) mClickedItem;
-
- int value = getValueForSingleChoiceDynamicDescriptionsSelection(scSetting, which);
- if (scSetting.getSelectedValue() != value)
- mView.onSettingChanged();
-
- scSetting.setSelectedValue(getSettings(), value);
-
- closeDialog();
- }
- else if (mClickedItem instanceof StringSingleChoiceSetting)
- {
- StringSingleChoiceSetting scSetting = (StringSingleChoiceSetting) mClickedItem;
- String value = scSetting.getValueAt(which);
- if (!scSetting.getSelectedValue().equals(value))
- mView.onSettingChanged();
-
- scSetting.setSelectedValue(getSettings(), value);
-
- closeDialog();
- }
- else if (mClickedItem instanceof IntSliderSetting)
- {
- IntSliderSetting sliderSetting = (IntSliderSetting) mClickedItem;
- if (sliderSetting.getSelectedValue() != mSeekbarProgress)
- mView.onSettingChanged();
-
- sliderSetting.setSelectedValue(getSettings(), mSeekbarProgress);
-
- closeDialog();
- }
- else if (mClickedItem instanceof FloatSliderSetting)
- {
- FloatSliderSetting sliderSetting = (FloatSliderSetting) mClickedItem;
- if (sliderSetting.getSelectedValue() != mSeekbarProgress)
- mView.onSettingChanged();
-
- sliderSetting.setSelectedValue(getSettings(), mSeekbarProgress);
-
- closeDialog();
- }
-
- mClickedItem = null;
- mSeekbarProgress = -1;
- }
-
- public void closeDialog()
- {
- if (mDialog != null)
- {
- if (mClickedPosition != -1)
- {
- notifyItemChanged(mClickedPosition);
- mClickedPosition = -1;
- }
- mDialog.dismiss();
- mDialog = null;
- }
- }
-
- @Override
- public void onValueChange(@NonNull Slider slider, float progress, boolean fromUser)
- {
- mSeekbarProgress = (int) progress;
- mTextSliderValue.setText(String.valueOf(mSeekbarProgress));
- }
-
- private int getValueForSingleChoiceSelection(SingleChoiceSetting item, int which)
- {
- int valuesId = item.getValuesId();
-
- if (valuesId > 0)
- {
- int[] valuesArray = mContext.getResources().getIntArray(valuesId);
- return valuesArray[which];
- }
- else
- {
- return which;
- }
- }
-
- private int getSelectionForSingleChoiceValue(SingleChoiceSetting item)
- {
- int value = item.getSelectedValue();
- int valuesId = item.getValuesId();
-
- if (valuesId > 0)
- {
- int[] valuesArray = mContext.getResources().getIntArray(valuesId);
- for (int index = 0; index < valuesArray.length; index++)
- {
- int current = valuesArray[index];
- if (current == value)
- {
- return index;
- }
- }
- }
- else
- {
- return value;
- }
-
- return -1;
- }
-
- private int getValueForSingleChoiceDynamicDescriptionsSelection(
- SingleChoiceSettingDynamicDescriptions item, int which)
- {
- int valuesId = item.getValuesId();
-
- if (valuesId > 0)
- {
- int[] valuesArray = mContext.getResources().getIntArray(valuesId);
- return valuesArray[which];
- }
- else
- {
- return which;
- }
- }
-
- private int getSelectionForSingleChoiceDynamicDescriptionsValue(
- SingleChoiceSettingDynamicDescriptions item)
- {
- int value = item.getSelectedValue();
- int valuesId = item.getValuesId();
-
- if (valuesId > 0)
- {
- int[] valuesArray = mContext.getResources().getIntArray(valuesId);
- for (int index = 0; index < valuesArray.length; index++)
- {
- int current = valuesArray[index];
- if (current == value)
- {
- return index;
- }
- }
- }
- else
- {
- return value;
- }
-
- return -1;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.kt
new file mode 100644
index 0000000000..d5df7c0e09
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.kt
@@ -0,0 +1,590 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.ui
+
+import android.content.Context
+import android.content.DialogInterface
+import android.content.Intent
+import android.graphics.PorterDuff
+import android.os.Build
+import android.provider.DocumentsContract
+import android.text.format.DateFormat
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.annotation.ColorInt
+import androidx.appcompat.app.AlertDialog
+import androidx.core.content.ContextCompat
+import androidx.recyclerview.widget.RecyclerView
+import com.google.android.material.color.MaterialColors
+import com.google.android.material.datepicker.CalendarConstraints
+import com.google.android.material.datepicker.MaterialDatePicker
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.google.android.material.elevation.ElevationOverlayProvider
+import com.google.android.material.slider.Slider
+import com.google.android.material.timepicker.MaterialTimePicker
+import com.google.android.material.timepicker.TimeFormat
+import org.dolphinemu.dolphinemu.R
+import org.dolphinemu.dolphinemu.databinding.*
+import org.dolphinemu.dolphinemu.features.input.model.view.InputMappingControlSetting
+import org.dolphinemu.dolphinemu.features.input.ui.AdvancedMappingDialog
+import org.dolphinemu.dolphinemu.features.input.ui.MotionAlertDialog
+import org.dolphinemu.dolphinemu.features.input.ui.viewholder.InputMappingControlSettingViewHolder
+import org.dolphinemu.dolphinemu.features.settings.model.Settings
+import org.dolphinemu.dolphinemu.features.settings.model.view.*
+import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.*
+import org.dolphinemu.dolphinemu.utils.DirectoryInitialization
+import org.dolphinemu.dolphinemu.utils.FileBrowserHelper
+import org.dolphinemu.dolphinemu.utils.Log
+import org.dolphinemu.dolphinemu.utils.PermissionsHandler
+import java.io.File
+import java.io.IOException
+import java.io.RandomAccessFile
+import java.util.*
+
+class SettingsAdapter(
+ private val fragmentView: SettingsFragmentView,
+ private val context: Context
+) :
+ RecyclerView.Adapter<SettingViewHolder>(), DialogInterface.OnClickListener,
+ Slider.OnChangeListener {
+ private var settingsList: ArrayList<SettingsItem>? = null
+ private var clickedItem: SettingsItem? = null
+ private var clickedPosition: Int = -1
+ private var seekbarProgress = 0
+ private var dialog: AlertDialog? = null
+ private var textSliderValue: TextView? = null
+
+ val settings: Settings?
+ get() = fragmentView.settings
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SettingViewHolder {
+ val inflater = LayoutInflater.from(parent.context)
+ return when (viewType) {
+ SettingsItem.TYPE_HEADER -> HeaderViewHolder(
+ ListItemHeaderBinding.inflate(inflater),
+ this
+ )
+ SettingsItem.TYPE_SWITCH -> SwitchSettingViewHolder(
+ ListItemSettingSwitchBinding.inflate(inflater),
+ this
+ )
+ SettingsItem.TYPE_STRING_SINGLE_CHOICE,
+ SettingsItem.TYPE_SINGLE_CHOICE_DYNAMIC_DESCRIPTIONS,
+ SettingsItem.TYPE_SINGLE_CHOICE -> SingleChoiceViewHolder(
+ ListItemSettingBinding.inflate(inflater),
+ this
+ )
+ SettingsItem.TYPE_SLIDER -> SliderViewHolder(
+ ListItemSettingBinding.inflate(
+ inflater
+ ), this, context
+ )
+ SettingsItem.TYPE_SUBMENU -> SubmenuViewHolder(
+ ListItemSubmenuBinding.inflate(
+ inflater
+ ), this
+ )
+ SettingsItem.TYPE_INPUT_MAPPING_CONTROL -> InputMappingControlSettingViewHolder(
+ ListItemMappingBinding.inflate(inflater),
+ this
+ )
+ SettingsItem.TYPE_FILE_PICKER -> FilePickerViewHolder(
+ ListItemSettingBinding.inflate(
+ inflater
+ ), this
+ )
+ SettingsItem.TYPE_RUN_RUNNABLE -> RunRunnableViewHolder(
+ ListItemSettingBinding.inflate(
+ inflater
+ ), this, context
+ )
+ SettingsItem.TYPE_STRING -> InputStringSettingViewHolder(
+ ListItemSettingBinding.inflate(
+ inflater
+ ), this
+ )
+ SettingsItem.TYPE_HYPERLINK_HEADER -> HeaderHyperLinkViewHolder(
+ ListItemHeaderBinding.inflate(
+ inflater
+ ), this
+ )
+ SettingsItem.TYPE_DATETIME_CHOICE -> DateTimeSettingViewHolder(
+ ListItemSettingBinding.inflate(
+ inflater
+ ), this
+ )
+ else -> throw IllegalArgumentException("Invalid view type: $viewType")
+ }
+ }
+
+ override fun onBindViewHolder(holder: SettingViewHolder, position: Int) {
+ holder.bind(getItem(position))
+ }
+
+ private fun getItem(position: Int): SettingsItem {
+ return settingsList!![position]
+ }
+
+ override fun getItemCount(): Int {
+ return if (settingsList != null) {
+ settingsList!!.size
+ } else {
+ 0
+ }
+ }
+
+ override fun getItemViewType(position: Int): Int {
+ return getItem(position).type
+ }
+
+ fun setSettings(settings: ArrayList<SettingsItem>?) {
+ settingsList = settings
+ notifyDataSetChanged()
+ }
+
+ fun clearSetting(item: SettingsItem) {
+ item.clear(settings!!)
+ fragmentView.onSettingChanged()
+ }
+
+ fun notifyAllSettingsChanged() {
+ notifyItemRangeChanged(0, itemCount)
+ fragmentView.onSettingChanged()
+ }
+
+ fun onBooleanClick(item: SwitchSetting, checked: Boolean) {
+ item.setChecked(settings, checked)
+ fragmentView.onSettingChanged()
+ }
+
+ fun onInputStringClick(item: InputStringSetting, position: Int) {
+ val inflater = LayoutInflater.from(context)
+ val binding = DialogInputStringBinding.inflate(inflater)
+ val input = binding.input
+ input.setText(item.selectedValue)
+ dialog = MaterialAlertDialogBuilder(fragmentView.fragmentActivity)
+ .setView(binding.root)
+ .setMessage(item.description)
+ .setPositiveButton(R.string.ok) { _: DialogInterface?, _: Int ->
+ val editTextInput = input.text.toString()
+ if (item.selectedValue != editTextInput) {
+ notifyItemChanged(position)
+ fragmentView.onSettingChanged()
+ }
+ item.setSelectedValue(fragmentView.settings!!, editTextInput)
+ }
+ .setNegativeButton(R.string.cancel, null)
+ .show()
+ }
+
+ fun onSingleChoiceClick(item: SingleChoiceSetting, position: Int) {
+ clickedItem = item
+ clickedPosition = position
+ val value = getSelectionForSingleChoiceValue(item)
+ dialog = MaterialAlertDialogBuilder(fragmentView.fragmentActivity)
+ .setTitle(item.name)
+ .setSingleChoiceItems(item.choicesId, value, this)
+ .show()
+ }
+
+ fun onStringSingleChoiceClick(item: StringSingleChoiceSetting, position: Int) {
+ clickedItem = item
+ clickedPosition = position
+ item.refreshChoicesAndValues()
+ val choices = item.choices
+ val noChoicesAvailableString = item.noChoicesAvailableString
+ dialog = if (noChoicesAvailableString != 0 && choices!!.isEmpty()) {
+ MaterialAlertDialogBuilder(fragmentView.fragmentActivity)
+ .setTitle(item.name)
+ .setMessage(noChoicesAvailableString)
+ .setPositiveButton(R.string.ok, null)
+ .show()
+ } else {
+ MaterialAlertDialogBuilder(fragmentView.fragmentActivity)
+ .setTitle(item.name)
+ .setSingleChoiceItems(
+ item.choices, item.selectedValueIndex,
+ this
+ )
+ .show()
+ }
+ }
+
+ fun onSingleChoiceDynamicDescriptionsClick(
+ item: SingleChoiceSettingDynamicDescriptions,
+ position: Int
+ ) {
+ clickedItem = item
+ clickedPosition = position
+
+ val value = getSelectionForSingleChoiceDynamicDescriptionsValue(item)
+
+ dialog = MaterialAlertDialogBuilder(fragmentView.fragmentActivity)
+ .setTitle(item.name)
+ .setSingleChoiceItems(item.choicesId, value, this)
+ .show()
+ }
+
+ fun onSliderClick(item: SliderSetting, position: Int) {
+ clickedItem = item
+ clickedPosition = position
+ seekbarProgress = item.selectedValue
+
+ val inflater = LayoutInflater.from(fragmentView.fragmentActivity)
+ val binding = DialogSliderBinding.inflate(inflater)
+
+ textSliderValue = binding.textValue
+ textSliderValue!!.text = seekbarProgress.toString()
+
+ binding.textUnits.text = item.units
+
+ val slider = binding.slider
+ slider.valueFrom = item.min.toFloat()
+ slider.valueTo = item.max.toFloat()
+ slider.value = seekbarProgress.toFloat()
+ slider.stepSize = item.stepSize.toFloat()
+ slider.addOnChangeListener(this)
+
+ dialog = MaterialAlertDialogBuilder(fragmentView.fragmentActivity)
+ .setTitle(item.name)
+ .setView(binding.root)
+ .setPositiveButton(R.string.ok, this)
+ .show()
+ }
+
+ fun onSubmenuClick(item: SubmenuSetting) {
+ fragmentView.loadSubMenu(item.menuKey)
+ }
+
+ fun onInputMappingClick(item: InputMappingControlSetting, position: Int) {
+ if (item.controller.defaultDevice.isEmpty() && !fragmentView.isMappingAllDevices) {
+ MaterialAlertDialogBuilder(fragmentView.fragmentActivity)
+ .setMessage(R.string.input_binding_no_device)
+ .setPositiveButton(R.string.ok, this)
+ .show()
+ return
+ }
+
+ val dialog = MotionAlertDialog(
+ fragmentView.fragmentActivity, item,
+ fragmentView.isMappingAllDevices
+ )
+
+ val background = ContextCompat.getDrawable(context, R.drawable.dialog_round)
+ @ColorInt val color = ElevationOverlayProvider(dialog.context).compositeOverlay(
+ MaterialColors.getColor(dialog.window!!.decorView, R.attr.colorSurface),
+ dialog.window!!.decorView.elevation
+ )
+ background!!.setColorFilter(color, PorterDuff.Mode.SRC_ATOP)
+ dialog.window!!.setBackgroundDrawable(background)
+
+ dialog.setTitle(R.string.input_binding)
+ dialog.setMessage(
+ String.format(
+ context.getString(R.string.input_binding_description),
+ item.name
+ )
+ )
+ dialog.setButton(AlertDialog.BUTTON_NEGATIVE, context.getString(R.string.cancel), this)
+ dialog.setButton(
+ AlertDialog.BUTTON_NEUTRAL,
+ context.getString(R.string.clear)
+ ) { _: DialogInterface?, _: Int -> item.clearValue() }
+ dialog.setOnDismissListener {
+ notifyItemChanged(position)
+ fragmentView.onSettingChanged()
+ }
+ dialog.setCanceledOnTouchOutside(false)
+ dialog.show()
+ }
+
+ fun onAdvancedInputMappingClick(item: InputMappingControlSetting, position: Int) {
+ val inflater = LayoutInflater.from(context)
+ val binding = DialogAdvancedMappingBinding.inflate(inflater)
+ val dialog = AdvancedMappingDialog(
+ context,
+ binding,
+ item.controlReference,
+ item.controller
+ )
+
+ val background = ContextCompat.getDrawable(context, R.drawable.dialog_round)
+ @ColorInt val color = ElevationOverlayProvider(dialog.context).compositeOverlay(
+ MaterialColors.getColor(dialog.window!!.decorView, R.attr.colorSurface),
+ dialog.window!!.decorView.elevation
+ )
+ background!!.setColorFilter(color, PorterDuff.Mode.SRC_ATOP)
+ dialog.window!!.setBackgroundDrawable(background)
+
+ dialog.setTitle(if (item.isInput) R.string.input_configure_input else R.string.input_configure_output)
+ dialog.setView(binding.root)
+ dialog.setButton(
+ AlertDialog.BUTTON_POSITIVE, context.getString(R.string.ok)
+ ) { _: DialogInterface?, _: Int ->
+ item.value = dialog.expression
+ notifyItemChanged(position)
+ fragmentView.onSettingChanged()
+ }
+ dialog.setButton(AlertDialog.BUTTON_NEGATIVE, context.getString(R.string.cancel), this)
+ dialog.setButton(
+ AlertDialog.BUTTON_NEUTRAL,
+ context.getString(R.string.clear)
+ ) { _: DialogInterface?, _: Int ->
+ item.clearValue()
+ notifyItemChanged(position)
+ fragmentView.onSettingChanged()
+ }
+ dialog.setCanceledOnTouchOutside(false)
+ dialog.show()
+ }
+
+ fun onFilePickerDirectoryClick(item: SettingsItem?, position: Int) {
+ clickedItem = item
+ clickedPosition = position
+
+ if (!PermissionsHandler.isExternalStorageLegacy()) {
+ MaterialAlertDialogBuilder(context)
+ .setMessage(R.string.path_not_changeable_scoped_storage)
+ .setPositiveButton(R.string.ok) { dialog: DialogInterface, _: Int -> dialog.dismiss() }
+ .show()
+ } else {
+ FileBrowserHelper.openDirectoryPicker(
+ fragmentView.fragmentActivity,
+ FileBrowserHelper.GAME_EXTENSIONS
+ )
+ }
+ }
+
+ fun onFilePickerFileClick(item: SettingsItem, position: Int) {
+ clickedItem = item
+ clickedPosition = position
+ val filePicker = item as FilePicker
+
+ val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
+ intent.addCategory(Intent.CATEGORY_OPENABLE)
+ intent.type = "*/*"
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, filePicker.getSelectedValue())
+ }
+
+ fragmentView.fragmentActivity.startActivityForResult(intent, filePicker.requestType)
+ }
+
+ fun onDateTimeClick(item: DateTimeChoiceSetting, position: Int) {
+ clickedItem = item
+ clickedPosition = position
+ val storedTime = java.lang.Long.decode(item.getSelectedValue()) * 1000
+
+ // Helper to extract hour and minute from epoch time
+ val calendar = Calendar.getInstance()
+ calendar.timeInMillis = storedTime
+ calendar.timeZone = TimeZone.getTimeZone("UTC")
+
+ // Start and end epoch times available for the Wii's date picker
+ val calendarConstraints = CalendarConstraints.Builder()
+ .setStart(946684800000L)
+ .setEnd(2082672000000L)
+ .build()
+
+ var timeFormat = TimeFormat.CLOCK_12H
+ if (DateFormat.is24HourFormat(fragmentView.fragmentActivity)) {
+ timeFormat = TimeFormat.CLOCK_24H
+ }
+
+ val datePicker = MaterialDatePicker.Builder.datePicker()
+ .setSelection(storedTime)
+ .setTitleText(R.string.select_rtc_date)
+ .setCalendarConstraints(calendarConstraints)
+ .build()
+ val timePicker = MaterialTimePicker.Builder()
+ .setTimeFormat(timeFormat)
+ .setHour(calendar[Calendar.HOUR_OF_DAY])
+ .setMinute(calendar[Calendar.MINUTE])
+ .setTitleText(R.string.select_rtc_time)
+ .build()
+
+ datePicker.addOnPositiveButtonClickListener {
+ timePicker.show(
+ fragmentView.fragmentActivity.supportFragmentManager,
+ "TimePicker"
+ )
+ }
+ timePicker.addOnPositiveButtonClickListener {
+ var epochTime = datePicker.selection!! / 1000
+ epochTime += timePicker.hour.toLong() * 60 * 60
+ epochTime += timePicker.minute.toLong() * 60
+ val rtcString = "0x" + java.lang.Long.toHexString(epochTime)
+ if (item.getSelectedValue() != rtcString) {
+ notifyItemChanged(clickedPosition)
+ fragmentView.onSettingChanged()
+ }
+ item.setSelectedValue(fragmentView.settings!!, rtcString)
+ clickedItem = null
+ }
+ datePicker.show(fragmentView.fragmentActivity.supportFragmentManager, "DatePicker")
+ }
+
+ fun onFilePickerConfirmation(selectedFile: String) {
+ val filePicker = clickedItem as FilePicker?
+
+ if (filePicker!!.getSelectedValue() != selectedFile) {
+ notifyItemChanged(clickedPosition)
+ fragmentView.onSettingChanged()
+ }
+
+ filePicker.setSelectedValue(fragmentView.settings!!, selectedFile)
+
+ clickedItem = null
+ }
+
+ fun onMenuTagAction(menuTag: MenuTag, value: Int) {
+ fragmentView.onMenuTagAction(menuTag, value)
+ }
+
+ fun hasMenuTagActionForValue(menuTag: MenuTag, value: Int): Boolean {
+ return fragmentView.hasMenuTagActionForValue(menuTag, value)
+ }
+
+ override fun onClick(dialog: DialogInterface, which: Int) {
+ when (clickedItem) {
+ is SingleChoiceSetting -> {
+ val scSetting = clickedItem as SingleChoiceSetting
+
+ val value = getValueForSingleChoiceSelection(scSetting, which)
+ if (scSetting.selectedValue != value) fragmentView.onSettingChanged()
+
+ scSetting.setSelectedValue(settings, value)
+
+ closeDialog()
+ }
+ is SingleChoiceSettingDynamicDescriptions -> {
+ val scSetting = clickedItem as SingleChoiceSettingDynamicDescriptions
+
+ val value = getValueForSingleChoiceDynamicDescriptionsSelection(scSetting, which)
+ if (scSetting.selectedValue != value) fragmentView.onSettingChanged()
+
+ scSetting.setSelectedValue(settings!!, value)
+
+ closeDialog()
+ }
+ is StringSingleChoiceSetting -> {
+ val scSetting = clickedItem as StringSingleChoiceSetting
+
+ val value = scSetting.getValueAt(which)
+ if (scSetting.selectedValue != value) fragmentView.onSettingChanged()
+
+ scSetting.setSelectedValue(settings, value)
+
+ closeDialog()
+ }
+ is IntSliderSetting -> {
+ val sliderSetting = clickedItem as IntSliderSetting
+ if (sliderSetting.selectedValue != seekbarProgress) fragmentView.onSettingChanged()
+ sliderSetting.setSelectedValue(settings, seekbarProgress)
+ closeDialog()
+ }
+ is FloatSliderSetting -> {
+ val sliderSetting = clickedItem as FloatSliderSetting
+
+ if (sliderSetting.selectedValue != seekbarProgress) fragmentView.onSettingChanged()
+
+ sliderSetting.setSelectedValue(settings, seekbarProgress.toFloat())
+
+ closeDialog()
+ }
+ }
+ clickedItem = null
+ seekbarProgress = -1
+ }
+
+ fun closeDialog() {
+ if (dialog != null) {
+ if (clickedPosition != -1) {
+ notifyItemChanged(clickedPosition)
+ clickedPosition = -1
+ }
+ dialog!!.dismiss()
+ dialog = null
+ }
+ }
+
+ override fun onValueChange(slider: Slider, progress: Float, fromUser: Boolean) {
+ seekbarProgress = progress.toInt()
+ textSliderValue!!.text = seekbarProgress.toString()
+ }
+
+ private fun getValueForSingleChoiceSelection(item: SingleChoiceSetting, which: Int): Int {
+ val valuesId = item.valuesId
+
+ return if (valuesId > 0) {
+ val valuesArray = context.resources.getIntArray(valuesId)
+ valuesArray[which]
+ } else {
+ which
+ }
+ }
+
+ private fun getSelectionForSingleChoiceValue(item: SingleChoiceSetting): Int {
+ val value = item.selectedValue
+ val valuesId = item.valuesId
+
+ if (valuesId > 0) {
+ val valuesArray = context.resources.getIntArray(valuesId)
+ for (index in valuesArray.indices) {
+ val current = valuesArray[index]
+ if (current == value) {
+ return index
+ }
+ }
+ } else {
+ return value
+ }
+ return -1
+ }
+
+ private fun getValueForSingleChoiceDynamicDescriptionsSelection(
+ item: SingleChoiceSettingDynamicDescriptions,
+ which: Int
+ ): Int {
+ val valuesId = item.valuesId
+ return if (valuesId > 0) {
+ val valuesArray = context.resources.getIntArray(valuesId)
+ valuesArray[which]
+ } else {
+ which
+ }
+ }
+
+ private fun getSelectionForSingleChoiceDynamicDescriptionsValue(
+ item: SingleChoiceSettingDynamicDescriptions
+ ): Int {
+ val value = item.selectedValue
+ val valuesId = item.valuesId
+ if (valuesId > 0) {
+ val valuesArray = context.resources.getIntArray(valuesId)
+ for (index in valuesArray.indices) {
+ val current = valuesArray[index]
+ if (current == value) {
+ return index
+ }
+ }
+ } else {
+ return value
+ }
+ return -1
+ }
+
+ companion object {
+ fun clearLog() {
+ // Don't delete the log in case it is being monitored by another app.
+ val log = File(DirectoryInitialization.getUserDirectory() + "/Logs/dolphin.log")
+ try {
+ val raf = RandomAccessFile(log, "rw")
+ raf.setLength(0)
+ } catch (e: IOException) {
+ Log.error("[SettingsAdapter] Failed to clear log file: " + e.message)
+ }
+ }
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.java
deleted file mode 100644
index 1a7905565d..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.java
+++ /dev/null
@@ -1,295 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.ui;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.core.graphics.Insets;
-import androidx.core.view.ViewCompat;
-import androidx.core.view.WindowInsetsCompat;
-import androidx.fragment.app.DialogFragment;
-import androidx.fragment.app.Fragment;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-
-import org.dolphinemu.dolphinemu.R;
-import org.dolphinemu.dolphinemu.databinding.FragmentSettingsBinding;
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
-public final class SettingsFragment extends Fragment implements SettingsFragmentView
-{
- private static final String ARGUMENT_MENU_TAG = "menu_tag";
- private static final String ARGUMENT_GAME_ID = "game_id";
-
- private SettingsFragmentPresenter mPresenter;
- private SettingsActivityView mActivity;
-
- private SettingsAdapter mAdapter;
-
- private int mOldControllerSettingsWarningHeight = 0;
-
- private static final Map<MenuTag, Integer> titles = new HashMap<>();
-
- static
- {
- titles.put(MenuTag.SETTINGS, R.string.settings);
- titles.put(MenuTag.CONFIG, R.string.config);
- titles.put(MenuTag.CONFIG_GENERAL, R.string.general_submenu);
- titles.put(MenuTag.CONFIG_INTERFACE, R.string.interface_submenu);
- titles.put(MenuTag.CONFIG_AUDIO, R.string.audio_submenu);
- titles.put(MenuTag.CONFIG_PATHS, R.string.paths_submenu);
- titles.put(MenuTag.CONFIG_GAME_CUBE, R.string.gamecube_submenu);
- titles.put(MenuTag.CONFIG_SERIALPORT1, R.string.serialport1_submenu);
- titles.put(MenuTag.CONFIG_WII, R.string.wii_submenu);
- titles.put(MenuTag.CONFIG_ADVANCED, R.string.advanced_submenu);
- titles.put(MenuTag.DEBUG, R.string.debug_submenu);
- titles.put(MenuTag.GRAPHICS, R.string.graphics_settings);
- titles.put(MenuTag.ENHANCEMENTS, R.string.enhancements_submenu);
- titles.put(MenuTag.STEREOSCOPY, R.string.stereoscopy_submenu);
- titles.put(MenuTag.HACKS, R.string.hacks_submenu);
- titles.put(MenuTag.STATISTICS, R.string.statistics_submenu);
- titles.put(MenuTag.ADVANCED_GRAPHICS, R.string.advanced_graphics_submenu);
- titles.put(MenuTag.CONFIG_LOG, R.string.log_submenu);
- titles.put(MenuTag.GCPAD_TYPE, R.string.gcpad_settings);
- titles.put(MenuTag.WIIMOTE, R.string.wiimote_settings);
- titles.put(MenuTag.WIIMOTE_EXTENSION, R.string.wiimote_extensions);
- titles.put(MenuTag.GCPAD_1, R.string.controller_0);
- titles.put(MenuTag.GCPAD_2, R.string.controller_1);
- titles.put(MenuTag.GCPAD_3, R.string.controller_2);
- titles.put(MenuTag.GCPAD_4, R.string.controller_3);
- titles.put(MenuTag.WIIMOTE_1, R.string.wiimote_0);
- titles.put(MenuTag.WIIMOTE_2, R.string.wiimote_1);
- titles.put(MenuTag.WIIMOTE_3, R.string.wiimote_2);
- titles.put(MenuTag.WIIMOTE_4, R.string.wiimote_3);
- titles.put(MenuTag.WIIMOTE_EXTENSION_1, R.string.wiimote_extension_0);
- titles.put(MenuTag.WIIMOTE_EXTENSION_2, R.string.wiimote_extension_1);
- titles.put(MenuTag.WIIMOTE_EXTENSION_3, R.string.wiimote_extension_2);
- titles.put(MenuTag.WIIMOTE_EXTENSION_4, R.string.wiimote_extension_3);
- titles.put(MenuTag.WIIMOTE_GENERAL_1, R.string.wiimote_general);
- titles.put(MenuTag.WIIMOTE_GENERAL_2, R.string.wiimote_general);
- titles.put(MenuTag.WIIMOTE_GENERAL_3, R.string.wiimote_general);
- titles.put(MenuTag.WIIMOTE_GENERAL_4, R.string.wiimote_general);
- titles.put(MenuTag.WIIMOTE_MOTION_SIMULATION_1, R.string.wiimote_motion_simulation);
- titles.put(MenuTag.WIIMOTE_MOTION_SIMULATION_2, R.string.wiimote_motion_simulation);
- titles.put(MenuTag.WIIMOTE_MOTION_SIMULATION_3, R.string.wiimote_motion_simulation);
- titles.put(MenuTag.WIIMOTE_MOTION_SIMULATION_4, R.string.wiimote_motion_simulation);
- titles.put(MenuTag.WIIMOTE_MOTION_INPUT_1, R.string.wiimote_motion_input);
- titles.put(MenuTag.WIIMOTE_MOTION_INPUT_2, R.string.wiimote_motion_input);
- titles.put(MenuTag.WIIMOTE_MOTION_INPUT_3, R.string.wiimote_motion_input);
- titles.put(MenuTag.WIIMOTE_MOTION_INPUT_4, R.string.wiimote_motion_input);
- }
-
- private FragmentSettingsBinding mBinding;
-
- public static Fragment newInstance(MenuTag menuTag, String gameId, Bundle extras)
- {
- SettingsFragment fragment = new SettingsFragment();
-
- Bundle arguments = new Bundle();
- if (extras != null)
- {
- arguments.putAll(extras);
- }
-
- arguments.putSerializable(ARGUMENT_MENU_TAG, menuTag);
- arguments.putString(ARGUMENT_GAME_ID, gameId);
-
- fragment.setArguments(arguments);
- return fragment;
- }
-
- @Override
- public void onAttach(@NonNull Context context)
- {
- super.onAttach(context);
-
- mActivity = (SettingsActivityView) context;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
-
- Bundle args = getArguments();
- MenuTag menuTag = (MenuTag) args.getSerializable(ARGUMENT_MENU_TAG);
- String gameId = getArguments().getString(ARGUMENT_GAME_ID);
-
- mPresenter = new SettingsFragmentPresenter(this, getContext());
- mAdapter = new SettingsAdapter(this, getContext());
-
- mPresenter.onCreate(menuTag, gameId, args);
- }
-
- @NonNull
- @Override
- public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
- @Nullable Bundle savedInstanceState)
- {
- mBinding = FragmentSettingsBinding.inflate(inflater, container, false);
- return mBinding.getRoot();
- }
-
- @Override
- public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
- {
- Bundle args = getArguments();
- MenuTag menuTag = (MenuTag) args.getSerializable(ARGUMENT_MENU_TAG);
-
- if (titles.containsKey(menuTag))
- {
- mActivity.setToolbarTitle(getString(titles.get(menuTag)));
- }
-
- LinearLayoutManager manager = new LinearLayoutManager(getActivity());
-
- RecyclerView recyclerView = mBinding.listSettings;
-
- recyclerView.setAdapter(mAdapter);
- recyclerView.setLayoutManager(manager);
-
- SettingsDividerItemDecoration divider = new SettingsDividerItemDecoration(requireActivity());
- recyclerView.addItemDecoration(divider);
-
- setInsets();
-
- SettingsActivityView activity = (SettingsActivityView) getActivity();
- mPresenter.onViewCreated(menuTag, activity.getSettings());
- }
-
- @Override
- public void onDestroyView()
- {
- super.onDestroyView();
- mBinding = null;
- }
-
- @Override
- public void onDetach()
- {
- super.onDetach();
- mActivity = null;
-
- if (mAdapter != null)
- {
- mAdapter.closeDialog();
- }
- }
-
- @Override
- public void onSettingsFileLoaded(
- org.dolphinemu.dolphinemu.features.settings.model.Settings settings)
- {
- mPresenter.setSettings(settings);
- }
-
- @Override
- public void showSettingsList(ArrayList<SettingsItem> settingsList)
- {
- mAdapter.setSettings(settingsList);
- }
-
- @Override
- public void loadDefaultSettings()
- {
- mPresenter.loadDefaultSettings();
- }
-
- @Override
- public SettingsAdapter getAdapter()
- {
- return mAdapter;
- }
-
- @Override
- public void loadSubMenu(MenuTag menuKey)
- {
- mActivity.showSettingsFragment(menuKey, null, true, getArguments().getString(ARGUMENT_GAME_ID));
- }
-
- @Override
- public void showDialogFragment(DialogFragment fragment)
- {
- mActivity.showDialogFragment(fragment);
- }
-
- @Override
- public void showToastMessage(String message)
- {
- mActivity.showToastMessage(message);
- }
-
- @Override
- public Settings getSettings()
- {
- return mPresenter.getSettings();
- }
-
- @Override
- public void onSettingChanged()
- {
- mActivity.onSettingChanged();
- }
-
- @Override
- public void onControllerSettingsChanged()
- {
- mAdapter.notifyAllSettingsChanged();
- mPresenter.updateOldControllerSettingsWarningVisibility();
- }
-
- @Override
- public void onMenuTagAction(@NonNull MenuTag menuTag, int value)
- {
- mActivity.onMenuTagAction(menuTag, value);
- }
-
- public boolean hasMenuTagActionForValue(@NonNull MenuTag menuTag, int value)
- {
- return mActivity.hasMenuTagActionForValue(menuTag, value);
- }
-
- @Override
- public void setMappingAllDevices(boolean allDevices)
- {
- mActivity.setMappingAllDevices(allDevices);
- }
-
- @Override
- public boolean isMappingAllDevices()
- {
- return mActivity.isMappingAllDevices();
- }
-
- @Override
- public void setOldControllerSettingsWarningVisibility(boolean visible)
- {
- mOldControllerSettingsWarningHeight =
- mActivity.setOldControllerSettingsWarningVisibility(visible);
-
- // Trigger the insets listener we've registered
- mBinding.listSettings.requestApplyInsets();
- }
-
- private void setInsets()
- {
- ViewCompat.setOnApplyWindowInsetsListener(mBinding.listSettings, (v, windowInsets) ->
- {
- Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
- int listSpacing = getResources().getDimensionPixelSize(R.dimen.spacing_list);
- v.setPadding(0, 0, 0, insets.bottom + listSpacing + mOldControllerSettingsWarningHeight);
- return windowInsets;
- });
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.kt
new file mode 100644
index 0000000000..d9ffd9113f
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragment.kt
@@ -0,0 +1,242 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.ui
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.updatePadding
+import androidx.fragment.app.DialogFragment
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentActivity
+import androidx.recyclerview.widget.LinearLayoutManager
+import org.dolphinemu.dolphinemu.R
+import org.dolphinemu.dolphinemu.databinding.FragmentSettingsBinding
+import org.dolphinemu.dolphinemu.features.settings.model.Settings
+import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
+import org.dolphinemu.dolphinemu.utils.SerializableHelper.serializable
+import java.util.*
+import kotlin.collections.ArrayList
+
+class SettingsFragment : Fragment(), SettingsFragmentView {
+ private lateinit var presenter: SettingsFragmentPresenter
+ private var activityView: SettingsActivityView? = null
+
+ private lateinit var menuTag: MenuTag
+
+ override val fragmentActivity: FragmentActivity
+ get() = requireActivity()
+
+ override var adapter: SettingsAdapter? = null
+
+ private var oldControllerSettingsWarningHeight = 0
+
+ private var binding: FragmentSettingsBinding? = null
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+
+ activityView = context as SettingsActivityView
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ menuTag = requireArguments().serializable(ARGUMENT_MENU_TAG)!!
+
+ val gameId = requireArguments().getString(ARGUMENT_GAME_ID)
+ presenter = SettingsFragmentPresenter(this, requireContext())
+ adapter = SettingsAdapter(this, requireContext())
+
+ presenter.onCreate(menuTag, gameId, requireArguments())
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentSettingsBinding.inflate(inflater, container, false)
+ return binding!!.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ if (titles.containsKey(menuTag)) {
+ activityView!!.setToolbarTitle(getString(titles[menuTag]!!))
+ }
+
+ val manager = LinearLayoutManager(activity)
+
+ val recyclerView = binding!!.listSettings
+ recyclerView.adapter = adapter
+ recyclerView.layoutManager = manager
+
+ val divider = SettingsDividerItemDecoration(requireActivity())
+ recyclerView.addItemDecoration(divider)
+
+ setInsets()
+
+ val activity = activity as SettingsActivityView?
+ presenter.onViewCreated(menuTag, activity!!.settings)
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ binding = null
+ }
+
+ override fun onDetach() {
+ super.onDetach()
+ activityView = null
+
+ if (adapter != null) {
+ adapter!!.closeDialog()
+ }
+ }
+
+ override fun onSettingsFileLoaded(settings: Settings) {
+ presenter.settings = settings
+ }
+
+ override fun showSettingsList(settingsList: ArrayList<SettingsItem>) {
+ adapter!!.setSettings(settingsList)
+ }
+
+ override fun loadDefaultSettings() {
+ presenter.loadDefaultSettings()
+ }
+
+ override fun loadSubMenu(menuKey: MenuTag) {
+ activityView!!.showSettingsFragment(
+ menuKey,
+ null,
+ true,
+ requireArguments().getString(ARGUMENT_GAME_ID)!!
+ )
+ }
+
+ override fun showDialogFragment(fragment: DialogFragment) {
+ activityView!!.showDialogFragment(fragment)
+ }
+
+ override fun showToastMessage(message: String) {
+ activityView!!.showToastMessage(message)
+ }
+
+ override val settings: Settings?
+ get() = presenter.settings
+
+ override fun onSettingChanged() {
+ activityView!!.onSettingChanged()
+ }
+
+ override fun onControllerSettingsChanged() {
+ adapter!!.notifyAllSettingsChanged()
+ presenter.updateOldControllerSettingsWarningVisibility()
+ }
+
+ override fun onMenuTagAction(menuTag: MenuTag, value: Int) {
+ activityView!!.onMenuTagAction(menuTag, value)
+ }
+
+ override fun hasMenuTagActionForValue(menuTag: MenuTag, value: Int): Boolean {
+ return activityView!!.hasMenuTagActionForValue(menuTag, value)
+ }
+
+ override var isMappingAllDevices: Boolean
+ get() = activityView!!.isMappingAllDevices
+ set(allDevices) {
+ activityView!!.isMappingAllDevices = allDevices
+ }
+
+ override fun setOldControllerSettingsWarningVisibility(visible: Boolean) {
+ oldControllerSettingsWarningHeight =
+ activityView!!.setOldControllerSettingsWarningVisibility(visible)
+
+ // Trigger the insets listener we've registered
+ binding!!.listSettings.requestApplyInsets()
+ }
+
+ private fun setInsets() {
+ ViewCompat.setOnApplyWindowInsetsListener(binding!!.listSettings) { v: View, windowInsets: WindowInsetsCompat ->
+ val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+ val listSpacing = resources.getDimensionPixelSize(R.dimen.spacing_list)
+ v.updatePadding(bottom = insets.bottom + listSpacing + oldControllerSettingsWarningHeight)
+ windowInsets
+ }
+ }
+
+ companion object {
+ private const val ARGUMENT_MENU_TAG = "menu_tag"
+ private const val ARGUMENT_GAME_ID = "game_id"
+ private val titles: MutableMap<MenuTag, Int> = EnumMap(MenuTag::class.java)
+
+ init {
+ titles[MenuTag.SETTINGS] = R.string.settings
+ titles[MenuTag.CONFIG] = R.string.config
+ titles[MenuTag.CONFIG_GENERAL] = R.string.general_submenu
+ titles[MenuTag.CONFIG_INTERFACE] = R.string.interface_submenu
+ titles[MenuTag.CONFIG_AUDIO] = R.string.audio_submenu
+ titles[MenuTag.CONFIG_PATHS] = R.string.paths_submenu
+ titles[MenuTag.CONFIG_GAME_CUBE] = R.string.gamecube_submenu
+ titles[MenuTag.CONFIG_SERIALPORT1] = R.string.serialport1_submenu
+ titles[MenuTag.CONFIG_WII] = R.string.wii_submenu
+ titles[MenuTag.CONFIG_ADVANCED] = R.string.advanced_submenu
+ titles[MenuTag.DEBUG] = R.string.debug_submenu
+ titles[MenuTag.GRAPHICS] = R.string.graphics_settings
+ titles[MenuTag.ENHANCEMENTS] = R.string.enhancements_submenu
+ titles[MenuTag.STEREOSCOPY] = R.string.stereoscopy_submenu
+ titles[MenuTag.HACKS] = R.string.hacks_submenu
+ titles[MenuTag.STATISTICS] = R.string.statistics_submenu
+ titles[MenuTag.ADVANCED_GRAPHICS] = R.string.advanced_graphics_submenu
+ titles[MenuTag.CONFIG_LOG] = R.string.log_submenu
+ titles[MenuTag.GCPAD_TYPE] = R.string.gcpad_settings
+ titles[MenuTag.WIIMOTE] = R.string.wiimote_settings
+ titles[MenuTag.WIIMOTE_EXTENSION] = R.string.wiimote_extensions
+ titles[MenuTag.GCPAD_1] = R.string.controller_0
+ titles[MenuTag.GCPAD_2] = R.string.controller_1
+ titles[MenuTag.GCPAD_3] = R.string.controller_2
+ titles[MenuTag.GCPAD_4] = R.string.controller_3
+ titles[MenuTag.WIIMOTE_1] = R.string.wiimote_0
+ titles[MenuTag.WIIMOTE_2] = R.string.wiimote_1
+ titles[MenuTag.WIIMOTE_3] = R.string.wiimote_2
+ titles[MenuTag.WIIMOTE_4] = R.string.wiimote_3
+ titles[MenuTag.WIIMOTE_EXTENSION_1] = R.string.wiimote_extension_0
+ titles[MenuTag.WIIMOTE_EXTENSION_2] = R.string.wiimote_extension_1
+ titles[MenuTag.WIIMOTE_EXTENSION_3] = R.string.wiimote_extension_2
+ titles[MenuTag.WIIMOTE_EXTENSION_4] = R.string.wiimote_extension_3
+ titles[MenuTag.WIIMOTE_GENERAL_1] = R.string.wiimote_general
+ titles[MenuTag.WIIMOTE_GENERAL_2] = R.string.wiimote_general
+ titles[MenuTag.WIIMOTE_GENERAL_3] = R.string.wiimote_general
+ titles[MenuTag.WIIMOTE_GENERAL_4] = R.string.wiimote_general
+ titles[MenuTag.WIIMOTE_MOTION_SIMULATION_1] = R.string.wiimote_motion_simulation
+ titles[MenuTag.WIIMOTE_MOTION_SIMULATION_2] = R.string.wiimote_motion_simulation
+ titles[MenuTag.WIIMOTE_MOTION_SIMULATION_3] = R.string.wiimote_motion_simulation
+ titles[MenuTag.WIIMOTE_MOTION_SIMULATION_4] = R.string.wiimote_motion_simulation
+ titles[MenuTag.WIIMOTE_MOTION_INPUT_1] = R.string.wiimote_motion_input
+ titles[MenuTag.WIIMOTE_MOTION_INPUT_2] = R.string.wiimote_motion_input
+ titles[MenuTag.WIIMOTE_MOTION_INPUT_3] = R.string.wiimote_motion_input
+ titles[MenuTag.WIIMOTE_MOTION_INPUT_4] = R.string.wiimote_motion_input
+ }
+
+ @JvmStatic
+ fun newInstance(menuTag: MenuTag?, gameId: String?, extras: Bundle?): Fragment {
+ val fragment = SettingsFragment()
+
+ val arguments = Bundle()
+ if (extras != null) {
+ arguments.putAll(extras)
+ }
+
+ arguments.putSerializable(ARGUMENT_MENU_TAG, menuTag)
+ arguments.putString(ARGUMENT_GAME_ID, gameId)
+
+ fragment.arguments = arguments
+ return fragment
+ }
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java
deleted file mode 100644
index 79b0666b5a..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java
+++ /dev/null
@@ -1,1402 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.ui;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.os.Bundle;
-import android.text.TextUtils;
-
-import androidx.annotation.NonNull;
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.collection.ArraySet;
-
-import org.dolphinemu.dolphinemu.NativeLibrary;
-import org.dolphinemu.dolphinemu.R;
-import org.dolphinemu.dolphinemu.activities.UserDataActivity;
-import org.dolphinemu.dolphinemu.features.input.model.InputMappingBooleanSetting;
-import org.dolphinemu.dolphinemu.features.input.model.InputMappingDoubleSetting;
-import org.dolphinemu.dolphinemu.features.input.model.InputMappingIntSetting;
-import org.dolphinemu.dolphinemu.features.input.model.controlleremu.ControlGroup;
-import org.dolphinemu.dolphinemu.features.input.model.ControlGroupEnabledSetting;
-import org.dolphinemu.dolphinemu.features.input.model.controlleremu.EmulatedController;
-import org.dolphinemu.dolphinemu.features.input.model.controlleremu.NumericSetting;
-import org.dolphinemu.dolphinemu.features.input.model.view.InputDeviceSetting;
-import org.dolphinemu.dolphinemu.features.input.model.view.InputMappingControlSetting;
-import org.dolphinemu.dolphinemu.features.input.ui.ProfileDialog;
-import org.dolphinemu.dolphinemu.features.input.ui.ProfileDialogPresenter;
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractBooleanSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.AbstractIntSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.AdHocBooleanSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.AdHocStringSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.FloatSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.IntSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.PostProcessing;
-import org.dolphinemu.dolphinemu.features.settings.model.ScaledIntSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-import org.dolphinemu.dolphinemu.features.settings.model.StringSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.DateTimeChoiceSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SwitchSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.FilePicker;
-import org.dolphinemu.dolphinemu.features.settings.model.view.FloatSliderSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.HeaderSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.HyperLinkHeaderSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.InputStringSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.IntSliderSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.InvertedSwitchSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.LogSwitchSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.PercentSliderSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.RunRunnable;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SingleChoiceSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SingleChoiceSettingDynamicDescriptions;
-import org.dolphinemu.dolphinemu.features.settings.model.view.StringSingleChoiceSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SubmenuSetting;
-import org.dolphinemu.dolphinemu.ui.main.MainPresenter;
-import org.dolphinemu.dolphinemu.utils.BooleanSupplier;
-import org.dolphinemu.dolphinemu.utils.EGLHelper;
-import org.dolphinemu.dolphinemu.utils.ThemeHelper;
-import org.dolphinemu.dolphinemu.utils.ThreadUtil;
-import org.dolphinemu.dolphinemu.utils.WiiUtils;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-
-public final class SettingsFragmentPresenter
-{
- private final SettingsFragmentView mView;
- private final Context mContext;
-
- private static final LinkedHashMap<String, String> LOG_TYPE_NAMES =
- NativeLibrary.GetLogTypeNames();
-
- public static final String ARG_CONTROLLER_TYPE = "controller_type";
- public static final String ARG_SERIALPORT1_TYPE = "serialport1_type";
- private MenuTag mMenuTag;
- private String mGameID;
-
- private Settings mSettings;
- private ArrayList<SettingsItem> mSettingsList;
- private boolean mHasOldControllerSettings = false;
-
- private int mSerialPort1Type;
- private int mControllerNumber;
- private int mControllerType;
-
- public SettingsFragmentPresenter(SettingsFragmentView view, Context context)
- {
- mView = view;
- mContext = context;
- }
-
- public void onCreate(MenuTag menuTag, String gameId, Bundle extras)
- {
- mGameID = gameId;
- this.mMenuTag = menuTag;
-
- if (menuTag.isGCPadMenu() || menuTag.isWiimoteExtensionMenu())
- {
- mControllerNumber = menuTag.getSubType();
- mControllerType = extras.getInt(ARG_CONTROLLER_TYPE);
- }
- else if (menuTag.isWiimoteMenu())
- {
- mControllerNumber = menuTag.getSubType();
- }
- else if (menuTag.isSerialPort1Menu())
- {
- mSerialPort1Type = extras.getInt(ARG_SERIALPORT1_TYPE);
- }
- }
-
- public void onViewCreated(MenuTag menuTag, Settings settings)
- {
- this.mMenuTag = menuTag;
-
- if (!TextUtils.isEmpty(mGameID))
- {
- mView.getActivity().setTitle(mContext.getString(R.string.game_settings, mGameID));
- }
-
- setSettings(settings);
- }
-
- public Settings getSettings()
- {
- return mSettings;
- }
-
- public void loadDefaultSettings()
- {
- loadSettingsList();
- }
-
- public void setSettings(Settings settings)
- {
- if (mSettingsList == null && settings != null)
- {
- mSettings = settings;
-
- loadSettingsList();
- }
- else
- {
- mView.showSettingsList(mSettingsList);
- mView.setOldControllerSettingsWarningVisibility(mHasOldControllerSettings);
- }
- }
-
- private void loadSettingsList()
- {
- ArrayList<SettingsItem> sl = new ArrayList<>();
-
- switch (mMenuTag)
- {
- case SETTINGS:
- addTopLevelSettings(sl);
- break;
-
- case CONFIG:
- addConfigSettings(sl);
- break;
-
- case CONFIG_GENERAL:
- addGeneralSettings(sl);
- break;
-
- case CONFIG_INTERFACE:
- addInterfaceSettings(sl);
- break;
-
- case CONFIG_AUDIO:
- addAudioSettings(sl);
- break;
-
- case CONFIG_PATHS:
- addPathsSettings(sl);
- break;
-
- case CONFIG_GAME_CUBE:
- addGameCubeSettings(sl);
- break;
-
- case CONFIG_WII:
- addWiiSettings(sl);
- break;
-
- case CONFIG_ADVANCED:
- addAdvancedSettings(sl);
- break;
-
- case GRAPHICS:
- addGraphicsSettings(sl);
- break;
-
- case CONFIG_SERIALPORT1:
- addSerialPortSubSettings(sl, mSerialPort1Type);
- break;
-
- case GCPAD_TYPE:
- addGcPadSettings(sl);
- break;
-
- case WIIMOTE:
- addWiimoteSettings(sl);
- break;
-
- case ENHANCEMENTS:
- addEnhanceSettings(sl);
- break;
-
- case STEREOSCOPY:
- addStereoSettings(sl);
- break;
-
- case HACKS:
- addHackSettings(sl);
- break;
-
- case STATISTICS:
- addStatisticsSettings(sl);
- break;
-
- case ADVANCED_GRAPHICS:
- addAdvancedGraphicsSettings(sl);
- break;
-
- case CONFIG_LOG:
- addLogConfigurationSettings(sl);
- break;
-
- case DEBUG:
- addDebugSettings(sl);
- break;
-
- case GCPAD_1:
- case GCPAD_2:
- case GCPAD_3:
- case GCPAD_4:
- addGcPadSubSettings(sl, mControllerNumber, mControllerType);
- break;
-
- case WIIMOTE_1:
- case WIIMOTE_2:
- case WIIMOTE_3:
- case WIIMOTE_4:
- addWiimoteSubSettings(sl, mControllerNumber);
- break;
-
- case WIIMOTE_EXTENSION_1:
- case WIIMOTE_EXTENSION_2:
- case WIIMOTE_EXTENSION_3:
- case WIIMOTE_EXTENSION_4:
- addExtensionTypeSettings(sl, mControllerNumber, mControllerType);
- break;
-
- case WIIMOTE_GENERAL_1:
- case WIIMOTE_GENERAL_2:
- case WIIMOTE_GENERAL_3:
- case WIIMOTE_GENERAL_4:
- addWiimoteGeneralSubSettings(sl, mControllerNumber);
- break;
-
- case WIIMOTE_MOTION_SIMULATION_1:
- case WIIMOTE_MOTION_SIMULATION_2:
- case WIIMOTE_MOTION_SIMULATION_3:
- case WIIMOTE_MOTION_SIMULATION_4:
- addWiimoteMotionSimulationSubSettings(sl, mControllerNumber);
- break;
-
- case WIIMOTE_MOTION_INPUT_1:
- case WIIMOTE_MOTION_INPUT_2:
- case WIIMOTE_MOTION_INPUT_3:
- case WIIMOTE_MOTION_INPUT_4:
- addWiimoteMotionInputSubSettings(sl, mControllerNumber);
- break;
-
- default:
- throw new UnsupportedOperationException("Unimplemented menu");
- }
-
- mSettingsList = sl;
- mView.showSettingsList(mSettingsList);
- }
-
- private void addTopLevelSettings(ArrayList<SettingsItem> sl)
- {
- sl.add(new SubmenuSetting(mContext, R.string.config, MenuTag.CONFIG));
- sl.add(new SubmenuSetting(mContext, R.string.graphics_settings, MenuTag.GRAPHICS));
-
- sl.add(new SubmenuSetting(mContext, R.string.gcpad_settings, MenuTag.GCPAD_TYPE));
- if (mSettings.isWii())
- {
- sl.add(new SubmenuSetting(mContext, R.string.wiimote_settings, MenuTag.WIIMOTE));
- }
-
- sl.add(new HeaderSetting(mContext, R.string.setting_clear_info, 0));
- }
-
- private void addConfigSettings(ArrayList<SettingsItem> sl)
- {
- sl.add(new SubmenuSetting(mContext, R.string.general_submenu, MenuTag.CONFIG_GENERAL));
- sl.add(new SubmenuSetting(mContext, R.string.interface_submenu, MenuTag.CONFIG_INTERFACE));
- sl.add(new SubmenuSetting(mContext, R.string.audio_submenu, MenuTag.CONFIG_AUDIO));
- sl.add(new SubmenuSetting(mContext, R.string.paths_submenu, MenuTag.CONFIG_PATHS));
- sl.add(new SubmenuSetting(mContext, R.string.gamecube_submenu, MenuTag.CONFIG_GAME_CUBE));
- sl.add(new SubmenuSetting(mContext, R.string.wii_submenu, MenuTag.CONFIG_WII));
- sl.add(new SubmenuSetting(mContext, R.string.advanced_submenu, MenuTag.CONFIG_ADVANCED));
- sl.add(new SubmenuSetting(mContext, R.string.log_submenu, MenuTag.CONFIG_LOG));
- sl.add(new SubmenuSetting(mContext, R.string.debug_submenu, MenuTag.DEBUG));
- sl.add(new RunRunnable(mContext, R.string.user_data_submenu, 0, 0, 0, false,
- () -> UserDataActivity.launch(mContext)));
- }
-
- private void addGeneralSettings(ArrayList<SettingsItem> sl)
- {
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_CPU_THREAD, R.string.dual_core,
- R.string.dual_core_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_ENABLE_CHEATS, R.string.enable_cheats,
- 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_OVERRIDE_REGION_SETTINGS,
- R.string.override_region_settings, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_AUTO_DISC_CHANGE,
- R.string.auto_disc_change, 0));
- sl.add(new PercentSliderSetting(mContext, FloatSetting.MAIN_EMULATION_SPEED,
- R.string.speed_limit, 0, 0, 200, "%", 1));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.MAIN_FALLBACK_REGION,
- R.string.fallback_region, 0, R.array.regionEntries, R.array.regionValues));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_ANALYTICS_ENABLED, R.string.analytics,
- 0));
- sl.add(new RunRunnable(mContext, R.string.analytics_new_id, 0,
- R.string.analytics_new_id_confirmation, 0, true,
- NativeLibrary::GenerateNewStatisticsId));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_ENABLE_SAVESTATES,
- R.string.enable_save_states, R.string.enable_save_states_description));
- }
-
- private void addInterfaceSettings(ArrayList<SettingsItem> sl)
- {
- // Hide the orientation setting if the device only supports one orientation. Old devices which
- // support both portrait and landscape may report support for neither, so we use ==, not &&.
- PackageManager packageManager = mContext.getPackageManager();
- if (packageManager.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT) ==
- packageManager.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE))
- {
- sl.add(new SingleChoiceSetting(mContext, IntSetting.MAIN_EMULATION_ORIENTATION,
- R.string.emulation_screen_orientation, 0, R.array.orientationEntries,
- R.array.orientationValues));
- }
-
- // Only android 9+ supports this feature.
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
- {
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_EXPAND_TO_CUTOUT_AREA,
- R.string.expand_to_cutout_area, R.string.expand_to_cutout_area_description));
- }
-
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_USE_PANIC_HANDLERS,
- R.string.panic_handlers, R.string.panic_handlers_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_OSD_MESSAGES, R.string.osd_messages,
- R.string.osd_messages_description));
-
- AbstractIntSetting appTheme = new AbstractIntSetting()
- {
- @Override
- public boolean isOverridden()
- {
- return IntSetting.MAIN_INTERFACE_THEME.isOverridden();
- }
-
- @Override
- public boolean isRuntimeEditable()
- {
- // This only affects app UI
- return true;
- }
-
- @Override
- public boolean delete(@NonNull Settings settings)
- {
- ThemeHelper.deleteThemeKey((AppCompatActivity) mView.getActivity());
- return IntSetting.MAIN_INTERFACE_THEME.delete(settings);
- }
-
- @Override
- public int getInt()
- {
- return IntSetting.MAIN_INTERFACE_THEME.getInt();
- }
-
- @Override
- public void setInt(@NonNull Settings settings, int newValue)
- {
- IntSetting.MAIN_INTERFACE_THEME.setInt(settings, newValue);
- ThemeHelper.saveTheme((AppCompatActivity) mView.getActivity(), newValue);
- }
- };
-
- // If a Monet theme is run on a device below API 31, the app will crash
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
- {
- sl.add(new SingleChoiceSetting(mContext, appTheme, R.string.change_theme, 0,
- R.array.themeEntriesA12, R.array.themeValuesA12));
- }
- else
- {
- sl.add(new SingleChoiceSetting(mContext, appTheme, R.string.change_theme, 0,
- R.array.themeEntries, R.array.themeValues));
- }
-
- AbstractIntSetting themeMode = new AbstractIntSetting()
- {
- @Override
- public boolean isOverridden()
- {
- return IntSetting.MAIN_INTERFACE_THEME_MODE.isOverridden();
- }
-
- @Override
- public boolean isRuntimeEditable()
- {
- // This only affects app UI
- return true;
- }
-
- @Override
- public boolean delete(@NonNull Settings settings)
- {
- ThemeHelper.deleteThemeModeKey((AppCompatActivity) mView.getActivity());
- return IntSetting.MAIN_INTERFACE_THEME_MODE.delete(settings);
- }
-
- @Override
- public int getInt()
- {
- return IntSetting.MAIN_INTERFACE_THEME_MODE.getInt();
- }
-
- @Override
- public void setInt(@NonNull Settings settings, int newValue)
- {
- IntSetting.MAIN_INTERFACE_THEME_MODE.setInt(settings, newValue);
- ThemeHelper.saveThemeMode((AppCompatActivity) mView.getActivity(), newValue);
- }
- };
-
- sl.add(new SingleChoiceSetting(mContext, themeMode, R.string.change_theme_mode, 0,
- R.array.themeModeEntries, R.array.themeModeValues));
-
- AbstractBooleanSetting blackBackgrounds = new AbstractBooleanSetting()
- {
- @Override
- public boolean isOverridden()
- {
- return BooleanSetting.MAIN_USE_BLACK_BACKGROUNDS.isOverridden();
- }
-
- @Override
- public boolean isRuntimeEditable()
- {
- return true;
- }
-
- @Override
- public boolean delete(@NonNull Settings settings)
- {
- ThemeHelper.deleteBackgroundSetting((AppCompatActivity) mView.getActivity());
- return BooleanSetting.MAIN_USE_BLACK_BACKGROUNDS.delete(settings);
- }
-
- @Override
- public boolean getBoolean()
- {
- return BooleanSetting.MAIN_USE_BLACK_BACKGROUNDS.getBoolean();
- }
-
- @Override
- public void setBoolean(@NonNull Settings settings, boolean newValue)
- {
- BooleanSetting.MAIN_USE_BLACK_BACKGROUNDS.setBoolean(settings, newValue);
- ThemeHelper.saveBackgroundSetting((AppCompatActivity) mView.getActivity(), newValue);
- }
- };
-
- sl.add(new SwitchSetting(mContext, blackBackgrounds, R.string.use_black_backgrounds,
- R.string.use_black_backgrounds_description));
- }
-
- private void addAudioSettings(ArrayList<SettingsItem> sl)
- {
- final int DSP_HLE = 0;
- final int DSP_LLE_RECOMPILER = 1;
- final int DSP_LLE_INTERPRETER = 2;
-
- AbstractIntSetting dspEmulationEngine = new AbstractIntSetting()
- {
- @Override
- public int getInt()
- {
- if (BooleanSetting.MAIN_DSP_HLE.getBoolean())
- {
- return DSP_HLE;
- }
- else
- {
- boolean jit = BooleanSetting.MAIN_DSP_JIT.getBoolean();
- return jit ? DSP_LLE_RECOMPILER : DSP_LLE_INTERPRETER;
- }
- }
-
- @Override
- public void setInt(@NonNull Settings settings, int newValue)
- {
- switch (newValue)
- {
- case DSP_HLE:
- BooleanSetting.MAIN_DSP_HLE.setBoolean(settings, true);
- BooleanSetting.MAIN_DSP_JIT.setBoolean(settings, true);
- break;
-
- case DSP_LLE_RECOMPILER:
- BooleanSetting.MAIN_DSP_HLE.setBoolean(settings, false);
- BooleanSetting.MAIN_DSP_JIT.setBoolean(settings, true);
- break;
-
- case DSP_LLE_INTERPRETER:
- BooleanSetting.MAIN_DSP_HLE.setBoolean(settings, false);
- BooleanSetting.MAIN_DSP_JIT.setBoolean(settings, false);
- break;
- }
- }
-
- @Override
- public boolean isOverridden()
- {
- return BooleanSetting.MAIN_DSP_HLE.isOverridden() ||
- BooleanSetting.MAIN_DSP_JIT.isOverridden();
- }
-
- @Override
- public boolean isRuntimeEditable()
- {
- return BooleanSetting.MAIN_DSP_HLE.isRuntimeEditable() &&
- BooleanSetting.MAIN_DSP_JIT.isRuntimeEditable();
- }
-
- @Override
- public boolean delete(@NonNull Settings settings)
- {
- // Not short circuiting
- return BooleanSetting.MAIN_DSP_HLE.delete(settings) &
- BooleanSetting.MAIN_DSP_JIT.delete(settings);
- }
- };
-
- // TODO: Exclude values from arrays instead of having multiple arrays.
- int defaultCpuCore = NativeLibrary.DefaultCPUCore();
- int dspEngineEntries;
- int dspEngineValues;
- if (defaultCpuCore == 1) // x86-64
- {
- dspEngineEntries = R.array.dspEngineEntriesX86_64;
- dspEngineValues = R.array.dspEngineValuesX86_64;
- }
- else // Generic
- {
- dspEngineEntries = R.array.dspEngineEntriesGeneric;
- dspEngineValues = R.array.dspEngineValuesGeneric;
- }
- sl.add(new SingleChoiceSetting(mContext, dspEmulationEngine, R.string.dsp_emulation_engine, 0,
- dspEngineEntries, dspEngineValues));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_AUDIO_STRETCH, R.string.audio_stretch,
- R.string.audio_stretch_description));
- sl.add(new IntSliderSetting(mContext, IntSetting.MAIN_AUDIO_VOLUME, R.string.audio_volume, 0,
- 0, 100, "%", 1));
- }
-
- private void addPathsSettings(ArrayList<SettingsItem> sl)
- {
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_RECURSIVE_ISO_PATHS,
- R.string.search_subfolders, 0));
- sl.add(new FilePicker(mContext, StringSetting.MAIN_DEFAULT_ISO, R.string.default_ISO, 0,
- MainPresenter.REQUEST_GAME_FILE, null));
- sl.add(new FilePicker(mContext, StringSetting.MAIN_FS_PATH, R.string.wii_NAND_root, 0,
- MainPresenter.REQUEST_DIRECTORY, "/Wii"));
- sl.add(new FilePicker(mContext, StringSetting.MAIN_DUMP_PATH, R.string.dump_path, 0,
- MainPresenter.REQUEST_DIRECTORY, "/Dump"));
- sl.add(new FilePicker(mContext, StringSetting.MAIN_LOAD_PATH, R.string.load_path, 0,
- MainPresenter.REQUEST_DIRECTORY, "/Load"));
- sl.add(new FilePicker(mContext, StringSetting.MAIN_RESOURCEPACK_PATH,
- R.string.resource_pack_path, 0, MainPresenter.REQUEST_DIRECTORY, "/ResourcePacks"));
- sl.add(new FilePicker(mContext, StringSetting.MAIN_WFS_PATH, R.string.wfs_path, 0,
- MainPresenter.REQUEST_DIRECTORY, "/WFS"));
- }
-
- private void addGameCubeSettings(ArrayList<SettingsItem> sl)
- {
- sl.add(new HeaderSetting(mContext, R.string.ipl_settings, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_SKIP_IPL, R.string.skip_main_menu,
- R.string.skip_main_menu_description));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.MAIN_GC_LANGUAGE, R.string.system_language,
- 0, R.array.gameCubeSystemLanguageEntries, R.array.gameCubeSystemLanguageValues));
-
- sl.add(new HeaderSetting(mContext, R.string.device_settings, 0));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.MAIN_SLOT_A, R.string.slot_a_device, 0,
- R.array.slotDeviceEntries, R.array.slotDeviceValues));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.MAIN_SLOT_B, R.string.slot_b_device, 0,
- R.array.slotDeviceEntries, R.array.slotDeviceValues));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.MAIN_SERIAL_PORT_1,
- R.string.serial_port_1_device, 0,
- R.array.serialPort1DeviceEntries, R.array.serialPort1DeviceValues,
- MenuTag.CONFIG_SERIALPORT1));
- }
-
- private void addWiiSettings(ArrayList<SettingsItem> sl)
- {
- sl.add(new HeaderSetting(mContext, R.string.wii_misc_settings, 0));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.SYSCONF_LANGUAGE, R.string.system_language,
- 0, R.array.wiiSystemLanguageEntries, R.array.wiiSystemLanguageValues));
- sl.add(new SwitchSetting(mContext, BooleanSetting.SYSCONF_WIDESCREEN, R.string.wii_widescreen,
- R.string.wii_widescreen_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.SYSCONF_PAL60, R.string.wii_pal60,
- R.string.wii_pal60_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.SYSCONF_SCREENSAVER,
- R.string.wii_screensaver, R.string.wii_screensaver_description));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.SYSCONF_SOUND_MODE, R.string.sound_mode, 0,
- R.array.soundModeEntries, R.array.soundModeValues));
-
- sl.add(new HeaderSetting(mContext, R.string.wii_sd_card_settings, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_WII_SD_CARD, R.string.insert_sd_card,
- R.string.insert_sd_card_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_ALLOW_SD_WRITES,
- R.string.wii_sd_card_allow_writes, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_WII_SD_CARD_ENABLE_FOLDER_SYNC,
- R.string.wii_sd_card_sync, R.string.wii_sd_card_sync_description));
- // TODO: Hardcoding "Load" here is wrong, because the user may have changed the Load path.
- // The code structure makes this hard to fix, and with scoped storage active the Load path
- // can't be changed anyway
- sl.add(new FilePicker(mContext, StringSetting.MAIN_WII_SD_CARD_IMAGE_PATH,
- R.string.wii_sd_card_path, 0, MainPresenter.REQUEST_SD_FILE, "/Load/WiiSD.raw"));
- sl.add(new FilePicker(mContext, StringSetting.MAIN_WII_SD_CARD_SYNC_FOLDER_PATH,
- R.string.wii_sd_sync_folder, 0, MainPresenter.REQUEST_DIRECTORY, "/Load/WiiSDSync/"));
- sl.add(new RunRunnable(mContext, R.string.wii_sd_card_folder_to_file, 0,
- R.string.wii_sd_card_folder_to_file_confirmation, 0, false,
- () -> convertOnThread(WiiUtils::syncSdFolderToSdImage)));
- sl.add(new RunRunnable(mContext, R.string.wii_sd_card_file_to_folder, 0,
- R.string.wii_sd_card_file_to_folder_confirmation, 0, false,
- () -> convertOnThread(WiiUtils::syncSdImageToSdFolder)));
-
- sl.add(new HeaderSetting(mContext, R.string.wii_wiimote_settings, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.SYSCONF_WIIMOTE_MOTOR,
- R.string.wiimote_rumble, 0));
- sl.add(new IntSliderSetting(mContext, IntSetting.SYSCONF_SPEAKER_VOLUME,
- R.string.wiimote_volume, 0, 0, 127, "", 1));
- sl.add(new IntSliderSetting(mContext, IntSetting.SYSCONF_SENSOR_BAR_SENSITIVITY,
- R.string.sensor_bar_sensitivity, 0, 1, 5, "", 1));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.SYSCONF_SENSOR_BAR_POSITION,
- R.string.sensor_bar_position, 0, R.array.sensorBarPositionEntries,
- R.array.sensorBarPositionValues));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_WIIMOTE_CONTINUOUS_SCANNING,
- R.string.wiimote_scanning, R.string.wiimote_scanning_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_WIIMOTE_ENABLE_SPEAKER,
- R.string.wiimote_speaker, R.string.wiimote_speaker_description));
-
- sl.add(new HeaderSetting(mContext, R.string.emulated_usb_devices, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_EMULATE_SKYLANDER_PORTAL,
- R.string.emulate_skylander_portal, 0));
- }
-
- private void addAdvancedSettings(ArrayList<SettingsItem> sl)
- {
- final int SYNC_GPU_NEVER = 0;
- final int SYNC_GPU_ON_IDLE_SKIP = 1;
- final int SYNC_GPU_ALWAYS = 2;
-
- AbstractIntSetting synchronizeGpuThread = new AbstractIntSetting()
- {
- @Override
- public int getInt()
- {
- if (BooleanSetting.MAIN_SYNC_GPU.getBoolean())
- {
- return SYNC_GPU_ALWAYS;
- }
- else
- {
- boolean syncOnSkipIdle = BooleanSetting.MAIN_SYNC_ON_SKIP_IDLE.getBoolean();
- return syncOnSkipIdle ? SYNC_GPU_ON_IDLE_SKIP : SYNC_GPU_NEVER;
- }
- }
-
- @Override
- public void setInt(@NonNull Settings settings, int newValue)
- {
- switch (newValue)
- {
- case SYNC_GPU_NEVER:
- BooleanSetting.MAIN_SYNC_ON_SKIP_IDLE.setBoolean(settings, false);
- BooleanSetting.MAIN_SYNC_GPU.setBoolean(settings, false);
- break;
-
- case SYNC_GPU_ON_IDLE_SKIP:
- BooleanSetting.MAIN_SYNC_ON_SKIP_IDLE.setBoolean(settings, true);
- BooleanSetting.MAIN_SYNC_GPU.setBoolean(settings, false);
- break;
-
- case SYNC_GPU_ALWAYS:
- BooleanSetting.MAIN_SYNC_ON_SKIP_IDLE.setBoolean(settings, true);
- BooleanSetting.MAIN_SYNC_GPU.setBoolean(settings, true);
- break;
- }
- }
-
- @Override
- public boolean isOverridden()
- {
- return BooleanSetting.MAIN_SYNC_ON_SKIP_IDLE.isOverridden() ||
- BooleanSetting.MAIN_SYNC_GPU.isOverridden();
- }
-
- @Override
- public boolean isRuntimeEditable()
- {
- return BooleanSetting.MAIN_SYNC_ON_SKIP_IDLE.isRuntimeEditable() &&
- BooleanSetting.MAIN_SYNC_GPU.isRuntimeEditable();
- }
-
- @Override
- public boolean delete(@NonNull Settings settings)
- {
- // Not short circuiting
- return BooleanSetting.MAIN_SYNC_ON_SKIP_IDLE.delete(settings) &
- BooleanSetting.MAIN_SYNC_GPU.delete(settings);
- }
- };
-
- // TODO: Having different emuCoresEntries/emuCoresValues for each architecture is annoying.
- // The proper solution would be to have one set of entries and one set of values
- // and exclude the values that aren't present in PowerPC::AvailableCPUCores().
- int defaultCpuCore = NativeLibrary.DefaultCPUCore();
- int emuCoresEntries;
- int emuCoresValues;
- if (defaultCpuCore == 1) // x86-64
- {
- emuCoresEntries = R.array.emuCoresEntriesX86_64;
- emuCoresValues = R.array.emuCoresValuesX86_64;
- }
- else if (defaultCpuCore == 4) // AArch64
- {
- emuCoresEntries = R.array.emuCoresEntriesARM64;
- emuCoresValues = R.array.emuCoresValuesARM64;
- }
- else
- {
- emuCoresEntries = R.array.emuCoresEntriesGeneric;
- emuCoresValues = R.array.emuCoresValuesGeneric;
- }
- sl.add(new HeaderSetting(mContext, R.string.cpu_options, 0));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.MAIN_CPU_CORE, R.string.cpu_core, 0,
- emuCoresEntries, emuCoresValues));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_MMU, R.string.mmu_enable,
- R.string.mmu_enable_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_PAUSE_ON_PANIC, R.string.pause_on_panic,
- R.string.pause_on_panic_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_ACCURATE_CPU_CACHE,
- R.string.enable_cpu_cache, R.string.enable_cpu_cache_description));
-
- sl.add(new HeaderSetting(mContext, R.string.clock_override, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_OVERCLOCK_ENABLE,
- R.string.overclock_enable, R.string.overclock_enable_description));
- sl.add(new PercentSliderSetting(mContext, FloatSetting.MAIN_OVERCLOCK, R.string.overclock_title,
- R.string.overclock_title_description, 0, 400, "%", 1));
-
- ScaledIntSetting mem1Size = new ScaledIntSetting(1024 * 1024, IntSetting.MAIN_MEM1_SIZE);
- ScaledIntSetting mem2Size = new ScaledIntSetting(1024 * 1024, IntSetting.MAIN_MEM2_SIZE);
-
- sl.add(new HeaderSetting(mContext, R.string.memory_override, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_RAM_OVERRIDE_ENABLE,
- R.string.enable_memory_size_override,
- R.string.enable_memory_size_override_description));
- sl.add(new IntSliderSetting(mContext, mem1Size, R.string.main_mem1_size, 0, 24, 64, "MB", 1));
- sl.add(new IntSliderSetting(mContext, mem2Size, R.string.main_mem2_size, 0, 64, 128, "MB", 1));
-
- sl.add(new HeaderSetting(mContext, R.string.gpu_options, 0));
- sl.add(new SingleChoiceSetting(mContext, synchronizeGpuThread, R.string.synchronize_gpu_thread,
- R.string.synchronize_gpu_thread_description, R.array.synchronizeGpuThreadEntries,
- R.array.synchronizeGpuThreadValues));
-
- sl.add(new HeaderSetting(mContext, R.string.custom_rtc_options, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_CUSTOM_RTC_ENABLE,
- R.string.custom_rtc_enable, R.string.custom_rtc_description));
- sl.add(new DateTimeChoiceSetting(mContext, StringSetting.MAIN_CUSTOM_RTC_VALUE,
- R.string.set_custom_rtc, 0));
-
- sl.add(new HeaderSetting(mContext, R.string.misc_settings, 0));
- sl.add(new InvertedSwitchSetting(mContext, BooleanSetting.MAIN_FAST_DISC_SPEED,
- R.string.emulate_disc_speed,
- R.string.emulate_disc_speed_description));
- }
-
- private void addSerialPortSubSettings(ArrayList<SettingsItem> sl, int serialPort1Type)
- {
- if (serialPort1Type == 10) // Broadband Adapter (XLink Kai)
- {
- sl.add(new HyperLinkHeaderSetting(mContext, R.string.xlink_kai_guide_header, 0));
- sl.add(new InputStringSetting(mContext, StringSetting.MAIN_BBA_XLINK_IP,
- R.string.xlink_kai_bba_ip, R.string.xlink_kai_bba_ip_description));
- }
- else if (serialPort1Type == 12) // Broadband Adapter (Built In)
- {
- sl.add(new InputStringSetting(mContext, StringSetting.MAIN_BBA_BUILTIN_DNS,
- R.string.bba_builtin_dns, R.string.bba_builtin_dns_description));
- }
- }
-
- private void addGcPadSettings(ArrayList<SettingsItem> sl)
- {
- sl.add(new SingleChoiceSetting(mContext, IntSetting.MAIN_SI_DEVICE_0, R.string.controller_0, 0,
- R.array.gcpadTypeEntries, R.array.gcpadTypeValues, MenuTag.getGCPadMenuTag(0)));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.MAIN_SI_DEVICE_1, R.string.controller_1, 0,
- R.array.gcpadTypeEntries, R.array.gcpadTypeValues, MenuTag.getGCPadMenuTag(1)));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.MAIN_SI_DEVICE_2, R.string.controller_2, 0,
- R.array.gcpadTypeEntries, R.array.gcpadTypeValues, MenuTag.getGCPadMenuTag(2)));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.MAIN_SI_DEVICE_3, R.string.controller_3, 0,
- R.array.gcpadTypeEntries, R.array.gcpadTypeValues, MenuTag.getGCPadMenuTag(3)));
- }
-
- private void addWiimoteSettings(ArrayList<SettingsItem> sl)
- {
- sl.add(new SingleChoiceSetting(mContext, IntSetting.WIIMOTE_1_SOURCE, R.string.wiimote_0, 0,
- R.array.wiimoteTypeEntries, R.array.wiimoteTypeValues, MenuTag.getWiimoteMenuTag(0)));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.WIIMOTE_2_SOURCE, R.string.wiimote_1, 0,
- R.array.wiimoteTypeEntries, R.array.wiimoteTypeValues, MenuTag.getWiimoteMenuTag(1)));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.WIIMOTE_3_SOURCE, R.string.wiimote_2, 0,
- R.array.wiimoteTypeEntries, R.array.wiimoteTypeValues, MenuTag.getWiimoteMenuTag(2)));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.WIIMOTE_4_SOURCE, R.string.wiimote_3, 0,
- R.array.wiimoteTypeEntries, R.array.wiimoteTypeValues, MenuTag.getWiimoteMenuTag(3)));
- }
-
- private void addGraphicsSettings(ArrayList<SettingsItem> sl)
- {
- sl.add(new HeaderSetting(mContext, R.string.graphics_general, 0));
- sl.add(new StringSingleChoiceSetting(mContext, StringSetting.MAIN_GFX_BACKEND,
- R.string.video_backend, 0, R.array.videoBackendEntries, R.array.videoBackendValues));
- sl.add(new SingleChoiceSettingDynamicDescriptions(mContext,
- IntSetting.GFX_SHADER_COMPILATION_MODE, R.string.shader_compilation_mode, 0,
- R.array.shaderCompilationModeEntries, R.array.shaderCompilationModeValues,
- R.array.shaderCompilationDescriptionEntries,
- R.array.shaderCompilationDescriptionValues));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_WAIT_FOR_SHADERS_BEFORE_STARTING,
- R.string.wait_for_shaders, R.string.wait_for_shaders_description));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.GFX_ASPECT_RATIO, R.string.aspect_ratio, 0,
- R.array.aspectRatioEntries, R.array.aspectRatioValues));
-
- sl.add(new HeaderSetting(mContext, R.string.graphics_more_settings, 0));
- sl.add(new SubmenuSetting(mContext, R.string.enhancements_submenu, MenuTag.ENHANCEMENTS));
- sl.add(new SubmenuSetting(mContext, R.string.hacks_submenu, MenuTag.HACKS));
- sl.add(new SubmenuSetting(mContext, R.string.statistics_submenu, MenuTag.STATISTICS));
- sl.add(new SubmenuSetting(mContext, R.string.advanced_graphics_submenu,
- MenuTag.ADVANCED_GRAPHICS));
- }
-
- private void addEnhanceSettings(ArrayList<SettingsItem> sl)
- {
- sl.add(new SingleChoiceSetting(mContext, IntSetting.GFX_EFB_SCALE, R.string.internal_resolution,
- R.string.internal_resolution_description, R.array.internalResolutionEntries,
- R.array.internalResolutionValues));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.GFX_MSAA, R.string.FSAA,
- R.string.FSAA_description, R.array.FSAAEntries, R.array.FSAAValues));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.GFX_ENHANCE_MAX_ANISOTROPY,
- R.string.anisotropic_filtering, R.string.anisotropic_filtering_description,
- R.array.anisotropicFilteringEntries, R.array.anisotropicFilteringValues));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.GFX_ENHANCE_FORCE_TEXTURE_FILTERING,
- R.string.texture_filtering, R.string.texture_filtering_description,
- R.array.textureFilteringEntries, R.array.textureFilteringValues));
-
- int stereoModeValue = IntSetting.GFX_STEREO_MODE.getInt();
- final int anaglyphMode = 3;
- String[] shaderList = stereoModeValue == anaglyphMode ?
- PostProcessing.getAnaglyphShaderList() : PostProcessing.getShaderList();
-
- String[] shaderListEntries = new String[shaderList.length + 1];
- shaderListEntries[0] = mContext.getString(R.string.off);
- System.arraycopy(shaderList, 0, shaderListEntries, 1, shaderList.length);
-
- String[] shaderListValues = new String[shaderList.length + 1];
- shaderListValues[0] = "";
- System.arraycopy(shaderList, 0, shaderListValues, 1, shaderList.length);
-
- sl.add(new StringSingleChoiceSetting(mContext, StringSetting.GFX_ENHANCE_POST_SHADER,
- R.string.post_processing_shader, 0, shaderListEntries, shaderListValues));
-
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_HACK_COPY_EFB_SCALED,
- R.string.scaled_efb_copy, R.string.scaled_efb_copy_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_ENABLE_PIXEL_LIGHTING,
- R.string.per_pixel_lighting, R.string.per_pixel_lighting_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_ENHANCE_FORCE_TRUE_COLOR,
- R.string.force_24bit_color, R.string.force_24bit_color_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_DISABLE_FOG, R.string.disable_fog,
- R.string.disable_fog_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_ENHANCE_DISABLE_COPY_FILTER,
- R.string.disable_copy_filter, R.string.disable_copy_filter_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION,
- R.string.arbitrary_mipmap_detection, R.string.arbitrary_mipmap_detection_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_WIDESCREEN_HACK,
- R.string.wide_screen_hack, R.string.wide_screen_hack_description));
-
- // Check if we support stereo
- // If we support desktop GL then we must support at least OpenGL 3.2
- // If we only support OpenGLES then we need both OpenGLES 3.1 and AEP
- EGLHelper helper = new EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT);
-
- if ((helper.supportsOpenGL() && helper.GetVersion() >= 320) ||
- (helper.supportsGLES3() && helper.GetVersion() >= 310 &&
- helper.SupportsExtension("GL_ANDROID_extension_pack_es31a")))
- {
- sl.add(new SubmenuSetting(mContext, R.string.stereoscopy_submenu, MenuTag.STEREOSCOPY));
- }
- }
-
- private void addHackSettings(ArrayList<SettingsItem> sl)
- {
- sl.add(new HeaderSetting(mContext, R.string.embedded_frame_buffer, 0));
- sl.add(new InvertedSwitchSetting(mContext, BooleanSetting.GFX_HACK_EFB_ACCESS_ENABLE,
- R.string.skip_efb_access, R.string.skip_efb_access_description));
- sl.add(new InvertedSwitchSetting(mContext, BooleanSetting.GFX_HACK_EFB_EMULATE_FORMAT_CHANGES,
- R.string.ignore_format_changes, R.string.ignore_format_changes_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_HACK_SKIP_EFB_COPY_TO_RAM,
- R.string.efb_copy_method, R.string.efb_copy_method_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_HACK_DEFER_EFB_COPIES,
- R.string.defer_efb_copies, R.string.defer_efb_copies_description));
-
- sl.add(new HeaderSetting(mContext, R.string.texture_cache, 0));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES,
- R.string.texture_cache_accuracy, R.string.texture_cache_accuracy_description,
- R.array.textureCacheAccuracyEntries, R.array.textureCacheAccuracyValues));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_ENABLE_GPU_TEXTURE_DECODING,
- R.string.gpu_texture_decoding, R.string.gpu_texture_decoding_description));
-
- sl.add(new HeaderSetting(mContext, R.string.external_frame_buffer, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_HACK_SKIP_XFB_COPY_TO_RAM,
- R.string.xfb_copy_method, R.string.xfb_copy_method_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_HACK_IMMEDIATE_XFB,
- R.string.immediate_xfb, R.string.immediate_xfb_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_HACK_SKIP_DUPLICATE_XFBS,
- R.string.skip_duplicate_xfbs, R.string.skip_duplicate_xfbs_description));
-
- sl.add(new HeaderSetting(mContext, R.string.other, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_FAST_DEPTH_CALC,
- R.string.fast_depth_calculation, R.string.fast_depth_calculation_description));
- sl.add(new InvertedSwitchSetting(mContext, BooleanSetting.GFX_HACK_BBOX_ENABLE,
- R.string.disable_bbox, R.string.disable_bbox_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_HACK_VERTEX_ROUNDING,
- R.string.vertex_rounding, R.string.vertex_rounding_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_HACK_VI_SKIP, R.string.vi_skip,
- R.string.vi_skip_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_SAVE_TEXTURE_CACHE_TO_STATE,
- R.string.texture_cache_to_state, R.string.texture_cache_to_state_description));
- }
-
- private void addStatisticsSettings(ArrayList<SettingsItem> sl)
- {
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_SHOW_FPS, R.string.show_fps,
- R.string.show_fps_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_SHOW_FTIMES, R.string.show_ftimes,
- R.string.show_ftimes_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_SHOW_VPS, R.string.show_vps,
- R.string.show_vps_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_SHOW_VTIMES, R.string.show_vtimes,
- R.string.show_vtimes_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_SHOW_GRAPHS, R.string.show_graphs,
- R.string.show_graphs_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_SHOW_SPEED, R.string.show_speed,
- R.string.show_speed_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_SHOW_SPEED_COLORS,
- R.string.show_speed_colors,
- R.string.show_speed_colors_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_LOG_RENDER_TIME_TO_FILE,
- R.string.log_render_time_to_file,
- R.string.log_render_time_to_file_description));
- sl.add(new IntSliderSetting(mContext, IntSetting.GFX_PERF_SAMP_WINDOW,
- R.string.performance_sample_window, R.string.performance_sample_window_description, 0,
- 10000, "ms", 100));
- }
-
- private void addAdvancedGraphicsSettings(ArrayList<SettingsItem> sl)
- {
- sl.add(new HeaderSetting(mContext, R.string.gfx_mods_and_custom_textures, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_MODS_ENABLE,
- R.string.gfx_mods, R.string.gfx_mods_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_HIRES_TEXTURES,
- R.string.load_custom_texture, R.string.load_custom_texture_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_CACHE_HIRES_TEXTURES,
- R.string.cache_custom_texture, R.string.cache_custom_texture_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_DUMP_TEXTURES,
- R.string.dump_texture, R.string.dump_texture_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_DUMP_BASE_TEXTURES,
- R.string.dump_base_texture, R.string.dump_base_texture_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_DUMP_MIP_TEXTURES,
- R.string.dump_mip_texture, R.string.dump_mip_texture_description));
-
- sl.add(new HeaderSetting(mContext, R.string.misc, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_CROP, R.string.crop,
- R.string.crop_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.SYSCONF_PROGRESSIVE_SCAN,
- R.string.progressive_scan, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_BACKEND_MULTITHREADING,
- R.string.backend_multithreading, R.string.backend_multithreading_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_PREFER_VS_FOR_LINE_POINT_EXPANSION,
- R.string.prefer_vs_for_point_line_expansion,
- R.string.prefer_vs_for_point_line_expansion_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_CPU_CULL, R.string.cpu_cull,
- R.string.cpu_cull_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_HACK_EFB_DEFER_INVALIDATION,
- R.string.defer_efb_invalidation, R.string.defer_efb_invalidation_description));
- sl.add(new InvertedSwitchSetting(mContext, BooleanSetting.GFX_HACK_FAST_TEXTURE_SAMPLING,
- R.string.manual_texture_sampling, R.string.manual_texture_sampling_description));
-
- sl.add(new HeaderSetting(mContext, R.string.frame_dumping, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_INTERNAL_RESOLUTION_FRAME_DUMPS,
- R.string.internal_resolution_dumps, R.string.internal_resolution_dumps_description));
- sl.add(new IntSliderSetting(mContext, IntSetting.GFX_PNG_COMPRESSION_LEVEL,
- R.string.png_compression_level, 0, 0, 9, "", 1));
-
- sl.add(new HeaderSetting(mContext, R.string.debugging, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_ENABLE_WIREFRAME,
- R.string.wireframe, R.string.leave_this_unchecked));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_OVERLAY_STATS,
- R.string.show_stats, R.string.leave_this_unchecked));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_TEXFMT_OVERLAY_ENABLE,
- R.string.texture_format, R.string.leave_this_unchecked));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_ENABLE_VALIDATION_LAYER,
- R.string.validation_layer, R.string.leave_this_unchecked));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_DUMP_EFB_TARGET,
- R.string.dump_efb, R.string.leave_this_unchecked));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_DUMP_XFB_TARGET,
- R.string.dump_xfb, R.string.leave_this_unchecked));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_HACK_DISABLE_COPY_TO_VRAM,
- R.string.disable_vram_copies, R.string.leave_this_unchecked));
- }
-
- private void addLogConfigurationSettings(ArrayList<SettingsItem> sl)
- {
- sl.add(new SwitchSetting(mContext, BooleanSetting.LOGGER_WRITE_TO_FILE, R.string.log_to_file,
- R.string.log_to_file_description));
- sl.add(new SingleChoiceSetting(mContext, IntSetting.LOGGER_VERBOSITY, R.string.log_verbosity, 0,
- getLogVerbosityEntries(), getLogVerbosityValues()));
- sl.add(new RunRunnable(mContext, R.string.log_enable_all, 0,
- R.string.log_enable_all_confirmation, 0, true, () -> setAllLogTypes(true)));
- sl.add(new RunRunnable(mContext, R.string.log_disable_all, 0,
- R.string.log_disable_all_confirmation, 0, true, () -> setAllLogTypes(false)));
- sl.add(new RunRunnable(mContext, R.string.log_clear, 0, R.string.log_clear_confirmation, 0,
- true, SettingsAdapter::clearLog));
-
- sl.add(new HeaderSetting(mContext, R.string.log_types, 0));
- for (Map.Entry<String, String> entry : LOG_TYPE_NAMES.entrySet())
- {
- sl.add(new LogSwitchSetting(entry.getKey(), entry.getValue(), ""));
- }
- }
-
- private void addDebugSettings(ArrayList<SettingsItem> sl)
- {
- sl.add(new HeaderSetting(mContext, R.string.debug_warning, 0));
- sl.add(new InvertedSwitchSetting(mContext, BooleanSetting.MAIN_FASTMEM,
- R.string.debug_fastmem, 0));
-
- sl.add(new HeaderSetting(mContext, R.string.debug_jit_header, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_DEBUG_JIT_OFF, R.string.debug_jitoff,
- 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_DEBUG_JIT_LOAD_STORE_OFF,
- R.string.debug_jitloadstoreoff, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_DEBUG_JIT_LOAD_STORE_FLOATING_OFF,
- R.string.debug_jitloadstorefloatingoff, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_DEBUG_JIT_LOAD_STORE_PAIRED_OFF,
- R.string.debug_jitloadstorepairedoff, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_DEBUG_JIT_FLOATING_POINT_OFF,
- R.string.debug_jitfloatingpointoff, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_DEBUG_JIT_INTEGER_OFF,
- R.string.debug_jitintegeroff, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_DEBUG_JIT_PAIRED_OFF,
- R.string.debug_jitpairedoff, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_DEBUG_JIT_SYSTEM_REGISTERS_OFF,
- R.string.debug_jitsystemregistersoff, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_DEBUG_JIT_BRANCH_OFF,
- R.string.debug_jitbranchoff, 0));
- sl.add(new SwitchSetting(mContext, BooleanSetting.MAIN_DEBUG_JIT_REGISTER_CACHE_OFF,
- R.string.debug_jitregistercacheoff, 0));
- }
-
- private void addStereoSettings(ArrayList<SettingsItem> sl)
- {
- sl.add(new SingleChoiceSetting(mContext, IntSetting.GFX_STEREO_MODE, R.string.stereoscopy_mode,
- 0, R.array.stereoscopyEntries, R.array.stereoscopyValues));
- sl.add(new IntSliderSetting(mContext, IntSetting.GFX_STEREO_DEPTH, R.string.stereoscopy_depth,
- R.string.stereoscopy_depth_description, 0, 100, "%", 1));
- sl.add(new IntSliderSetting(mContext, IntSetting.GFX_STEREO_CONVERGENCE_PERCENTAGE,
- R.string.stereoscopy_convergence, R.string.stereoscopy_convergence_description, 0, 200,
- "%", 1));
- sl.add(new SwitchSetting(mContext, BooleanSetting.GFX_STEREO_SWAP_EYES,
- R.string.stereoscopy_swap_eyes, R.string.stereoscopy_swap_eyes_description));
- }
-
- private void addGcPadSubSettings(ArrayList<SettingsItem> sl, int gcPadNumber, int gcPadType)
- {
- if (gcPadType == 6) // Emulated
- {
- EmulatedController gcPad = EmulatedController.getGcPad(gcPadNumber);
-
- if (!TextUtils.isEmpty(mGameID))
- {
- addControllerPerGameSettings(sl, "Pad", gcPadNumber);
- }
- else
- {
- addControllerMetaSettings(sl, gcPad);
- addControllerMappingSettings(sl, gcPad, null);
- }
- }
- else if (gcPadType == 12) // Adapter
- {
- sl.add(new SwitchSetting(mContext, BooleanSetting.getSettingForAdapterRumble(gcPadNumber),
- R.string.gc_adapter_rumble, R.string.gc_adapter_rumble_description));
- sl.add(new SwitchSetting(mContext, BooleanSetting.getSettingForSimulateKonga(gcPadNumber),
- R.string.gc_adapter_bongos, R.string.gc_adapter_bongos_description));
- }
- }
-
- private void addWiimoteSubSettings(ArrayList<SettingsItem> sl, int wiimoteNumber)
- {
- EmulatedController wiimote = EmulatedController.getWiimote(wiimoteNumber);
-
- if (!TextUtils.isEmpty(mGameID))
- {
- addControllerPerGameSettings(sl, "Wiimote", wiimoteNumber);
- }
- else
- {
- addControllerMetaSettings(sl, wiimote);
-
- sl.add(new HeaderSetting(mContext, R.string.wiimote, 0));
- sl.add(new SubmenuSetting(mContext, R.string.wiimote_general,
- MenuTag.getWiimoteGeneralMenuTag(wiimoteNumber)));
- sl.add(new SubmenuSetting(mContext, R.string.wiimote_motion_simulation,
- MenuTag.getWiimoteMotionSimulationMenuTag(wiimoteNumber)));
- sl.add(new SubmenuSetting(mContext, R.string.wiimote_motion_input,
- MenuTag.getWiimoteMotionInputMenuTag(wiimoteNumber)));
-
- // TYPE_OTHER is included here instead of in addWiimoteGeneralSubSettings so that touchscreen
- // users won't have to dig into a submenu to find the Sideways Wii Remote setting
- addControllerMappingSettings(sl, wiimote, new ArraySet<>(
- Arrays.asList(ControlGroup.TYPE_ATTACHMENTS, ControlGroup.TYPE_OTHER)));
- }
- }
-
- private void addExtensionTypeSettings(ArrayList<SettingsItem> sl, int wiimoteNumber,
- int extensionType)
- {
- addControllerMappingSettings(sl,
- EmulatedController.getWiimoteAttachment(wiimoteNumber, extensionType), null);
- }
-
- private void addWiimoteGeneralSubSettings(ArrayList<SettingsItem> sl, int wiimoteNumber)
- {
- addControllerMappingSettings(sl, EmulatedController.getWiimote(wiimoteNumber),
- Collections.singleton(ControlGroup.TYPE_BUTTONS));
- }
-
- private void addWiimoteMotionSimulationSubSettings(ArrayList<SettingsItem> sl, int wiimoteNumber)
- {
- addControllerMappingSettings(sl, EmulatedController.getWiimote(wiimoteNumber),
- new ArraySet<>(Arrays.asList(ControlGroup.TYPE_FORCE, ControlGroup.TYPE_TILT,
- ControlGroup.TYPE_CURSOR, ControlGroup.TYPE_SHAKE)));
- }
-
- private void addWiimoteMotionInputSubSettings(ArrayList<SettingsItem> sl, int wiimoteNumber)
- {
- addControllerMappingSettings(sl, EmulatedController.getWiimote(wiimoteNumber),
- new ArraySet<>(Arrays.asList(ControlGroup.TYPE_IMU_ACCELEROMETER,
- ControlGroup.TYPE_IMU_GYROSCOPE, ControlGroup.TYPE_IMU_CURSOR)));
- }
-
- /**
- * Adds controller settings that can be set on a per-game basis.
- *
- * @param sl The list to place controller settings into.
- * @param profileString The prefix used for the profile setting in game INI files.
- * @param controllerNumber The index of the controller, 0-3.
- */
- private void addControllerPerGameSettings(ArrayList<SettingsItem> sl, String profileString,
- int controllerNumber)
- {
- String[] profiles = new ProfileDialogPresenter(mMenuTag).getProfileNames(false);
- String profileKey = profileString + "Profile" + (controllerNumber + 1);
- sl.add(new StringSingleChoiceSetting(mContext,
- new AdHocStringSetting(Settings.FILE_GAME_SETTINGS_ONLY, "Controls", profileKey, ""),
- R.string.input_profile, 0, profiles, profiles, R.string.input_profiles_empty));
- }
-
- /**
- * Adds settings and actions that apply to a controller as a whole.
- * For instance, the device setting and the Clear action.
- *
- * @param sl The list to place controller settings into.
- * @param controller The controller to add settings for.
- */
- private void addControllerMetaSettings(ArrayList<SettingsItem> sl, EmulatedController controller)
- {
- sl.add(new InputDeviceSetting(mContext, R.string.input_device, 0, controller));
-
- sl.add(new SwitchSetting(mContext, new AbstractBooleanSetting()
- {
- @Override
- public boolean isOverridden()
- {
- return false;
- }
-
- @Override
- public boolean isRuntimeEditable()
- {
- return true;
- }
-
- @Override
- public boolean delete(@NonNull Settings settings)
- {
- mView.setMappingAllDevices(false);
- return true;
- }
-
- @Override
- public boolean getBoolean()
- {
- return mView.isMappingAllDevices();
- }
-
- @Override
- public void setBoolean(@NonNull Settings settings, boolean newValue)
- {
- mView.setMappingAllDevices(newValue);
- }
- }, R.string.input_device_all_devices, R.string.input_device_all_devices_description));
-
- sl.add(new RunRunnable(mContext, R.string.input_reset_to_default,
- R.string.input_reset_to_default_description, R.string.input_reset_warning, 0, true,
- () -> loadDefaultControllerSettings(controller)));
-
- sl.add(new RunRunnable(mContext, R.string.input_clear, R.string.input_clear_description,
- R.string.input_reset_warning, 0, true, () -> clearControllerSettings(controller)));
-
- sl.add(new RunRunnable(mContext, R.string.input_profiles, 0, 0, 0, true,
- () -> mView.showDialogFragment(ProfileDialog.create(mMenuTag))));
-
- updateOldControllerSettingsWarningVisibility(controller);
- }
-
- /**
- * Adds mapping settings and other control-specific settings.
- *
- * @param sl The list to place controller settings into.
- * @param controller The controller to add settings for.
- * @param groupTypeFilter If this is non-null, only groups whose types match this are considered.
- */
- private void addControllerMappingSettings(ArrayList<SettingsItem> sl,
- EmulatedController controller, Set<Integer> groupTypeFilter)
- {
- updateOldControllerSettingsWarningVisibility(controller);
-
- int groupCount = controller.getGroupCount();
- for (int i = 0; i < groupCount; i++)
- {
- ControlGroup group = controller.getGroup(i);
- int groupType = group.getGroupType();
- if (groupTypeFilter != null && !groupTypeFilter.contains(groupType))
- continue;
-
- sl.add(new HeaderSetting(group.getUiName(), ""));
-
- if (group.getDefaultEnabledValue() != ControlGroup.DEFAULT_ENABLED_ALWAYS)
- {
- sl.add(new SwitchSetting(mContext, new ControlGroupEnabledSetting(group), R.string.enabled,
- 0));
- }
-
- int controlCount = group.getControlCount();
- for (int j = 0; j < controlCount; j++)
- {
- sl.add(new InputMappingControlSetting(group.getControl(j), controller));
- }
-
- if (groupType == ControlGroup.TYPE_ATTACHMENTS)
- {
- NumericSetting attachmentSetting = group.getAttachmentSetting();
- sl.add(new SingleChoiceSetting(mContext, new InputMappingIntSetting(attachmentSetting),
- R.string.wiimote_extensions, 0, R.array.wiimoteExtensionsEntries,
- R.array.wiimoteExtensionsValues,
- MenuTag.getWiimoteExtensionMenuTag(mControllerNumber)));
- }
-
- int numericSettingCount = group.getNumericSettingCount();
- for (int j = 0; j < numericSettingCount; j++)
- {
- addNumericSetting(sl, group.getNumericSetting(j));
- }
- }
- }
-
- private void addNumericSetting(ArrayList<SettingsItem> sl, NumericSetting setting)
- {
- switch (setting.getType())
- {
- case NumericSetting.TYPE_DOUBLE:
- sl.add(new FloatSliderSetting(new InputMappingDoubleSetting(setting), setting.getUiName(),
- "", (int) Math.ceil(setting.getDoubleMin()),
- (int) Math.floor(setting.getDoubleMax()), setting.getUiSuffix()));
- break;
- case NumericSetting.TYPE_BOOLEAN:
- sl.add(new SwitchSetting(new InputMappingBooleanSetting(setting), setting.getUiName(),
- setting.getUiDescription()));
- break;
- }
- }
-
- public void updateOldControllerSettingsWarningVisibility()
- {
- updateOldControllerSettingsWarningVisibility(mMenuTag.getCorrespondingEmulatedController());
- }
-
- private void updateOldControllerSettingsWarningVisibility(EmulatedController controller)
- {
- String defaultDevice = controller.getDefaultDevice();
-
- mHasOldControllerSettings = defaultDevice.startsWith("Android/") &&
- defaultDevice.endsWith("/Touchscreen");
-
- mView.setOldControllerSettingsWarningVisibility(mHasOldControllerSettings);
- }
-
- private void loadDefaultControllerSettings(EmulatedController controller)
- {
- controller.loadDefaultSettings();
- mView.onControllerSettingsChanged();
- }
-
- private void clearControllerSettings(EmulatedController controller)
- {
- controller.clearSettings();
- mView.onControllerSettingsChanged();
- }
-
- private static int getLogVerbosityEntries()
- {
- // Value obtained from LogLevel in Common/Logging/Log.h
- if (NativeLibrary.GetMaxLogLevel() == 5)
- {
- return R.array.logVerbosityEntriesMaxLevelDebug;
- }
- else
- {
- return R.array.logVerbosityEntriesMaxLevelInfo;
- }
- }
-
- private static int getLogVerbosityValues()
- {
- // Value obtained from LogLevel in Common/Logging/Log.h
- if (NativeLibrary.GetMaxLogLevel() == 5)
- {
- return R.array.logVerbosityValuesMaxLevelDebug;
- }
- else
- {
- return R.array.logVerbosityValuesMaxLevelInfo;
- }
- }
-
- public void setAllLogTypes(boolean value)
- {
- Settings settings = mView.getSettings();
-
- for (Map.Entry<String, String> entry : LOG_TYPE_NAMES.entrySet())
- {
- new AdHocBooleanSetting(Settings.FILE_LOGGER, Settings.SECTION_LOGGER_LOGS, entry.getKey(),
- false).setBoolean(settings, value);
- }
-
- mView.getAdapter().notifyAllSettingsChanged();
- }
-
- private void convertOnThread(BooleanSupplier f)
- {
- ThreadUtil.runOnThreadAndShowResult(mView.getActivity(), R.string.wii_converting, 0, () ->
- mContext.getResources().getString(
- f.get() ? R.string.wii_convert_success : R.string.wii_convert_failure));
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt
new file mode 100644
index 0000000000..72649a39fd
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.kt
@@ -0,0 +1,2329 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.ui
+
+import android.content.Context
+import android.content.pm.PackageManager
+import android.os.Build
+import android.os.Bundle
+import android.text.TextUtils
+import androidx.appcompat.app.AppCompatActivity
+import androidx.collection.ArraySet
+import org.dolphinemu.dolphinemu.NativeLibrary
+import org.dolphinemu.dolphinemu.R
+import org.dolphinemu.dolphinemu.activities.UserDataActivity
+import org.dolphinemu.dolphinemu.features.input.model.ControlGroupEnabledSetting
+import org.dolphinemu.dolphinemu.features.input.model.InputMappingBooleanSetting
+import org.dolphinemu.dolphinemu.features.input.model.InputMappingDoubleSetting
+import org.dolphinemu.dolphinemu.features.input.model.InputMappingIntSetting
+import org.dolphinemu.dolphinemu.features.input.model.controlleremu.ControlGroup
+import org.dolphinemu.dolphinemu.features.input.model.controlleremu.EmulatedController
+import org.dolphinemu.dolphinemu.features.input.model.controlleremu.NumericSetting
+import org.dolphinemu.dolphinemu.features.input.model.view.InputDeviceSetting
+import org.dolphinemu.dolphinemu.features.input.model.view.InputMappingControlSetting
+import org.dolphinemu.dolphinemu.features.input.ui.ProfileDialog
+import org.dolphinemu.dolphinemu.features.input.ui.ProfileDialogPresenter
+import org.dolphinemu.dolphinemu.features.settings.model.*
+import org.dolphinemu.dolphinemu.features.settings.model.view.*
+import org.dolphinemu.dolphinemu.ui.main.MainPresenter
+import org.dolphinemu.dolphinemu.utils.*
+import java.util.*
+import kotlin.math.ceil
+import kotlin.math.floor
+
+class SettingsFragmentPresenter(
+ private val fragmentView: SettingsFragmentView,
+ private val context: Context
+) {
+ private var menuTag: MenuTag? = null
+ private var gameId: String? = null
+
+ private var settingsList: ArrayList<SettingsItem>? = null
+ private var hasOldControllerSettings = false
+
+ private var serialPort1Type = 0
+ private var controllerNumber = 0
+ private var controllerType = 0
+
+ fun onCreate(menuTag: MenuTag, gameId: String?, extras: Bundle) {
+ this.gameId = gameId
+ this.menuTag = menuTag
+
+ if (menuTag.isGCPadMenu || menuTag.isWiimoteExtensionMenu) {
+ controllerNumber = menuTag.subType
+ controllerType = extras.getInt(ARG_CONTROLLER_TYPE)
+ } else if (menuTag.isWiimoteMenu) {
+ controllerNumber = menuTag.subType
+ } else if (menuTag.isSerialPort1Menu) {
+ serialPort1Type = extras.getInt(ARG_SERIALPORT1_TYPE)
+ }
+ }
+
+ fun onViewCreated(menuTag: MenuTag?, settings: Settings?) {
+ this.menuTag = menuTag
+
+ if (!TextUtils.isEmpty(gameId)) {
+ fragmentView.fragmentActivity.title = context.getString(R.string.game_settings, gameId)
+ }
+
+ this.settings = settings
+ }
+
+ var settings: Settings? = null
+ set(settings) {
+ field = settings
+ if (settingsList == null && settings != null) {
+ loadSettingsList()
+ } else {
+ fragmentView.showSettingsList(settingsList!!)
+ fragmentView.setOldControllerSettingsWarningVisibility(hasOldControllerSettings)
+ }
+ }
+
+ fun loadDefaultSettings() {
+ loadSettingsList()
+ }
+
+ private fun loadSettingsList() {
+ val sl = ArrayList<SettingsItem>()
+ when (menuTag) {
+ MenuTag.SETTINGS -> addTopLevelSettings(sl)
+ MenuTag.CONFIG -> addConfigSettings(sl)
+ MenuTag.CONFIG_GENERAL -> addGeneralSettings(sl)
+ MenuTag.CONFIG_INTERFACE -> addInterfaceSettings(sl)
+ MenuTag.CONFIG_AUDIO -> addAudioSettings(sl)
+ MenuTag.CONFIG_PATHS -> addPathsSettings(sl)
+ MenuTag.CONFIG_GAME_CUBE -> addGameCubeSettings(sl)
+ MenuTag.CONFIG_WII -> addWiiSettings(sl)
+ MenuTag.CONFIG_ADVANCED -> addAdvancedSettings(sl)
+ MenuTag.GRAPHICS -> addGraphicsSettings(sl)
+ MenuTag.CONFIG_SERIALPORT1 -> addSerialPortSubSettings(sl, serialPort1Type)
+ MenuTag.GCPAD_TYPE -> addGcPadSettings(sl)
+ MenuTag.WIIMOTE -> addWiimoteSettings(sl)
+ MenuTag.ENHANCEMENTS -> addEnhanceSettings(sl)
+ MenuTag.STEREOSCOPY -> addStereoSettings(sl)
+ MenuTag.HACKS -> addHackSettings(sl)
+ MenuTag.STATISTICS -> addStatisticsSettings(sl)
+ MenuTag.ADVANCED_GRAPHICS -> addAdvancedGraphicsSettings(sl)
+ MenuTag.CONFIG_LOG -> addLogConfigurationSettings(sl)
+ MenuTag.DEBUG -> addDebugSettings(sl)
+ MenuTag.GCPAD_1,
+ MenuTag.GCPAD_2,
+ MenuTag.GCPAD_3,
+ MenuTag.GCPAD_4 -> addGcPadSubSettings(
+ sl,
+ controllerNumber,
+ controllerType
+ )
+ MenuTag.WIIMOTE_1,
+ MenuTag.WIIMOTE_2,
+ MenuTag.WIIMOTE_3,
+ MenuTag.WIIMOTE_4 -> addWiimoteSubSettings(
+ sl,
+ controllerNumber
+ )
+ MenuTag.WIIMOTE_EXTENSION_1,
+ MenuTag.WIIMOTE_EXTENSION_2,
+ MenuTag.WIIMOTE_EXTENSION_3,
+ MenuTag.WIIMOTE_EXTENSION_4 -> addExtensionTypeSettings(
+ sl,
+ controllerNumber,
+ controllerType
+ )
+ MenuTag.WIIMOTE_GENERAL_1,
+ MenuTag.WIIMOTE_GENERAL_2,
+ MenuTag.WIIMOTE_GENERAL_3,
+ MenuTag.WIIMOTE_GENERAL_4 -> addWiimoteGeneralSubSettings(
+ sl,
+ controllerNumber
+ )
+ MenuTag.WIIMOTE_MOTION_SIMULATION_1,
+ MenuTag.WIIMOTE_MOTION_SIMULATION_2,
+ MenuTag.WIIMOTE_MOTION_SIMULATION_3,
+ MenuTag.WIIMOTE_MOTION_SIMULATION_4 -> addWiimoteMotionSimulationSubSettings(
+ sl,
+ controllerNumber
+ )
+ MenuTag.WIIMOTE_MOTION_INPUT_1,
+ MenuTag.WIIMOTE_MOTION_INPUT_2,
+ MenuTag.WIIMOTE_MOTION_INPUT_3,
+ MenuTag.WIIMOTE_MOTION_INPUT_4 -> addWiimoteMotionInputSubSettings(
+ sl,
+ controllerNumber
+ )
+ else -> throw UnsupportedOperationException("Unimplemented menu")
+ }
+
+ settingsList = sl
+ fragmentView.showSettingsList(settingsList!!)
+ }
+
+ private fun addTopLevelSettings(sl: ArrayList<SettingsItem>) {
+ sl.add(SubmenuSetting(context, R.string.config, MenuTag.CONFIG))
+ sl.add(SubmenuSetting(context, R.string.graphics_settings, MenuTag.GRAPHICS))
+
+ sl.add(SubmenuSetting(context, R.string.gcpad_settings, MenuTag.GCPAD_TYPE))
+ if (settings!!.isWii) {
+ sl.add(SubmenuSetting(context, R.string.wiimote_settings, MenuTag.WIIMOTE))
+ }
+
+ sl.add(HeaderSetting(context, R.string.setting_clear_info, 0))
+ }
+
+ private fun addConfigSettings(sl: ArrayList<SettingsItem>) {
+ sl.add(SubmenuSetting(context, R.string.general_submenu, MenuTag.CONFIG_GENERAL))
+ sl.add(SubmenuSetting(context, R.string.interface_submenu, MenuTag.CONFIG_INTERFACE))
+ sl.add(SubmenuSetting(context, R.string.audio_submenu, MenuTag.CONFIG_AUDIO))
+ sl.add(SubmenuSetting(context, R.string.paths_submenu, MenuTag.CONFIG_PATHS))
+ sl.add(SubmenuSetting(context, R.string.gamecube_submenu, MenuTag.CONFIG_GAME_CUBE))
+ sl.add(SubmenuSetting(context, R.string.wii_submenu, MenuTag.CONFIG_WII))
+ sl.add(SubmenuSetting(context, R.string.advanced_submenu, MenuTag.CONFIG_ADVANCED))
+ sl.add(SubmenuSetting(context, R.string.log_submenu, MenuTag.CONFIG_LOG))
+ sl.add(SubmenuSetting(context, R.string.debug_submenu, MenuTag.DEBUG))
+ sl.add(
+ RunRunnable(context, R.string.user_data_submenu, 0, 0, 0, false)
+ { UserDataActivity.launch(context) }
+ )
+ }
+
+ private fun addGeneralSettings(sl: ArrayList<SettingsItem>) {
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_CPU_THREAD,
+ R.string.dual_core,
+ R.string.dual_core_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_ENABLE_CHEATS,
+ R.string.enable_cheats,
+ 0
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_OVERRIDE_REGION_SETTINGS,
+ R.string.override_region_settings,
+ 0
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_AUTO_DISC_CHANGE,
+ R.string.auto_disc_change,
+ 0
+ )
+ )
+ sl.add(
+ PercentSliderSetting(
+ context,
+ FloatSetting.MAIN_EMULATION_SPEED,
+ R.string.speed_limit,
+ 0,
+ 0,
+ 200,
+ "%",
+ 1
+ )
+ )
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.MAIN_FALLBACK_REGION,
+ R.string.fallback_region,
+ 0,
+ R.array.regionEntries,
+ R.array.regionValues
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_ANALYTICS_ENABLED,
+ R.string.analytics,
+ 0
+ )
+ )
+ sl.add(
+ RunRunnable(
+ context,
+ R.string.analytics_new_id,
+ 0,
+ R.string.analytics_new_id_confirmation,
+ 0,
+ true
+ ) { NativeLibrary.GenerateNewStatisticsId() }
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_ENABLE_SAVESTATES,
+ R.string.enable_save_states,
+ R.string.enable_save_states_description
+ )
+ )
+ }
+
+ private fun addInterfaceSettings(sl: ArrayList<SettingsItem>) {
+ // Hide the orientation setting if the device only supports one orientation. Old devices which
+ // support both portrait and landscape may report support for neither, so we use ==, not &&.
+ val packageManager = context.packageManager
+ if (packageManager.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT) ==
+ packageManager.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE)
+ ) {
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.MAIN_EMULATION_ORIENTATION,
+ R.string.emulation_screen_orientation,
+ 0,
+ R.array.orientationEntries,
+ R.array.orientationValues
+ )
+ )
+ }
+
+ // Only android 9+ supports this feature.
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_EXPAND_TO_CUTOUT_AREA,
+ R.string.expand_to_cutout_area,
+ R.string.expand_to_cutout_area_description
+ )
+ )
+ }
+
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_USE_PANIC_HANDLERS,
+ R.string.panic_handlers,
+ R.string.panic_handlers_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_OSD_MESSAGES,
+ R.string.osd_messages,
+ R.string.osd_messages_description
+ )
+ )
+
+ val appTheme: AbstractIntSetting = object : AbstractIntSetting {
+ override val isOverridden: Boolean
+ get() = IntSetting.MAIN_INTERFACE_THEME.isOverridden
+
+ // This only affects app UI
+ override val isRuntimeEditable: Boolean = true
+
+ override fun delete(settings: Settings): Boolean {
+ ThemeHelper.deleteThemeKey((fragmentView.fragmentActivity as AppCompatActivity))
+ return IntSetting.MAIN_INTERFACE_THEME.delete(settings)
+ }
+
+ override val int: Int
+ get() = IntSetting.MAIN_INTERFACE_THEME.int
+
+ override fun setInt(settings: Settings, newValue: Int) {
+ IntSetting.MAIN_INTERFACE_THEME.setInt(settings, newValue)
+ ThemeHelper.saveTheme(
+ (fragmentView.fragmentActivity as AppCompatActivity),
+ newValue
+ )
+ }
+ }
+
+ // If a Monet theme is run on a device below API 31, the app will crash
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ appTheme,
+ R.string.change_theme,
+ 0,
+ R.array.themeEntriesA12,
+ R.array.themeValuesA12
+ )
+ )
+ } else {
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ appTheme,
+ R.string.change_theme,
+ 0,
+ R.array.themeEntries,
+ R.array.themeValues
+ )
+ )
+ }
+
+ val themeMode: AbstractIntSetting = object : AbstractIntSetting {
+ override val isOverridden: Boolean
+ get() = IntSetting.MAIN_INTERFACE_THEME_MODE.isOverridden
+
+ // This only affects app UI
+ override val isRuntimeEditable: Boolean = true
+
+ override fun delete(settings: Settings): Boolean {
+ ThemeHelper.deleteThemeModeKey((fragmentView.fragmentActivity as AppCompatActivity))
+ return IntSetting.MAIN_INTERFACE_THEME_MODE.delete(settings)
+ }
+
+ override val int: Int
+ get() = IntSetting.MAIN_INTERFACE_THEME_MODE.int
+
+ override fun setInt(settings: Settings, newValue: Int) {
+ IntSetting.MAIN_INTERFACE_THEME_MODE.setInt(settings, newValue)
+ ThemeHelper.saveThemeMode(
+ (fragmentView.fragmentActivity as AppCompatActivity),
+ newValue
+ )
+ }
+ }
+
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ themeMode,
+ R.string.change_theme_mode,
+ 0,
+ R.array.themeModeEntries,
+ R.array.themeModeValues
+ )
+ )
+
+ val blackBackgrounds: AbstractBooleanSetting = object : AbstractBooleanSetting {
+ override val isOverridden: Boolean
+ get() = BooleanSetting.MAIN_USE_BLACK_BACKGROUNDS.isOverridden
+
+ override val isRuntimeEditable: Boolean = true
+
+ override fun delete(settings: Settings): Boolean {
+ ThemeHelper.deleteBackgroundSetting((fragmentView.fragmentActivity as AppCompatActivity))
+ return BooleanSetting.MAIN_USE_BLACK_BACKGROUNDS.delete(settings)
+ }
+
+ override val boolean: Boolean
+ get() = BooleanSetting.MAIN_USE_BLACK_BACKGROUNDS.boolean
+
+ override fun setBoolean(settings: Settings, newValue: Boolean) {
+ BooleanSetting.MAIN_USE_BLACK_BACKGROUNDS.setBoolean(settings, newValue)
+ ThemeHelper.saveBackgroundSetting(
+ (fragmentView.fragmentActivity as AppCompatActivity),
+ newValue
+ )
+ }
+ }
+
+ sl.add(
+ SwitchSetting(
+ context,
+ blackBackgrounds,
+ R.string.use_black_backgrounds,
+ R.string.use_black_backgrounds_description
+ )
+ )
+ }
+
+ private fun addAudioSettings(sl: ArrayList<SettingsItem>) {
+ val DSP_HLE = 0
+ val DSP_LLE_RECOMPILER = 1
+ val DSP_LLE_INTERPRETER = 2
+
+ val dspEmulationEngine: AbstractIntSetting = object : AbstractIntSetting {
+ override val int: Int
+ get() = if (BooleanSetting.MAIN_DSP_HLE.boolean) {
+ DSP_HLE
+ } else {
+ val jit = BooleanSetting.MAIN_DSP_JIT.boolean
+ if (jit) DSP_LLE_RECOMPILER else DSP_LLE_INTERPRETER
+ }
+
+ override fun setInt(settings: Settings, newValue: Int) {
+ when (newValue) {
+ DSP_HLE -> {
+ BooleanSetting.MAIN_DSP_HLE.setBoolean(settings, true)
+ BooleanSetting.MAIN_DSP_JIT.setBoolean(settings, true)
+ }
+ DSP_LLE_RECOMPILER -> {
+ BooleanSetting.MAIN_DSP_HLE.setBoolean(settings, false)
+ BooleanSetting.MAIN_DSP_JIT.setBoolean(settings, true)
+ }
+ DSP_LLE_INTERPRETER -> {
+ BooleanSetting.MAIN_DSP_HLE.setBoolean(settings, false)
+ BooleanSetting.MAIN_DSP_JIT.setBoolean(settings, false)
+ }
+ }
+ }
+
+ override val isOverridden: Boolean
+ get() = BooleanSetting.MAIN_DSP_HLE.isOverridden ||
+ BooleanSetting.MAIN_DSP_JIT.isOverridden
+
+ override val isRuntimeEditable: Boolean
+ get() = BooleanSetting.MAIN_DSP_HLE.isRuntimeEditable &&
+ BooleanSetting.MAIN_DSP_JIT.isRuntimeEditable
+
+ override fun delete(settings: Settings): Boolean {
+ // Not short circuiting
+ return BooleanSetting.MAIN_DSP_HLE.delete(settings) and
+ BooleanSetting.MAIN_DSP_JIT.delete(settings)
+ }
+ }
+
+ // TODO: Exclude values from arrays instead of having multiple arrays.
+ val defaultCpuCore = NativeLibrary.DefaultCPUCore()
+ val dspEngineEntries: Int
+ val dspEngineValues: Int
+ if (defaultCpuCore == 1) {
+ dspEngineEntries = R.array.dspEngineEntriesX86_64
+ dspEngineValues = R.array.dspEngineValuesX86_64
+ } else {
+ dspEngineEntries = R.array.dspEngineEntriesGeneric
+ dspEngineValues = R.array.dspEngineValuesGeneric
+ }
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ dspEmulationEngine,
+ R.string.dsp_emulation_engine,
+ 0,
+ dspEngineEntries,
+ dspEngineValues
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_AUDIO_STRETCH,
+ R.string.audio_stretch,
+ R.string.audio_stretch_description
+ )
+ )
+ sl.add(
+ IntSliderSetting(
+ context,
+ IntSetting.MAIN_AUDIO_VOLUME,
+ R.string.audio_volume,
+ 0,
+ 0,
+ 100,
+ "%",
+ 1
+ )
+ )
+ }
+
+ private fun addPathsSettings(sl: ArrayList<SettingsItem>) {
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_RECURSIVE_ISO_PATHS,
+ R.string.search_subfolders,
+ 0
+ )
+ )
+ sl.add(
+ FilePicker(
+ context,
+ StringSetting.MAIN_DEFAULT_ISO,
+ R.string.default_ISO,
+ 0,
+ MainPresenter.REQUEST_GAME_FILE,
+ null
+ )
+ )
+ sl.add(
+ FilePicker(
+ context,
+ StringSetting.MAIN_FS_PATH,
+ R.string.wii_NAND_root,
+ 0,
+ MainPresenter.REQUEST_DIRECTORY,
+ "/Wii"
+ )
+ )
+ sl.add(
+ FilePicker(
+ context,
+ StringSetting.MAIN_DUMP_PATH,
+ R.string.dump_path,
+ 0,
+ MainPresenter.REQUEST_DIRECTORY,
+ "/Dump"
+ )
+ )
+ sl.add(
+ FilePicker(
+ context,
+ StringSetting.MAIN_LOAD_PATH,
+ R.string.load_path,
+ 0,
+ MainPresenter.REQUEST_DIRECTORY,
+ "/Load"
+ )
+ )
+ sl.add(
+ FilePicker(
+ context,
+ StringSetting.MAIN_RESOURCEPACK_PATH,
+ R.string.resource_pack_path,
+ 0,
+ MainPresenter.REQUEST_DIRECTORY,
+ "/ResourcePacks"
+ )
+ )
+ sl.add(
+ FilePicker(
+ context,
+ StringSetting.MAIN_WFS_PATH,
+ R.string.wfs_path,
+ 0,
+ MainPresenter.REQUEST_DIRECTORY,
+ "/WFS"
+ )
+ )
+ }
+
+ private fun addGameCubeSettings(sl: ArrayList<SettingsItem>) {
+ sl.add(HeaderSetting(context, R.string.ipl_settings, 0))
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_SKIP_IPL,
+ R.string.skip_main_menu,
+ R.string.skip_main_menu_description
+ )
+ )
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.MAIN_GC_LANGUAGE,
+ R.string.system_language,
+ 0,
+ R.array.gameCubeSystemLanguageEntries,
+ R.array.gameCubeSystemLanguageValues
+ )
+ )
+
+ sl.add(HeaderSetting(context, R.string.device_settings, 0))
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.MAIN_SLOT_A,
+ R.string.slot_a_device,
+ 0,
+ R.array.slotDeviceEntries,
+ R.array.slotDeviceValues
+ )
+ )
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.MAIN_SLOT_B,
+ R.string.slot_b_device,
+ 0,
+ R.array.slotDeviceEntries,
+ R.array.slotDeviceValues
+ )
+ )
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.MAIN_SERIAL_PORT_1,
+ R.string.serial_port_1_device,
+ 0,
+ R.array.serialPort1DeviceEntries,
+ R.array.serialPort1DeviceValues,
+ MenuTag.CONFIG_SERIALPORT1
+ )
+ )
+ }
+
+ private fun addWiiSettings(sl: ArrayList<SettingsItem>) {
+ sl.add(HeaderSetting(context, R.string.wii_misc_settings, 0))
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.SYSCONF_LANGUAGE,
+ R.string.system_language,
+ 0,
+ R.array.wiiSystemLanguageEntries,
+ R.array.wiiSystemLanguageValues
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.SYSCONF_WIDESCREEN,
+ R.string.wii_widescreen,
+ R.string.wii_widescreen_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.SYSCONF_PAL60,
+ R.string.wii_pal60,
+ R.string.wii_pal60_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.SYSCONF_SCREENSAVER,
+ R.string.wii_screensaver,
+ R.string.wii_screensaver_description
+ )
+ )
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.SYSCONF_SOUND_MODE,
+ R.string.sound_mode,
+ 0,
+ R.array.soundModeEntries,
+ R.array.soundModeValues
+ )
+ )
+
+ sl.add(HeaderSetting(context, R.string.wii_sd_card_settings, 0))
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_WII_SD_CARD,
+ R.string.insert_sd_card,
+ R.string.insert_sd_card_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_ALLOW_SD_WRITES,
+ R.string.wii_sd_card_allow_writes,
+ 0
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_WII_SD_CARD_ENABLE_FOLDER_SYNC,
+ R.string.wii_sd_card_sync,
+ R.string.wii_sd_card_sync_description
+ )
+ )
+ // TODO: Hardcoding "Load" here is wrong, because the user may have changed the Load path.
+ // The code structure makes this hard to fix, and with scoped storage active the Load path
+ // can't be changed anyway
+ sl.add(
+ FilePicker(
+ context,
+ StringSetting.MAIN_WII_SD_CARD_IMAGE_PATH,
+ R.string.wii_sd_card_path,
+ 0,
+ MainPresenter.REQUEST_SD_FILE,
+ "/Load/WiiSD.raw"
+ )
+ )
+ sl.add(
+ FilePicker(
+ context,
+ StringSetting.MAIN_WII_SD_CARD_SYNC_FOLDER_PATH,
+ R.string.wii_sd_sync_folder,
+ 0,
+ MainPresenter.REQUEST_DIRECTORY,
+ "/Load/WiiSDSync/"
+ )
+ )
+ sl.add(
+ RunRunnable(
+ context,
+ R.string.wii_sd_card_folder_to_file,
+ 0,
+ R.string.wii_sd_card_folder_to_file_confirmation,
+ 0,
+ false
+ ) { convertOnThread { WiiUtils.syncSdFolderToSdImage() } }
+ )
+ sl.add(
+ RunRunnable(
+ context,
+ R.string.wii_sd_card_file_to_folder,
+ 0,
+ R.string.wii_sd_card_file_to_folder_confirmation,
+ 0,
+ false
+ ) { convertOnThread { WiiUtils.syncSdImageToSdFolder() } }
+ )
+
+ sl.add(HeaderSetting(context, R.string.wii_wiimote_settings, 0))
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.SYSCONF_WIIMOTE_MOTOR,
+ R.string.wiimote_rumble,
+ 0
+ )
+ )
+ sl.add(
+ IntSliderSetting(
+ context,
+ IntSetting.SYSCONF_SPEAKER_VOLUME,
+ R.string.wiimote_volume,
+ 0,
+ 0,
+ 127,
+ "",
+ 1
+ )
+ )
+ sl.add(
+ IntSliderSetting(
+ context,
+ IntSetting.SYSCONF_SENSOR_BAR_SENSITIVITY,
+ R.string.sensor_bar_sensitivity,
+ 0,
+ 1,
+ 5,
+ "",
+ 1
+ )
+ )
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.SYSCONF_SENSOR_BAR_POSITION,
+ R.string.sensor_bar_position,
+ 0,
+ R.array.sensorBarPositionEntries,
+ R.array.sensorBarPositionValues
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_WIIMOTE_CONTINUOUS_SCANNING,
+ R.string.wiimote_scanning,
+ R.string.wiimote_scanning_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_WIIMOTE_ENABLE_SPEAKER,
+ R.string.wiimote_speaker,
+ R.string.wiimote_speaker_description
+ )
+ )
+
+ sl.add(HeaderSetting(context, R.string.emulated_usb_devices, 0))
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_EMULATE_SKYLANDER_PORTAL,
+ R.string.emulate_skylander_portal,
+ 0
+ )
+ )
+ }
+
+ private fun addAdvancedSettings(sl: ArrayList<SettingsItem>) {
+ val SYNC_GPU_NEVER = 0
+ val SYNC_GPU_ON_IDLE_SKIP = 1
+ val SYNC_GPU_ALWAYS = 2
+
+ val synchronizeGpuThread: AbstractIntSetting = object : AbstractIntSetting {
+ override val int: Int
+ get() = if (BooleanSetting.MAIN_SYNC_GPU.boolean) {
+ SYNC_GPU_ALWAYS
+ } else {
+ val syncOnSkipIdle = BooleanSetting.MAIN_SYNC_ON_SKIP_IDLE.boolean
+ if (syncOnSkipIdle) SYNC_GPU_ON_IDLE_SKIP else SYNC_GPU_NEVER
+ }
+
+ override fun setInt(settings: Settings, newValue: Int) {
+ when (newValue) {
+ SYNC_GPU_NEVER -> {
+ BooleanSetting.MAIN_SYNC_ON_SKIP_IDLE.setBoolean(settings, false)
+ BooleanSetting.MAIN_SYNC_GPU.setBoolean(settings, false)
+ }
+ SYNC_GPU_ON_IDLE_SKIP -> {
+ BooleanSetting.MAIN_SYNC_ON_SKIP_IDLE.setBoolean(settings, true)
+ BooleanSetting.MAIN_SYNC_GPU.setBoolean(settings, false)
+ }
+ SYNC_GPU_ALWAYS -> {
+ BooleanSetting.MAIN_SYNC_ON_SKIP_IDLE.setBoolean(settings, true)
+ BooleanSetting.MAIN_SYNC_GPU.setBoolean(settings, true)
+ }
+ }
+ }
+
+ override val isOverridden: Boolean
+ get() = BooleanSetting.MAIN_SYNC_ON_SKIP_IDLE.isOverridden ||
+ BooleanSetting.MAIN_SYNC_GPU.isOverridden
+
+ override val isRuntimeEditable: Boolean
+ get() = BooleanSetting.MAIN_SYNC_ON_SKIP_IDLE.isRuntimeEditable &&
+ BooleanSetting.MAIN_SYNC_GPU.isRuntimeEditable
+
+ override fun delete(settings: Settings): Boolean {
+ // Not short circuiting
+ return BooleanSetting.MAIN_SYNC_ON_SKIP_IDLE.delete(settings) and
+ BooleanSetting.MAIN_SYNC_GPU.delete(settings)
+ }
+ }
+
+ // TODO: Having different emuCoresEntries/emuCoresValues for each architecture is annoying.
+ // The proper solution would be to have one set of entries and one set of values
+ // and exclude the values that aren't present in PowerPC::AvailableCPUCores().
+ val defaultCpuCore = NativeLibrary.DefaultCPUCore()
+ val emuCoresEntries: Int
+ val emuCoresValues: Int
+ when (defaultCpuCore) {
+ 1 -> {
+ emuCoresEntries = R.array.emuCoresEntriesX86_64
+ emuCoresValues = R.array.emuCoresValuesX86_64
+ }
+ 4 -> {
+ emuCoresEntries = R.array.emuCoresEntriesARM64
+ emuCoresValues = R.array.emuCoresValuesARM64
+ }
+ else -> {
+ emuCoresEntries = R.array.emuCoresEntriesGeneric
+ emuCoresValues = R.array.emuCoresValuesGeneric
+ }
+ }
+
+ sl.add(HeaderSetting(context, R.string.cpu_options, 0))
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.MAIN_CPU_CORE,
+ R.string.cpu_core,
+ 0,
+ emuCoresEntries,
+ emuCoresValues
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_MMU,
+ R.string.mmu_enable,
+ R.string.mmu_enable_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_PAUSE_ON_PANIC,
+ R.string.pause_on_panic,
+ R.string.pause_on_panic_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_ACCURATE_CPU_CACHE,
+ R.string.enable_cpu_cache,
+ R.string.enable_cpu_cache_description
+ )
+ )
+
+ sl.add(HeaderSetting(context, R.string.clock_override, 0))
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_OVERCLOCK_ENABLE,
+ R.string.overclock_enable,
+ R.string.overclock_enable_description
+ )
+ )
+ sl.add(
+ PercentSliderSetting(
+ context,
+ FloatSetting.MAIN_OVERCLOCK,
+ R.string.overclock_title,
+ R.string.overclock_title_description,
+ 0,
+ 400,
+ "%",
+ 1
+ )
+ )
+
+ val mem1Size = ScaledIntSetting(1024 * 1024, IntSetting.MAIN_MEM1_SIZE)
+ val mem2Size = ScaledIntSetting(1024 * 1024, IntSetting.MAIN_MEM2_SIZE)
+
+ sl.add(HeaderSetting(context, R.string.memory_override, 0))
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_RAM_OVERRIDE_ENABLE,
+ R.string.enable_memory_size_override,
+ R.string.enable_memory_size_override_description
+ )
+ )
+ sl.add(
+ IntSliderSetting(
+ context,
+ mem1Size,
+ R.string.main_mem1_size,
+ 0,
+ 24,
+ 64,
+ "MB",
+ 1
+ )
+ )
+ sl.add(
+ IntSliderSetting(
+ context,
+ mem2Size,
+ R.string.main_mem2_size,
+ 0,
+ 64,
+ 128,
+ "MB",
+ 1
+ )
+ )
+
+ sl.add(HeaderSetting(context, R.string.gpu_options, 0))
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ synchronizeGpuThread,
+ R.string.synchronize_gpu_thread,
+ R.string.synchronize_gpu_thread_description,
+ R.array.synchronizeGpuThreadEntries,
+ R.array.synchronizeGpuThreadValues
+ )
+ )
+
+ sl.add(HeaderSetting(context, R.string.custom_rtc_options, 0))
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_CUSTOM_RTC_ENABLE,
+ R.string.custom_rtc_enable,
+ R.string.custom_rtc_description
+ )
+ )
+ sl.add(
+ DateTimeChoiceSetting(
+ context,
+ StringSetting.MAIN_CUSTOM_RTC_VALUE,
+ R.string.set_custom_rtc,
+ 0
+ )
+ )
+
+ sl.add(HeaderSetting(context, R.string.misc_settings, 0))
+ sl.add(
+ InvertedSwitchSetting(
+ context,
+ BooleanSetting.MAIN_FAST_DISC_SPEED,
+ R.string.emulate_disc_speed,
+ R.string.emulate_disc_speed_description
+ )
+ )
+ }
+
+ private fun addSerialPortSubSettings(sl: ArrayList<SettingsItem>, serialPort1Type: Int) {
+ if (serialPort1Type == 10) {
+ // Broadband Adapter (XLink Kai)
+ sl.add(HyperLinkHeaderSetting(context, R.string.xlink_kai_guide_header, 0))
+ sl.add(
+ InputStringSetting(
+ context,
+ StringSetting.MAIN_BBA_XLINK_IP,
+ R.string.xlink_kai_bba_ip,
+ R.string.xlink_kai_bba_ip_description
+ )
+ )
+ } else if (serialPort1Type == 12) {
+ // Broadband Adapter (Built In)
+ sl.add(
+ InputStringSetting(
+ context,
+ StringSetting.MAIN_BBA_BUILTIN_DNS,
+ R.string.bba_builtin_dns,
+ R.string.bba_builtin_dns_description
+ )
+ )
+ }
+ }
+
+ private fun addGcPadSettings(sl: ArrayList<SettingsItem>) {
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.MAIN_SI_DEVICE_0,
+ R.string.controller_0,
+ 0,
+ R.array.gcpadTypeEntries,
+ R.array.gcpadTypeValues,
+ MenuTag.getGCPadMenuTag(0)
+ )
+ )
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.MAIN_SI_DEVICE_1,
+ R.string.controller_1,
+ 0,
+ R.array.gcpadTypeEntries,
+ R.array.gcpadTypeValues,
+ MenuTag.getGCPadMenuTag(1)
+ )
+ )
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.MAIN_SI_DEVICE_2,
+ R.string.controller_2,
+ 0,
+ R.array.gcpadTypeEntries,
+ R.array.gcpadTypeValues,
+ MenuTag.getGCPadMenuTag(2)
+ )
+ )
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.MAIN_SI_DEVICE_3,
+ R.string.controller_3,
+ 0,
+ R.array.gcpadTypeEntries,
+ R.array.gcpadTypeValues,
+ MenuTag.getGCPadMenuTag(3)
+ )
+ )
+ }
+
+ private fun addWiimoteSettings(sl: ArrayList<SettingsItem>) {
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.WIIMOTE_1_SOURCE,
+ R.string.wiimote_0,
+ 0,
+ R.array.wiimoteTypeEntries,
+ R.array.wiimoteTypeValues,
+ MenuTag.getWiimoteMenuTag(0)
+ )
+ )
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.WIIMOTE_2_SOURCE,
+ R.string.wiimote_1,
+ 0,
+ R.array.wiimoteTypeEntries,
+ R.array.wiimoteTypeValues,
+ MenuTag.getWiimoteMenuTag(1)
+ )
+ )
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.WIIMOTE_3_SOURCE,
+ R.string.wiimote_2,
+ 0,
+ R.array.wiimoteTypeEntries,
+ R.array.wiimoteTypeValues,
+ MenuTag.getWiimoteMenuTag(2)
+ )
+ )
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.WIIMOTE_4_SOURCE,
+ R.string.wiimote_3,
+ 0,
+ R.array.wiimoteTypeEntries,
+ R.array.wiimoteTypeValues,
+ MenuTag.getWiimoteMenuTag(3)
+ )
+ )
+ }
+
+ private fun addGraphicsSettings(sl: ArrayList<SettingsItem>) {
+ sl.add(HeaderSetting(context, R.string.graphics_general, 0))
+ sl.add(
+ StringSingleChoiceSetting(
+ context,
+ StringSetting.MAIN_GFX_BACKEND,
+ R.string.video_backend,
+ 0,
+ R.array.videoBackendEntries,
+ R.array.videoBackendValues
+ )
+ )
+ sl.add(
+ SingleChoiceSettingDynamicDescriptions(
+ context,
+ IntSetting.GFX_SHADER_COMPILATION_MODE,
+ R.string.shader_compilation_mode,
+ 0,
+ R.array.shaderCompilationModeEntries,
+ R.array.shaderCompilationModeValues,
+ R.array.shaderCompilationDescriptionEntries,
+ R.array.shaderCompilationDescriptionValues
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_WAIT_FOR_SHADERS_BEFORE_STARTING,
+ R.string.wait_for_shaders,
+ R.string.wait_for_shaders_description
+ )
+ )
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.GFX_ASPECT_RATIO,
+ R.string.aspect_ratio,
+ 0,
+ R.array.aspectRatioEntries,
+ R.array.aspectRatioValues
+ )
+ )
+
+ sl.add(HeaderSetting(context, R.string.graphics_more_settings, 0))
+ sl.add(
+ SubmenuSetting(
+ context,
+ R.string.enhancements_submenu,
+ MenuTag.ENHANCEMENTS
+ )
+ )
+ sl.add(
+ SubmenuSetting(
+ context,
+ R.string.hacks_submenu,
+ MenuTag.HACKS
+ )
+ )
+ sl.add(
+ SubmenuSetting(
+ context,
+ R.string.statistics_submenu,
+ MenuTag.STATISTICS
+ )
+ )
+ sl.add(
+ SubmenuSetting(
+ context,
+ R.string.advanced_graphics_submenu,
+ MenuTag.ADVANCED_GRAPHICS
+ )
+ )
+ }
+
+ private fun addEnhanceSettings(sl: ArrayList<SettingsItem>) {
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.GFX_EFB_SCALE,
+ R.string.internal_resolution,
+ R.string.internal_resolution_description,
+ R.array.internalResolutionEntries,
+ R.array.internalResolutionValues
+ )
+ )
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.GFX_MSAA,
+ R.string.FSAA,
+ R.string.FSAA_description,
+ R.array.FSAAEntries,
+ R.array.FSAAValues
+ )
+ )
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.GFX_ENHANCE_MAX_ANISOTROPY,
+ R.string.anisotropic_filtering,
+ R.string.anisotropic_filtering_description,
+ R.array.anisotropicFilteringEntries,
+ R.array.anisotropicFilteringValues
+ )
+ )
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.GFX_ENHANCE_FORCE_TEXTURE_FILTERING,
+ R.string.texture_filtering,
+ R.string.texture_filtering_description,
+ R.array.textureFilteringEntries,
+ R.array.textureFilteringValues
+ )
+ )
+
+ val stereoModeValue = IntSetting.GFX_STEREO_MODE.int
+ val anaglyphMode = 3
+ val shaderList =
+ if (stereoModeValue == anaglyphMode) PostProcessing.anaglyphShaderList else PostProcessing.shaderList
+
+ val shaderListEntries = arrayOfNulls<String>(shaderList.size + 1)
+ shaderListEntries[0] = context.getString(R.string.off)
+ System.arraycopy(shaderList, 0, shaderListEntries, 1, shaderList.size)
+
+ val shaderListValues = arrayOfNulls<String>(shaderList.size + 1)
+ shaderListValues[0] = ""
+ System.arraycopy(shaderList, 0, shaderListValues, 1, shaderList.size)
+
+ sl.add(
+ StringSingleChoiceSetting(
+ context,
+ StringSetting.GFX_ENHANCE_POST_SHADER,
+ R.string.post_processing_shader,
+ 0,
+ shaderListEntries,
+ shaderListValues
+ )
+ )
+
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_HACK_COPY_EFB_SCALED,
+ R.string.scaled_efb_copy,
+ R.string.scaled_efb_copy_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_ENABLE_PIXEL_LIGHTING,
+ R.string.per_pixel_lighting,
+ R.string.per_pixel_lighting_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_ENHANCE_FORCE_TRUE_COLOR,
+ R.string.force_24bit_color,
+ R.string.force_24bit_color_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_DISABLE_FOG,
+ R.string.disable_fog,
+ R.string.disable_fog_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_ENHANCE_DISABLE_COPY_FILTER,
+ R.string.disable_copy_filter,
+ R.string.disable_copy_filter_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION,
+ R.string.arbitrary_mipmap_detection,
+ R.string.arbitrary_mipmap_detection_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_WIDESCREEN_HACK,
+ R.string.wide_screen_hack,
+ R.string.wide_screen_hack_description
+ )
+ )
+
+ // Check if we support stereo
+ // If we support desktop GL then we must support at least OpenGL 3.2
+ // If we only support OpenGLES then we need both OpenGLES 3.1 and AEP
+ val helper = EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT)
+
+ if (helper.supportsOpenGL() && helper.GetVersion() >= 320 || helper.supportsGLES3() && helper.GetVersion() >= 310 && helper.SupportsExtension(
+ "GL_ANDROID_extension_pack_es31a"
+ )
+ ) {
+ sl.add(
+ SubmenuSetting(
+ context,
+ R.string.stereoscopy_submenu,
+ MenuTag.STEREOSCOPY
+ )
+ )
+ }
+ }
+
+ private fun addHackSettings(sl: ArrayList<SettingsItem>) {
+ sl.add(HeaderSetting(context, R.string.embedded_frame_buffer, 0))
+ sl.add(
+ InvertedSwitchSetting(
+ context,
+ BooleanSetting.GFX_HACK_EFB_ACCESS_ENABLE,
+ R.string.skip_efb_access,
+ R.string.skip_efb_access_description
+ )
+ )
+ sl.add(
+ InvertedSwitchSetting(
+ context,
+ BooleanSetting.GFX_HACK_EFB_EMULATE_FORMAT_CHANGES,
+ R.string.ignore_format_changes,
+ R.string.ignore_format_changes_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_HACK_SKIP_EFB_COPY_TO_RAM,
+ R.string.efb_copy_method,
+ R.string.efb_copy_method_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_HACK_DEFER_EFB_COPIES,
+ R.string.defer_efb_copies,
+ R.string.defer_efb_copies_description
+ )
+ )
+
+ sl.add(HeaderSetting(context, R.string.texture_cache, 0))
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES,
+ R.string.texture_cache_accuracy,
+ R.string.texture_cache_accuracy_description,
+ R.array.textureCacheAccuracyEntries,
+ R.array.textureCacheAccuracyValues
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_ENABLE_GPU_TEXTURE_DECODING,
+ R.string.gpu_texture_decoding,
+ R.string.gpu_texture_decoding_description
+ )
+ )
+
+ sl.add(HeaderSetting(context, R.string.external_frame_buffer, 0))
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_HACK_SKIP_XFB_COPY_TO_RAM,
+ R.string.xfb_copy_method,
+ R.string.xfb_copy_method_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_HACK_IMMEDIATE_XFB,
+ R.string.immediate_xfb,
+ R.string.immediate_xfb_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_HACK_SKIP_DUPLICATE_XFBS,
+ R.string.skip_duplicate_xfbs,
+ R.string.skip_duplicate_xfbs_description
+ )
+ )
+
+ sl.add(HeaderSetting(context, R.string.other, 0))
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_FAST_DEPTH_CALC,
+ R.string.fast_depth_calculation,
+ R.string.fast_depth_calculation_description
+ )
+ )
+ sl.add(
+ InvertedSwitchSetting(
+ context,
+ BooleanSetting.GFX_HACK_BBOX_ENABLE,
+ R.string.disable_bbox,
+ R.string.disable_bbox_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_HACK_VERTEX_ROUNDING,
+ R.string.vertex_rounding,
+ R.string.vertex_rounding_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_HACK_VI_SKIP,
+ R.string.vi_skip,
+ R.string.vi_skip_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_SAVE_TEXTURE_CACHE_TO_STATE,
+ R.string.texture_cache_to_state,
+ R.string.texture_cache_to_state_description
+ )
+ )
+ }
+
+ private fun addStatisticsSettings(sl: ArrayList<SettingsItem>) {
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_SHOW_FPS,
+ R.string.show_fps,
+ R.string.show_fps_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_SHOW_FTIMES,
+ R.string.show_ftimes,
+ R.string.show_ftimes_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_SHOW_VPS,
+ R.string.show_vps,
+ R.string.show_vps_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_SHOW_VTIMES,
+ R.string.show_vtimes,
+ R.string.show_vtimes_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_SHOW_GRAPHS,
+ R.string.show_graphs,
+ R.string.show_graphs_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_SHOW_SPEED,
+ R.string.show_speed,
+ R.string.show_speed_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_SHOW_SPEED_COLORS,
+ R.string.show_speed_colors,
+ R.string.show_speed_colors_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_LOG_RENDER_TIME_TO_FILE,
+ R.string.log_render_time_to_file,
+ R.string.log_render_time_to_file_description
+ )
+ )
+ sl.add(
+ IntSliderSetting(
+ context,
+ IntSetting.GFX_PERF_SAMP_WINDOW,
+ R.string.performance_sample_window,
+ R.string.performance_sample_window_description,
+ 0,
+ 10000,
+ "ms",
+ 100
+ )
+ )
+ }
+
+ private fun addAdvancedGraphicsSettings(sl: ArrayList<SettingsItem>) {
+ sl.add(HeaderSetting(context, R.string.gfx_mods_and_custom_textures, 0))
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_MODS_ENABLE,
+ R.string.gfx_mods,
+ R.string.gfx_mods_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_HIRES_TEXTURES,
+ R.string.load_custom_texture,
+ R.string.load_custom_texture_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_CACHE_HIRES_TEXTURES,
+ R.string.cache_custom_texture,
+ R.string.cache_custom_texture_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_DUMP_TEXTURES,
+ R.string.dump_texture,
+ R.string.dump_texture_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_DUMP_BASE_TEXTURES,
+ R.string.dump_base_texture,
+ R.string.dump_base_texture_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_DUMP_MIP_TEXTURES,
+ R.string.dump_mip_texture,
+ R.string.dump_mip_texture_description
+ )
+ )
+
+ sl.add(HeaderSetting(context, R.string.misc, 0))
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_CROP,
+ R.string.crop,
+ R.string.crop_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.SYSCONF_PROGRESSIVE_SCAN,
+ R.string.progressive_scan,
+ 0
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_BACKEND_MULTITHREADING,
+ R.string.backend_multithreading,
+ R.string.backend_multithreading_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_PREFER_VS_FOR_LINE_POINT_EXPANSION,
+ R.string.prefer_vs_for_point_line_expansion,
+ R.string.prefer_vs_for_point_line_expansion_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_CPU_CULL,
+ R.string.cpu_cull,
+ R.string.cpu_cull_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_HACK_EFB_DEFER_INVALIDATION,
+ R.string.defer_efb_invalidation,
+ R.string.defer_efb_invalidation_description
+ )
+ )
+ sl.add(
+ InvertedSwitchSetting(
+ context,
+ BooleanSetting.GFX_HACK_FAST_TEXTURE_SAMPLING,
+ R.string.manual_texture_sampling,
+ R.string.manual_texture_sampling_description
+ )
+ )
+
+ sl.add(HeaderSetting(context, R.string.frame_dumping, 0))
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_INTERNAL_RESOLUTION_FRAME_DUMPS,
+ R.string.internal_resolution_dumps,
+ R.string.internal_resolution_dumps_description
+ )
+ )
+ sl.add(
+ IntSliderSetting(
+ context,
+ IntSetting.GFX_PNG_COMPRESSION_LEVEL,
+ R.string.png_compression_level,
+ 0,
+ 0,
+ 9,
+ "",
+ 1
+ )
+ )
+
+ sl.add(HeaderSetting(context, R.string.debugging, 0))
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_ENABLE_WIREFRAME,
+ R.string.wireframe,
+ R.string.leave_this_unchecked
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_OVERLAY_STATS,
+ R.string.show_stats,
+ R.string.leave_this_unchecked
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_TEXFMT_OVERLAY_ENABLE,
+ R.string.texture_format,
+ R.string.leave_this_unchecked
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_ENABLE_VALIDATION_LAYER,
+ R.string.validation_layer,
+ R.string.leave_this_unchecked
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_DUMP_EFB_TARGET,
+ R.string.dump_efb,
+ R.string.leave_this_unchecked
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_DUMP_XFB_TARGET,
+ R.string.dump_xfb,
+ R.string.leave_this_unchecked
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_HACK_DISABLE_COPY_TO_VRAM,
+ R.string.disable_vram_copies,
+ R.string.leave_this_unchecked
+ )
+ )
+ }
+
+ private fun addLogConfigurationSettings(sl: ArrayList<SettingsItem>) {
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.LOGGER_WRITE_TO_FILE,
+ R.string.log_to_file,
+ R.string.log_to_file_description
+ )
+ )
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.LOGGER_VERBOSITY,
+ R.string.log_verbosity,
+ 0,
+ logVerbosityEntries, logVerbosityValues
+ )
+ )
+ sl.add(
+ RunRunnable(
+ context,
+ R.string.log_enable_all,
+ 0,
+ R.string.log_enable_all_confirmation,
+ 0,
+ true
+ ) { setAllLogTypes(true) })
+ sl.add(
+ RunRunnable(
+ context,
+ R.string.log_disable_all,
+ 0,
+ R.string.log_disable_all_confirmation,
+ 0,
+ true
+ ) { setAllLogTypes(false) })
+ sl.add(
+ RunRunnable(
+ context,
+ R.string.log_clear,
+ 0,
+ R.string.log_clear_confirmation,
+ 0,
+ true
+ ) { SettingsAdapter.clearLog() })
+
+ sl.add(HeaderSetting(context, R.string.log_types, 0))
+ for ((key, value) in LOG_TYPE_NAMES) {
+ sl.add(LogSwitchSetting(key, value, ""))
+ }
+ }
+
+ private fun addDebugSettings(sl: ArrayList<SettingsItem>) {
+ sl.add(HeaderSetting(context, R.string.debug_warning, 0))
+ sl.add(
+ InvertedSwitchSetting(
+ context,
+ BooleanSetting.MAIN_FASTMEM,
+ R.string.debug_fastmem,
+ 0
+ )
+ )
+
+ sl.add(HeaderSetting(context, R.string.debug_jit_header, 0))
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_DEBUG_JIT_OFF,
+ R.string.debug_jitoff,
+ 0
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_DEBUG_JIT_LOAD_STORE_OFF,
+ R.string.debug_jitloadstoreoff,
+ 0
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_DEBUG_JIT_LOAD_STORE_FLOATING_OFF,
+ R.string.debug_jitloadstorefloatingoff,
+ 0
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_DEBUG_JIT_LOAD_STORE_PAIRED_OFF,
+ R.string.debug_jitloadstorepairedoff,
+ 0
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_DEBUG_JIT_FLOATING_POINT_OFF,
+ R.string.debug_jitfloatingpointoff,
+ 0
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_DEBUG_JIT_INTEGER_OFF,
+ R.string.debug_jitintegeroff,
+ 0
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_DEBUG_JIT_PAIRED_OFF,
+ R.string.debug_jitpairedoff,
+ 0
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_DEBUG_JIT_SYSTEM_REGISTERS_OFF,
+ R.string.debug_jitsystemregistersoff,
+ 0
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_DEBUG_JIT_BRANCH_OFF,
+ R.string.debug_jitbranchoff,
+ 0
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.MAIN_DEBUG_JIT_REGISTER_CACHE_OFF,
+ R.string.debug_jitregistercacheoff,
+ 0
+ )
+ )
+ }
+
+ private fun addStereoSettings(sl: ArrayList<SettingsItem>) {
+ sl.add(
+ SingleChoiceSetting(
+ context,
+ IntSetting.GFX_STEREO_MODE,
+ R.string.stereoscopy_mode,
+ 0,
+ R.array.stereoscopyEntries,
+ R.array.stereoscopyValues
+ )
+ )
+ sl.add(
+ IntSliderSetting(
+ context,
+ IntSetting.GFX_STEREO_DEPTH,
+ R.string.stereoscopy_depth,
+ R.string.stereoscopy_depth_description,
+ 0,
+ 100,
+ "%",
+ 1
+ )
+ )
+ sl.add(
+ IntSliderSetting(
+ context,
+ IntSetting.GFX_STEREO_CONVERGENCE_PERCENTAGE,
+ R.string.stereoscopy_convergence,
+ R.string.stereoscopy_convergence_description,
+ 0,
+ 200,
+ "%",
+ 1
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.GFX_STEREO_SWAP_EYES,
+ R.string.stereoscopy_swap_eyes,
+ R.string.stereoscopy_swap_eyes_description
+ )
+ )
+ }
+
+ private fun addGcPadSubSettings(sl: ArrayList<SettingsItem>, gcPadNumber: Int, gcPadType: Int) {
+ if (gcPadType == 6) {
+ // Emulated
+ val gcPad = EmulatedController.getGcPad(gcPadNumber)
+
+ if (!TextUtils.isEmpty(gameId)) {
+ addControllerPerGameSettings(sl, "Pad", gcPadNumber)
+ } else {
+ addControllerMetaSettings(sl, gcPad)
+ addControllerMappingSettings(sl, gcPad, null)
+ }
+ } else if (gcPadType == 12) {
+ // Adapter
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.getSettingForAdapterRumble(gcPadNumber),
+ R.string.gc_adapter_rumble,
+ R.string.gc_adapter_rumble_description
+ )
+ )
+ sl.add(
+ SwitchSetting(
+ context,
+ BooleanSetting.getSettingForSimulateKonga(gcPadNumber),
+ R.string.gc_adapter_bongos,
+ R.string.gc_adapter_bongos_description
+ )
+ )
+ }
+ }
+
+ private fun addWiimoteSubSettings(sl: ArrayList<SettingsItem>, wiimoteNumber: Int) {
+ val wiimote = EmulatedController.getWiimote(wiimoteNumber)
+
+ if (!TextUtils.isEmpty(gameId)) {
+ addControllerPerGameSettings(sl, "Wiimote", wiimoteNumber)
+ } else {
+ addControllerMetaSettings(sl, wiimote)
+
+ sl.add(HeaderSetting(context, R.string.wiimote, 0))
+ sl.add(
+ SubmenuSetting(
+ context,
+ R.string.wiimote_general,
+ MenuTag.getWiimoteGeneralMenuTag(wiimoteNumber)
+ )
+ )
+ sl.add(
+ SubmenuSetting(
+ context,
+ R.string.wiimote_motion_simulation,
+ MenuTag.getWiimoteMotionSimulationMenuTag(wiimoteNumber)
+ )
+ )
+ sl.add(
+ SubmenuSetting(
+ context,
+ R.string.wiimote_motion_input,
+ MenuTag.getWiimoteMotionInputMenuTag(wiimoteNumber)
+ )
+ )
+
+ // TYPE_OTHER is included here instead of in addWiimoteGeneralSubSettings so that touchscreen
+ // users won't have to dig into a submenu to find the Sideways Wii Remote setting
+ addControllerMappingSettings(
+ sl,
+ wiimote,
+ ArraySet(listOf(ControlGroup.TYPE_ATTACHMENTS, ControlGroup.TYPE_OTHER))
+ )
+ }
+ }
+
+ private fun addExtensionTypeSettings(
+ sl: ArrayList<SettingsItem>,
+ wiimoteNumber: Int,
+ extensionType: Int
+ ) {
+ addControllerMappingSettings(
+ sl,
+ EmulatedController.getWiimoteAttachment(wiimoteNumber, extensionType),
+ null
+ )
+ }
+
+ private fun addWiimoteGeneralSubSettings(sl: ArrayList<SettingsItem>, wiimoteNumber: Int) {
+ addControllerMappingSettings(
+ sl,
+ EmulatedController.getWiimote(wiimoteNumber),
+ setOf(ControlGroup.TYPE_BUTTONS)
+ )
+ }
+
+ private fun addWiimoteMotionSimulationSubSettings(
+ sl: ArrayList<SettingsItem>,
+ wiimoteNumber: Int
+ ) {
+ addControllerMappingSettings(
+ sl, EmulatedController.getWiimote(wiimoteNumber),
+ ArraySet(
+ listOf(
+ ControlGroup.TYPE_FORCE,
+ ControlGroup.TYPE_TILT,
+ ControlGroup.TYPE_CURSOR,
+ ControlGroup.TYPE_SHAKE
+ )
+ )
+ )
+ }
+
+ private fun addWiimoteMotionInputSubSettings(sl: ArrayList<SettingsItem>, wiimoteNumber: Int) {
+ addControllerMappingSettings(
+ sl, EmulatedController.getWiimote(wiimoteNumber),
+ ArraySet(
+ listOf(
+ ControlGroup.TYPE_IMU_ACCELEROMETER,
+ ControlGroup.TYPE_IMU_GYROSCOPE,
+ ControlGroup.TYPE_IMU_CURSOR
+ )
+ )
+ )
+ }
+
+ /**
+ * Adds controller settings that can be set on a per-game basis.
+ *
+ * @param sl The list to place controller settings into.
+ * @param profileString The prefix used for the profile setting in game INI files.
+ * @param controllerNumber The index of the controller, 0-3.
+ */
+ private fun addControllerPerGameSettings(
+ sl: ArrayList<SettingsItem>,
+ profileString: String,
+ controllerNumber: Int
+ ) {
+ val profiles = ProfileDialogPresenter(menuTag).getProfileNames(false)
+ val profileKey = profileString + "Profile" + (controllerNumber + 1)
+ sl.add(
+ StringSingleChoiceSetting(
+ context,
+ AdHocStringSetting(Settings.FILE_GAME_SETTINGS_ONLY, "Controls", profileKey, ""),
+ R.string.input_profile,
+ 0,
+ profiles,
+ profiles,
+ R.string.input_profiles_empty
+ )
+ )
+ }
+
+ /**
+ * Adds settings and actions that apply to a controller as a whole.
+ * For instance, the device setting and the Clear action.
+ *
+ * @param sl The list to place controller settings into.
+ * @param controller The controller to add settings for.
+ */
+ private fun addControllerMetaSettings(
+ sl: ArrayList<SettingsItem>,
+ controller: EmulatedController
+ ) {
+ sl.add(
+ InputDeviceSetting(
+ context,
+ R.string.input_device,
+ 0,
+ controller
+ )
+ )
+
+ sl.add(SwitchSetting(context, object : AbstractBooleanSetting {
+ override val isOverridden: Boolean = false
+
+ override val isRuntimeEditable: Boolean = true
+
+ override fun delete(settings: Settings): Boolean {
+ fragmentView.isMappingAllDevices = false
+ return true
+ }
+
+ override val boolean: Boolean
+ get() = fragmentView.isMappingAllDevices
+
+ override fun setBoolean(settings: Settings, newValue: Boolean) {
+ fragmentView.isMappingAllDevices = newValue
+ }
+ }, R.string.input_device_all_devices, R.string.input_device_all_devices_description))
+
+ sl.add(
+ RunRunnable(
+ context,
+ R.string.input_reset_to_default,
+ R.string.input_reset_to_default_description,
+ R.string.input_reset_warning,
+ 0,
+ true
+ ) { loadDefaultControllerSettings(controller) })
+ sl.add(
+ RunRunnable(
+ context,
+ R.string.input_clear,
+ R.string.input_clear_description,
+ R.string.input_reset_warning,
+ 0,
+ true
+ ) { clearControllerSettings(controller) })
+ sl.add(
+ RunRunnable(
+ context,
+ R.string.input_profiles,
+ 0,
+ 0,
+ 0,
+ true
+ ) { fragmentView.showDialogFragment(ProfileDialog.create(menuTag!!)) })
+
+ updateOldControllerSettingsWarningVisibility(controller)
+ }
+
+ /**
+ * Adds mapping settings and other control-specific settings.
+ *
+ * @param sl The list to place controller settings into.
+ * @param controller The controller to add settings for.
+ * @param groupTypeFilter If this is non-null, only groups whose types match this are considered.
+ */
+ private fun addControllerMappingSettings(
+ sl: ArrayList<SettingsItem>,
+ controller: EmulatedController,
+ groupTypeFilter: Set<Int>?
+ ) {
+ updateOldControllerSettingsWarningVisibility(controller)
+
+ val groupCount = controller.groupCount
+ for (i in 0 until groupCount) {
+ val group = controller.getGroup(i)
+ val groupType = group.groupType
+ if (groupTypeFilter != null && !groupTypeFilter.contains(groupType)) continue
+
+ sl.add(HeaderSetting(group.uiName, ""))
+
+ if (group.defaultEnabledValue != ControlGroup.DEFAULT_ENABLED_ALWAYS) {
+ sl.add(
+ SwitchSetting(
+ context,
+ ControlGroupEnabledSetting(group),
+ R.string.enabled,
+ 0
+ )
+ )
+ }
+
+ val controlCount = group.controlCount
+ for (j in 0 until controlCount) {
+ sl.add(InputMappingControlSetting(group.getControl(j), controller))
+ }
+
+ if (groupType == ControlGroup.TYPE_ATTACHMENTS) {
+ val attachmentSetting = group.attachmentSetting
+ sl.add(
+ SingleChoiceSetting(
+ context, InputMappingIntSetting(attachmentSetting),
+ R.string.wiimote_extensions, 0, R.array.wiimoteExtensionsEntries,
+ R.array.wiimoteExtensionsValues,
+ MenuTag.getWiimoteExtensionMenuTag(controllerNumber)
+ )
+ )
+ }
+
+ val numericSettingCount = group.numericSettingCount
+ for (j in 0 until numericSettingCount) {
+ addNumericSetting(sl, group.getNumericSetting(j))
+ }
+ }
+ }
+
+ private fun addNumericSetting(sl: ArrayList<SettingsItem>, setting: NumericSetting) {
+ when (setting.type) {
+ NumericSetting.TYPE_DOUBLE -> sl.add(
+ FloatSliderSetting(
+ InputMappingDoubleSetting(setting),
+ setting.uiName,
+ "",
+ ceil(setting.doubleMin).toInt(),
+ floor(setting.doubleMax).toInt(),
+ setting.uiSuffix
+ )
+ )
+ NumericSetting.TYPE_BOOLEAN -> sl.add(
+ SwitchSetting(
+ InputMappingBooleanSetting(setting),
+ setting.uiName,
+ setting.uiDescription
+ )
+ )
+ }
+ }
+
+ fun updateOldControllerSettingsWarningVisibility() {
+ updateOldControllerSettingsWarningVisibility(menuTag!!.correspondingEmulatedController)
+ }
+
+ private fun updateOldControllerSettingsWarningVisibility(controller: EmulatedController) {
+ val defaultDevice = controller.defaultDevice
+
+ hasOldControllerSettings = defaultDevice.startsWith("Android/") &&
+ defaultDevice.endsWith("/Touchscreen")
+
+ fragmentView.setOldControllerSettingsWarningVisibility(hasOldControllerSettings)
+ }
+
+ private fun loadDefaultControllerSettings(controller: EmulatedController) {
+ controller.loadDefaultSettings()
+ fragmentView.onControllerSettingsChanged()
+ }
+
+ private fun clearControllerSettings(controller: EmulatedController) {
+ controller.clearSettings()
+ fragmentView.onControllerSettingsChanged()
+ }
+
+ fun setAllLogTypes(value: Boolean) {
+ val settings = fragmentView.settings
+
+ for ((key) in LOG_TYPE_NAMES) {
+ AdHocBooleanSetting(
+ Settings.FILE_LOGGER,
+ Settings.SECTION_LOGGER_LOGS,
+ key,
+ false
+ ).setBoolean(settings!!, value)
+ }
+
+ fragmentView.adapter!!.notifyAllSettingsChanged()
+ }
+
+ private fun convertOnThread(f: BooleanSupplier) {
+ ThreadUtil.runOnThreadAndShowResult(
+ fragmentView.fragmentActivity,
+ R.string.wii_converting,
+ 0,
+ { context.resources.getString(if (f.get()) R.string.wii_convert_success else R.string.wii_convert_failure) }
+ )
+ }
+
+ companion object {
+ private val LOG_TYPE_NAMES = NativeLibrary.GetLogTypeNames()
+ const val ARG_CONTROLLER_TYPE = "controller_type"
+ const val ARG_SERIALPORT1_TYPE = "serialport1_type"
+
+ // Value obtained from LogLevel in Common/Logging/Log.h
+ private val logVerbosityEntries: Int
+ get() =
+ if (NativeLibrary.GetMaxLogLevel() == 5) {
+ R.array.logVerbosityEntriesMaxLevelDebug
+ } else {
+ R.array.logVerbosityEntriesMaxLevelInfo
+ }
+
+ // Value obtained from LogLevel in Common/Logging/Log.h
+ private val logVerbosityValues: Int
+ get() =
+ if (NativeLibrary.GetMaxLogLevel() == 5) {
+ R.array.logVerbosityValuesMaxLevelDebug
+ } else {
+ R.array.logVerbosityValuesMaxLevelInfo
+ }
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentView.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentView.java
deleted file mode 100644
index 809f26f7cc..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentView.java
+++ /dev/null
@@ -1,123 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.ui;
-
-import androidx.annotation.NonNull;
-import androidx.fragment.app.DialogFragment;
-import androidx.fragment.app.FragmentActivity;
-
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
-
-import java.util.ArrayList;
-
-/**
- * Abstraction for a screen showing a list of settings. Instances of
- * this type of view will each display a layer of the setting hierarchy.
- */
-public interface SettingsFragmentView
-{
- /**
- * Called by the containing Activity to notify the Fragment that an
- * asynchronous load operation completed.
- *
- * @param settings The (possibly null) result of the ini load operation.
- */
- void onSettingsFileLoaded(Settings settings);
-
- /**
- * Pass an ArrayList of settings to the View so that it can be displayed on screen.
- *
- * @param settingsList The settings to display
- */
- void showSettingsList(ArrayList<SettingsItem> settingsList);
-
- /**
- * Called by the containing Activity when an asynchronous load operation fails.
- * Instructs the Fragment to load the settings screen with defaults selected.
- */
- void loadDefaultSettings();
-
- /**
- * @return The Fragment's containing activity.
- */
- FragmentActivity getActivity();
-
- /**
- * @return The Fragment's SettingsAdapter.
- */
- SettingsAdapter getAdapter();
-
- /**
- * Tell the Fragment to tell the containing Activity to show a new
- * Fragment containing a submenu of settings.
- *
- * @param menuKey Identifier for the settings group that should be shown.
- */
- void loadSubMenu(MenuTag menuKey);
-
- void showDialogFragment(DialogFragment fragment);
-
- /**
- * Tell the Fragment to tell the containing activity to display a toast message.
- *
- * @param message Text to be shown in the Toast
- */
- void showToastMessage(String message);
-
- /**
- * @return The backing settings store.
- */
- Settings getSettings();
-
- /**
- * Have the fragment tell the containing Activity that a setting was modified.
- */
- void onSettingChanged();
-
- /**
- * Refetches the values of all controller settings.
- *
- * To be used when loading an input profile or performing some other action that changes all
- * controller settings at once.
- */
- void onControllerSettingsChanged();
-
- /**
- * Have the fragment tell the containing Activity that the user wants to open the MenuTag
- * associated with a setting.
- *
- * @param menuTag The MenuTag of the setting.
- * @param value The current value of the setting.
- */
- void onMenuTagAction(@NonNull MenuTag menuTag, int value);
-
- /**
- * Returns whether anything will happen when the user wants to open the MenuTag associated with a
- * setting, given the current value of the setting.
- *
- * @param menuTag The MenuTag of the setting.
- * @param value The current value of the setting.
- */
- boolean hasMenuTagActionForValue(@NonNull MenuTag menuTag, int value);
-
- /**
- * Sets whether the input mapping dialog should detect inputs from all devices,
- * not just the device configured for the controller.
- */
- void setMappingAllDevices(boolean allDevices);
-
- /**
- * Returns whether the input mapping dialog should detect inputs from all devices,
- * not just the device configured for the controller.
- */
- boolean isMappingAllDevices();
-
- /**
- * Shows or hides a warning telling the user that they're using incompatible controller settings.
- * The warning is hidden by default.
- *
- * @param visible Whether the warning should be visible.
- */
- void setOldControllerSettingsWarningVisibility(boolean visible);
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentView.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentView.kt
new file mode 100644
index 0000000000..fa861153dd
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentView.kt
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.ui
+
+import androidx.fragment.app.DialogFragment
+import androidx.fragment.app.FragmentActivity
+import org.dolphinemu.dolphinemu.features.settings.model.Settings
+import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
+
+/**
+ * Abstraction for a screen showing a list of settings. Instances of
+ * this type of view will each display a layer of the Setting hierarchy.
+ */
+interface SettingsFragmentView {
+ /**
+ * Called by the containing Activity to notify the Fragment that an
+ * asynchronous load operation completed.
+ *
+ * @param settings The (possibly null) result of the ini load operation.
+ */
+ fun onSettingsFileLoaded(settings: Settings)
+
+ /**
+ * Pass an ArrayList of settings to the View so that it can be displayed on screen.
+ *
+ * @param settingsList The settings to display
+ */
+ fun showSettingsList(settingsList: ArrayList<SettingsItem>)
+
+ /**
+ * Called by the containing Activity when an asynchronous load operation fails.
+ * Instructs the Fragment to load the settings screen with defaults selected.
+ */
+ fun loadDefaultSettings()
+
+ /**
+ * @return The Fragment's containing activity.
+ */
+ val fragmentActivity: FragmentActivity
+
+ /**
+ * @return The Fragment's SettingsAdapter.
+ */
+ val adapter: SettingsAdapter?
+
+ /**
+ * Tell the Fragment to tell the containing Activity to show a new
+ * Fragment containing a submenu of settings.
+ *
+ * @param menuKey Identifier for the settings group that should be shown.
+ */
+ fun loadSubMenu(menuKey: MenuTag)
+ fun showDialogFragment(fragment: DialogFragment)
+
+ /**
+ * Tell the Fragment to tell the containing activity to display a toast message.
+ *
+ * @param message Text to be shown in the Toast
+ */
+ fun showToastMessage(message: String)
+
+ /**
+ * @return The backing settings store.
+ */
+ val settings: Settings?
+
+ /**
+ * Have the fragment tell the containing Activity that a Setting was modified.
+ */
+ fun onSettingChanged()
+
+ /**
+ * Refetches the values of all controller settings.
+ *
+ * To be used when loading an input profile or performing some other action that changes all
+ * controller settings at once.
+ */
+ fun onControllerSettingsChanged()
+
+ /**
+ * Have the fragment tell the containing Activity that the user wants to open the MenuTag
+ * associated with a Setting.
+ *
+ * @param menuTag The MenuTag of the Setting.
+ * @param value The current value of the Setting.
+ */
+ fun onMenuTagAction(menuTag: MenuTag, value: Int)
+
+ /**
+ * Returns whether anything will happen when the user wants to open the MenuTag associated with a
+ * stringSetting, given the current value of the Setting.
+ *
+ * @param menuTag The MenuTag of the Setting.
+ * @param value The current value of the Setting.
+ */
+ fun hasMenuTagActionForValue(menuTag: MenuTag, value: Int): Boolean
+ /**
+ * Returns whether the input mapping dialog should detect inputs from all devices,
+ * not just the device configured for the controller.
+ */
+ /**
+ * Sets whether the input mapping dialog should detect inputs from all devices,
+ * not just the device configured for the controller.
+ */
+ var isMappingAllDevices: Boolean
+
+ /**
+ * Shows or hides a warning telling the user that they're using incompatible controller settings.
+ * The warning is hidden by default.
+ *
+ * @param visible Whether the warning should be visible.
+ */
+ fun setOldControllerSettingsWarningVisibility(visible: Boolean)
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsViewModel.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsViewModel.java
deleted file mode 100644
index fe67445cc0..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsViewModel.java
+++ /dev/null
@@ -1,17 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.ui;
-
-import androidx.lifecycle.ViewModel;
-
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-
-public class SettingsViewModel extends ViewModel
-{
- private final Settings mSettings = new Settings();
-
- public Settings getSettings()
- {
- return mSettings;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsViewModel.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsViewModel.kt
new file mode 100644
index 0000000000..0685c23388
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsViewModel.kt
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.ui
+
+import androidx.lifecycle.ViewModel
+import org.dolphinemu.dolphinemu.features.settings.model.Settings
+
+class SettingsViewModel : ViewModel() {
+ val settings = Settings()
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/DateTimeSettingViewHolder.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/DateTimeSettingViewHolder.kt
index 2778a489fc..07201e31d6 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/DateTimeSettingViewHolder.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/DateTimeSettingViewHolder.kt
@@ -18,12 +18,15 @@ class DateTimeSettingViewHolder(
private val binding: ListItemSettingBinding,
adapter: SettingsAdapter
) : SettingViewHolder(binding.root, adapter) {
- private var mItem: DateTimeChoiceSetting? = null
+ lateinit var setting: DateTimeChoiceSetting
+
+ override val item: SettingsItem
+ get() = setting
override fun bind(item: SettingsItem) {
- mItem = item as DateTimeChoiceSetting
- val inputTime = mItem!!.getSelectedValue()
- binding.textSettingName.text = item.getName()
+ setting = item as DateTimeChoiceSetting
+ val inputTime = setting.getSelectedValue()
+ binding.textSettingName.text = item.name
if (!TextUtils.isEmpty(inputTime)) {
val epochTime = inputTime.substring(2).toLong(16)
@@ -32,21 +35,17 @@ class DateTimeSettingViewHolder(
val dateFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
binding.textSettingDescription.text = dateFormatter.format(zonedTime)
} else {
- binding.textSettingDescription.text = item.getDescription()
+ binding.textSettingDescription.text = item.description
}
- setStyle(binding.textSettingName, mItem)
+ setStyle(binding.textSettingName, setting)
}
override fun onClick(clicked: View) {
- if (!mItem!!.isEditable) {
+ if (!setting.isEditable) {
showNotRuntimeEditableError()
return
}
- adapter.onDateTimeClick(mItem, bindingAdapterPosition)
- setStyle(binding.textSettingName, mItem)
- }
-
- override fun getItem(): SettingsItem? {
- return mItem
+ adapter.onDateTimeClick(setting, bindingAdapterPosition)
+ setStyle(binding.textSettingName, setting)
}
}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/FilePickerViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/FilePickerViewHolder.java
deleted file mode 100644
index 1b75bb72b2..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/FilePickerViewHolder.java
+++ /dev/null
@@ -1,99 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.ui.viewholder;
-
-import android.text.TextUtils;
-import android.view.View;
-
-import androidx.annotation.Nullable;
-
-import org.dolphinemu.dolphinemu.R;
-import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding;
-import org.dolphinemu.dolphinemu.features.settings.model.view.FilePicker;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
-import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
-import org.dolphinemu.dolphinemu.ui.main.MainPresenter;
-import org.dolphinemu.dolphinemu.utils.DirectoryInitialization;
-import org.dolphinemu.dolphinemu.utils.FileBrowserHelper;
-
-public final class FilePickerViewHolder extends SettingViewHolder
-{
- private FilePicker mFilePicker;
- private SettingsItem mItem;
-
- private final ListItemSettingBinding mBinding;
-
- public FilePickerViewHolder(ListItemSettingBinding binding, SettingsAdapter adapter)
- {
- super(binding.getRoot(), adapter);
- mBinding = binding;
- }
-
- @Override
- public void bind(SettingsItem item)
- {
- mFilePicker = (FilePicker) item;
- mItem = item;
-
- String path = mFilePicker.getSelectedValue();
-
- if (FileBrowserHelper.isPathEmptyOrValid(path))
- {
- itemView.setBackground(mBinding.getRoot().getBackground());
- }
- else
- {
- itemView.setBackgroundResource(R.drawable.invalid_setting_background);
- }
-
- mBinding.textSettingName.setText(item.getName());
-
- if (!TextUtils.isEmpty(item.getDescription()))
- {
- mBinding.textSettingDescription.setText(item.getDescription());
- }
- else
- {
- if (TextUtils.isEmpty(path))
- {
- String defaultPathRelative = mFilePicker.getDefaultPathRelativeToUserDirectory();
- if (defaultPathRelative != null)
- {
- path = DirectoryInitialization.getUserDirectory() + defaultPathRelative;
- }
- }
-
- mBinding.textSettingDescription.setText(path);
- }
-
- setStyle(mBinding.textSettingName, mItem);
- }
-
- @Override
- public void onClick(View clicked)
- {
- if (!mItem.isEditable())
- {
- showNotRuntimeEditableError();
- return;
- }
-
- int position = getBindingAdapterPosition();
- if (mFilePicker.getRequestType() == MainPresenter.REQUEST_DIRECTORY)
- {
- getAdapter().onFilePickerDirectoryClick(mItem, position);
- }
- else
- {
- getAdapter().onFilePickerFileClick(mItem, position);
- }
-
- setStyle(mBinding.textSettingName, mItem);
- }
-
- @Nullable @Override
- protected SettingsItem getItem()
- {
- return mItem;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/FilePickerViewHolder.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/FilePickerViewHolder.kt
new file mode 100644
index 0000000000..215615828e
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/FilePickerViewHolder.kt
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.ui.viewholder
+
+import android.text.TextUtils
+import android.view.View
+import org.dolphinemu.dolphinemu.R
+import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding
+import org.dolphinemu.dolphinemu.features.settings.model.view.FilePicker
+import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
+import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
+import org.dolphinemu.dolphinemu.ui.main.MainPresenter
+import org.dolphinemu.dolphinemu.utils.DirectoryInitialization
+import org.dolphinemu.dolphinemu.utils.FileBrowserHelper
+
+class FilePickerViewHolder(
+ private val binding: ListItemSettingBinding,
+ adapter: SettingsAdapter?
+) : SettingViewHolder(binding.getRoot(), adapter!!) {
+ lateinit var setting: FilePicker
+
+ override val item: SettingsItem
+ get() = setting
+
+ override fun bind(item: SettingsItem) {
+ setting = item as FilePicker
+
+ var path = setting.getSelectedValue()
+
+ if (FileBrowserHelper.isPathEmptyOrValid(path)) {
+ itemView.background = binding.getRoot().background
+ } else {
+ itemView.setBackgroundResource(R.drawable.invalid_setting_background)
+ }
+
+ binding.textSettingName.text = setting.name
+
+ if (!TextUtils.isEmpty(setting.description)) {
+ binding.textSettingDescription.text = setting.description
+ } else {
+ if (TextUtils.isEmpty(path)) {
+ val defaultPathRelative = setting.defaultPathRelativeToUserDirectory
+ if (defaultPathRelative != null) {
+ path = DirectoryInitialization.getUserDirectory() + defaultPathRelative
+ }
+ }
+ binding.textSettingDescription.text = path
+ }
+
+ setStyle(binding.textSettingName, setting)
+ }
+
+ override fun onClick(clicked: View) {
+ if (!setting.isEditable) {
+ showNotRuntimeEditableError()
+ return
+ }
+
+ val position = bindingAdapterPosition
+ if (setting.requestType == MainPresenter.REQUEST_DIRECTORY) {
+ adapter.onFilePickerDirectoryClick(setting, position)
+ } else {
+ adapter.onFilePickerFileClick(setting, position)
+ }
+
+ setStyle(binding.textSettingName, setting)
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/HeaderHyperLinkViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/HeaderHyperLinkViewHolder.java
deleted file mode 100644
index 2d3e9ac5d0..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/HeaderHyperLinkViewHolder.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.ui.viewholder;
-
-import android.text.method.LinkMovementMethod;
-
-import androidx.annotation.NonNull;
-
-import com.google.android.material.color.MaterialColors;
-
-import org.dolphinemu.dolphinemu.R;
-import org.dolphinemu.dolphinemu.databinding.ListItemHeaderBinding;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
-import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
-
-public final class HeaderHyperLinkViewHolder extends HeaderViewHolder
-{
- private final ListItemHeaderBinding mBinding;
-
- public HeaderHyperLinkViewHolder(@NonNull ListItemHeaderBinding binding, SettingsAdapter adapter)
- {
- super(binding, adapter);
- mBinding = binding;
- itemView.setOnClickListener(null);
- }
-
- @Override
- public void bind(@NonNull SettingsItem item)
- {
- super.bind(item);
-
- mBinding.textHeaderName.setMovementMethod(LinkMovementMethod.getInstance());
- mBinding.textHeaderName.setLinkTextColor(
- MaterialColors.getColor(itemView, R.attr.colorTertiary));
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/HeaderHyperLinkViewHolder.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/HeaderHyperLinkViewHolder.kt
new file mode 100644
index 0000000000..5bb58cf489
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/HeaderHyperLinkViewHolder.kt
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.ui.viewholder
+
+import android.text.method.LinkMovementMethod
+import com.google.android.material.color.MaterialColors
+import org.dolphinemu.dolphinemu.R
+import org.dolphinemu.dolphinemu.databinding.ListItemHeaderBinding
+import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
+import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
+
+class HeaderHyperLinkViewHolder(
+ private val binding: ListItemHeaderBinding,
+ adapter: SettingsAdapter?
+) : HeaderViewHolder(binding, adapter) {
+ init {
+ itemView.setOnClickListener(null)
+ }
+
+ override fun bind(item: SettingsItem) {
+ super.bind(item)
+ binding.textHeaderName.movementMethod = LinkMovementMethod.getInstance()
+ binding.textHeaderName.setLinkTextColor(
+ MaterialColors.getColor(itemView, R.attr.colorTertiary)
+ )
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/HeaderViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/HeaderViewHolder.java
deleted file mode 100644
index 889b087396..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/HeaderViewHolder.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.ui.viewholder;
-
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
-import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
-import org.dolphinemu.dolphinemu.databinding.ListItemHeaderBinding;
-
-public class HeaderViewHolder extends SettingViewHolder
-{
- private final ListItemHeaderBinding mBinding;
-
- public HeaderViewHolder(@NonNull ListItemHeaderBinding binding, SettingsAdapter adapter)
- {
- super(binding.getRoot(), adapter);
- itemView.setOnClickListener(null);
- mBinding = binding;
- }
-
- @Override
- public void bind(@NonNull SettingsItem item)
- {
- mBinding.textHeaderName.setText(item.getName());
- }
-
- @Override
- public void onClick(View clicked)
- {
- // no-op
- }
-
- @Nullable @Override
- protected SettingsItem getItem()
- {
- return null;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/HeaderViewHolder.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/HeaderViewHolder.kt
new file mode 100644
index 0000000000..0f28bf1ffe
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/HeaderViewHolder.kt
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.ui.viewholder
+
+import android.view.View
+import org.dolphinemu.dolphinemu.databinding.ListItemHeaderBinding
+import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
+import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
+
+open class HeaderViewHolder(
+ private val binding: ListItemHeaderBinding,
+ adapter: SettingsAdapter?
+) : SettingViewHolder(binding.root, adapter!!) {
+ override val item: SettingsItem? = null
+
+ init {
+ itemView.setOnClickListener(null)
+ }
+
+ override fun bind(item: SettingsItem) {
+ binding.textHeaderName.text = item.name
+ }
+
+ override fun onClick(clicked: View) {
+ // no-op
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/InputStringSettingViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/InputStringSettingViewHolder.java
deleted file mode 100644
index 6743808079..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/InputStringSettingViewHolder.java
+++ /dev/null
@@ -1,71 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.ui.viewholder;
-
-import android.text.TextUtils;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding;
-import org.dolphinemu.dolphinemu.features.settings.model.view.InputStringSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
-import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
-
-public final class InputStringSettingViewHolder extends SettingViewHolder
-{
- private InputStringSetting mInputString;
-
- private final ListItemSettingBinding mBinding;
-
- public InputStringSettingViewHolder(@NonNull ListItemSettingBinding binding,
- SettingsAdapter adapter)
- {
- super(binding.getRoot(), adapter);
- mBinding = binding;
- }
-
- @Override
- public void bind(SettingsItem item)
- {
- mInputString = (InputStringSetting) item;
-
- String inputString = mInputString.getSelectedValue();
-
- mBinding.textSettingName.setText(item.getName());
-
- if (!TextUtils.isEmpty(inputString))
- {
- mBinding.textSettingDescription.setText(inputString);
- }
- else
- {
- mBinding.textSettingDescription.setText(item.getDescription());
- }
-
- setStyle(mBinding.textSettingName, mInputString);
- }
-
- @Override
- public void onClick(View clicked)
- {
- if (!mInputString.isEditable())
- {
- showNotRuntimeEditableError();
- return;
- }
-
- int position = getBindingAdapterPosition();
-
- getAdapter().onInputStringClick(mInputString, position);
-
- setStyle(mBinding.textSettingName, mInputString);
- }
-
- @Nullable @Override
- protected SettingsItem getItem()
- {
- return mInputString;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/InputStringSettingViewHolder.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/InputStringSettingViewHolder.kt
new file mode 100644
index 0000000000..4af0019c30
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/InputStringSettingViewHolder.kt
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.ui.viewholder
+
+import android.text.TextUtils
+import android.view.View
+import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding
+import org.dolphinemu.dolphinemu.features.settings.model.view.InputStringSetting
+import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
+import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
+
+class InputStringSettingViewHolder(
+ private val binding: ListItemSettingBinding,
+ adapter: SettingsAdapter
+) : SettingViewHolder(binding.getRoot(), adapter) {
+ private lateinit var setting: InputStringSetting
+
+ override val item: SettingsItem
+ get() = setting
+
+ override fun bind(item: SettingsItem) {
+ setting = item as InputStringSetting
+
+ val inputString = setting.selectedValue
+
+ binding.textSettingName.text = setting.name
+
+ if (!TextUtils.isEmpty(inputString)) {
+ binding.textSettingDescription.text = inputString
+ } else {
+ binding.textSettingDescription.text = setting.description
+ }
+
+ setStyle(binding.textSettingName, setting)
+ }
+
+ override fun onClick(clicked: View) {
+ if (!setting.isEditable) {
+ showNotRuntimeEditableError()
+ return
+ }
+
+ val position = bindingAdapterPosition
+
+ adapter.onInputStringClick(setting, position)
+
+ setStyle(binding.textSettingName, setting)
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/RunRunnableViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/RunRunnableViewHolder.java
deleted file mode 100644
index 6104a2aa2e..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/RunRunnableViewHolder.java
+++ /dev/null
@@ -1,93 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.ui.viewholder;
-
-import android.content.Context;
-import android.view.View;
-import android.widget.Toast;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-
-import org.dolphinemu.dolphinemu.R;
-import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding;
-import org.dolphinemu.dolphinemu.features.settings.model.view.RunRunnable;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
-import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
-
-public final class RunRunnableViewHolder extends SettingViewHolder
-{
- private RunRunnable mItem;
-
- private final Context mContext;
-
- private final ListItemSettingBinding mBinding;
-
- public RunRunnableViewHolder(@NonNull ListItemSettingBinding binding, SettingsAdapter adapter,
- Context context)
- {
- super(binding.getRoot(), adapter);
- mBinding = binding;
- mContext = context;
- }
-
- @Override
- public void bind(SettingsItem item)
- {
- mItem = (RunRunnable) item;
-
- mBinding.textSettingName.setText(item.getName());
- mBinding.textSettingDescription.setText(item.getDescription());
-
- setStyle(mBinding.textSettingName, mItem);
- }
-
- @Override
- public void onClick(View clicked)
- {
- if (!mItem.isEditable())
- {
- showNotRuntimeEditableError();
- return;
- }
-
- int alertTextID = mItem.getAlertText();
-
- if (alertTextID > 0)
- {
- new MaterialAlertDialogBuilder(mContext)
- .setTitle(mItem.getName())
- .setMessage(alertTextID)
- .setPositiveButton(R.string.ok, (dialog, whichButton) ->
- {
- runRunnable();
- dialog.dismiss();
- })
- .setNegativeButton(R.string.cancel, (dialog, whichButton) -> dialog.dismiss())
- .show();
- }
- else
- {
- runRunnable();
- }
- }
-
- @Nullable @Override
- protected SettingsItem getItem()
- {
- return mItem;
- }
-
- private void runRunnable()
- {
- mItem.getRunnable().run();
-
- if (mItem.getToastTextAfterRun() > 0)
- {
- Toast.makeText(mContext, mContext.getString(mItem.getToastTextAfterRun()), Toast.LENGTH_SHORT)
- .show();
- }
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/RunRunnableViewHolder.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/RunRunnableViewHolder.kt
new file mode 100644
index 0000000000..2ff39d51d5
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/RunRunnableViewHolder.kt
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.ui.viewholder
+
+import android.content.Context
+import android.content.DialogInterface
+import android.view.View
+import android.widget.Toast
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import org.dolphinemu.dolphinemu.R
+import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding
+import org.dolphinemu.dolphinemu.features.settings.model.view.RunRunnable
+import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
+import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
+
+class RunRunnableViewHolder(
+ private val mBinding: ListItemSettingBinding, adapter: SettingsAdapter?,
+ private val mContext: Context
+) : SettingViewHolder(mBinding.getRoot(), adapter!!) {
+ private lateinit var setting: RunRunnable
+
+ override val item: SettingsItem
+ get() = setting
+
+ override fun bind(item: SettingsItem) {
+ setting = item as RunRunnable
+
+ mBinding.textSettingName.text = setting.name
+ mBinding.textSettingDescription.text = setting.description
+
+ setStyle(mBinding.textSettingName, setting)
+ }
+
+ override fun onClick(clicked: View) {
+ if (!setting.isEditable) {
+ showNotRuntimeEditableError()
+ return
+ }
+
+ val alertTextID = setting.alertText
+
+ if (alertTextID > 0) {
+ MaterialAlertDialogBuilder(mContext)
+ .setTitle(setting.name)
+ .setMessage(alertTextID)
+ .setPositiveButton(R.string.ok) { dialog: DialogInterface, _: Int ->
+ runRunnable()
+ dialog.dismiss()
+ }
+ .setNegativeButton(R.string.cancel) { dialog: DialogInterface, _: Int -> dialog.dismiss() }
+ .show()
+ } else {
+ runRunnable()
+ }
+ }
+
+ private fun runRunnable() {
+ setting.runnable.run()
+
+ if (setting.toastTextAfterRun > 0) {
+ Toast.makeText(
+ mContext,
+ mContext.getString(setting.toastTextAfterRun),
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SettingViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SettingViewHolder.java
deleted file mode 100644
index 5217e4f889..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SettingViewHolder.java
+++ /dev/null
@@ -1,111 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.ui.viewholder;
-
-import android.content.Context;
-import android.graphics.Paint;
-import android.graphics.Typeface;
-import android.view.View;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import androidx.annotation.Nullable;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-
-import org.dolphinemu.dolphinemu.DolphinApplication;
-import org.dolphinemu.dolphinemu.R;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
-import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
-
-public abstract class SettingViewHolder extends RecyclerView.ViewHolder
- implements View.OnClickListener, View.OnLongClickListener
-{
- private SettingsAdapter mAdapter;
-
- public SettingViewHolder(View itemView, SettingsAdapter adapter)
- {
- super(itemView);
-
- mAdapter = adapter;
-
- itemView.setOnClickListener(this);
- itemView.setOnLongClickListener(this);
- }
-
- protected SettingsAdapter getAdapter()
- {
- return mAdapter;
- }
-
- protected void setStyle(TextView textView, SettingsItem settingsItem)
- {
- boolean overridden = settingsItem.isOverridden();
- textView.setTypeface(null, overridden ? Typeface.BOLD : Typeface.NORMAL);
-
- if (!settingsItem.isEditable())
- textView.setPaintFlags(textView.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
- }
-
- protected static void showNotRuntimeEditableError()
- {
- Toast.makeText(DolphinApplication.getAppContext(), R.string.setting_not_runtime_editable,
- Toast.LENGTH_SHORT).show();
- }
-
- protected static void showIplNotAvailableError()
- {
- Toast.makeText(DolphinApplication.getAppContext(), R.string.ipl_not_found, Toast.LENGTH_SHORT)
- .show();
- }
-
- /**
- * Called by the adapter to set this ViewHolder's child views to display the list item
- * it must now represent.
- *
- * @param item The list item that should be represented by this ViewHolder.
- */
- public abstract void bind(SettingsItem item);
-
- /**
- * Called when this ViewHolder's view is clicked on. Implementations should usually pass
- * this event up to the adapter.
- *
- * @param clicked The view that was clicked on.
- */
- public abstract void onClick(View clicked);
-
- @Nullable
- protected abstract SettingsItem getItem();
-
- public boolean onLongClick(View clicked)
- {
- SettingsItem item = getItem();
-
- if (item == null || !item.canClear())
- return false;
-
- if (!item.isEditable())
- {
- showNotRuntimeEditableError();
- return true;
- }
-
- Context context = clicked.getContext();
-
- new MaterialAlertDialogBuilder(context)
- .setMessage(R.string.setting_clear_confirm)
- .setPositiveButton(R.string.ok, (dialog, whichButton) ->
- {
- getAdapter().clearSetting(item);
- bind(item);
- Toast.makeText(context, R.string.setting_cleared, Toast.LENGTH_SHORT).show();
- dialog.dismiss();
- })
- .setNegativeButton(R.string.cancel, (dialog, whichButton) -> dialog.dismiss())
- .show();
-
- return true;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SettingViewHolder.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SettingViewHolder.kt
new file mode 100644
index 0000000000..0767840154
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SettingViewHolder.kt
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.ui.viewholder
+
+import android.content.DialogInterface
+import android.graphics.Paint
+import android.graphics.Typeface
+import android.view.View
+import android.view.View.OnLongClickListener
+import android.widget.TextView
+import android.widget.Toast
+import androidx.recyclerview.widget.RecyclerView
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import org.dolphinemu.dolphinemu.DolphinApplication
+import org.dolphinemu.dolphinemu.R
+import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
+import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
+
+abstract class SettingViewHolder(itemView: View, protected val adapter: SettingsAdapter) :
+ RecyclerView.ViewHolder(itemView), View.OnClickListener, OnLongClickListener {
+
+ init {
+ itemView.setOnClickListener(this)
+ itemView.setOnLongClickListener(this)
+ }
+
+ protected fun setStyle(textView: TextView, settingsItem: SettingsItem) {
+ val overridden = settingsItem.isOverridden
+ textView.setTypeface(null, if (overridden) Typeface.BOLD else Typeface.NORMAL)
+
+ if (!settingsItem.isEditable) textView.paintFlags =
+ textView.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
+ }
+
+ /**
+ * Called by the adapter to set this ViewHolder's child views to display the list item
+ * it must now represent.
+ *
+ * @param item The list item that should be represented by this ViewHolder.
+ */
+ abstract fun bind(item: SettingsItem)
+
+ /**
+ * Called when this ViewHolder's view is clicked on. Implementations should usually pass
+ * this event up to the adapter.
+ *
+ * @param clicked The view that was clicked on.
+ */
+ abstract override fun onClick(clicked: View)
+
+ protected abstract val item: SettingsItem?
+
+ override fun onLongClick(clicked: View): Boolean {
+ val item = item
+
+ if (item == null || !item.canClear()) return false
+
+ if (!item.isEditable) {
+ showNotRuntimeEditableError()
+ return true
+ }
+
+ val context = clicked.context
+
+ MaterialAlertDialogBuilder(context)
+ .setMessage(R.string.setting_clear_confirm)
+ .setPositiveButton(R.string.ok) { dialog: DialogInterface, _: Int ->
+ adapter.clearSetting(item)
+ bind(item)
+ Toast.makeText(
+ context,
+ R.string.setting_cleared,
+ Toast.LENGTH_SHORT
+ ).show()
+ dialog.dismiss()
+ }
+ .setNegativeButton(R.string.cancel) { dialog: DialogInterface, _: Int -> dialog.dismiss() }
+ .show()
+
+ return true
+ }
+
+ protected fun showIplNotAvailableError() {
+ Toast.makeText(
+ DolphinApplication.getAppContext(),
+ R.string.ipl_not_found,
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+
+ protected fun showNotRuntimeEditableError() {
+ Toast.makeText(
+ DolphinApplication.getAppContext(),
+ R.string.setting_not_runtime_editable,
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SingleChoiceViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SingleChoiceViewHolder.java
deleted file mode 100644
index 15ebaf4e82..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SingleChoiceViewHolder.java
+++ /dev/null
@@ -1,148 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.ui.viewholder;
-
-import android.content.res.Resources;
-import android.text.TextUtils;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding;
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SingleChoiceSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SingleChoiceSettingDynamicDescriptions;
-import org.dolphinemu.dolphinemu.features.settings.model.view.StringSingleChoiceSetting;
-import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
-import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
-
-import java.util.function.Supplier;
-
-public final class SingleChoiceViewHolder extends SettingViewHolder
-{
- private SettingsItem mItem;
-
- private final ListItemSettingBinding mBinding;
-
- public SingleChoiceViewHolder(@NonNull ListItemSettingBinding binding, SettingsAdapter adapter)
- {
- super(binding.getRoot(), adapter);
- mBinding = binding;
- }
-
- @Override
- public void bind(SettingsItem item)
- {
- mItem = item;
-
- mBinding.textSettingName.setText(item.getName());
-
- if (!TextUtils.isEmpty(item.getDescription()))
- {
- mBinding.textSettingDescription.setText(item.getDescription());
- }
- else if (item instanceof SingleChoiceSetting)
- {
- SingleChoiceSetting setting = (SingleChoiceSetting) item;
- int selected = setting.getSelectedValue();
- Resources resMgr = mBinding.textSettingDescription.getContext().getResources();
- String[] choices = resMgr.getStringArray(setting.getChoicesId());
- int[] values = resMgr.getIntArray(setting.getValuesId());
- for (int i = 0; i < values.length; ++i)
- {
- if (values[i] == selected)
- {
- mBinding.textSettingDescription.setText(choices[i]);
- }
- }
- }
- else if (item instanceof StringSingleChoiceSetting)
- {
- StringSingleChoiceSetting setting = (StringSingleChoiceSetting) item;
- String choice = setting.getSelectedChoice();
- mBinding.textSettingDescription.setText(choice);
- }
- else if (item instanceof SingleChoiceSettingDynamicDescriptions)
- {
- SingleChoiceSettingDynamicDescriptions setting =
- (SingleChoiceSettingDynamicDescriptions) item;
- int selected = setting.getSelectedValue();
- Resources resMgr = mBinding.textSettingDescription.getContext().getResources();
- String[] choices = resMgr.getStringArray(setting.getDescriptionChoicesId());
- int[] values = resMgr.getIntArray(setting.getDescriptionValuesId());
- for (int i = 0; i < values.length; ++i)
- {
- if (values[i] == selected)
- {
- mBinding.textSettingDescription.setText(choices[i]);
- }
- }
- }
-
- MenuTag menuTag = null;
- Supplier<Integer> getSelectedValue = null;
- if (item instanceof SingleChoiceSetting)
- {
- SingleChoiceSetting setting = (SingleChoiceSetting) item;
- menuTag = setting.getMenuTag();
- getSelectedValue = setting::getSelectedValue;
- }
- else if (item instanceof StringSingleChoiceSetting)
- {
- StringSingleChoiceSetting setting = (StringSingleChoiceSetting) item;
- menuTag = setting.getMenuTag();
- getSelectedValue = setting::getSelectedValueIndex;
- }
-
- if (menuTag != null && getAdapter().hasMenuTagActionForValue(menuTag, getSelectedValue.get()))
- {
- mBinding.buttonMoreSettings.setVisibility(View.VISIBLE);
-
- final MenuTag finalMenuTag = menuTag;
- final Supplier<Integer> finalGetSelectedValue = getSelectedValue;
- mBinding.buttonMoreSettings.setOnClickListener((view) ->
- getAdapter().onMenuTagAction(finalMenuTag, finalGetSelectedValue.get()));
- }
- else
- {
- mBinding.buttonMoreSettings.setVisibility(View.GONE);
- }
-
- setStyle(mBinding.textSettingName, mItem);
- }
-
- @Override
- public void onClick(View clicked)
- {
- if (!mItem.isEditable())
- {
- showNotRuntimeEditableError();
- return;
- }
-
- int position = getBindingAdapterPosition();
- if (mItem instanceof SingleChoiceSetting)
- {
- getAdapter().onSingleChoiceClick((SingleChoiceSetting) mItem, position);
- }
- else if (mItem instanceof StringSingleChoiceSetting)
- {
- getAdapter().onStringSingleChoiceClick((StringSingleChoiceSetting) mItem, position);
- }
- else if (mItem instanceof SingleChoiceSettingDynamicDescriptions)
- {
- getAdapter().onSingleChoiceDynamicDescriptionsClick(
- (SingleChoiceSettingDynamicDescriptions) mItem, position);
- }
-
- setStyle(mBinding.textSettingName, mItem);
- }
-
- @Nullable @Override
- protected SettingsItem getItem()
- {
- return mItem;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt
new file mode 100644
index 0000000000..dabc51a986
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.ui.viewholder
+
+import android.text.TextUtils
+import android.view.View
+import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding
+import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
+import org.dolphinemu.dolphinemu.features.settings.model.view.SingleChoiceSetting
+import org.dolphinemu.dolphinemu.features.settings.model.view.SingleChoiceSettingDynamicDescriptions
+import org.dolphinemu.dolphinemu.features.settings.model.view.StringSingleChoiceSetting
+import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag
+import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
+
+class SingleChoiceViewHolder(
+ private val binding: ListItemSettingBinding,
+ adapter: SettingsAdapter
+) : SettingViewHolder(binding.getRoot(), adapter) {
+ override var item: SettingsItem? = null
+
+ override fun bind(item: SettingsItem) {
+ this.item = item
+
+ binding.textSettingName.text = item.name
+
+ if (!TextUtils.isEmpty(item.description)) {
+ binding.textSettingDescription.text = item.description
+ } else if (item is SingleChoiceSetting) {
+ val selected = item.selectedValue
+ val resources = binding.textSettingDescription.context.resources
+ val choices = resources.getStringArray(item.choicesId)
+ val values = resources.getIntArray(item.valuesId)
+ for (i in values.indices) {
+ if (values[i] == selected) {
+ binding.textSettingDescription.text = choices[i]
+ }
+ }
+ } else if (item is StringSingleChoiceSetting) {
+ val choice = item.selectedChoice
+ binding.textSettingDescription.text = choice
+ } else if (item is SingleChoiceSettingDynamicDescriptions) {
+ val selected = item.selectedValue
+ val resMgr = binding.textSettingDescription.context.resources
+ val choices = resMgr.getStringArray(item.descriptionChoicesId)
+ val values = resMgr.getIntArray(item.descriptionValuesId)
+ for (i in values.indices) {
+ if (values[i] == selected) {
+ binding.textSettingDescription.text = choices[i]
+ }
+ }
+ }
+
+ var menuTag: MenuTag? = null
+ var selectedValue = 0
+ if (item is SingleChoiceSetting) {
+ menuTag = item.menuTag
+ selectedValue = item.selectedValue
+ } else if (item is StringSingleChoiceSetting) {
+ menuTag = item.menuTag
+ selectedValue = item.selectedValueIndex
+ }
+
+ if (menuTag != null && adapter.hasMenuTagActionForValue(menuTag, selectedValue)) {
+ binding.buttonMoreSettings.visibility = View.VISIBLE
+
+ binding.buttonMoreSettings.setOnClickListener {
+ adapter.onMenuTagAction(menuTag, selectedValue)
+ }
+ } else {
+ binding.buttonMoreSettings.visibility = View.GONE
+ }
+ setStyle(binding.textSettingName, item)
+ }
+
+ override fun onClick(clicked: View) {
+ if (!item?.isEditable!!) {
+ showNotRuntimeEditableError()
+ return
+ }
+
+ val position = bindingAdapterPosition
+ when (item) {
+ is SingleChoiceSetting -> {
+ adapter.onSingleChoiceClick(item as SingleChoiceSetting, position)
+ }
+ is StringSingleChoiceSetting -> {
+ adapter.onStringSingleChoiceClick(item as StringSingleChoiceSetting, position)
+ }
+ is SingleChoiceSettingDynamicDescriptions -> {
+ adapter.onSingleChoiceDynamicDescriptionsClick(
+ item as SingleChoiceSettingDynamicDescriptions,
+ position
+ )
+ }
+ }
+ setStyle(binding.textSettingName, item!!)
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SliderViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SliderViewHolder.java
deleted file mode 100644
index 8d53bb1365..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SliderViewHolder.java
+++ /dev/null
@@ -1,74 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.ui.viewholder;
-
-import android.content.Context;
-import android.text.TextUtils;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import org.dolphinemu.dolphinemu.R;
-import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SliderSetting;
-import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
-
-public final class SliderViewHolder extends SettingViewHolder
-{
- private final Context mContext;
-
- private SliderSetting mItem;
-
- private final ListItemSettingBinding mBinding;
-
- public SliderViewHolder(@NonNull ListItemSettingBinding binding, SettingsAdapter adapter,
- Context context)
- {
- super(binding.getRoot(), adapter);
- mBinding = binding;
- mContext = context;
- }
-
- @Override
- public void bind(SettingsItem item)
- {
- mItem = (SliderSetting) item;
-
- mBinding.textSettingName.setText(item.getName());
-
- if (!TextUtils.isEmpty(item.getDescription()))
- {
- mBinding.textSettingDescription.setText(item.getDescription());
- }
- else
- {
- mBinding.textSettingDescription.setText(mContext.getString(R.string.slider_setting_value,
- mItem.getSelectedValue(), mItem.getUnits()));
- }
-
- setStyle(mBinding.textSettingName, mItem);
- }
-
- @Override
- public void onClick(View clicked)
- {
- if (!mItem.isEditable())
- {
- showNotRuntimeEditableError();
- return;
- }
-
- getAdapter().onSliderClick(mItem, getBindingAdapterPosition());
-
- setStyle(mBinding.textSettingName, mItem);
- }
-
- @Nullable @Override
- protected SettingsItem getItem()
- {
- return mItem;
- }
-}
-
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SliderViewHolder.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SliderViewHolder.kt
new file mode 100644
index 0000000000..9009be4e7d
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SliderViewHolder.kt
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.ui.viewholder
+
+import android.content.Context
+import android.text.TextUtils
+import android.view.View
+import org.dolphinemu.dolphinemu.R
+import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding
+import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
+import org.dolphinemu.dolphinemu.features.settings.model.view.SliderSetting
+import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
+
+class SliderViewHolder(
+ private val binding: ListItemSettingBinding, adapter: SettingsAdapter?,
+ private val context: Context
+) : SettingViewHolder(binding.getRoot(), adapter!!) {
+ private lateinit var setting: SliderSetting
+
+ override val item: SettingsItem
+ get() = setting
+
+ override fun bind(item: SettingsItem) {
+ setting = item as SliderSetting
+
+ binding.textSettingName.text = item.name
+
+ if (!TextUtils.isEmpty(item.description)) {
+ binding.textSettingDescription.text = item.description
+ } else {
+ binding.textSettingDescription.text = context.getString(
+ R.string.slider_setting_value,
+ setting.selectedValue,
+ setting.units
+ )
+ }
+
+ setStyle(binding.textSettingName, setting)
+ }
+
+ override fun onClick(clicked: View) {
+ if (!setting.isEditable) {
+ showNotRuntimeEditableError()
+ return
+ }
+
+ adapter.onSliderClick(setting, bindingAdapterPosition)
+
+ setStyle(binding.textSettingName, setting)
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SubmenuViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SubmenuViewHolder.java
deleted file mode 100644
index 828e538874..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SubmenuViewHolder.java
+++ /dev/null
@@ -1,46 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.ui.viewholder;
-
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import org.dolphinemu.dolphinemu.databinding.ListItemSubmenuBinding;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SubmenuSetting;
-import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
-
-public final class SubmenuViewHolder extends SettingViewHolder
-{
- private SubmenuSetting mItem;
-
- private final ListItemSubmenuBinding mBinding;
-
- public SubmenuViewHolder(@NonNull ListItemSubmenuBinding binding, SettingsAdapter adapter)
- {
- super(binding.getRoot(), adapter);
- mBinding = binding;
- }
-
- @Override
- public void bind(SettingsItem item)
- {
- mItem = (SubmenuSetting) item;
-
- mBinding.textSettingName.setText(item.getName());
- }
-
- @Override
- public void onClick(View clicked)
- {
- getAdapter().onSubmenuClick(mItem);
- }
-
- @Nullable @Override
- protected SettingsItem getItem()
- {
- return mItem;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SubmenuViewHolder.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SubmenuViewHolder.kt
new file mode 100644
index 0000000000..414e85e3e3
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SubmenuViewHolder.kt
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.ui.viewholder
+
+import android.view.View
+import org.dolphinemu.dolphinemu.databinding.ListItemSubmenuBinding
+import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
+import org.dolphinemu.dolphinemu.features.settings.model.view.SubmenuSetting
+import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
+
+class SubmenuViewHolder(
+ private val mBinding: ListItemSubmenuBinding,
+ adapter: SettingsAdapter
+) : SettingViewHolder(mBinding.root, adapter) {
+ private lateinit var setting: SubmenuSetting
+
+ override val item: SettingsItem
+ get() = setting
+
+ override fun bind(item: SettingsItem) {
+ setting = item as SubmenuSetting
+ mBinding.textSettingName.text = item.name
+ }
+
+ override fun onClick(clicked: View) {
+ adapter.onSubmenuClick(setting)
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SwitchSettingViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SwitchSettingViewHolder.java
deleted file mode 100644
index 398711bea2..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SwitchSettingViewHolder.java
+++ /dev/null
@@ -1,106 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.ui.viewholder;
-
-import android.view.View;
-
-import androidx.annotation.Nullable;
-
-import org.dolphinemu.dolphinemu.databinding.ListItemSettingSwitchBinding;
-import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SwitchSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
-import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
-import org.dolphinemu.dolphinemu.utils.DirectoryInitialization;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-public final class SwitchSettingViewHolder extends SettingViewHolder
-{
- private SwitchSetting mItem;
- private boolean iplExists = false;
-
- private final ListItemSettingSwitchBinding mBinding;
-
- public SwitchSettingViewHolder(ListItemSettingSwitchBinding binding, SettingsAdapter adapter)
- {
- super(binding.getRoot(), adapter);
- mBinding = binding;
- }
-
- @Override
- public void bind(SettingsItem item)
- {
- mItem = (SwitchSetting) item;
-
- mBinding.textSettingName.setText(item.getName());
- mBinding.textSettingDescription.setText(item.getDescription());
-
- mBinding.settingSwitch.setChecked(mItem.isChecked());
- mBinding.settingSwitch.setEnabled(mItem.isEditable());
-
- // Check for IPL to make sure user can skip.
- if (mItem.getSetting() == BooleanSetting.MAIN_SKIP_IPL)
- {
- ArrayList<String> iplDirs = new ArrayList<>(Arrays.asList("USA", "JAP", "EUR"));
- for (String dir : iplDirs)
- {
- File iplFile = new File(DirectoryInitialization.getUserDirectory(),
- File.separator + "GC" + File.separator + dir + File.separator + "IPL.bin");
- if (iplFile.exists())
- {
- iplExists = true;
- break;
- }
- }
-
- mBinding.settingSwitch.setEnabled(iplExists || !mItem.isChecked());
- }
-
- mBinding.settingSwitch.setOnCheckedChangeListener((buttonView, isChecked) ->
- {
- // If a user has skip IPL disabled previously and deleted their IPL file, we need to allow
- // them to skip it or else their game will appear broken. However, once this is enabled, we
- // need to disable the option again to prevent the same issue from occurring.
- if (mItem.getSetting() == BooleanSetting.MAIN_SKIP_IPL && !iplExists && isChecked)
- {
- mBinding.settingSwitch.setEnabled(false);
- }
-
- getAdapter().onBooleanClick(mItem, mBinding.settingSwitch.isChecked());
-
- setStyle(mBinding.textSettingName, mItem);
- });
-
- setStyle(mBinding.textSettingName, mItem);
- }
-
- @Override
- public void onClick(View clicked)
- {
- if (!mItem.isEditable())
- {
- showNotRuntimeEditableError();
- return;
- }
-
- if (mItem.getSetting() == BooleanSetting.MAIN_SKIP_IPL && !iplExists)
- {
- if (mItem.isChecked())
- {
- showIplNotAvailableError();
- return;
- }
- }
-
- mBinding.settingSwitch.toggle();
- }
-
- @Nullable @Override
- protected SettingsItem getItem()
- {
- return mItem;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt
new file mode 100644
index 0000000000..fc575ead48
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.ui.viewholder
+
+import android.view.View
+import android.widget.CompoundButton
+import org.dolphinemu.dolphinemu.databinding.ListItemSettingSwitchBinding
+import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting
+import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
+import org.dolphinemu.dolphinemu.features.settings.model.view.SwitchSetting
+import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
+import org.dolphinemu.dolphinemu.utils.DirectoryInitialization
+import java.io.File
+import java.util.*
+
+class SwitchSettingViewHolder(
+ private val binding: ListItemSettingSwitchBinding,
+ adapter: SettingsAdapter
+) : SettingViewHolder(binding.root, adapter) {
+ private lateinit var setting: SwitchSetting
+
+ override val item: SettingsItem
+ get() = setting
+
+ private var iplExists = false
+
+ override fun bind(item: SettingsItem) {
+ setting = item as SwitchSetting
+
+ binding.textSettingName.text = item.name
+ binding.textSettingDescription.text = item.description
+
+ binding.settingSwitch.isChecked = setting.isChecked
+ binding.settingSwitch.isEnabled = setting.isEditable
+
+ // Check for IPL to make sure user can skip.
+ if (setting.setting === BooleanSetting.MAIN_SKIP_IPL) {
+ val iplDirs = ArrayList(listOf("USA", "JAP", "EUR"))
+ for (dir in iplDirs) {
+ val iplFile = File(
+ DirectoryInitialization.getUserDirectory(),
+ File.separator + "GC" + File.separator + dir + File.separator + "IPL.bin"
+ )
+ if (iplFile.exists()) {
+ iplExists = true
+ break
+ }
+ }
+ binding.settingSwitch.isEnabled = iplExists || !setting.isChecked
+ }
+
+ binding.settingSwitch.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
+ // If a user has skip IPL disabled previously and deleted their IPL file, we need to allow
+ // them to skip it or else their game will appear broken. However, once this is enabled, we
+ // need to disable the option again to prevent the same issue from occurring.
+ if (setting.setting === BooleanSetting.MAIN_SKIP_IPL && !iplExists && isChecked) {
+ binding.settingSwitch.isEnabled = false
+ }
+
+ adapter.onBooleanClick(setting, binding.settingSwitch.isChecked)
+
+ setStyle(binding.textSettingName, setting)
+ }
+ setStyle(binding.textSettingName, setting)
+ }
+
+ override fun onClick(clicked: View) {
+ if (!setting.isEditable) {
+ showNotRuntimeEditableError()
+ return
+ }
+
+ if (setting.setting === BooleanSetting.MAIN_SKIP_IPL && !iplExists) {
+ if (setting.isChecked) {
+ showIplNotAvailableError()
+ return
+ }
+ }
+
+ binding.settingSwitch.toggle()
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java
deleted file mode 100644
index acad8c2d19..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java
+++ /dev/null
@@ -1,131 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.features.settings.utils;
-
-import androidx.annotation.NonNull;
-
-import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivityView;
-import org.dolphinemu.dolphinemu.utils.BiMap;
-import org.dolphinemu.dolphinemu.utils.DirectoryInitialization;
-import org.dolphinemu.dolphinemu.utils.IniFile;
-import org.dolphinemu.dolphinemu.utils.Log;
-
-import java.io.File;
-
-/**
- * Contains static methods for interacting with .ini files in which settings are stored.
- */
-public final class SettingsFile
-{
- public static final String KEY_ISO_PATH_BASE = "ISOPath";
- public static final String KEY_ISO_PATHS = "ISOPaths";
-
- private static BiMap<String, String> sectionsMap = new BiMap<>();
-
- static
- {
- sectionsMap.add("Hardware", "Video_Hardware");
- sectionsMap.add("Settings", "Video_Settings");
- sectionsMap.add("Enhancements", "Video_Enhancements");
- sectionsMap.add("Stereoscopy", "Video_Stereoscopy");
- sectionsMap.add("Hacks", "Video_Hacks");
- sectionsMap.add("GameSpecific", "Video");
- }
-
- private SettingsFile()
- {
- }
-
- /**
- * Reads a given .ini file from disk and returns it.
- * If unsuccessful, outputs an error telling why it failed.
- *
- * @param file The ini file to load the settings from
- * @param ini The object to load into
- * @param view The current view.
- */
- static void readFile(final File file, IniFile ini, SettingsActivityView view)
- {
- if (!ini.load(file, true))
- {
- Log.error("[SettingsFile] Error reading from: " + file.getAbsolutePath());
- if (view != null)
- view.onSettingsFileNotFound();
- }
- }
-
- public static void readFile(final String fileName, IniFile ini, SettingsActivityView view)
- {
- readFile(getSettingsFile(fileName), ini, view);
- }
-
- /**
- * Reads a given .ini file from disk and returns it.
- * If unsuccessful, outputs an error telling why it failed.
- *
- * @param gameId the id of the game to load settings for.
- * @param ini The object to load into
- * @param view The current view.
- */
- public static void readCustomGameSettings(final String gameId, IniFile ini,
- SettingsActivityView view)
- {
- readFile(getCustomGameSettingsFile(gameId), ini, view);
- }
-
- /**
- * Saves a given .ini file on disk.
- * If unsuccessful, outputs an error telling why it failed.
- *
- * @param fileName The target filename without a path or extension.
- * @param ini The IniFile we want to serialize.
- * @param view The current view.
- */
- public static void saveFile(final String fileName, IniFile ini, SettingsActivityView view)
- {
- if (!ini.save(getSettingsFile(fileName)))
- {
- Log.error("[SettingsFile] Error saving to: " + fileName + ".ini");
- if (view != null)
- view.showToastMessage("Error saving " + fileName + ".ini");
- }
- }
-
- public static void saveCustomGameSettings(final String gameId, IniFile ini)
- {
- ini.save(getCustomGameSettingsFile(gameId));
- }
-
- public static String mapSectionNameFromIni(String generalSectionName)
- {
- if (sectionsMap.getForward(generalSectionName) != null)
- {
- return sectionsMap.getForward(generalSectionName);
- }
-
- return generalSectionName;
- }
-
- public static String mapSectionNameToIni(String generalSectionName)
- {
- if (sectionsMap.getBackward(generalSectionName) != null)
- {
- return sectionsMap.getBackward(generalSectionName);
- }
-
- return generalSectionName;
- }
-
- @NonNull
- public static File getSettingsFile(String fileName)
- {
- return new File(
- DirectoryInitialization.getUserDirectory() + "/Config/" + fileName + ".ini");
- }
-
- public static File getCustomGameSettingsFile(String gameId)
- {
- return new File(
- DirectoryInitialization.getUserDirectory() + "/GameSettings/" + gameId + ".ini");
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.kt
new file mode 100644
index 0000000000..827f04cbf3
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.kt
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.settings.utils
+
+import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivityView
+import org.dolphinemu.dolphinemu.utils.BiMap
+import org.dolphinemu.dolphinemu.utils.DirectoryInitialization
+import org.dolphinemu.dolphinemu.utils.IniFile
+import org.dolphinemu.dolphinemu.utils.Log
+import java.io.File
+
+/**
+ * Contains static methods for interacting with .ini files in which settings are stored.
+ */
+object SettingsFile {
+ const val KEY_ISO_PATH_BASE = "ISOPath"
+ const val KEY_ISO_PATHS = "ISOPaths"
+ private val sectionsMap = BiMap<String?, String?>()
+
+ init {
+ sectionsMap.apply {
+ add("Hardware", "Video_Hardware")
+ add("Settings", "Video_Settings")
+ add("Enhancements", "Video_Enhancements")
+ add("Stereoscopy", "Video_Stereoscopy")
+ add("Hacks", "Video_Hacks")
+ add("GameSpecific", "Video")
+ }
+ }
+
+ /**
+ * Reads a given .ini file from disk and returns it.
+ * If unsuccessful, outputs an error telling why it failed.
+ *
+ * @param file The ini file to load the settings from
+ * @param ini The object to load into
+ * @param view The current view.
+ */
+ private fun readFile(file: File, ini: IniFile, view: SettingsActivityView) {
+ if (!ini.load(file, true)) {
+ Log.error("[SettingsFile] Error reading from: " + file.absolutePath)
+ view.onSettingsFileNotFound()
+ }
+ }
+
+ fun readFile(fileName: String, ini: IniFile, view: SettingsActivityView) {
+ readFile(getSettingsFile(fileName), ini, view)
+ }
+
+ /**
+ * Reads a given .ini file from disk and returns it.
+ * If unsuccessful, outputs an error telling why it failed.
+ *
+ * @param gameId the id of the game to load settings for.
+ * @param ini The object to load into
+ * @param view The current view.
+ */
+ fun readCustomGameSettings(
+ gameId: String,
+ ini: IniFile,
+ view: SettingsActivityView
+ ) {
+ readFile(getCustomGameSettingsFile(gameId), ini, view)
+ }
+
+ /**
+ * Saves a given .ini file on disk.
+ * If unsuccessful, outputs an error telling why it failed.
+ *
+ * @param fileName The target filename without a path or extension.
+ * @param ini The IniFile we want to serialize.
+ * @param view The current view.
+ */
+ fun saveFile(fileName: String, ini: IniFile, view: SettingsActivityView) {
+ if (!ini.save(getSettingsFile(fileName))) {
+ Log.error("[SettingsFile] Error saving to: $fileName.ini")
+ view.showToastMessage("Error saving $fileName.ini")
+ }
+ }
+
+ fun saveCustomGameSettings(gameId: String, ini: IniFile) {
+ ini.save(getCustomGameSettingsFile(gameId))
+ }
+
+ fun mapSectionNameFromIni(generalSectionName: String): String? {
+ return if (sectionsMap.getForward(generalSectionName) != null) {
+ sectionsMap.getForward(generalSectionName)
+ } else generalSectionName
+ }
+
+ fun mapSectionNameToIni(generalSectionName: String): String? {
+ return if (sectionsMap.getBackward(generalSectionName) != null) {
+ sectionsMap.getBackward(generalSectionName)
+ } else generalSectionName
+ }
+
+ @JvmStatic
+ fun getSettingsFile(fileName: String): File {
+ return File(DirectoryInitialization.getUserDirectory() + "/Config/" + fileName + ".ini")
+ }
+
+ private fun getCustomGameSettingsFile(gameId: String): File {
+ return File(
+ DirectoryInitialization.getUserDirectory() + "/GameSettings/" + gameId + ".ini"
+ )
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SerializableHelper.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SerializableHelper.kt
new file mode 100644
index 0000000000..cad3b548ce
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SerializableHelper.kt
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.utils
+
+import android.content.Intent
+import android.os.Build
+import android.os.Bundle
+import java.io.Serializable
+
+object SerializableHelper {
+ inline fun <reified T : Serializable> Intent.serializable(key: String): T? {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
+ getSerializableExtra(key, T::class.java)
+ else
+ getSerializableExtra(key) as T?
+ }
+
+ inline fun <reified T : Serializable> Bundle.serializable(key: String): T? {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
+ getSerializable(key, T::class.java)
+ else
+ getSerializable(key) as T?
+ }
+}