From 95f0be002605fbf2c014f30dfb721d6b2f100eb2 Mon Sep 17 00:00:00 2001 From: adas20 Date: Wed, 16 Jul 2025 14:00:02 -0400 Subject: [PATCH 01/23] Base starting commit for Feature Impl --- .../app/src/main/java/org/citra/citra_emu/NativeLibrary.kt | 1 + src/android/app/src/main/res/values/integers.xml | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/NativeLibrary.kt b/src/android/app/src/main/java/org/citra/citra_emu/NativeLibrary.kt index 6d93725a4..f0da32b9e 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/NativeLibrary.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/NativeLibrary.kt @@ -783,6 +783,7 @@ object NativeLibrary { const val BUTTON_GPIO14 = 782 const val BUTTON_SWAP = 800 const val BUTTON_TURBO = 801 + const val BUTTON_COMBO = 802 } /** diff --git a/src/android/app/src/main/res/values/integers.xml b/src/android/app/src/main/res/values/integers.xml index 1f19c2373..4956243af 100644 --- a/src/android/app/src/main/res/values/integers.xml +++ b/src/android/app/src/main/res/values/integers.xml @@ -35,6 +35,8 @@ 850 630 850 + 900 + 900 810 @@ -69,5 +71,7 @@ 675 453 720 + 900 + 1600 From c2b58c7224d991c059b983c806039593060508d5 Mon Sep 17 00:00:00 2001 From: adas20 Date: Wed, 16 Jul 2025 14:38:27 -0400 Subject: [PATCH 02/23] Base commit 2 (off of closed PR, impl details of the actual button will likely be different.) --- .../src/main/res/drawable/button_combo.xml | 32 +++++++++++++++++++ .../res/drawable/button_combo_pressed.xml | 28 ++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 src/android/app/src/main/res/drawable/button_combo.xml create mode 100644 src/android/app/src/main/res/drawable/button_combo_pressed.xml diff --git a/src/android/app/src/main/res/drawable/button_combo.xml b/src/android/app/src/main/res/drawable/button_combo.xml new file mode 100644 index 000000000..fdd9a79a4 --- /dev/null +++ b/src/android/app/src/main/res/drawable/button_combo.xml @@ -0,0 +1,32 @@ + + + + + + + + diff --git a/src/android/app/src/main/res/drawable/button_combo_pressed.xml b/src/android/app/src/main/res/drawable/button_combo_pressed.xml new file mode 100644 index 000000000..d8825692d --- /dev/null +++ b/src/android/app/src/main/res/drawable/button_combo_pressed.xml @@ -0,0 +1,28 @@ + + + + From e2e216bcde530607fb4cb427141b23954d3e17e6 Mon Sep 17 00:00:00 2001 From: adas20 Date: Thu, 17 Jul 2025 16:01:16 -0400 Subject: [PATCH 03/23] Added Combo Button Bool setting to use for later implementation. --- .../citra/citra_emu/features/settings/model/BooleanSetting.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt index 3f6a14480..d3a1c6cf9 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt @@ -48,7 +48,8 @@ enum class BooleanSetting( DEBUG_RENDERER("renderer_debug", Settings.SECTION_DEBUG, false), DISABLE_RIGHT_EYE_RENDER("disable_right_eye_render", Settings.SECTION_RENDERER, false), USE_ARTIC_BASE_CONTROLLER("use_artic_base_controller", Settings.SECTION_CONTROLS, false), - UPRIGHT_SCREEN("upright_screen", Settings.SECTION_LAYOUT, false); + UPRIGHT_SCREEN("upright_screen", Settings.SECTION_LAYOUT, false), + ENABLE_COMBO_KEY("enable_combo_key", Settings.SECTION_CONTROLS, true); override var boolean: Boolean = defaultValue From a31634c28a38ab9b153020902463d9a0d27b8a36 Mon Sep 17 00:00:00 2001 From: adas20 Date: Mon, 21 Jul 2025 15:44:46 -0400 Subject: [PATCH 04/23] Added Combo Button Submenu and associated strings. Need to implement button displaying for user to interact with. --- .../features/settings/model/Settings.kt | 1 + .../settings/ui/SettingsFragmentPresenter.kt | 39 +++++++++++++++++++ .../app/src/main/res/values/strings.xml | 5 +++ 3 files changed, 45 insertions(+) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt index b229ffe17..6476644bf 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt @@ -112,6 +112,7 @@ class Settings { const val SECTION_CUSTOM_LANDSCAPE = "Custom Landscape Layout" const val SECTION_CUSTOM_PORTRAIT = "Custom Portrait Layout" const val SECTION_PERFORMANCE_OVERLAY = "Performance Overlay" + const val SECTION_COMBO = "Combo Button" const val KEY_BUTTON_A = "button_a" const val KEY_BUTTON_B = "button_b" diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt index e6b67e448..4e8e6dfb3 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -104,6 +104,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) Settings.SECTION_CUSTOM_LANDSCAPE -> addCustomLandscapeSettings(sl) Settings.SECTION_CUSTOM_PORTRAIT -> addCustomPortraitSettings(sl) Settings.SECTION_PERFORMANCE_OVERLAY -> addPerformanceOverlaySettings(sl) + Settings.SECTION_COMBO -> addComboButtonSettings(sl) else -> { fragmentView.showToastMessage("Unimplemented menu", false) return @@ -795,9 +796,47 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) BooleanSetting.USE_ARTIC_BASE_CONTROLLER.defaultValue ) ) + add( + SubmenuSetting( + R.string.combo_key_options, + R.string.combo_key_description, + R.drawable.button_combo, + Settings.SECTION_COMBO + ) + ) } } + private fun addComboButtonSettings(sl: ArrayList) { + settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.combo_key)) + sl.apply { + add( + SwitchSetting( + BooleanSetting.ENABLE_COMBO_KEY, + R.string.combo_key_enable, + R.string.combo_key_submenu_description, + BooleanSetting.ENABLE_COMBO_KEY.key, + BooleanSetting.ENABLE_COMBO_KEY.defaultValue, + ) + ) + add(HeaderSetting(R.string.combo_key_options)) + // TODO: Implement displaying selectable buttons + /* + add( + StringSingleChoiceSetting( + comboSetting, + R.string.emulated_language, + 0, + R.array.n3dsButtons, + R.array. + ) + ) + + */ + } + + } + private fun getInputObject(key: String): AbstractStringSetting { return object : AbstractStringSetting { override var string: String diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 3d47200be..76937f301 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -153,6 +153,11 @@ Turbo Speed Turbo Speed Enabled Turbo Speed Disabled + Combo Key + Enable Combo Button + Combo Key Settings + Enable and Change Combo Button Bindings. + Changes whether or not Combo Button can be displayed and used in game. System Files From 3f27121d4f343bbdebd0f97a2901f62156fba5ec Mon Sep 17 00:00:00 2001 From: adas20 Date: Mon, 21 Jul 2025 17:04:09 -0400 Subject: [PATCH 05/23] Added layout file for combo settings for potential impl --- .../src/main/res/layout/combo_settings.xml | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 src/android/app/src/main/res/layout/combo_settings.xml diff --git a/src/android/app/src/main/res/layout/combo_settings.xml b/src/android/app/src/main/res/layout/combo_settings.xml new file mode 100644 index 000000000..e8d64851d --- /dev/null +++ b/src/android/app/src/main/res/layout/combo_settings.xml @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + From 77081d002a76da6495b0f0c708c1c9c6f7387fc1 Mon Sep 17 00:00:00 2001 From: adas20 Date: Mon, 21 Jul 2025 17:16:35 -0400 Subject: [PATCH 06/23] Removed combo settings as it wasn't liked. Starting Multi Choice impl --- .../settings/model/view/MultiChoiceSetting.kt | 62 ++++++++ .../settings/model/view/SettingsItem.kt | 1 + .../src/main/res/layout/combo_settings.xml | 143 ------------------ 3 files changed, 63 insertions(+), 143 deletions(-) create mode 100644 src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt delete mode 100644 src/android/app/src/main/res/layout/combo_settings.xml diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt new file mode 100644 index 000000000..92f74d7c8 --- /dev/null +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt @@ -0,0 +1,62 @@ +// Copyright 2023 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +package org.citra.citra_emu.features.settings.model.view + +import org.citra.citra_emu.features.settings.model.AbstractIntSetting +import org.citra.citra_emu.features.settings.model.AbstractSetting +import org.citra.citra_emu.features.settings.model.AbstractShortSetting + +class MultiChoiceSetting( + setting: AbstractSetting?, + titleId: Int, + descriptionId: Int, + val choicesId: Int, + val valuesId: Int, + val key: String? = null, + val defaultValues: Int? = null, + override var isEnabled: Boolean = true +) : SettingsItem(setting, titleId, descriptionId) { + override val type = TYPE_MULTI_CHOICE + + val selectedValue: Int + get() { + if (setting == null) { + return defaultValues!! + } + + try { + val setting = setting as AbstractIntSetting + return setting.int + } catch (_: ClassCastException) { + } + + try { + val setting = setting as AbstractShortSetting + return setting.short.toInt() + } catch (_: ClassCastException) { + } + + return defaultValues!! + } + + /** + * Write a value to the backing int. If that int was previously null, + * initializes a new one and returns it, so it can be added to the Hashmap. + * + * @param selection New value of the int. + * @return the existing setting with the new value applied. + */ + fun setSelectedValue(selection: Int): AbstractIntSetting { + val intSetting = setting as AbstractIntSetting + intSetting.int = selection + return intSetting + } + + fun setSelectedValue(selection: Short): AbstractShortSetting { + val shortSetting = setting as AbstractShortSetting + shortSetting.short = selection + return shortSetting + } +} diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/SettingsItem.kt index c3f11def5..68aa2226c 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/SettingsItem.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/SettingsItem.kt @@ -47,5 +47,6 @@ abstract class SettingsItem( const val TYPE_INPUT_BINDING = 8 const val TYPE_STRING_INPUT = 9 const val TYPE_FLOAT_INPUT = 10 + const val TYPE_MULTI_CHOICE = 11 } } diff --git a/src/android/app/src/main/res/layout/combo_settings.xml b/src/android/app/src/main/res/layout/combo_settings.xml deleted file mode 100644 index e8d64851d..000000000 --- a/src/android/app/src/main/res/layout/combo_settings.xml +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - From bfcafccb8e3403b49b92523c0007215ee988fc08 Mon Sep 17 00:00:00 2001 From: adas20 Date: Tue, 22 Jul 2025 14:19:35 -0400 Subject: [PATCH 07/23] Added Multi Choice Impl. Need to Refactor OnClick for MultiChoice and debug Impl when adding combo button. --- .../model/AbstractMultiBooleanSetting.kt | 9 ++ .../model/AbstractMultiFloatSetting.kt | 9 ++ .../settings/model/AbstractMultiIntSetting.kt | 9 ++ .../model/AbstractMultiShortSetting.kt | 9 ++ .../model/AbstractMultiStringSetting.kt | 9 ++ .../settings/model/view/MultiChoiceSetting.kt | 28 ++--- .../settings/model/view/SettingsItem.kt | 1 + .../model/view/StringMultiChoiceSetting.kt | 92 ++++++++++++++ .../features/settings/ui/SettingsAdapter.kt | 118 +++++++++++++++++- .../ui/viewholder/MultiChoiceViewHolder.kt | 94 ++++++++++++++ 10 files changed, 363 insertions(+), 15 deletions(-) create mode 100644 src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiBooleanSetting.kt create mode 100644 src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiFloatSetting.kt create mode 100644 src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiIntSetting.kt create mode 100644 src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiShortSetting.kt create mode 100644 src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiStringSetting.kt create mode 100644 src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt create mode 100644 src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/MultiChoiceViewHolder.kt diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiBooleanSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiBooleanSetting.kt new file mode 100644 index 000000000..a4cf9ca3d --- /dev/null +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiBooleanSetting.kt @@ -0,0 +1,9 @@ +// Copyright 2023 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +package org.citra.citra_emu.features.settings.model + +interface AbstractMultiBooleanSetting : AbstractSetting { + var booleans: List +} diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiFloatSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiFloatSetting.kt new file mode 100644 index 000000000..f1a21ed8d --- /dev/null +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiFloatSetting.kt @@ -0,0 +1,9 @@ +// Copyright 2023 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +package org.citra.citra_emu.features.settings.model + +interface AbstractMultiFloatSetting : AbstractSetting { + var floats: List +} diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiIntSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiIntSetting.kt new file mode 100644 index 000000000..eda30030e --- /dev/null +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiIntSetting.kt @@ -0,0 +1,9 @@ +// Copyright 2023 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +package org.citra.citra_emu.features.settings.model + +interface AbstractMultiIntSetting : AbstractSetting { + var ints: List +} diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiShortSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiShortSetting.kt new file mode 100644 index 000000000..6ff003b40 --- /dev/null +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiShortSetting.kt @@ -0,0 +1,9 @@ +// Copyright 2023 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +package org.citra.citra_emu.features.settings.model + +interface AbstractMultiShortSetting : AbstractSetting { + var shorts: List +} diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiStringSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiStringSetting.kt new file mode 100644 index 000000000..9d1735290 --- /dev/null +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiStringSetting.kt @@ -0,0 +1,9 @@ +// Copyright 2023 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +package org.citra.citra_emu.features.settings.model + +interface AbstractMultiStringSetting : AbstractSetting { + var strings: List +} diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt index 92f74d7c8..16b31492d 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt @@ -4,9 +4,9 @@ package org.citra.citra_emu.features.settings.model.view -import org.citra.citra_emu.features.settings.model.AbstractIntSetting +import org.citra.citra_emu.features.settings.model.AbstractMultiIntSetting import org.citra.citra_emu.features.settings.model.AbstractSetting -import org.citra.citra_emu.features.settings.model.AbstractShortSetting +import org.citra.citra_emu.features.settings.model.AbstractMultiShortSetting class MultiChoiceSetting( setting: AbstractSetting?, @@ -15,26 +15,26 @@ class MultiChoiceSetting( val choicesId: Int, val valuesId: Int, val key: String? = null, - val defaultValues: Int? = null, + val defaultValues: List? = null, override var isEnabled: Boolean = true ) : SettingsItem(setting, titleId, descriptionId) { override val type = TYPE_MULTI_CHOICE - val selectedValue: Int + val selectedValues: List get() { if (setting == null) { return defaultValues!! } try { - val setting = setting as AbstractIntSetting - return setting.int + val setting = setting as AbstractMultiIntSetting + return setting.ints } catch (_: ClassCastException) { } try { - val setting = setting as AbstractShortSetting - return setting.short.toInt() + val setting = setting as AbstractMultiShortSetting + return setting.shorts.map { it.toInt() } } catch (_: ClassCastException) { } @@ -48,15 +48,15 @@ class MultiChoiceSetting( * @param selection New value of the int. * @return the existing setting with the new value applied. */ - fun setSelectedValue(selection: Int): AbstractIntSetting { - val intSetting = setting as AbstractIntSetting - intSetting.int = selection + fun setSelectedValues(selection: List): AbstractMultiIntSetting { + val intSetting = setting as AbstractMultiIntSetting + intSetting.ints = selection return intSetting } - fun setSelectedValue(selection: Short): AbstractShortSetting { - val shortSetting = setting as AbstractShortSetting - shortSetting.short = selection + fun setSelectedValues(selection: List): AbstractMultiShortSetting { + val shortSetting = setting as AbstractMultiShortSetting + shortSetting.shorts = selection return shortSetting } } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/SettingsItem.kt index 68aa2226c..a1c0dd6ce 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/SettingsItem.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/SettingsItem.kt @@ -48,5 +48,6 @@ abstract class SettingsItem( const val TYPE_STRING_INPUT = 9 const val TYPE_FLOAT_INPUT = 10 const val TYPE_MULTI_CHOICE = 11 + const val TYPE_STRING_MULTI_CHOICE = 12 } } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt new file mode 100644 index 000000000..9b420ad07 --- /dev/null +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt @@ -0,0 +1,92 @@ +// Copyright 2023 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +package org.citra.citra_emu.features.settings.model.view + +import org.citra.citra_emu.features.settings.model.AbstractSetting +import org.citra.citra_emu.features.settings.model.AbstractMultiShortSetting +import org.citra.citra_emu.features.settings.model.AbstractMultiStringSetting + +class StringMultiChoiceSetting( + setting: AbstractSetting?, + titleId: Int, + descriptionId: Int, + val choices: Array, + val values: Array?, + val key: String? = null, + private val defaultValue: List? = null, + override var isEnabled: Boolean = true +) : SettingsItem(setting, titleId, descriptionId) { + override val type = TYPE_STRING_MULTI_CHOICE + + fun getValueAt(index: Int): String? { + if (values == null) return null + return if (index >= 0 && index < values.size) { + values[index] + } else { + "" + } + } + + val selectedValues: List + get() { + if (setting == null) { + return defaultValue!! + } + + try { + val setting = setting as AbstractMultiStringSetting + return setting.strings + } catch (_: ClassCastException) { + } + + try { + val setting = setting as AbstractMultiShortSetting + return setting.shorts.map { it.toString() } + } catch (_: ClassCastException) { + } + return defaultValue!! + } + val selectValueIndices: BooleanArray + get() { + val noneList = values?.let { + ArrayList(BooleanArray(it.size) { false }.toList()) + } ?: ArrayList() + + val chosenindices = mutableListOf() + val selectedValues = selectedValues + for (i in values!!.indices) { + if (values[i] in selectedValues) { + chosenindices.add(true) + } else { + chosenindices.add(false) + } + } + if (chosenindices == null) { + return noneList.toBooleanArray() + } else { + return chosenindices.toBooleanArray() + } + + } + + /** + * Write a value to the backing int. If that int was previously null, + * initializes a new one and returns it, so it can be added to the Hashmap. + * + * @param selection New value of the int. + * @return the existing setting with the new value applied. + */ + fun setSelectedValues(selection: List): AbstractMultiStringSetting { + val stringSetting = setting as AbstractMultiStringSetting + stringSetting.strings = selection + return stringSetting + } + + fun setSelectedValues(selection: List): AbstractMultiShortSetting { + val shortSetting = setting as AbstractMultiShortSetting + shortSetting.shorts = selection + return shortSetting + } +} \ No newline at end of file diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt index bc55bd5d6..2ac2162c0 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt @@ -45,16 +45,19 @@ import org.citra.citra_emu.features.settings.model.ScaledFloatSetting import org.citra.citra_emu.features.settings.model.AbstractShortSetting import org.citra.citra_emu.features.settings.model.view.DateTimeSetting import org.citra.citra_emu.features.settings.model.view.InputBindingSetting +import org.citra.citra_emu.features.settings.model.view.MultiChoiceSetting import org.citra.citra_emu.features.settings.model.view.SettingsItem import org.citra.citra_emu.features.settings.model.view.SingleChoiceSetting import org.citra.citra_emu.features.settings.model.view.SliderSetting import org.citra.citra_emu.features.settings.model.view.StringInputSetting +import org.citra.citra_emu.features.settings.model.view.StringMultiChoiceSetting import org.citra.citra_emu.features.settings.model.view.StringSingleChoiceSetting import org.citra.citra_emu.features.settings.model.view.SubmenuSetting import org.citra.citra_emu.features.settings.model.view.SwitchSetting import org.citra.citra_emu.features.settings.ui.viewholder.DateTimeViewHolder import org.citra.citra_emu.features.settings.ui.viewholder.HeaderViewHolder import org.citra.citra_emu.features.settings.ui.viewholder.InputBindingSettingViewHolder +import org.citra.citra_emu.features.settings.ui.viewholder.MultiChoiceViewHolder import org.citra.citra_emu.features.settings.ui.viewholder.RunnableViewHolder import org.citra.citra_emu.features.settings.ui.viewholder.SettingViewHolder import org.citra.citra_emu.features.settings.ui.viewholder.SingleChoiceViewHolder @@ -72,7 +75,7 @@ import kotlin.math.roundToInt class SettingsAdapter( private val fragmentView: SettingsFragmentView, public val context: Context -) : RecyclerView.Adapter(), DialogInterface.OnClickListener { +) : RecyclerView.Adapter(), DialogInterface.OnClickListener, DialogInterface.OnMultiChoiceClickListener { private var settings: ArrayList? = null private var clickedItem: SettingsItem? = null private var clickedPosition: Int @@ -128,6 +131,10 @@ class SettingsAdapter( StringInputViewHolder(ListItemSettingBinding.inflate(inflater), this) } + SettingsItem.TYPE_MULTI_CHOICE, SettingsItem.TYPE_STRING_MULTI_CHOICE -> { + MultiChoiceViewHolder(ListItemSettingBinding.inflate(inflater), this) + } + else -> { // TODO: Create an error view since we can't return null now HeaderViewHolder(ListItemSettingsHeaderBinding.inflate(inflater), this) @@ -632,4 +639,113 @@ class SettingsAdapter( } return -1 } + + private fun getSelectionForMultiChoiceValues(item: MultiChoiceSetting): BooleanArray { + val checked_values = mutableListOf() + val values = item.selectedValues + val valuesId = item.valuesId + if (valuesId > 0) { + val valuesArray = context.resources.getIntArray(valuesId) + for (index in valuesArray.indices) { + val current = valuesArray[index] + if (current in values) { + checked_values.add(true) + } else { + checked_values.add(false) + } + } + } + + if (checked_values == null) { + return booleanArrayOf(false) + } else { + return checked_values.toBooleanArray() + } + } + + private fun onMultiChoiceClick(item: MultiChoiceSetting) { + clickedItem = item + val values = getSelectionForMultiChoiceValues(item) + dialog = MaterialAlertDialogBuilder(context) + .setTitle(item.nameId) + .setMultiChoiceItems(item.choicesId, values, this) + .show() + } + + fun onMultiChoiceClick(item: MultiChoiceSetting, position: Int) { + clickedPosition = position + onMultiChoiceClick(item) + } + + private fun onStringMultiChoiceClick(item: StringMultiChoiceSetting) { + clickedItem = item + dialog = context?.let { + MaterialAlertDialogBuilder(it) + .setTitle(item.nameId) + .setMultiChoiceItems(item.choices, item.selectValueIndices, this) + .show() + } + } + + fun onStringMultiChoiceClick(item: StringMultiChoiceSetting, position: Int) { + clickedPosition = position + onStringMultiChoiceClick(item) + } + + //TODO: REFACTOR TO BE MULTICHOICE + override fun onClick(dialog: DialogInterface?, which: Int, is_checked: Boolean) { + when (clickedItem) { + is SingleChoiceSetting -> { + val scSetting = clickedItem as? SingleChoiceSetting + scSetting?.let { + val setting = when (it.setting) { + is AbstractIntSetting -> { + val value = getValueForSingleChoiceSelection(it, which) + if (it.selectedValue != value) { + fragmentView?.onSettingChanged() + } + it.setSelectedValue(value) + } + + is AbstractShortSetting -> { + val value = getValueForSingleChoiceSelection(it, which).toShort() + if (it.selectedValue.toShort() != value) { + fragmentView?.onSettingChanged() + } + it.setSelectedValue(value) + } + + else -> throw IllegalStateException("Unrecognized type used for SingleChoiceSetting!") + } + fragmentView?.putSetting(setting) + fragmentView.loadSettingsList() + closeDialog() + } + } + + is StringSingleChoiceSetting -> { + val scSetting = clickedItem as? StringSingleChoiceSetting + scSetting?.let { + val setting = when (it.setting) { + is AbstractStringSetting -> { + val value = it.getValueAt(which) + if (it.selectedValue != value) fragmentView?.onSettingChanged() + it.setSelectedValue(value ?: "") + } + + is AbstractShortSetting -> { + if (it.selectValueIndex != which) fragmentView?.onSettingChanged() + it.setSelectedValue(it.getValueAt(which)?.toShort() ?: 1) + } + + else -> throw IllegalStateException("Unrecognized type used for StringSingleChoiceSetting!") + } + + fragmentView?.putSetting(setting) + fragmentView.loadSettingsList() + closeDialog() + } + } + } + } } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/MultiChoiceViewHolder.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/MultiChoiceViewHolder.kt new file mode 100644 index 000000000..76fe809fc --- /dev/null +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/MultiChoiceViewHolder.kt @@ -0,0 +1,94 @@ +// Copyright Citra Emulator Project / Azahar Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +package org.citra.citra_emu.features.settings.ui.viewholder + +import android.view.View +import org.citra.citra_emu.databinding.ListItemSettingBinding +import org.citra.citra_emu.features.settings.model.view.MultiChoiceSetting +import org.citra.citra_emu.features.settings.model.view.SettingsItem +import org.citra.citra_emu.features.settings.model.view.StringMultiChoiceSetting +import org.citra.citra_emu.features.settings.ui.SettingsAdapter + +class MultiChoiceViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) : + SettingViewHolder(binding.root, adapter) { + private lateinit var setting: SettingsItem + + override fun bind(item: SettingsItem) { + setting = item + binding.textSettingName.setText(item.nameId) + if (item.descriptionId != 0) { + binding.textSettingDescription.visibility = View.VISIBLE + binding.textSettingDescription.setText(item.descriptionId) + } else { + binding.textSettingDescription.visibility = View.GONE + } + binding.textSettingValue.visibility = View.VISIBLE + binding.textSettingValue.text = getTextSetting() + + if (setting.isActive) { + binding.textSettingName.alpha = 1f + binding.textSettingDescription.alpha = 1f + binding.textSettingValue.alpha = 1f + } else { + binding.textSettingName.alpha = 0.5f + binding.textSettingDescription.alpha = 0.5f + binding.textSettingValue.alpha = 0.5f + } + } + + private fun getTextSetting(): String { + when (val item = setting) { + is MultiChoiceSetting -> { + val resMgr = binding.textSettingDescription.context.resources + val values = resMgr.getIntArray(item.valuesId) + values.forEachIndexed { i: Int, value: Int -> + if (value in (setting as MultiChoiceSetting).selectedValues) { + return resMgr.getStringArray(item.choicesId)[i] + } + } + return "" + } + + is StringMultiChoiceSetting -> { + item.values?.forEachIndexed { i: Int, value: String -> + if (value in item.selectedValues) { + return item.choices[i] + } + } + return "" + } + + else -> return "" + } + } + + override fun onClick(clicked: View) { + if (!setting.isEditable || !setting.isEnabled) { + adapter.onClickDisabledSetting(!setting.isEditable) + return + } + + if (setting is MultiChoiceSetting) { + adapter.onMultiChoiceClick( + (setting as MultiChoiceSetting), + bindingAdapterPosition + ) + } else if (setting is StringMultiChoiceSetting) { + adapter.onStringMultiChoiceClick( + (setting as StringMultiChoiceSetting), + bindingAdapterPosition + ) + } + } + + override fun onLongClick(clicked: View): Boolean { + if (setting.isActive) { + return adapter.onLongClick(setting.setting!!, bindingAdapterPosition) + } else { + adapter.onClickDisabledSetting(!setting.isEditable) + } + return false + } +} \ No newline at end of file From eaf9baee93342a8784e723162e47b9529dd34394 Mon Sep 17 00:00:00 2001 From: adas20 Date: Wed, 23 Jul 2025 11:52:18 -0400 Subject: [PATCH 08/23] Change List<> in Multi Files to be MutableSet<> to allow adds while prevent potential duplicates. Finished primary multi choice backend impl. --- .../model/AbstractMultiBooleanSetting.kt | 2 +- .../model/AbstractMultiFloatSetting.kt | 2 +- .../settings/model/AbstractMultiIntSetting.kt | 2 +- .../model/AbstractMultiShortSetting.kt | 2 +- .../model/AbstractMultiStringSetting.kt | 2 +- .../settings/model/view/MultiChoiceSetting.kt | 12 +++-- .../model/view/StringMultiChoiceSetting.kt | 10 ++-- .../features/settings/ui/SettingsAdapter.kt | 54 ++++++++++++------- 8 files changed, 51 insertions(+), 35 deletions(-) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiBooleanSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiBooleanSetting.kt index a4cf9ca3d..0eb759add 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiBooleanSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiBooleanSetting.kt @@ -5,5 +5,5 @@ package org.citra.citra_emu.features.settings.model interface AbstractMultiBooleanSetting : AbstractSetting { - var booleans: List + var booleans: MutableSet } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiFloatSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiFloatSetting.kt index f1a21ed8d..ebfa544d8 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiFloatSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiFloatSetting.kt @@ -5,5 +5,5 @@ package org.citra.citra_emu.features.settings.model interface AbstractMultiFloatSetting : AbstractSetting { - var floats: List + var floats: MutableSet } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiIntSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiIntSetting.kt index eda30030e..a0d73aefc 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiIntSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiIntSetting.kt @@ -5,5 +5,5 @@ package org.citra.citra_emu.features.settings.model interface AbstractMultiIntSetting : AbstractSetting { - var ints: List + var ints: MutableSet } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiShortSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiShortSetting.kt index 6ff003b40..f2abaa4d0 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiShortSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiShortSetting.kt @@ -5,5 +5,5 @@ package org.citra.citra_emu.features.settings.model interface AbstractMultiShortSetting : AbstractSetting { - var shorts: List + var shorts: MutableSet } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiStringSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiStringSetting.kt index 9d1735290..534ade024 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiStringSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiStringSetting.kt @@ -5,5 +5,5 @@ package org.citra.citra_emu.features.settings.model interface AbstractMultiStringSetting : AbstractSetting { - var strings: List + var strings: MutableSet } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt index 16b31492d..407a22df3 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt @@ -7,6 +7,8 @@ package org.citra.citra_emu.features.settings.model.view import org.citra.citra_emu.features.settings.model.AbstractMultiIntSetting import org.citra.citra_emu.features.settings.model.AbstractSetting import org.citra.citra_emu.features.settings.model.AbstractMultiShortSetting +import org.citra.citra_emu.features.settings.model.AbstractIntSetting +import org.citra.citra_emu.features.settings.model.AbstractShortSetting class MultiChoiceSetting( setting: AbstractSetting?, @@ -28,7 +30,7 @@ class MultiChoiceSetting( try { val setting = setting as AbstractMultiIntSetting - return setting.ints + return setting.ints.toList() } catch (_: ClassCastException) { } @@ -48,15 +50,15 @@ class MultiChoiceSetting( * @param selection New value of the int. * @return the existing setting with the new value applied. */ - fun setSelectedValues(selection: List): AbstractMultiIntSetting { + fun setSelectedValues(selection: Int): AbstractMultiIntSetting { val intSetting = setting as AbstractMultiIntSetting - intSetting.ints = selection + intSetting.ints.add(selection) return intSetting } - fun setSelectedValues(selection: List): AbstractMultiShortSetting { + fun setSelectedValues(selection: Short): AbstractMultiShortSetting { val shortSetting = setting as AbstractMultiShortSetting - shortSetting.shorts = selection + shortSetting.shorts.add(selection) return shortSetting } } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt index 9b420ad07..351a750a0 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt @@ -37,7 +37,7 @@ class StringMultiChoiceSetting( try { val setting = setting as AbstractMultiStringSetting - return setting.strings + return setting.strings.toList() } catch (_: ClassCastException) { } @@ -78,15 +78,15 @@ class StringMultiChoiceSetting( * @param selection New value of the int. * @return the existing setting with the new value applied. */ - fun setSelectedValues(selection: List): AbstractMultiStringSetting { + fun setSelectedValues(selection: String): AbstractMultiStringSetting { val stringSetting = setting as AbstractMultiStringSetting - stringSetting.strings = selection + stringSetting.strings.add(selection) return stringSetting } - fun setSelectedValues(selection: List): AbstractMultiShortSetting { + fun setSelectedValues(selection: Short): AbstractMultiShortSetting { val shortSetting = setting as AbstractMultiShortSetting - shortSetting.shorts = selection + shortSetting.shorts.add(selection) return shortSetting } } \ No newline at end of file diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt index 2ac2162c0..92befc80e 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt @@ -38,6 +38,9 @@ import org.citra.citra_emu.databinding.ListItemSettingsHeaderBinding import org.citra.citra_emu.features.settings.model.AbstractBooleanSetting import org.citra.citra_emu.features.settings.model.AbstractFloatSetting import org.citra.citra_emu.features.settings.model.AbstractIntSetting +import org.citra.citra_emu.features.settings.model.AbstractMultiIntSetting +import org.citra.citra_emu.features.settings.model.AbstractMultiShortSetting +import org.citra.citra_emu.features.settings.model.AbstractMultiStringSetting import org.citra.citra_emu.features.settings.model.AbstractSetting import org.citra.citra_emu.features.settings.model.AbstractStringSetting import org.citra.citra_emu.features.settings.model.FloatSetting @@ -663,6 +666,17 @@ class SettingsAdapter( } } + private fun getValueForMultiChoiceSelection(item: MultiChoiceSetting, which: Int, is_checked: Boolean): Int { + val valuesId = item.valuesId + if (valuesId > 0) { + val valuesArray = context.resources.getIntArray(valuesId) + if (is_checked) { + return valuesArray[which] + } + } + return which + } + private fun onMultiChoiceClick(item: MultiChoiceSetting) { clickedItem = item val values = getSelectionForMultiChoiceValues(item) @@ -695,27 +709,27 @@ class SettingsAdapter( //TODO: REFACTOR TO BE MULTICHOICE override fun onClick(dialog: DialogInterface?, which: Int, is_checked: Boolean) { when (clickedItem) { - is SingleChoiceSetting -> { - val scSetting = clickedItem as? SingleChoiceSetting + is MultiChoiceSetting -> { + val scSetting = clickedItem as? MultiChoiceSetting scSetting?.let { val setting = when (it.setting) { - is AbstractIntSetting -> { - val value = getValueForSingleChoiceSelection(it, which) - if (it.selectedValue != value) { + is AbstractMultiIntSetting -> { + val value = getValueForMultiChoiceSelection(it, which, is_checked) + if (value !in it.selectedValues) { fragmentView?.onSettingChanged() } - it.setSelectedValue(value) + it.setSelectedValues(value) } - is AbstractShortSetting -> { - val value = getValueForSingleChoiceSelection(it, which).toShort() - if (it.selectedValue.toShort() != value) { + is AbstractMultiShortSetting -> { + val value = getValueForMultiChoiceSelection(it, which, is_checked).toShort() + if (value !in it.selectedValues.map { it.toShort() }) { fragmentView?.onSettingChanged() } - it.setSelectedValue(value) + it.setSelectedValues(value) } - else -> throw IllegalStateException("Unrecognized type used for SingleChoiceSetting!") + else -> throw IllegalStateException("Unrecognized type used for MultiChoiceSetting!") } fragmentView?.putSetting(setting) fragmentView.loadSettingsList() @@ -723,22 +737,22 @@ class SettingsAdapter( } } - is StringSingleChoiceSetting -> { - val scSetting = clickedItem as? StringSingleChoiceSetting + is StringMultiChoiceSetting -> { + val scSetting = clickedItem as? StringMultiChoiceSetting scSetting?.let { val setting = when (it.setting) { - is AbstractStringSetting -> { + is AbstractMultiStringSetting -> { val value = it.getValueAt(which) - if (it.selectedValue != value) fragmentView?.onSettingChanged() - it.setSelectedValue(value ?: "") + if (value !in it.selectedValues ) fragmentView?.onSettingChanged() + it.setSelectedValues(value ?: "") } - is AbstractShortSetting -> { - if (it.selectValueIndex != which) fragmentView?.onSettingChanged() - it.setSelectedValue(it.getValueAt(which)?.toShort() ?: 1) + is AbstractMultiShortSetting -> { + if (is_checked != it.selectValueIndices[which]) fragmentView?.onSettingChanged() + it.setSelectedValues(it.getValueAt(which)?.toShort() ?: 1) } - else -> throw IllegalStateException("Unrecognized type used for StringSingleChoiceSetting!") + else -> throw IllegalStateException("Unrecognized type used for StringMultiChoiceSetting!") } fragmentView?.putSetting(setting) From 334f9385ba7b3fabfe50c1fa31ea58d5d5685741 Mon Sep 17 00:00:00 2001 From: adas20 Date: Wed, 23 Jul 2025 15:44:20 -0400 Subject: [PATCH 09/23] used correct lisencing procedure for multi files --- .../features/settings/model/AbstractMultiBooleanSetting.kt | 2 +- .../features/settings/model/AbstractMultiFloatSetting.kt | 2 +- .../features/settings/model/AbstractMultiIntSetting.kt | 2 +- .../features/settings/model/AbstractMultiShortSetting.kt | 2 +- .../features/settings/model/AbstractMultiStringSetting.kt | 2 +- .../features/settings/model/view/MultiChoiceSetting.kt | 2 +- .../features/settings/model/view/StringMultiChoiceSetting.kt | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiBooleanSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiBooleanSetting.kt index 0eb759add..2b3f2e1fc 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiBooleanSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiBooleanSetting.kt @@ -1,4 +1,4 @@ -// Copyright 2023 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiFloatSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiFloatSetting.kt index ebfa544d8..2d9d92873 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiFloatSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiFloatSetting.kt @@ -1,4 +1,4 @@ -// Copyright 2023 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiIntSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiIntSetting.kt index a0d73aefc..0c916bab7 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiIntSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiIntSetting.kt @@ -1,4 +1,4 @@ -// Copyright 2023 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiShortSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiShortSetting.kt index f2abaa4d0..acbc7b7a2 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiShortSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiShortSetting.kt @@ -1,4 +1,4 @@ -// Copyright 2023 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiStringSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiStringSetting.kt index 534ade024..ddd48306f 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiStringSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiStringSetting.kt @@ -1,4 +1,4 @@ -// Copyright 2023 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt index 407a22df3..d09146c4c 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt @@ -1,4 +1,4 @@ -// Copyright 2023 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt index 351a750a0..8977c7880 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt @@ -1,4 +1,4 @@ -// Copyright 2023 Citra Emulator Project +// Copyright Citra Emulator Project / Azahar Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. From db04f2c29d4eb0e8d4ef85f2a78b59e23764a4bf Mon Sep 17 00:00:00 2001 From: adas20 Date: Thu, 24 Jul 2025 14:07:08 -0400 Subject: [PATCH 10/23] Added code in arrays.xml to display the buttons. This code has the buttons display but clicking on them crashes the app. Will debug further. Also replaced setSelectedValues with add and remove SelectedValue for clarity purposes. --- .../features/settings/model/Settings.kt | 2 ++ .../settings/model/view/MultiChoiceSetting.kt | 21 ++++++++--- .../model/view/StringMultiChoiceSetting.kt | 21 ++++++++--- .../features/settings/ui/SettingsAdapter.kt | 28 ++++++++++----- .../settings/ui/SettingsFragmentPresenter.kt | 35 ++++++++++++++----- .../app/src/main/res/values/arrays.xml | 14 ++++++++ 6 files changed, 94 insertions(+), 27 deletions(-) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt index 6476644bf..3928675ea 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt @@ -220,6 +220,8 @@ class Settings { R.string.turbo_limit_hotkey ) + val comboSelection = mutableSetOf() + const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch" const val PREF_MATERIAL_YOU = "MaterialYouTheme" const val PREF_THEME_MODE = "ThemeMode" diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt index d09146c4c..b8cfe41f6 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt @@ -44,21 +44,32 @@ class MultiChoiceSetting( } /** - * Write a value to the backing int. If that int was previously null, - * initializes a new one and returns it, so it can be added to the Hashmap. + * Add values to multi choice backing mutable sets. * * @param selection New value of the int. - * @return the existing setting with the new value applied. + * @return the existing setting with the new value added. */ - fun setSelectedValues(selection: Int): AbstractMultiIntSetting { + fun addSelectedValue(selection: Int): AbstractMultiIntSetting { val intSetting = setting as AbstractMultiIntSetting intSetting.ints.add(selection) return intSetting } - fun setSelectedValues(selection: Short): AbstractMultiShortSetting { + fun addSelectedValue(selection: Short): AbstractMultiShortSetting { val shortSetting = setting as AbstractMultiShortSetting shortSetting.shorts.add(selection) return shortSetting } + + fun removeSelectedValue(selection: Int): AbstractMultiIntSetting { + val intSetting = setting as AbstractMultiIntSetting + intSetting.ints.remove(selection) + return intSetting + } + + fun removeSelectedValue(selection: Short): AbstractMultiShortSetting { + val shortSetting = setting as AbstractMultiShortSetting + shortSetting.shorts.remove(selection) + return shortSetting + } } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt index 8977c7880..ced239289 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt @@ -72,21 +72,32 @@ class StringMultiChoiceSetting( } /** - * Write a value to the backing int. If that int was previously null, - * initializes a new one and returns it, so it can be added to the Hashmap. + * Add values to multi choice through the backing mutable sets. * * @param selection New value of the int. - * @return the existing setting with the new value applied. + * @return the existing setting with the new value added. */ - fun setSelectedValues(selection: String): AbstractMultiStringSetting { + fun addSelectedValue(selection: String): AbstractMultiStringSetting { val stringSetting = setting as AbstractMultiStringSetting stringSetting.strings.add(selection) return stringSetting } - fun setSelectedValues(selection: Short): AbstractMultiShortSetting { + fun addSelectedValue(selection: Short): AbstractMultiShortSetting { val shortSetting = setting as AbstractMultiShortSetting shortSetting.shorts.add(selection) return shortSetting } + + fun removeSelectedValue(selection: String): AbstractMultiStringSetting { + val stringSetting = setting as AbstractMultiStringSetting + stringSetting.strings.remove(selection) + return stringSetting + } + + fun removeSelectedValue(selection: Short): AbstractMultiShortSetting { + val shortSetting = setting as AbstractMultiShortSetting + shortSetting.shorts.remove(selection) + return shortSetting + } } \ No newline at end of file diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt index 92befc80e..c3620d1ff 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt @@ -716,22 +716,26 @@ class SettingsAdapter( is AbstractMultiIntSetting -> { val value = getValueForMultiChoiceSelection(it, which, is_checked) if (value !in it.selectedValues) { + it.removeSelectedValue(value) fragmentView?.onSettingChanged() + } else { + it.addSelectedValue(value) } - it.setSelectedValues(value) } is AbstractMultiShortSetting -> { val value = getValueForMultiChoiceSelection(it, which, is_checked).toShort() if (value !in it.selectedValues.map { it.toShort() }) { + it.removeSelectedValue(value) fragmentView?.onSettingChanged() + } else { + it.addSelectedValue(value) } - it.setSelectedValues(value) } else -> throw IllegalStateException("Unrecognized type used for MultiChoiceSetting!") } - fragmentView?.putSetting(setting) + fragmentView?.putSetting(setting as AbstractSetting) fragmentView.loadSettingsList() closeDialog() } @@ -743,19 +747,27 @@ class SettingsAdapter( val setting = when (it.setting) { is AbstractMultiStringSetting -> { val value = it.getValueAt(which) - if (value !in it.selectedValues ) fragmentView?.onSettingChanged() - it.setSelectedValues(value ?: "") + if (value !in it.selectedValues ) { + it.removeSelectedValue(value ?: "") + fragmentView?.onSettingChanged() + } else { + it.addSelectedValue(value ?: "") + } } is AbstractMultiShortSetting -> { - if (is_checked != it.selectValueIndices[which]) fragmentView?.onSettingChanged() - it.setSelectedValues(it.getValueAt(which)?.toShort() ?: 1) + if (is_checked != it.selectValueIndices[which]) { + it.removeSelectedValue(it.getValueAt(which)?.toShort() ?: 1) + fragmentView?.onSettingChanged() + } else { + it.addSelectedValue(it.getValueAt(which)?.toShort() ?: 1) + } } else -> throw IllegalStateException("Unrecognized type used for StringMultiChoiceSetting!") } - fragmentView?.putSetting(setting) + fragmentView?.putSetting(setting as AbstractSetting) fragmentView.loadSettingsList() closeDialog() } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt index 4e8e6dfb3..8cd1c2193 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -21,6 +21,7 @@ import org.citra.citra_emu.display.PortraitScreenLayout import org.citra.citra_emu.display.ScreenLayout import org.citra.citra_emu.features.settings.model.AbstractBooleanSetting import org.citra.citra_emu.features.settings.model.AbstractIntSetting +import org.citra.citra_emu.features.settings.model.AbstractMultiStringSetting import org.citra.citra_emu.features.settings.model.AbstractSetting import org.citra.citra_emu.features.settings.model.AbstractShortSetting import org.citra.citra_emu.features.settings.model.AbstractStringSetting @@ -38,6 +39,7 @@ import org.citra.citra_emu.features.settings.model.view.SettingsItem import org.citra.citra_emu.features.settings.model.view.SingleChoiceSetting import org.citra.citra_emu.features.settings.model.view.SliderSetting import org.citra.citra_emu.features.settings.model.view.StringInputSetting +import org.citra.citra_emu.features.settings.model.view.StringMultiChoiceSetting import org.citra.citra_emu.features.settings.model.view.StringSingleChoiceSetting import org.citra.citra_emu.features.settings.model.view.SubmenuSetting import org.citra.citra_emu.features.settings.model.view.SwitchSetting @@ -809,6 +811,26 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) private fun addComboButtonSettings(sl: ArrayList) { settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.combo_key)) + val comboSetting = object : AbstractMultiStringSetting { + override var strings: MutableSet + get() { + return Settings.comboSelection + } + set(values) { + for (item in values) { + Settings.comboSelection.add(item) + } + } + override val key = null + override val section = null + override val isRuntimeEditable = false + override val valueAsString get() = "" + override val defaultValue = "" + } + + val buttons = settingsActivity.resources.getStringArray(R.array.n3dsButtons).take(10).toTypedArray() + val combo_values = settingsActivity.resources.getStringArray(R.array.combovalues) + sl.apply { add( SwitchSetting( @@ -819,20 +841,15 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) BooleanSetting.ENABLE_COMBO_KEY.defaultValue, ) ) - add(HeaderSetting(R.string.combo_key_options)) - // TODO: Implement displaying selectable buttons - /* add( - StringSingleChoiceSetting( + StringMultiChoiceSetting( comboSetting, - R.string.emulated_language, + R.string.combo_key_options, 0, - R.array.n3dsButtons, - R.array. + buttons, + combo_values ) ) - - */ } } diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index 543b59913..bbf104653 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -169,6 +169,20 @@ @string/button_turbo + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + + @string/blank @string/still_image From fbb1944fa3e3a12035df7cce55b07c23cb291bf1 Mon Sep 17 00:00:00 2001 From: adas20 Date: Sat, 26 Jul 2025 16:09:53 -0400 Subject: [PATCH 11/23] Deleted Int Combo Value array in arrays.xml as it was not needed. Able to Click multiple buttons at once but unchecking them causes app to crash. (within the MultiChoice OnClick for SettingsAdapter.kt) Also debating whether to remove the normal MultiChoice addition as it wasn't added. --- .../model/view/StringMultiChoiceSetting.kt | 1 + .../features/settings/ui/SettingsAdapter.kt | 18 +++++++++++------- .../settings/ui/SettingsFragmentPresenter.kt | 4 ++-- src/android/app/src/main/res/values/arrays.xml | 14 -------------- 4 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt index ced239289..8330ed186 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt @@ -48,6 +48,7 @@ class StringMultiChoiceSetting( } return defaultValue!! } + val selectValueIndices: BooleanArray get() { val noneList = values?.let { diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt index c3620d1ff..96c8b54e8 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt @@ -665,7 +665,8 @@ class SettingsAdapter( return checked_values.toBooleanArray() } } - + // TODO: Part of MultiChoice Impl + /* private fun getValueForMultiChoiceSelection(item: MultiChoiceSetting, which: Int, is_checked: Boolean): Int { val valuesId = item.valuesId if (valuesId > 0) { @@ -676,6 +677,7 @@ class SettingsAdapter( } return which } + */ private fun onMultiChoiceClick(item: MultiChoiceSetting) { clickedItem = item @@ -706,9 +708,10 @@ class SettingsAdapter( onStringMultiChoiceClick(item) } - //TODO: REFACTOR TO BE MULTICHOICE + //TODO: I only added MultiChoice for fleshing out backend, debating whether to remove MultiChoiceSetting and related code for cleaning up override fun onClick(dialog: DialogInterface?, which: Int, is_checked: Boolean) { when (clickedItem) { + /* is MultiChoiceSetting -> { val scSetting = clickedItem as? MultiChoiceSetting scSetting?.let { @@ -736,18 +739,19 @@ class SettingsAdapter( else -> throw IllegalStateException("Unrecognized type used for MultiChoiceSetting!") } fragmentView?.putSetting(setting as AbstractSetting) - fragmentView.loadSettingsList() - closeDialog() + //fragmentView.loadSettingsList() + //closeDialog() } } + */ is StringMultiChoiceSetting -> { val scSetting = clickedItem as? StringMultiChoiceSetting scSetting?.let { val setting = when (it.setting) { is AbstractMultiStringSetting -> { val value = it.getValueAt(which) - if (value !in it.selectedValues ) { + if (value in it.selectedValues && !is_checked) { it.removeSelectedValue(value ?: "") fragmentView?.onSettingChanged() } else { @@ -768,8 +772,8 @@ class SettingsAdapter( } fragmentView?.putSetting(setting as AbstractSetting) - fragmentView.loadSettingsList() - closeDialog() + //fragmentView.loadSettingsList() + //closeDialog() } } } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt index 8cd1c2193..500a5df4b 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -34,6 +34,7 @@ import org.citra.citra_emu.features.settings.model.StringSetting import org.citra.citra_emu.features.settings.model.view.DateTimeSetting import org.citra.citra_emu.features.settings.model.view.HeaderSetting import org.citra.citra_emu.features.settings.model.view.InputBindingSetting +import org.citra.citra_emu.features.settings.model.view.MultiChoiceSetting import org.citra.citra_emu.features.settings.model.view.RunnableSetting import org.citra.citra_emu.features.settings.model.view.SettingsItem import org.citra.citra_emu.features.settings.model.view.SingleChoiceSetting @@ -829,7 +830,6 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) } val buttons = settingsActivity.resources.getStringArray(R.array.n3dsButtons).take(10).toTypedArray() - val combo_values = settingsActivity.resources.getStringArray(R.array.combovalues) sl.apply { add( @@ -847,7 +847,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) R.string.combo_key_options, 0, buttons, - combo_values + buttons ) ) } diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index bbf104653..543b59913 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -169,20 +169,6 @@ @string/button_turbo - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - - @string/blank @string/still_image From c0afc61c73c573931c5593121e4b80512cf94d8f Mon Sep 17 00:00:00 2001 From: adas20 Date: Sun, 27 Jul 2025 22:56:46 -0400 Subject: [PATCH 12/23] Attempt to deal with merge conflicts --- .../citra/citra_emu/features/settings/model/BooleanSetting.kt | 1 + .../java/org/citra/citra_emu/features/settings/model/Settings.kt | 1 + 2 files changed, 2 insertions(+) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt index d3a1c6cf9..bcdab3aad 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/BooleanSetting.kt @@ -49,6 +49,7 @@ enum class BooleanSetting( DISABLE_RIGHT_EYE_RENDER("disable_right_eye_render", Settings.SECTION_RENDERER, false), USE_ARTIC_BASE_CONTROLLER("use_artic_base_controller", Settings.SECTION_CONTROLS, false), UPRIGHT_SCREEN("upright_screen", Settings.SECTION_LAYOUT, false), + COMPRESS_INSTALLED_CIA_CONTENT("compress_cia_installs", Settings.SECTION_STORAGE, false), ENABLE_COMBO_KEY("enable_combo_key", Settings.SECTION_CONTROLS, true); override var boolean: Boolean = defaultValue diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt index 3928675ea..ca2dbffcd 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt @@ -112,6 +112,7 @@ class Settings { const val SECTION_CUSTOM_LANDSCAPE = "Custom Landscape Layout" const val SECTION_CUSTOM_PORTRAIT = "Custom Portrait Layout" const val SECTION_PERFORMANCE_OVERLAY = "Performance Overlay" + const val SECTION_STORAGE = "Storage" const val SECTION_COMBO = "Combo Button" const val KEY_BUTTON_A = "button_a" From 5d6c9cb6bf4b5c33f4ffcf1d730ef9e6e2d08b52 Mon Sep 17 00:00:00 2001 From: adas20 Date: Mon, 28 Jul 2025 11:36:05 -0400 Subject: [PATCH 13/23] Moved OnSettingChange after I add or remove selected vals to fix crashing issue. --- .../citra/citra_emu/features/settings/ui/SettingsAdapter.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt index 96c8b54e8..3cfd67178 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt @@ -753,7 +753,6 @@ class SettingsAdapter( val value = it.getValueAt(which) if (value in it.selectedValues && !is_checked) { it.removeSelectedValue(value ?: "") - fragmentView?.onSettingChanged() } else { it.addSelectedValue(value ?: "") } @@ -762,7 +761,6 @@ class SettingsAdapter( is AbstractMultiShortSetting -> { if (is_checked != it.selectValueIndices[which]) { it.removeSelectedValue(it.getValueAt(which)?.toShort() ?: 1) - fragmentView?.onSettingChanged() } else { it.addSelectedValue(it.getValueAt(which)?.toShort() ?: 1) } @@ -771,8 +769,9 @@ class SettingsAdapter( else -> throw IllegalStateException("Unrecognized type used for StringMultiChoiceSetting!") } + fragmentView?.onSettingChanged() fragmentView?.putSetting(setting as AbstractSetting) - //fragmentView.loadSettingsList() + fragmentView.loadSettingsList() //closeDialog() } } From 1fb2013090b5146c02b4610b745400fcc0d89ef2 Mon Sep 17 00:00:00 2001 From: adas20 Date: Mon, 28 Jul 2025 13:43:33 -0400 Subject: [PATCH 14/23] Displayed combo button in both landscape and portrait --- .../citra/citra_emu/overlay/InputOverlay.kt | 28 +++++++++++++++++++ .../app/src/main/res/values/integers.xml | 8 +++--- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt index 23dcddc78..42d79380a 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt @@ -542,6 +542,18 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex ) ) } + + if (preferences.getBoolean("buttonToggle16", true)) { + overlayButtons.add( + initializeOverlayButton( + context, + R.drawable.button_combo, + R.drawable.button_combo_pressed, + NativeLibrary.ButtonType.BUTTON_COMBO, + orientation + ) + ) + } } fun refreshControls() { @@ -755,6 +767,14 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex NativeLibrary.ButtonType.BUTTON_TURBO.toString() + "-Y", resources.getInteger(R.integer.N3DS_BUTTON_TURBO_Y).toFloat() / 1000 * maxY ) + .putFloat( + NativeLibrary.ButtonType.BUTTON_COMBO.toString() + "-X", + resources.getInteger(R.integer.N3DS_BUTTON_COMBO_X).toFloat() / 1000 * maxX + ) + .putFloat( + NativeLibrary.ButtonType.BUTTON_COMBO.toString() + "-Y", + resources.getInteger(R.integer.N3DS_BUTTON_COMBO_Y).toFloat() / 1000 * maxY + ) .apply() } @@ -906,6 +926,14 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex NativeLibrary.ButtonType.BUTTON_TURBO.toString() + portrait + "-Y", resources.getInteger(R.integer.N3DS_BUTTON_TURBO_PORTRAIT_Y).toFloat() / 1000 * maxY ) + .putFloat( + NativeLibrary.ButtonType.BUTTON_COMBO.toString() + portrait + "-X", + resources.getInteger(R.integer.N3DS_BUTTON_COMBO_X).toFloat() / 1000 * maxX + ) + .putFloat( + NativeLibrary.ButtonType.BUTTON_COMBO.toString() + portrait + "-Y", + resources.getInteger(R.integer.N3DS_BUTTON_COMBO_Y).toFloat() / 1000 * maxY + ) .apply() } diff --git a/src/android/app/src/main/res/values/integers.xml b/src/android/app/src/main/res/values/integers.xml index 4956243af..133b4d16f 100644 --- a/src/android/app/src/main/res/values/integers.xml +++ b/src/android/app/src/main/res/values/integers.xml @@ -35,8 +35,8 @@ 850 630 850 - 900 - 900 + 750 + 800 810 @@ -71,7 +71,7 @@ 675 453 720 - 900 - 1600 + 460 + 550 From 8b90606564ef416bb18c5c47a45a67c0bbbff484 Mon Sep 17 00:00:00 2001 From: adas20 Date: Mon, 28 Jul 2025 14:48:57 -0400 Subject: [PATCH 15/23] WIP on Button Impl, made combo button setting run time editable --- .../citra/citra_emu/features/settings/ui/SettingsAdapter.kt | 2 +- .../features/settings/ui/SettingsFragmentPresenter.kt | 2 +- .../main/java/org/citra/citra_emu/overlay/InputOverlay.kt | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt index 3cfd67178..a69667c5d 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt @@ -771,7 +771,7 @@ class SettingsAdapter( fragmentView?.onSettingChanged() fragmentView?.putSetting(setting as AbstractSetting) - fragmentView.loadSettingsList() + //fragmentView.loadSettingsList() //closeDialog() } } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt index 64f9eac97..4c38a0fcf 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -834,7 +834,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) } override val key = null override val section = null - override val isRuntimeEditable = false + override val isRuntimeEditable = true override val valueAsString get() = "" override val defaultValue = "" } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt index 42d79380a..840ce45bf 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt @@ -140,6 +140,11 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex else if (button.id == NativeLibrary.ButtonType.BUTTON_TURBO && button.status == NativeLibrary.ButtonState.PRESSED) { TurboHelper.toggleTurbo(true) } + /* + else if (button.id == NativeLibrary.ButtonType.BUTTON_COMBO && button.status == NativeLibrary.ButtonState.PRESSED) { + var comboButtonArray = + } + */ NativeLibrary.onGamePadEvent( NativeLibrary.TouchScreenDevice, From f62a5f25104ccc6e43629d3fff1d75dddb38ef36 Mon Sep 17 00:00:00 2001 From: adas20 Date: Tue, 29 Jul 2025 14:48:23 -0400 Subject: [PATCH 16/23] Changed the combo_key string into button_combo, added functionality (impl could be better), added combo key as an input bindable setting within the buttons tab --- .../features/settings/model/Settings.kt | 7 ++- .../model/view/InputBindingSetting.kt | 2 + .../features/settings/ui/SettingsAdapter.kt | 8 ++++ .../settings/ui/SettingsFragmentPresenter.kt | 3 +- .../citra/citra_emu/overlay/InputOverlay.kt | 8 ++-- .../org/citra/citra_emu/utils/ComboHelper.kt | 47 +++++++++++++++++++ .../app/src/main/res/values/strings.xml | 2 +- 7 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt index 8d10a946c..49eb6c4b5 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt @@ -131,6 +131,7 @@ class Settings { const val KEY_BUTTON_R = "button_r" const val KEY_BUTTON_ZL = "button_zl" const val KEY_BUTTON_ZR = "button_zr" + const val KEY_BUTTON_COMBO = "button_combo" const val KEY_CIRCLEPAD_AXIS_VERTICAL = "circlepad_axis_vertical" const val KEY_CIRCLEPAD_AXIS_HORIZONTAL = "circlepad_axis_horizontal" const val KEY_CSTICK_AXIS_VERTICAL = "cstick_axis_vertical" @@ -152,7 +153,8 @@ class Settings { KEY_BUTTON_Y, KEY_BUTTON_SELECT, KEY_BUTTON_START, - KEY_BUTTON_HOME + KEY_BUTTON_HOME, + KEY_BUTTON_COMBO ) val buttonTitles = listOf( R.string.button_a, @@ -161,7 +163,8 @@ class Settings { R.string.button_y, R.string.button_select, R.string.button_start, - R.string.button_home + R.string.button_home, + R.string.button_combo ) val circlePadKeys = listOf( KEY_CIRCLEPAD_AXIS_VERTICAL, diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/InputBindingSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/InputBindingSetting.kt index 64827d89d..c10b12d7c 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/InputBindingSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/InputBindingSetting.kt @@ -123,6 +123,7 @@ class InputBindingSetting( Settings.KEY_BUTTON_SELECT -> NativeLibrary.ButtonType.BUTTON_SELECT Settings.KEY_BUTTON_START -> NativeLibrary.ButtonType.BUTTON_START Settings.KEY_BUTTON_HOME -> NativeLibrary.ButtonType.BUTTON_HOME + Settings.KEY_BUTTON_COMBO -> NativeLibrary.ButtonType.BUTTON_COMBO Settings.KEY_BUTTON_UP -> NativeLibrary.ButtonType.DPAD_UP Settings.KEY_BUTTON_DOWN -> NativeLibrary.ButtonType.DPAD_DOWN Settings.KEY_BUTTON_LEFT -> NativeLibrary.ButtonType.DPAD_LEFT @@ -277,6 +278,7 @@ class InputBindingSetting( NativeLibrary.ButtonType.BUTTON_SELECT -> Settings.KEY_BUTTON_SELECT NativeLibrary.ButtonType.BUTTON_START -> Settings.KEY_BUTTON_START NativeLibrary.ButtonType.BUTTON_HOME -> Settings.KEY_BUTTON_HOME + NativeLibrary.ButtonType.BUTTON_COMBO -> Settings.KEY_BUTTON_COMBO NativeLibrary.ButtonType.DPAD_UP -> Settings.KEY_BUTTON_UP NativeLibrary.ButtonType.DPAD_DOWN -> Settings.KEY_BUTTON_DOWN NativeLibrary.ButtonType.DPAD_LEFT -> Settings.KEY_BUTTON_LEFT diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt index a69667c5d..7e20e9e7b 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt @@ -46,6 +46,7 @@ import org.citra.citra_emu.features.settings.model.AbstractStringSetting import org.citra.citra_emu.features.settings.model.FloatSetting import org.citra.citra_emu.features.settings.model.ScaledFloatSetting import org.citra.citra_emu.features.settings.model.AbstractShortSetting +import org.citra.citra_emu.features.settings.model.Settings import org.citra.citra_emu.features.settings.model.view.DateTimeSetting import org.citra.citra_emu.features.settings.model.view.InputBindingSetting import org.citra.citra_emu.features.settings.model.view.MultiChoiceSetting @@ -745,6 +746,9 @@ class SettingsAdapter( } */ + + //TODO: Don't fully know how to grab the setting itself for the buttons so I'm adding them to a backing array to be called later + //TODO: Likely need to be reimplemented is StringMultiChoiceSetting -> { val scSetting = clickedItem as? StringMultiChoiceSetting scSetting?.let { @@ -752,16 +756,20 @@ class SettingsAdapter( is AbstractMultiStringSetting -> { val value = it.getValueAt(which) if (value in it.selectedValues && !is_checked) { + Settings.comboSelection.remove(value ?: "") it.removeSelectedValue(value ?: "") } else { + Settings.comboSelection.add(value ?: "") it.addSelectedValue(value ?: "") } } is AbstractMultiShortSetting -> { if (is_checked != it.selectValueIndices[which]) { + Settings.comboSelection.remove((it.getValueAt(which)?.toShort() ?: 1).toString()) it.removeSelectedValue(it.getValueAt(which)?.toShort() ?: 1) } else { + Settings.comboSelection.add((it.getValueAt(which)?.toShort() ?: 1).toString()) it.addSelectedValue(it.getValueAt(which)?.toShort() ?: 1) } } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt index 4c38a0fcf..d021681cb 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -34,7 +34,6 @@ import org.citra.citra_emu.features.settings.model.StringSetting import org.citra.citra_emu.features.settings.model.view.DateTimeSetting import org.citra.citra_emu.features.settings.model.view.HeaderSetting import org.citra.citra_emu.features.settings.model.view.InputBindingSetting -import org.citra.citra_emu.features.settings.model.view.MultiChoiceSetting import org.citra.citra_emu.features.settings.model.view.RunnableSetting import org.citra.citra_emu.features.settings.model.view.SettingsItem import org.citra.citra_emu.features.settings.model.view.SingleChoiceSetting @@ -821,7 +820,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) } private fun addComboButtonSettings(sl: ArrayList) { - settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.combo_key)) + settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.button_combo)) val comboSetting = object : AbstractMultiStringSetting { override var strings: MutableSet get() { diff --git a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt index 840ce45bf..1199f112b 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt @@ -26,6 +26,7 @@ import org.citra.citra_emu.NativeLibrary import org.citra.citra_emu.R import org.citra.citra_emu.utils.EmulationMenuSettings import org.citra.citra_emu.utils.TurboHelper +import org.citra.citra_emu.utils.ComboHelper import java.lang.NullPointerException import kotlin.math.min @@ -140,11 +141,10 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex else if (button.id == NativeLibrary.ButtonType.BUTTON_TURBO && button.status == NativeLibrary.ButtonState.PRESSED) { TurboHelper.toggleTurbo(true) } - /* - else if (button.id == NativeLibrary.ButtonType.BUTTON_COMBO && button.status == NativeLibrary.ButtonState.PRESSED) { - var comboButtonArray = + else if (button.id == NativeLibrary.ButtonType.BUTTON_COMBO) { + ComboHelper.comboActivate(button) } - */ + NativeLibrary.onGamePadEvent( NativeLibrary.TouchScreenDevice, diff --git a/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt b/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt new file mode 100644 index 000000000..77746d140 --- /dev/null +++ b/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt @@ -0,0 +1,47 @@ +// Copyright Citra Emulator Project / Azahar Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +package org.citra.citra_emu.utils + +import org.citra.citra_emu.CitraApplication +import org.citra.citra_emu.NativeLibrary +import org.citra.citra_emu.R +import org.citra.citra_emu.features.settings.model.BooleanSetting +import org.citra.citra_emu.features.settings.model.Settings +import org.citra.citra_emu.overlay.InputOverlayDrawableButton + +object ComboHelper { + + fun getButton(button: String): Int { + when (button) { + "A" -> return NativeLibrary.ButtonType.BUTTON_A + "B" -> return NativeLibrary.ButtonType.BUTTON_B + "X" -> return NativeLibrary.ButtonType.BUTTON_X + "Y" -> return NativeLibrary.ButtonType.BUTTON_Y + "L" -> return NativeLibrary.ButtonType.TRIGGER_L + "R" -> return NativeLibrary.ButtonType.TRIGGER_R + "ZL" -> return NativeLibrary.ButtonType.BUTTON_ZL + "ZR" -> return NativeLibrary.ButtonType.BUTTON_ZR + "START" -> return NativeLibrary.ButtonType.BUTTON_START + "SELECT" -> return NativeLibrary.ButtonType.BUTTON_SELECT + } + return -1 + } + + fun comboActivate(button: InputOverlayDrawableButton) { + var comboArray = Settings.comboSelection + for (selectedbutton in comboArray) { + var nativebutton = getButton(selectedbutton) + if (nativebutton == -1) { + println("Bad Button") + } else { + NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, nativebutton, button.status) + } + } + } + + + + +} diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index ab30d09fc..ae12566a7 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -142,6 +142,7 @@ HOME Swap Screens Turbo + Combo Key X Y L @@ -153,7 +154,6 @@ Turbo Speed Turbo Speed Enabled Turbo Speed Disabled - Combo Key Enable Combo Button Combo Key Settings Enable and Change Combo Button Bindings. From 34c470ac247394d140cb1bf5ab2e3522dd35ae87 Mon Sep 17 00:00:00 2001 From: adas20 Date: Sun, 3 Aug 2025 13:07:56 -0400 Subject: [PATCH 17/23] Moved Combo Settings into just controls instead of having its own submenu --- .../features/settings/model/Settings.kt | 1 - .../settings/ui/SettingsFragmentPresenter.kt | 66 +++++++------------ 2 files changed, 22 insertions(+), 45 deletions(-) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt index 49eb6c4b5..a530a817f 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt @@ -113,7 +113,6 @@ class Settings { const val SECTION_CUSTOM_PORTRAIT = "Custom Portrait Layout" const val SECTION_PERFORMANCE_OVERLAY = "Performance Overlay" const val SECTION_STORAGE = "Storage" - const val SECTION_COMBO = "Combo Button" const val KEY_BUTTON_A = "button_a" diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt index d021681cb..3bc96d01a 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -106,7 +106,6 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) Settings.SECTION_CUSTOM_LANDSCAPE -> addCustomLandscapeSettings(sl) Settings.SECTION_CUSTOM_PORTRAIT -> addCustomPortraitSettings(sl) Settings.SECTION_PERFORMANCE_OVERLAY -> addPerformanceOverlaySettings(sl) - Settings.SECTION_COMBO -> addComboButtonSettings(sl) else -> { fragmentView.showToastMessage("Unimplemented menu", false) return @@ -757,6 +756,26 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) private fun addControlsSettings(sl: ArrayList) { settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_controls)) + + val comboSetting = object : AbstractMultiStringSetting { + override var strings: MutableSet + get() { + return Settings.comboSelection + } + set(values) { + for (item in values) { + Settings.comboSelection.add(item) + } + } + override val key = null + override val section = null + override val isRuntimeEditable = true + override val valueAsString get() = "" + override val defaultValue = "" + } + + val buttons = settingsActivity.resources.getStringArray(R.array.n3dsButtons).take(10).toTypedArray() + sl.apply { add(HeaderSetting(R.string.generic_buttons)) Settings.buttonKeys.forEachIndexed { i: Int, key: String -> @@ -808,48 +827,6 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) BooleanSetting.USE_ARTIC_BASE_CONTROLLER.defaultValue ) ) - add( - SubmenuSetting( - R.string.combo_key_options, - R.string.combo_key_description, - R.drawable.button_combo, - Settings.SECTION_COMBO - ) - ) - } - } - - private fun addComboButtonSettings(sl: ArrayList) { - settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.button_combo)) - val comboSetting = object : AbstractMultiStringSetting { - override var strings: MutableSet - get() { - return Settings.comboSelection - } - set(values) { - for (item in values) { - Settings.comboSelection.add(item) - } - } - override val key = null - override val section = null - override val isRuntimeEditable = true - override val valueAsString get() = "" - override val defaultValue = "" - } - - val buttons = settingsActivity.resources.getStringArray(R.array.n3dsButtons).take(10).toTypedArray() - - sl.apply { - add( - SwitchSetting( - BooleanSetting.ENABLE_COMBO_KEY, - R.string.combo_key_enable, - R.string.combo_key_submenu_description, - BooleanSetting.ENABLE_COMBO_KEY.key, - BooleanSetting.ENABLE_COMBO_KEY.defaultValue, - ) - ) add( StringMultiChoiceSetting( comboSetting, @@ -860,9 +837,10 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) ) ) } - } + + private fun getInputObject(key: String): AbstractStringSetting { return object : AbstractStringSetting { override var string: String From 5339a46ba27c1ff3051d944b9d33b88df3d9cec9 Mon Sep 17 00:00:00 2001 From: adas20 Date: Mon, 4 Aug 2025 15:10:38 -0400 Subject: [PATCH 18/23] Made ComboHelper code more readable and added the key setting to be toggleable in game --- .../citra/citra_emu/fragments/EmulationFragment.kt | 9 +++++++-- .../java/org/citra/citra_emu/overlay/InputOverlay.kt | 2 +- .../java/org/citra/citra_emu/utils/ComboHelper.kt | 12 ++++++------ .../app/src/main/res/menu/menu_overlay_options.xml | 3 +++ src/android/app/src/main/res/values/arrays.xml | 1 + 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/citra/citra_emu/fragments/EmulationFragment.kt index fbf3e5525..55646f035 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/fragments/EmulationFragment.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/fragments/EmulationFragment.kt @@ -785,6 +785,11 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram true } + R.id.menu_emulation_adjust_scale_button_combo -> { + showAdjustScaleDialog("controlScale-" + NativeLibrary.ButtonType.BUTTON_COMBO) + true + } + R.id.menu_emulation_adjust_opacity -> { showAdjustOpacityDialog() true @@ -1002,12 +1007,12 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram private fun showToggleControlsDialog() { val editor = preferences.edit() - val enabledButtons = BooleanArray(16) + val enabledButtons = BooleanArray(17) enabledButtons.forEachIndexed { i: Int, _: Boolean -> // Buttons that are disabled by default var defaultValue = true when (i) { - 6, 7, 12, 13, 14, 15 -> defaultValue = false + 6, 7, 12, 13, 14, 15, 16 -> defaultValue = false } enabledButtons[i] = preferences.getBoolean("buttonToggle$i", defaultValue) } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt index 1199f112b..4f5fddf96 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt @@ -548,7 +548,7 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex ) } - if (preferences.getBoolean("buttonToggle16", true)) { + if (preferences.getBoolean("buttonToggle16", false)) { overlayButtons.add( initializeOverlayButton( context, diff --git a/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt b/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt index 77746d140..80fbf97af 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt @@ -4,10 +4,7 @@ package org.citra.citra_emu.utils -import org.citra.citra_emu.CitraApplication import org.citra.citra_emu.NativeLibrary -import org.citra.citra_emu.R -import org.citra.citra_emu.features.settings.model.BooleanSetting import org.citra.citra_emu.features.settings.model.Settings import org.citra.citra_emu.overlay.InputOverlayDrawableButton @@ -33,10 +30,13 @@ object ComboHelper { var comboArray = Settings.comboSelection for (selectedbutton in comboArray) { var nativebutton = getButton(selectedbutton) - if (nativebutton == -1) { + if (nativebutton == -1) + { println("Bad Button") - } else { - NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, nativebutton, button.status) + } + else + { + NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, nativebutton, button.status) } } } diff --git a/src/android/app/src/main/res/menu/menu_overlay_options.xml b/src/android/app/src/main/res/menu/menu_overlay_options.xml index 8bb19ee26..34589ebc3 100644 --- a/src/android/app/src/main/res/menu/menu_overlay_options.xml +++ b/src/android/app/src/main/res/menu/menu_overlay_options.xml @@ -79,6 +79,9 @@ + diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index 543b59913..92e549620 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -167,6 +167,7 @@ @string/button_home @string/button_swap @string/button_turbo + @string/button_combo From 3b62a383f66eeb93e880948abaff094b042cca5c Mon Sep 17 00:00:00 2001 From: adas20 Date: Wed, 6 Aug 2025 15:51:56 -0400 Subject: [PATCH 19/23] Edited Layout integers of combo button. Made Combo Button display properly in normal portrait mode. --- .../main/java/org/citra/citra_emu/overlay/InputOverlay.kt | 4 ++-- src/android/app/src/main/res/values/integers.xml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt index 4f5fddf96..0d3505b80 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt @@ -933,11 +933,11 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex ) .putFloat( NativeLibrary.ButtonType.BUTTON_COMBO.toString() + portrait + "-X", - resources.getInteger(R.integer.N3DS_BUTTON_COMBO_X).toFloat() / 1000 * maxX + resources.getInteger(R.integer.N3DS_BUTTON_COMBO_PORTRAIT_X).toFloat() / 1000 * maxX ) .putFloat( NativeLibrary.ButtonType.BUTTON_COMBO.toString() + portrait + "-Y", - resources.getInteger(R.integer.N3DS_BUTTON_COMBO_Y).toFloat() / 1000 * maxY + resources.getInteger(R.integer.N3DS_BUTTON_COMBO_PORTRAIT_Y).toFloat() / 1000 * maxY ) .apply() } diff --git a/src/android/app/src/main/res/values/integers.xml b/src/android/app/src/main/res/values/integers.xml index 133b4d16f..0c091a48b 100644 --- a/src/android/app/src/main/res/values/integers.xml +++ b/src/android/app/src/main/res/values/integers.xml @@ -35,8 +35,8 @@ 850 630 850 - 750 - 800 + 740 + 480 810 @@ -71,7 +71,7 @@ 675 453 720 - 460 - 550 + 445 + 925 From 4baecabd8c53f895e36791d9f8d61b19b8741242 Mon Sep 17 00:00:00 2001 From: ADAS2024 Date: Wed, 4 Mar 2026 15:59:05 -0500 Subject: [PATCH 20/23] Code Cleanup and Start of Reimplementation based off #1430 --- ...FloatSetting.kt => AbstractListSetting.kt} | 6 +- .../model/AbstractMultiBooleanSetting.kt | 9 --- .../settings/model/StringListSetting.kt | 39 ++++++++++ .../settings/model/view/MultiChoiceSetting.kt | 75 ------------------- .../model/view/StringMultiChoiceSetting.kt | 1 + .../features/settings/ui/SettingsAdapter.kt | 61 ++------------- ...lder.kt => StringMultiChoiceViewHolder.kt} | 21 +----- .../features/settings/utils/SettingsFile.kt | 6 ++ 8 files changed, 58 insertions(+), 160 deletions(-) rename src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/{AbstractMultiFloatSetting.kt => AbstractListSetting.kt} (68%) delete mode 100644 src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiBooleanSetting.kt create mode 100644 src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/StringListSetting.kt delete mode 100644 src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt rename src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/{MultiChoiceViewHolder.kt => StringMultiChoiceViewHolder.kt} (74%) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiFloatSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractListSetting.kt similarity index 68% rename from src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiFloatSetting.kt rename to src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractListSetting.kt index 2d9d92873..25a7338fe 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiFloatSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractListSetting.kt @@ -4,6 +4,6 @@ package org.citra.citra_emu.features.settings.model -interface AbstractMultiFloatSetting : AbstractSetting { - var floats: MutableSet -} +interface AbstractListSetting : AbstractSetting { + var list: List +} \ No newline at end of file diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiBooleanSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiBooleanSetting.kt deleted file mode 100644 index 2b3f2e1fc..000000000 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiBooleanSetting.kt +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright Citra Emulator Project / Azahar Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -package org.citra.citra_emu.features.settings.model - -interface AbstractMultiBooleanSetting : AbstractSetting { - var booleans: MutableSet -} diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/StringListSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/StringListSetting.kt new file mode 100644 index 000000000..12f8d77f6 --- /dev/null +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/StringListSetting.kt @@ -0,0 +1,39 @@ +// Copyright Citra Emulator Project / Azahar Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +package org.citra.citra_emu.features.settings.model + +enum class StringListSetting( + override val key: String, + override val section: String, + override val defaultValue: List +) : AbstractListSetting { + COMBO_KEY_LIST("combo_key_list", Settings.SECTION_CONTROLS, listOf("A", "B", "X", "Y", "L", "R", "ZL", "ZR", "Start", "Select")); + + override var list: List = defaultValue + + override val valueAsString: String + get() = list.joinToString() + + + override val isRuntimeEditable: Boolean + get() { + for (setting in NOT_RUNTIME_EDITABLE) { + if (setting == this) { + return false + } + } + return true + } + + companion object { + private val NOT_RUNTIME_EDITABLE:List = listOf(); + + + fun from(key: String): StringListSetting? = + values().firstOrNull { it.key == key } + + fun clear() = values().forEach { it.list = it.defaultValue } + } +} \ No newline at end of file diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt deleted file mode 100644 index b8cfe41f6..000000000 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/MultiChoiceSetting.kt +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright Citra Emulator Project / Azahar Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -package org.citra.citra_emu.features.settings.model.view - -import org.citra.citra_emu.features.settings.model.AbstractMultiIntSetting -import org.citra.citra_emu.features.settings.model.AbstractSetting -import org.citra.citra_emu.features.settings.model.AbstractMultiShortSetting -import org.citra.citra_emu.features.settings.model.AbstractIntSetting -import org.citra.citra_emu.features.settings.model.AbstractShortSetting - -class MultiChoiceSetting( - setting: AbstractSetting?, - titleId: Int, - descriptionId: Int, - val choicesId: Int, - val valuesId: Int, - val key: String? = null, - val defaultValues: List? = null, - override var isEnabled: Boolean = true -) : SettingsItem(setting, titleId, descriptionId) { - override val type = TYPE_MULTI_CHOICE - - val selectedValues: List - get() { - if (setting == null) { - return defaultValues!! - } - - try { - val setting = setting as AbstractMultiIntSetting - return setting.ints.toList() - } catch (_: ClassCastException) { - } - - try { - val setting = setting as AbstractMultiShortSetting - return setting.shorts.map { it.toInt() } - } catch (_: ClassCastException) { - } - - return defaultValues!! - } - - /** - * Add values to multi choice backing mutable sets. - * - * @param selection New value of the int. - * @return the existing setting with the new value added. - */ - fun addSelectedValue(selection: Int): AbstractMultiIntSetting { - val intSetting = setting as AbstractMultiIntSetting - intSetting.ints.add(selection) - return intSetting - } - - fun addSelectedValue(selection: Short): AbstractMultiShortSetting { - val shortSetting = setting as AbstractMultiShortSetting - shortSetting.shorts.add(selection) - return shortSetting - } - - fun removeSelectedValue(selection: Int): AbstractMultiIntSetting { - val intSetting = setting as AbstractMultiIntSetting - intSetting.ints.remove(selection) - return intSetting - } - - fun removeSelectedValue(selection: Short): AbstractMultiShortSetting { - val shortSetting = setting as AbstractMultiShortSetting - shortSetting.shorts.remove(selection) - return shortSetting - } -} diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt index 8330ed186..f99b2719c 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt @@ -7,6 +7,7 @@ package org.citra.citra_emu.features.settings.model.view import org.citra.citra_emu.features.settings.model.AbstractSetting import org.citra.citra_emu.features.settings.model.AbstractMultiShortSetting import org.citra.citra_emu.features.settings.model.AbstractMultiStringSetting +import org.citra.citra_emu.features.settings.model.StringListSetting class StringMultiChoiceSetting( setting: AbstractSetting?, diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt index 13476ae24..73006bb81 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt @@ -38,7 +38,6 @@ import org.citra.citra_emu.databinding.ListItemSettingsHeaderBinding import org.citra.citra_emu.features.settings.model.AbstractBooleanSetting import org.citra.citra_emu.features.settings.model.AbstractFloatSetting import org.citra.citra_emu.features.settings.model.AbstractIntSetting -import org.citra.citra_emu.features.settings.model.AbstractMultiIntSetting import org.citra.citra_emu.features.settings.model.AbstractMultiShortSetting import org.citra.citra_emu.features.settings.model.AbstractMultiStringSetting import org.citra.citra_emu.features.settings.model.AbstractSetting @@ -49,7 +48,6 @@ import org.citra.citra_emu.features.settings.model.AbstractShortSetting import org.citra.citra_emu.features.settings.model.Settings import org.citra.citra_emu.features.settings.model.view.DateTimeSetting import org.citra.citra_emu.features.settings.model.view.InputBindingSetting -import org.citra.citra_emu.features.settings.model.view.MultiChoiceSetting import org.citra.citra_emu.features.settings.model.view.SettingsItem import org.citra.citra_emu.features.settings.model.view.SingleChoiceSetting import org.citra.citra_emu.features.settings.model.view.SliderSetting @@ -61,7 +59,7 @@ import org.citra.citra_emu.features.settings.model.view.SwitchSetting import org.citra.citra_emu.features.settings.ui.viewholder.DateTimeViewHolder import org.citra.citra_emu.features.settings.ui.viewholder.HeaderViewHolder import org.citra.citra_emu.features.settings.ui.viewholder.InputBindingSettingViewHolder -import org.citra.citra_emu.features.settings.ui.viewholder.MultiChoiceViewHolder +import org.citra.citra_emu.features.settings.ui.viewholder.StringMultiChoiceViewHolder import org.citra.citra_emu.features.settings.ui.viewholder.RunnableViewHolder import org.citra.citra_emu.features.settings.ui.viewholder.SettingViewHolder import org.citra.citra_emu.features.settings.ui.viewholder.SingleChoiceViewHolder @@ -136,7 +134,7 @@ class SettingsAdapter( } SettingsItem.TYPE_MULTI_CHOICE, SettingsItem.TYPE_STRING_MULTI_CHOICE -> { - MultiChoiceViewHolder(ListItemSettingBinding.inflate(inflater), this) + StringMultiChoiceViewHolder(ListItemSettingBinding.inflate(inflater), this) } else -> { @@ -207,6 +205,9 @@ class SettingsAdapter( SettingsItem.TYPE_STRING_INPUT -> { (oldItem as StringInputSetting).isEnabled == (newItem as StringInputSetting).isEnabled } + SettingsItem.TYPE_STRING_MULTI_CHOICE -> { + (oldItem as StringMultiChoiceSetting).isEnabled == (newItem as StringMultiChoiceSetting).isEnabled + } else -> { oldItem == newItem } @@ -659,55 +660,7 @@ class SettingsAdapter( return -1 } - private fun getSelectionForMultiChoiceValues(item: MultiChoiceSetting): BooleanArray { - val checked_values = mutableListOf() - val values = item.selectedValues - val valuesId = item.valuesId - if (valuesId > 0) { - val valuesArray = context.resources.getIntArray(valuesId) - for (index in valuesArray.indices) { - val current = valuesArray[index] - if (current in values) { - checked_values.add(true) - } else { - checked_values.add(false) - } - } - } - if (checked_values == null) { - return booleanArrayOf(false) - } else { - return checked_values.toBooleanArray() - } - } - // TODO: Part of MultiChoice Impl - /* - private fun getValueForMultiChoiceSelection(item: MultiChoiceSetting, which: Int, is_checked: Boolean): Int { - val valuesId = item.valuesId - if (valuesId > 0) { - val valuesArray = context.resources.getIntArray(valuesId) - if (is_checked) { - return valuesArray[which] - } - } - return which - } - */ - - private fun onMultiChoiceClick(item: MultiChoiceSetting) { - clickedItem = item - val values = getSelectionForMultiChoiceValues(item) - dialog = MaterialAlertDialogBuilder(context) - .setTitle(item.nameId) - .setMultiChoiceItems(item.choicesId, values, this) - .show() - } - - fun onMultiChoiceClick(item: MultiChoiceSetting, position: Int) { - clickedPosition = position - onMultiChoiceClick(item) - } private fun onStringMultiChoiceClick(item: StringMultiChoiceSetting) { clickedItem = item @@ -765,8 +718,8 @@ class SettingsAdapter( //TODO: Don't fully know how to grab the setting itself for the buttons so I'm adding them to a backing array to be called later //TODO: Likely need to be reimplemented is StringMultiChoiceSetting -> { - val scSetting = clickedItem as? StringMultiChoiceSetting - scSetting?.let { + val mcSetting = clickedItem as? StringMultiChoiceSetting + mcSetting?.let { val setting = when (it.setting) { is AbstractMultiStringSetting -> { val value = it.getValueAt(which) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/MultiChoiceViewHolder.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/StringMultiChoiceViewHolder.kt similarity index 74% rename from src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/MultiChoiceViewHolder.kt rename to src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/StringMultiChoiceViewHolder.kt index 76fe809fc..35d4d6e79 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/MultiChoiceViewHolder.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/StringMultiChoiceViewHolder.kt @@ -6,12 +6,11 @@ package org.citra.citra_emu.features.settings.ui.viewholder import android.view.View import org.citra.citra_emu.databinding.ListItemSettingBinding -import org.citra.citra_emu.features.settings.model.view.MultiChoiceSetting import org.citra.citra_emu.features.settings.model.view.SettingsItem import org.citra.citra_emu.features.settings.model.view.StringMultiChoiceSetting import org.citra.citra_emu.features.settings.ui.SettingsAdapter -class MultiChoiceViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) : +class StringMultiChoiceViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) : SettingViewHolder(binding.root, adapter) { private lateinit var setting: SettingsItem @@ -40,16 +39,6 @@ class MultiChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Settin private fun getTextSetting(): String { when (val item = setting) { - is MultiChoiceSetting -> { - val resMgr = binding.textSettingDescription.context.resources - val values = resMgr.getIntArray(item.valuesId) - values.forEachIndexed { i: Int, value: Int -> - if (value in (setting as MultiChoiceSetting).selectedValues) { - return resMgr.getStringArray(item.choicesId)[i] - } - } - return "" - } is StringMultiChoiceSetting -> { item.values?.forEachIndexed { i: Int, value: String -> @@ -69,13 +58,7 @@ class MultiChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Settin adapter.onClickDisabledSetting(!setting.isEditable) return } - - if (setting is MultiChoiceSetting) { - adapter.onMultiChoiceClick( - (setting as MultiChoiceSetting), - bindingAdapterPosition - ) - } else if (setting is StringMultiChoiceSetting) { + if (setting is StringMultiChoiceSetting) { adapter.onStringMultiChoiceClick( (setting as StringMultiChoiceSetting), bindingAdapterPosition diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/utils/SettingsFile.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/utils/SettingsFile.kt index dec3e4e0a..ba94a6a1a 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/utils/SettingsFile.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/utils/SettingsFile.kt @@ -16,6 +16,7 @@ import org.citra.citra_emu.features.settings.model.IntSetting import org.citra.citra_emu.features.settings.model.ScaledFloatSetting import org.citra.citra_emu.features.settings.model.SettingSection import org.citra.citra_emu.features.settings.model.Settings.SettingsSectionMap +import org.citra.citra_emu.features.settings.model.StringListSetting import org.citra.citra_emu.features.settings.model.StringSetting import org.citra.citra_emu.features.settings.ui.SettingsActivityView import org.citra.citra_emu.utils.BiMap @@ -255,6 +256,11 @@ object SettingsFile { return stringSetting } + val stringListSetting = StringListSetting.from(key) + if (stringListSetting != null) { + stringListSetting.list = value.split(", ").map { it } + } + return null } From 13e80ec1fe49a373af5cb47690cbeddaaf4dc344 Mon Sep 17 00:00:00 2001 From: ADAS2024 Date: Sun, 29 Mar 2026 14:54:22 -0400 Subject: [PATCH 21/23] Progress commit for better impl, need to have the pop up menu show up to select buttons --- .../settings/model/AbstractMultiIntSetting.kt | 9 -- .../model/AbstractMultiShortSetting.kt | 9 -- .../settings/model/StringListSetting.kt | 19 +++- .../model/view/StringMultiChoiceSetting.kt | 70 ++------------- .../features/settings/ui/SettingsAdapter.kt | 89 ++++++++++++++++--- .../settings/ui/SettingsFragmentPresenter.kt | 31 ++----- .../ui/viewholder/MultiChoiceViewHolder.kt | 17 ++++ .../viewholder/StringMultiChoiceViewHolder.kt | 77 ---------------- .../org/citra/citra_emu/utils/ComboHelper.kt | 12 +-- 9 files changed, 134 insertions(+), 199 deletions(-) delete mode 100644 src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiIntSetting.kt delete mode 100644 src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiShortSetting.kt delete mode 100644 src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/StringMultiChoiceViewHolder.kt diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiIntSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiIntSetting.kt deleted file mode 100644 index 0c916bab7..000000000 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiIntSetting.kt +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright Citra Emulator Project / Azahar Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -package org.citra.citra_emu.features.settings.model - -interface AbstractMultiIntSetting : AbstractSetting { - var ints: MutableSet -} diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiShortSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiShortSetting.kt deleted file mode 100644 index acbc7b7a2..000000000 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiShortSetting.kt +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright Citra Emulator Project / Azahar Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -package org.citra.citra_emu.features.settings.model - -interface AbstractMultiShortSetting : AbstractSetting { - var shorts: MutableSet -} diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/StringListSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/StringListSetting.kt index 12f8d77f6..dd12c54dc 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/StringListSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/StringListSetting.kt @@ -7,11 +7,24 @@ package org.citra.citra_emu.features.settings.model enum class StringListSetting( override val key: String, override val section: String, - override val defaultValue: List + override val defaultValue: List, + val canBeEmpty: Boolean = true ) : AbstractListSetting { - COMBO_KEY_LIST("combo_key_list", Settings.SECTION_CONTROLS, listOf("A", "B", "X", "Y", "L", "R", "ZL", "ZR", "Start", "Select")); + COMBO_KEYS("combo_keys", Settings.SECTION_CONTROLS, listOf("A", "B", "X", "Y", "L", "R", "ZL", "ZR", "Start", "Select")); - override var list: List = defaultValue + private var backingList: List = defaultValue + private var lastValidList : List = defaultValue + + override var list: List + get() = backingList + set(value) { + if (!canBeEmpty && value.isEmpty()) { + backingList = lastValidList + } else { + backingList = value + lastValidList = value + } + } override val valueAsString: String get() = list.joinToString() diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt index f99b2719c..b6dd0a8a9 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt @@ -3,12 +3,8 @@ // Refer to the license.txt file included. package org.citra.citra_emu.features.settings.model.view - import org.citra.citra_emu.features.settings.model.AbstractSetting -import org.citra.citra_emu.features.settings.model.AbstractMultiShortSetting -import org.citra.citra_emu.features.settings.model.AbstractMultiStringSetting import org.citra.citra_emu.features.settings.model.StringListSetting - class StringMultiChoiceSetting( setting: AbstractSetting?, titleId: Int, @@ -29,77 +25,29 @@ class StringMultiChoiceSetting( "" } } - val selectedValues: List get() { if (setting == null) { return defaultValue!! } - try { - val setting = setting as AbstractMultiStringSetting - return setting.strings.toList() - } catch (_: ClassCastException) { - } - - try { - val setting = setting as AbstractMultiShortSetting - return setting.shorts.map { it.toString() } - } catch (_: ClassCastException) { + val setting = setting as StringListSetting + return setting.list + }catch (_: ClassCastException) { } return defaultValue!! } - val selectValueIndices: BooleanArray - get() { - val noneList = values?.let { - ArrayList(BooleanArray(it.size) { false }.toList()) - } ?: ArrayList() - - val chosenindices = mutableListOf() - val selectedValues = selectedValues - for (i in values!!.indices) { - if (values[i] in selectedValues) { - chosenindices.add(true) - } else { - chosenindices.add(false) - } - } - if (chosenindices == null) { - return noneList.toBooleanArray() - } else { - return chosenindices.toBooleanArray() - } - - } - /** - * Add values to multi choice through the backing mutable sets. + * Write a value to the backing list. If that list was previously null, + * initializes a new one and returns it, so it can be added to the Hashmap. * * @param selection New value of the int. - * @return the existing setting with the new value added. + * @return the existing setting with the new value applied. */ - fun addSelectedValue(selection: String): AbstractMultiStringSetting { - val stringSetting = setting as AbstractMultiStringSetting - stringSetting.strings.add(selection) + fun setSelectedValue(selection: List): StringListSetting { + val stringSetting = setting as StringListSetting + stringSetting.list = selection return stringSetting } - - fun addSelectedValue(selection: Short): AbstractMultiShortSetting { - val shortSetting = setting as AbstractMultiShortSetting - shortSetting.shorts.add(selection) - return shortSetting - } - - fun removeSelectedValue(selection: String): AbstractMultiStringSetting { - val stringSetting = setting as AbstractMultiStringSetting - stringSetting.strings.remove(selection) - return stringSetting - } - - fun removeSelectedValue(selection: Short): AbstractMultiShortSetting { - val shortSetting = setting as AbstractMultiShortSetting - shortSetting.shorts.remove(selection) - return shortSetting - } } \ No newline at end of file diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt index 5673d4e9c..dc07fd209 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt @@ -38,7 +38,6 @@ import org.citra.citra_emu.databinding.ListItemSettingsHeaderBinding import org.citra.citra_emu.features.settings.model.AbstractBooleanSetting import org.citra.citra_emu.features.settings.model.AbstractFloatSetting import org.citra.citra_emu.features.settings.model.AbstractIntSetting -import org.citra.citra_emu.features.settings.model.AbstractMultiShortSetting import org.citra.citra_emu.features.settings.model.AbstractMultiStringSetting import org.citra.citra_emu.features.settings.model.AbstractSetting import org.citra.citra_emu.features.settings.model.AbstractStringSetting @@ -61,7 +60,6 @@ import org.citra.citra_emu.features.settings.model.view.SwitchSetting import org.citra.citra_emu.features.settings.ui.viewholder.DateTimeViewHolder import org.citra.citra_emu.features.settings.ui.viewholder.HeaderViewHolder import org.citra.citra_emu.features.settings.ui.viewholder.InputBindingSettingViewHolder -import org.citra.citra_emu.features.settings.ui.viewholder.StringMultiChoiceViewHolder // TODO: Remove and integrate within MultiChoiceViewHolder import org.citra.citra_emu.features.settings.ui.viewholder.MultiChoiceViewHolder import org.citra.citra_emu.features.settings.ui.viewholder.RunnableViewHolder import org.citra.citra_emu.features.settings.ui.viewholder.SettingViewHolder @@ -143,7 +141,7 @@ class SettingsAdapter( } SettingsItem.TYPE_MULTI_CHOICE, SettingsItem.TYPE_STRING_MULTI_CHOICE -> { - StringMultiChoiceViewHolder(ListItemSettingBinding.inflate(inflater), this) + MultiChoiceViewHolder(ListItemSettingBinding.inflate(inflater), this) } else -> { @@ -285,6 +283,26 @@ class SettingsAdapter( onMultiChoiceClick(item) } + private fun onStringMultiChoiceClick(item: StringMultiChoiceSetting) { + clickedItem = item + val values: BooleanArray = getSelectionForStringMultiChoiceValue(item); + dialog = MaterialAlertDialogBuilder(context) + .setTitle(item.nameId) + .setMultiChoiceItems(item.choices, values, this) + .setOnDismissListener { + if (clickedPosition != -1) { + notifyItemChanged(clickedPosition) + clickedPosition = -1 + } + } + .show() + } + + fun onStringMultiChoiceClick(item: StringMultiChoiceSetting, position: Int) { + clickedPosition = position + onStringMultiChoiceClick(item) + } + private fun onStringSingleChoiceClick(item: StringSingleChoiceSetting) { clickedItem = item dialog = context?.let { @@ -585,15 +603,34 @@ class SettingsAdapter( //onclick for multichoice override fun onClick(dialog: DialogInterface?, which: Int, isChecked: Boolean) { - val mcsetting = clickedItem as? MultiChoiceSetting - mcsetting?.let { - val value = getValueForMultiChoiceSelection(it, which) - if (it.selectedValues.contains(value) != isChecked) { - val setting = it.setSelectedValue((if (isChecked) it.selectedValues + value else it.selectedValues - value).sorted()) - fragmentView?.putSetting(setting) - fragmentView?.onSettingChanged() + when (clickedItem) { + is MultiChoiceSetting -> { + val mcsetting = clickedItem as? MultiChoiceSetting + mcsetting?.let { + val value = getValueForMultiChoiceSelection(it, which) + if (it.selectedValues.contains(value) != isChecked) { + val setting = + it.setSelectedValue((if (isChecked) it.selectedValues + value else it.selectedValues - value).sorted()) + fragmentView?.putSetting(setting) + fragmentView?.onSettingChanged() + } + fragmentView.loadSettingsList() + } + } + + is StringMultiChoiceSetting -> { + val mcsetting = clickedItem as? StringMultiChoiceSetting + mcsetting?.let { + val value = it.getValueAt(which) + if (it.selectedValues.contains(value) != isChecked) { + val setting = + it.setSelectedValue((if (isChecked) it.selectedValues + value.toString() else it.selectedValues - value.toString()).sorted()) + fragmentView?.putSetting(setting) + fragmentView?.onSettingChanged() + } + fragmentView.loadSettingsList() + } } - fragmentView.loadSettingsList() } } @@ -728,6 +765,7 @@ class SettingsAdapter( } } + private fun getSelectionForSingleChoiceValue(item: SingleChoiceSetting): Int { val value = item.selectedValue val valuesId = item.valuesId @@ -760,8 +798,33 @@ class SettingsAdapter( } return BooleanArray(1){false}; } - + + //TODO: Properly Implement in line with string single choice + private fun getSelectionForStringMultiChoiceValue(item: StringMultiChoiceSetting): BooleanArray { + val values = item.selectedValues; + val available_values = item.values; + val res = BooleanArray(available_values?.size ?: 0){false} + var index = 0; + + if (available_values != null) { + for (choice_val in available_values) { + if (values.contains(choice_val)) { + res[index] = true; + index++; + } + } + } + return if (res.isNotEmpty()) { + res; + } else { + BooleanArray(1) { false }; + } + } + + + //TODO: I only added MultiChoice for fleshing out backend, debating whether to remove MultiChoiceSetting and related code for cleaning up + /* override fun onClick(dialog: DialogInterface?, which: Int, is_checked: Boolean) { when (clickedItem) { /* @@ -836,4 +899,6 @@ class SettingsAdapter( } } } + + */ } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt index 1747a2df6..290cdffd7 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -22,7 +22,6 @@ import org.citra.citra_emu.display.StereoMode import org.citra.citra_emu.display.StereoWhichDisplay import org.citra.citra_emu.features.settings.model.AbstractBooleanSetting import org.citra.citra_emu.features.settings.model.AbstractIntSetting -import org.citra.citra_emu.features.settings.model.AbstractMultiStringSetting import org.citra.citra_emu.features.settings.model.AbstractSetting import org.citra.citra_emu.features.settings.model.AbstractShortSetting import org.citra.citra_emu.features.settings.model.AbstractStringSetting @@ -32,6 +31,7 @@ import org.citra.citra_emu.features.settings.model.IntSetting import org.citra.citra_emu.features.settings.model.IntListSetting import org.citra.citra_emu.features.settings.model.ScaledFloatSetting import org.citra.citra_emu.features.settings.model.Settings +import org.citra.citra_emu.features.settings.model.StringListSetting import org.citra.citra_emu.features.settings.model.StringSetting import org.citra.citra_emu.features.settings.model.view.DateTimeSetting import org.citra.citra_emu.features.settings.model.view.HeaderSetting @@ -781,25 +781,6 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) private fun addControlsSettings(sl: ArrayList) { settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_controls)) - val comboSetting = object : AbstractMultiStringSetting { - override var strings: MutableSet - get() { - return Settings.comboSelection - } - set(values) { - for (item in values) { - Settings.comboSelection.add(item) - } - } - override val key = null - override val section = null - override val isRuntimeEditable = true - override val valueAsString get() = "" - override val defaultValue = "" - } - - val buttons = settingsActivity.resources.getStringArray(R.array.n3dsButtons).take(10).toTypedArray() - sl.apply { add( RunnableSetting( @@ -861,13 +842,17 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) BooleanSetting.USE_ARTIC_BASE_CONTROLLER.defaultValue ) ) + + val buttons = settingsActivity.resources.getStringArray(R.array.n3dsButtons).take(10).toTypedArray() add( StringMultiChoiceSetting( - comboSetting, + StringListSetting.COMBO_KEYS, R.string.combo_key_options, - 0, + R.string.combo_key_description, buttons, - buttons + buttons, + StringListSetting.COMBO_KEYS.key, + StringListSetting.COMBO_KEYS.defaultValue ) ) } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/MultiChoiceViewHolder.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/MultiChoiceViewHolder.kt index 8493115a4..4e59ed984 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/MultiChoiceViewHolder.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/MultiChoiceViewHolder.kt @@ -8,6 +8,7 @@ import android.view.View import org.citra.citra_emu.databinding.ListItemSettingBinding import org.citra.citra_emu.features.settings.model.view.SettingsItem import org.citra.citra_emu.features.settings.model.view.MultiChoiceSetting +import org.citra.citra_emu.features.settings.model.view.StringMultiChoiceSetting import org.citra.citra_emu.features.settings.ui.SettingsAdapter class MultiChoiceViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) : @@ -51,6 +52,16 @@ class MultiChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Settin return resList.joinToString(); } + is StringMultiChoiceSetting -> { + var resList:List = emptyList(); + item.values?.forEachIndexed { i: Int, value: String -> + if (value in item.selectedValues) { + resList = resList + item.choices[i] + } + } + return resList.joinToString() + } + else -> return "" } } @@ -67,6 +78,12 @@ class MultiChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Settin bindingAdapterPosition ) } + if (setting is StringMultiChoiceSetting) { + adapter.onStringMultiChoiceClick( + (setting as StringMultiChoiceSetting), + bindingAdapterPosition + ) + } } override fun onLongClick(clicked: View): Boolean { diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/StringMultiChoiceViewHolder.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/StringMultiChoiceViewHolder.kt deleted file mode 100644 index 35d4d6e79..000000000 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/StringMultiChoiceViewHolder.kt +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright Citra Emulator Project / Azahar Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -package org.citra.citra_emu.features.settings.ui.viewholder - -import android.view.View -import org.citra.citra_emu.databinding.ListItemSettingBinding -import org.citra.citra_emu.features.settings.model.view.SettingsItem -import org.citra.citra_emu.features.settings.model.view.StringMultiChoiceSetting -import org.citra.citra_emu.features.settings.ui.SettingsAdapter - -class StringMultiChoiceViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) : - SettingViewHolder(binding.root, adapter) { - private lateinit var setting: SettingsItem - - override fun bind(item: SettingsItem) { - setting = item - binding.textSettingName.setText(item.nameId) - if (item.descriptionId != 0) { - binding.textSettingDescription.visibility = View.VISIBLE - binding.textSettingDescription.setText(item.descriptionId) - } else { - binding.textSettingDescription.visibility = View.GONE - } - binding.textSettingValue.visibility = View.VISIBLE - binding.textSettingValue.text = getTextSetting() - - if (setting.isActive) { - binding.textSettingName.alpha = 1f - binding.textSettingDescription.alpha = 1f - binding.textSettingValue.alpha = 1f - } else { - binding.textSettingName.alpha = 0.5f - binding.textSettingDescription.alpha = 0.5f - binding.textSettingValue.alpha = 0.5f - } - } - - private fun getTextSetting(): String { - when (val item = setting) { - - is StringMultiChoiceSetting -> { - item.values?.forEachIndexed { i: Int, value: String -> - if (value in item.selectedValues) { - return item.choices[i] - } - } - return "" - } - - else -> return "" - } - } - - override fun onClick(clicked: View) { - if (!setting.isEditable || !setting.isEnabled) { - adapter.onClickDisabledSetting(!setting.isEditable) - return - } - if (setting is StringMultiChoiceSetting) { - adapter.onStringMultiChoiceClick( - (setting as StringMultiChoiceSetting), - bindingAdapterPosition - ) - } - } - - override fun onLongClick(clicked: View): Boolean { - if (setting.isActive) { - return adapter.onLongClick(setting.setting!!, bindingAdapterPosition) - } else { - adapter.onClickDisabledSetting(!setting.isEditable) - } - return false - } -} \ No newline at end of file diff --git a/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt b/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt index 80fbf97af..29400e7cd 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt @@ -7,6 +7,7 @@ package org.citra.citra_emu.utils import org.citra.citra_emu.NativeLibrary import org.citra.citra_emu.features.settings.model.Settings import org.citra.citra_emu.overlay.InputOverlayDrawableButton +import org.citra.citra_emu.features.settings.model.StringListSetting object ComboHelper { @@ -27,16 +28,17 @@ object ComboHelper { } fun comboActivate(button: InputOverlayDrawableButton) { - var comboArray = Settings.comboSelection - for (selectedbutton in comboArray) { - var nativebutton = getButton(selectedbutton) - if (nativebutton == -1) + var comboArray = StringListSetting.COMBO_KEYS.list + for (selected_button in comboArray) { + var native_button = getButton(selected_button) + if (native_button == -1) { + //TODO: Need proper error handling here println("Bad Button") } else { - NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, nativebutton, button.status) + NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, native_button, button.status) } } } From 244a1e1fdf50ffccccf2154529237766b918ddb5 Mon Sep 17 00:00:00 2001 From: ADAS2024 Date: Sun, 29 Mar 2026 15:53:46 -0400 Subject: [PATCH 22/23] Code cleanup and bug fix to properly map values. --- .../features/settings/model/Settings.kt | 2 - .../features/settings/ui/SettingsAdapter.kt | 89 +------------------ .../org/citra/citra_emu/utils/ComboHelper.kt | 1 - 3 files changed, 4 insertions(+), 88 deletions(-) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt index 5572e1941..70056503b 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/Settings.kt @@ -228,8 +228,6 @@ class Settings { R.string.turbo_limit_hotkey ) - val comboSelection = mutableSetOf() - // TODO: Move these in with the other setting keys in GenerateSettingKeys.cmake const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch" const val PREF_MATERIAL_YOU = "MaterialYouTheme" diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt index dc07fd209..1c6fd8c14 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt @@ -624,7 +624,7 @@ class SettingsAdapter( val value = it.getValueAt(which) if (it.selectedValues.contains(value) != isChecked) { val setting = - it.setSelectedValue((if (isChecked) it.selectedValues + value.toString() else it.selectedValues - value.toString()).sorted()) + it.setSelectedValue((if (isChecked) it.selectedValues + value.toString() else it.selectedValues - value.toString())) fragmentView?.putSetting(setting) fragmentView?.onSettingChanged() } @@ -803,14 +803,14 @@ class SettingsAdapter( private fun getSelectionForStringMultiChoiceValue(item: StringMultiChoiceSetting): BooleanArray { val values = item.selectedValues; val available_values = item.values; - val res = BooleanArray(available_values?.size ?: 0){false} - var index = 0; + val res = BooleanArray(available_values?.size ?: 10){false} + if (available_values != null) { for (choice_val in available_values) { if (values.contains(choice_val)) { + val index = available_values.indexOf(choice_val) res[index] = true; - index++; } } } @@ -820,85 +820,4 @@ class SettingsAdapter( BooleanArray(1) { false }; } } - - - - //TODO: I only added MultiChoice for fleshing out backend, debating whether to remove MultiChoiceSetting and related code for cleaning up - /* - override fun onClick(dialog: DialogInterface?, which: Int, is_checked: Boolean) { - when (clickedItem) { - /* - is MultiChoiceSetting -> { - val scSetting = clickedItem as? MultiChoiceSetting - scSetting?.let { - val setting = when (it.setting) { - is AbstractMultiIntSetting -> { - val value = getValueForMultiChoiceSelection(it, which, is_checked) - if (value !in it.selectedValues) { - it.removeSelectedValue(value) - fragmentView?.onSettingChanged() - } else { - it.addSelectedValue(value) - } - } - - is AbstractMultiShortSetting -> { - val value = getValueForMultiChoiceSelection(it, which, is_checked).toShort() - if (value !in it.selectedValues.map { it.toShort() }) { - it.removeSelectedValue(value) - fragmentView?.onSettingChanged() - } else { - it.addSelectedValue(value) - } - } - - else -> throw IllegalStateException("Unrecognized type used for MultiChoiceSetting!") - } - fragmentView?.putSetting(setting as AbstractSetting) - //fragmentView.loadSettingsList() - //closeDialog() - } - } - - */ - - //TODO: Don't fully know how to grab the setting itself for the buttons so I'm adding them to a backing array to be called later - //TODO: Likely need to be reimplemented - is StringMultiChoiceSetting -> { - val mcSetting = clickedItem as? StringMultiChoiceSetting - mcSetting?.let { - val setting = when (it.setting) { - is AbstractMultiStringSetting -> { - val value = it.getValueAt(which) - if (value in it.selectedValues && !is_checked) { - Settings.comboSelection.remove(value ?: "") - it.removeSelectedValue(value ?: "") - } else { - Settings.comboSelection.add(value ?: "") - it.addSelectedValue(value ?: "") - } - } - - is AbstractMultiShortSetting -> { - if (is_checked != it.selectValueIndices[which]) { - Settings.comboSelection.remove((it.getValueAt(which)?.toShort() ?: 1).toString()) - it.removeSelectedValue(it.getValueAt(which)?.toShort() ?: 1) - } else { - Settings.comboSelection.add((it.getValueAt(which)?.toShort() ?: 1).toString()) - it.addSelectedValue(it.getValueAt(which)?.toShort() ?: 1) - } - } - - else -> throw IllegalStateException("Unrecognized type used for StringMultiChoiceSetting!") - } - - fragmentView?.onSettingChanged() - fragmentView?.putSetting(setting as AbstractSetting) - //fragmentView.loadSettingsList() - //closeDialog() - } - } - } - - */ } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt b/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt index 29400e7cd..943b93a49 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt @@ -5,7 +5,6 @@ package org.citra.citra_emu.utils import org.citra.citra_emu.NativeLibrary -import org.citra.citra_emu.features.settings.model.Settings import org.citra.citra_emu.overlay.InputOverlayDrawableButton import org.citra.citra_emu.features.settings.model.StringListSetting From 485778be95f81b17b88ca51b7f5b48553ad88a5b Mon Sep 17 00:00:00 2001 From: ADAS2024 Date: Mon, 30 Mar 2026 12:36:57 -0400 Subject: [PATCH 23/23] Deleted Multi String Setting, added basic error handling, added comment explaining hardcoded size --- .../settings/model/AbstractMultiStringSetting.kt | 9 --------- .../citra_emu/features/settings/ui/SettingsAdapter.kt | 4 ++-- .../main/java/org/citra/citra_emu/utils/ComboHelper.kt | 8 ++++---- 3 files changed, 6 insertions(+), 15 deletions(-) delete mode 100644 src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiStringSetting.kt diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiStringSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiStringSetting.kt deleted file mode 100644 index ddd48306f..000000000 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiStringSetting.kt +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright Citra Emulator Project / Azahar Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -package org.citra.citra_emu.features.settings.model - -interface AbstractMultiStringSetting : AbstractSetting { - var strings: MutableSet -} diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt index 1c6fd8c14..bd89861f6 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt @@ -38,7 +38,6 @@ import org.citra.citra_emu.databinding.ListItemSettingsHeaderBinding import org.citra.citra_emu.features.settings.model.AbstractBooleanSetting import org.citra.citra_emu.features.settings.model.AbstractFloatSetting import org.citra.citra_emu.features.settings.model.AbstractIntSetting -import org.citra.citra_emu.features.settings.model.AbstractMultiStringSetting import org.citra.citra_emu.features.settings.model.AbstractSetting import org.citra.citra_emu.features.settings.model.AbstractStringSetting import org.citra.citra_emu.features.settings.model.FloatSetting @@ -803,7 +802,8 @@ class SettingsAdapter( private fun getSelectionForStringMultiChoiceValue(item: StringMultiChoiceSetting): BooleanArray { val values = item.selectedValues; val available_values = item.values; - val res = BooleanArray(available_values?.size ?: 10){false} + val res = BooleanArray(available_values?.size ?: 10){false} // 10 is used because we have 10 reasonable options. + // prob shouldn't hardcode the size value here if (available_values != null) { diff --git a/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt b/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt index 943b93a49..603fd1796 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt @@ -27,13 +27,13 @@ object ComboHelper { } fun comboActivate(button: InputOverlayDrawableButton) { - var comboArray = StringListSetting.COMBO_KEYS.list + val comboArray = StringListSetting.COMBO_KEYS.list for (selected_button in comboArray) { - var native_button = getButton(selected_button) + val native_button = getButton(selected_button) if (native_button == -1) { - //TODO: Need proper error handling here - println("Bad Button") + val cause = IllegalStateException("Button is not in bindable inputs.") + throw IllegalArgumentException("Input must be non-negative.", cause) } else {