From 95f0be002605fbf2c014f30dfb721d6b2f100eb2 Mon Sep 17 00:00:00 2001 From: adas20 Date: Wed, 16 Jul 2025 14:00:02 -0400 Subject: [PATCH 01/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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/30] 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 { From c91fb120b15fd3e6742f027c0d023e454a55830b Mon Sep 17 00:00:00 2001 From: ADAS2024 Date: Tue, 14 Apr 2026 17:28:27 -0400 Subject: [PATCH 24/30] Changed Combo Button to be a HotKey, changed impl to be default multi choice, and removed StringMultiChoice details --- .../citra_emu/features/hotkeys/Hotkey.kt | 3 +- .../features/hotkeys/HotkeyUtility.kt | 15 ++++- .../features/settings/model/BooleanSetting.kt | 3 +- .../features/settings/model/IntListSetting.kt | 3 +- .../features/settings/model/Settings.kt | 13 ++-- .../settings/model/StringListSetting.kt | 52 --------------- .../model/view/InputBindingSetting.kt | 3 +- .../model/view/StringMultiChoiceSetting.kt | 53 --------------- .../features/settings/ui/SettingsAdapter.kt | 65 ------------------- .../settings/ui/SettingsFragmentPresenter.kt | 15 ++--- .../ui/viewholder/MultiChoiceViewHolder.kt | 17 ----- .../features/settings/utils/SettingsFile.kt | 8 +-- .../citra/citra_emu/overlay/InputOverlay.kt | 18 +++-- .../org/citra/citra_emu/utils/ComboHelper.kt | 46 ++++++------- .../app/src/main/res/values/arrays.xml | 27 ++++++++ 15 files changed, 98 insertions(+), 243 deletions(-) delete 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/StringMultiChoiceSetting.kt diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/hotkeys/Hotkey.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/hotkeys/Hotkey.kt index e2319a7e4..293017b31 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/hotkeys/Hotkey.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/hotkeys/Hotkey.kt @@ -12,5 +12,6 @@ enum class Hotkey(val button: Int) { QUICKSAVE(10005), QUICKLOAD(10006), TURBO_LIMIT(10007), - ENABLE(10008); + ENABLE(10008), + COMBO_KEY(10009); } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/hotkeys/HotkeyUtility.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/hotkeys/HotkeyUtility.kt index d01d5f769..d3f493ecd 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/hotkeys/HotkeyUtility.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/hotkeys/HotkeyUtility.kt @@ -13,9 +13,11 @@ import org.citra.citra_emu.NativeLibrary import org.citra.citra_emu.R import org.citra.citra_emu.utils.EmulationLifecycleUtil import org.citra.citra_emu.utils.TurboHelper +import org.citra.citra_emu.utils.ComboHelper import org.citra.citra_emu.display.ScreenAdjustmentUtil import org.citra.citra_emu.features.settings.model.view.InputBindingSetting import org.citra.citra_emu.features.settings.model.Settings +import org.citra.citra_emu.utils.Log class HotkeyUtility( private val screenAdjustmentUtil: ScreenAdjustmentUtil, @@ -81,6 +83,7 @@ class HotkeyUtility( // this is a hotkey button if (hotkeyButtons.contains(button)) { currentlyPressedButtons.remove(button) + handleHotkeyRelease(button) if (!currentlyPressedButtons.any { hotkeyButtons.contains(it) }) { // all hotkeys are no longer pressed hotkeyIsPressed = false @@ -106,6 +109,14 @@ class HotkeyUtility( return handled } + fun handleHotkeyRelease(bindedButton: Int): Boolean { + Log.debug("Handling hotkey button release: " + bindedButton) + if (bindedButton == Hotkey.COMBO_KEY.button) { + ComboHelper.comboActivate(NativeLibrary.ButtonState.RELEASED) + } + return true + } + fun handleHotkey(bindedButton: Int): Boolean { when (bindedButton) { Hotkey.SWAP_SCREEN.button -> screenAdjustmentUtil.swapScreen() @@ -121,7 +132,6 @@ class HotkeyUtility( Toast.LENGTH_SHORT ).show() } - Hotkey.QUICKLOAD.button -> { val wasLoaded = NativeLibrary.loadStateIfAvailable(NativeLibrary.QUICKSAVE_SLOT) val stringRes = if (wasLoaded) { @@ -135,6 +145,9 @@ class HotkeyUtility( Toast.LENGTH_SHORT ).show() } + Hotkey.COMBO_KEY.button -> { + ComboHelper.comboActivate(NativeLibrary.ButtonState.PRESSED) + } else -> {} } 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 e3a482174..803a068d4 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 @@ -55,8 +55,7 @@ enum class BooleanSetting( COMPRESS_INSTALLED_CIA_CONTENT(SettingKeys.compress_cia_installs(), Settings.SECTION_STORAGE, false), ANDROID_HIDE_IMAGES(SettingKeys.android_hide_images(), Settings.SECTION_MISC, false), APPLY_REGION_FREE_PATCH(SettingKeys.apply_region_free_patch(), Settings.SECTION_SYSTEM, true), - USE_INTEGER_SCALING(SettingKeys.use_integer_scaling(), Settings.SECTION_RENDERER, false), - ENABLE_COMBO_KEY("enable_combo_key", Settings.SECTION_CONTROLS, true); + USE_INTEGER_SCALING(SettingKeys.use_integer_scaling(), Settings.SECTION_RENDERER, false); override var boolean: Boolean = defaultValue diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntListSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntListSetting.kt index 0de51acce..e08dbd049 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntListSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntListSetting.kt @@ -11,7 +11,8 @@ enum class IntListSetting( val canBeEmpty: Boolean = true ) : AbstractListSetting { - LAYOUTS_TO_CYCLE("layouts_to_cycle", Settings.SECTION_LAYOUT, listOf(0, 1, 2, 3, 4, 5), canBeEmpty = false); + LAYOUTS_TO_CYCLE("layouts_to_cycle", Settings.SECTION_LAYOUT, listOf(0, 1, 2, 3, 4, 5), canBeEmpty = false), + COMBO_KEYS("combo_keys", Settings.SECTION_CONTROLS, listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), canBeEmpty = true); private var backingList: List = defaultValue private var lastValidList : List = 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 70056503b..2c2be85c2 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 @@ -146,6 +146,7 @@ class Settings { const val HOTKEY_QUICKSAVE = "hotkey_quickload" const val HOTKEY_QUICKlOAD = "hotkey_quickpause" const val HOTKEY_TURBO_LIMIT = "hotkey_turbo_limit" + const val HOTKEY_BUTTON_COMBO = "hotkey_button_combo" val buttonKeys = listOf( KEY_BUTTON_A, @@ -154,8 +155,7 @@ class Settings { KEY_BUTTON_Y, KEY_BUTTON_SELECT, KEY_BUTTON_START, - KEY_BUTTON_HOME, - KEY_BUTTON_COMBO + KEY_BUTTON_HOME ) val buttonTitles = listOf( R.string.button_a, @@ -164,8 +164,7 @@ class Settings { R.string.button_y, R.string.button_select, R.string.button_start, - R.string.button_home, - R.string.button_combo + R.string.button_home ) val circlePadKeys = listOf( KEY_CIRCLEPAD_AXIS_VERTICAL, @@ -215,7 +214,8 @@ class Settings { HOTKEY_PAUSE_OR_RESUME, HOTKEY_QUICKSAVE, HOTKEY_QUICKlOAD, - HOTKEY_TURBO_LIMIT + HOTKEY_TURBO_LIMIT, + HOTKEY_BUTTON_COMBO ) val hotkeyTitles = listOf( R.string.controller_hotkey_enable_button, @@ -225,7 +225,8 @@ class Settings { R.string.emulation_toggle_pause, R.string.emulation_quicksave, R.string.emulation_quickload, - R.string.turbo_limit_hotkey + R.string.turbo_limit_hotkey, + R.string.button_combo ) // TODO: Move these in with the other setting keys in GenerateSettingKeys.cmake 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 deleted file mode 100644 index dd12c54dc..000000000 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/StringListSetting.kt +++ /dev/null @@ -1,52 +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 - -enum class StringListSetting( - override val key: String, - override val section: String, - override val defaultValue: List, - val canBeEmpty: Boolean = true -) : AbstractListSetting { - COMBO_KEYS("combo_keys", Settings.SECTION_CONTROLS, listOf("A", "B", "X", "Y", "L", "R", "ZL", "ZR", "Start", "Select")); - - 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() - - - 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/InputBindingSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/InputBindingSetting.kt index 1b16cb070..5a1a8f07f 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 @@ -125,7 +125,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_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 @@ -138,6 +138,7 @@ class InputBindingSetting( Settings.HOTKEY_QUICKSAVE -> Hotkey.QUICKSAVE.button Settings.HOTKEY_QUICKlOAD -> Hotkey.QUICKLOAD.button Settings.HOTKEY_TURBO_LIMIT -> Hotkey.TURBO_LIMIT.button + Settings.HOTKEY_BUTTON_COMBO -> Hotkey.COMBO_KEY.button else -> -1 } 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 deleted file mode 100644 index b6dd0a8a9..000000000 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt +++ /dev/null @@ -1,53 +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.AbstractSetting -import org.citra.citra_emu.features.settings.model.StringListSetting -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 StringListSetting - return setting.list - }catch (_: ClassCastException) { - } - return defaultValue!! - } - - /** - * 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 applied. - */ - fun setSelectedValue(selection: List): StringListSetting { - val stringSetting = setting as StringListSetting - stringSetting.list = selection - return stringSetting - } -} \ 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 bd89861f6..81dbf597b 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 @@ -52,7 +52,6 @@ import org.citra.citra_emu.features.settings.model.view.SingleChoiceSetting import org.citra.citra_emu.features.settings.model.view.MultiChoiceSetting 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 @@ -139,10 +138,6 @@ 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) @@ -208,10 +203,6 @@ class SettingsAdapter( SettingsItem.TYPE_MULTI_CHOICE -> { (oldItem as MultiChoiceSetting).isEnabled == (newItem as MultiChoiceSetting).isEnabled } - - SettingsItem.TYPE_STRING_MULTI_CHOICE -> { - (oldItem as StringMultiChoiceSetting).isEnabled == (newItem as StringMultiChoiceSetting).isEnabled - } SettingsItem.TYPE_DATETIME_SETTING -> { (oldItem as DateTimeSetting).isEnabled == (newItem as DateTimeSetting).isEnabled @@ -282,26 +273,6 @@ 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 { @@ -616,20 +587,6 @@ class SettingsAdapter( 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())) - fragmentView?.putSetting(setting) - fragmentView?.onSettingChanged() - } - fragmentView.loadSettingsList() - } - } } } @@ -798,26 +755,4 @@ 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 ?: 10){false} // 10 is used because we have 10 reasonable options. - // prob shouldn't hardcode the size value here - - - 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; - } - } - } - return if (res.isNotEmpty()) { - res; - } else { - BooleanArray(1) { false }; - } - } } 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 290cdffd7..7642e8bb3 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 @@ -31,7 +31,6 @@ 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 @@ -42,7 +41,6 @@ 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 @@ -843,16 +841,15 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) ) ) - val buttons = settingsActivity.resources.getStringArray(R.array.n3dsButtons).take(10).toTypedArray() add( - StringMultiChoiceSetting( - StringListSetting.COMBO_KEYS, + MultiChoiceSetting( + IntListSetting.COMBO_KEYS, R.string.combo_key_options, R.string.combo_key_description, - buttons, - buttons, - StringListSetting.COMBO_KEYS.key, - StringListSetting.COMBO_KEYS.defaultValue + R.array.comboOptions, + R.array.comboOptionValues, + IntListSetting.COMBO_KEYS.key, + IntListSetting.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 4e59ed984..8493115a4 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,7 +8,6 @@ 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) : @@ -52,16 +51,6 @@ 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 "" } } @@ -78,12 +67,6 @@ 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/utils/SettingsFile.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/utils/SettingsFile.kt index 2ff8727c6..fc75d9eeb 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 @@ -17,7 +17,6 @@ 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 @@ -256,15 +255,10 @@ object SettingsFile { stringSetting.string = value return stringSetting } - - val stringListSetting = StringListSetting.from(key) - if (stringListSetting != null) { - stringListSetting.list = value.split(", ").map { it } - } val intListSetting = IntListSetting.from(key) if (intListSetting != null) { - intListSetting.list = value.split(", ").map { it.toInt() } + intListSetting.list = value.split(", ").mapNotNull { it.toIntOrNull() } } return null 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 84fd0e8d9..3716ebc17 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 @@ -24,6 +24,7 @@ import androidx.preference.PreferenceManager import org.citra.citra_emu.CitraApplication import org.citra.citra_emu.NativeLibrary import org.citra.citra_emu.R +import org.citra.citra_emu.features.hotkeys.Hotkey import org.citra.citra_emu.utils.EmulationMenuSettings import org.citra.citra_emu.utils.TurboHelper import org.citra.citra_emu.utils.ComboHelper @@ -177,9 +178,16 @@ 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 == Hotkey.COMBO_KEY.button && button.status == NativeLibrary.ButtonState.PRESSED) { + ComboHelper.comboActivate(NativeLibrary.ButtonState.PRESSED) + } + + /* else if (button.id == NativeLibrary.ButtonType.BUTTON_COMBO) { ComboHelper.comboActivate(button) } + */ + NativeLibrary.onGamePadEvent( NativeLibrary.TouchScreenDevice, @@ -580,7 +588,7 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex context, R.drawable.button_combo, R.drawable.button_combo_pressed, - NativeLibrary.ButtonType.BUTTON_COMBO, + Hotkey.COMBO_KEY.button, orientation ) ) @@ -799,11 +807,11 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex resources.getInteger(R.integer.N3DS_BUTTON_TURBO_Y).toFloat() / 1000 * maxY ) .putFloat( - NativeLibrary.ButtonType.BUTTON_COMBO.toString() + "-X", + Hotkey.COMBO_KEY.button.toString() + "-X", resources.getInteger(R.integer.N3DS_BUTTON_COMBO_X).toFloat() / 1000 * maxX ) .putFloat( - NativeLibrary.ButtonType.BUTTON_COMBO.toString() + "-Y", + Hotkey.COMBO_KEY.button.toString() + "-Y", resources.getInteger(R.integer.N3DS_BUTTON_COMBO_Y).toFloat() / 1000 * maxY ) .apply() @@ -958,11 +966,11 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex resources.getInteger(R.integer.N3DS_BUTTON_TURBO_PORTRAIT_Y).toFloat() / 1000 * maxY ) .putFloat( - NativeLibrary.ButtonType.BUTTON_COMBO.toString() + portrait + "-X", + Hotkey.COMBO_KEY.button.toString() + portrait + "-X", resources.getInteger(R.integer.N3DS_BUTTON_COMBO_PORTRAIT_X).toFloat() / 1000 * maxX ) .putFloat( - NativeLibrary.ButtonType.BUTTON_COMBO.toString() + portrait + "-Y", + Hotkey.COMBO_KEY.button.toString() + portrait + "-Y", resources.getInteger(R.integer.N3DS_BUTTON_COMBO_PORTRAIT_Y).toFloat() / 1000 * maxY ) .apply() 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 603fd1796..bf0ef8ac6 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,39 +5,39 @@ package org.citra.citra_emu.utils import org.citra.citra_emu.NativeLibrary -import org.citra.citra_emu.overlay.InputOverlayDrawableButton -import org.citra.citra_emu.features.settings.model.StringListSetting +import org.citra.citra_emu.features.settings.model.IntListSetting object ComboHelper { - - fun getButton(button: String): Int { + fun getButton(button: Int): 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 + 0 -> return NativeLibrary.ButtonType.BUTTON_A + 1 -> return NativeLibrary.ButtonType.BUTTON_B + 2 -> return NativeLibrary.ButtonType.BUTTON_X + 3 -> return NativeLibrary.ButtonType.BUTTON_Y + 4 -> return NativeLibrary.ButtonType.TRIGGER_L + 5 -> return NativeLibrary.ButtonType.TRIGGER_R + 6 -> return NativeLibrary.ButtonType.BUTTON_ZL + 7 -> return NativeLibrary.ButtonType.BUTTON_ZR + 8 -> return NativeLibrary.ButtonType.BUTTON_START + 9 -> return NativeLibrary.ButtonType.BUTTON_SELECT } return -1 } - - fun comboActivate(button: InputOverlayDrawableButton) { - val comboArray = StringListSetting.COMBO_KEYS.list - for (selected_button in comboArray) { - val native_button = getButton(selected_button) - if (native_button == -1) + fun comboActivate(buttonStatus: Int) { + val comboArray = IntListSetting.COMBO_KEYS.list + Log.info("Combo Array: $comboArray") + for (selectedButton in comboArray) { + val nativeButton = getButton(selectedButton) + Log.info("Native Button: $nativeButton") + if (nativeButton == -1) { - val cause = IllegalStateException("Button is not in bindable inputs.") - throw IllegalArgumentException("Input must be non-negative.", cause) + // We don't want to parse any bad inputs here so we continue loop + continue } else { - NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, native_button, button.status) + Log.debug("Handling combo button press: $nativeButton") + NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, nativeButton, buttonStatus) } } } diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index d581e4f65..3a0e40050 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -184,6 +184,33 @@ @string/button_combo + + @string/button_a + @string/button_b + @string/button_x + @string/button_y + @string/button_l + @string/button_r + @string/button_zl + @string/button_zr + @string/button_start + @string/button_select + + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + + + @string/blank @string/still_image From f905a1656e55987b21084405c53c539815114b51 Mon Sep 17 00:00:00 2001 From: ADAS2024 Date: Tue, 14 Apr 2026 17:34:02 -0400 Subject: [PATCH 25/30] Remove Commented Code --- .../features/settings/model/view/InputBindingSetting.kt | 1 - .../main/java/org/citra/citra_emu/overlay/InputOverlay.kt | 7 ------- 2 files changed, 8 deletions(-) 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 5a1a8f07f..54fa8d6a3 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 @@ -125,7 +125,6 @@ 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 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 3716ebc17..85a04c741 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 @@ -182,13 +182,6 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex ComboHelper.comboActivate(NativeLibrary.ButtonState.PRESSED) } - /* - else if (button.id == NativeLibrary.ButtonType.BUTTON_COMBO) { - ComboHelper.comboActivate(button) - } - */ - - NativeLibrary.onGamePadEvent( NativeLibrary.TouchScreenDevice, button.id, From 65b2332a89e399efbc8671eaa9de49a0b33df8e9 Mon Sep 17 00:00:00 2001 From: ADAS2024 Date: Wed, 15 Apr 2026 14:47:26 -0400 Subject: [PATCH 26/30] Changed ComboHelper.kt to use Native Button ints, removed rest of initial implementation traces --- .../java/org/citra/citra_emu/NativeLibrary.kt | 1 - .../features/settings/model/IntListSetting.kt | 14 ++++++++++++- .../model/view/InputBindingSetting.kt | 1 - .../settings/model/view/SettingsItem.kt | 1 - .../citra_emu/fragments/EmulationFragment.kt | 3 ++- .../org/citra/citra_emu/utils/ComboHelper.kt | 18 +--------------- .../app/src/main/res/values/arrays.xml | 21 ++++++++++--------- 7 files changed, 27 insertions(+), 32 deletions(-) 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 90c953644..20c3c0868 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 @@ -920,7 +920,6 @@ 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/java/org/citra/citra_emu/features/settings/model/IntListSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntListSetting.kt index e08dbd049..06f2ebd52 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntListSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntListSetting.kt @@ -4,6 +4,8 @@ package org.citra.citra_emu.features.settings.model +import org.citra.citra_emu.NativeLibrary + enum class IntListSetting( override val key: String, override val section: String, @@ -12,7 +14,17 @@ enum class IntListSetting( ) : AbstractListSetting { LAYOUTS_TO_CYCLE("layouts_to_cycle", Settings.SECTION_LAYOUT, listOf(0, 1, 2, 3, 4, 5), canBeEmpty = false), - COMBO_KEYS("combo_keys", Settings.SECTION_CONTROLS, listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), canBeEmpty = true); + COMBO_KEYS("combo_keys", Settings.SECTION_CONTROLS, listOf + (NativeLibrary.ButtonType.BUTTON_A, + NativeLibrary.ButtonType.BUTTON_B, + NativeLibrary.ButtonType.BUTTON_X, + NativeLibrary.ButtonType.BUTTON_Y, + NativeLibrary.ButtonType.TRIGGER_L, + NativeLibrary.ButtonType.TRIGGER_R, + NativeLibrary.ButtonType.BUTTON_ZL, + NativeLibrary.ButtonType.BUTTON_ZR, + NativeLibrary.ButtonType.BUTTON_START, + NativeLibrary.ButtonType.BUTTON_SELECT), canBeEmpty = true); private var backingList: List = defaultValue private var lastValidList : List = defaultValue 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 54fa8d6a3..bf2a042ae 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 @@ -523,7 +523,6 @@ 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/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/SettingsItem.kt index c855d2b03..066912dd9 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,6 +48,5 @@ 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/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/citra/citra_emu/fragments/EmulationFragment.kt index 46b6b7d89..9ca913622 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 @@ -66,6 +66,7 @@ import org.citra.citra_emu.databinding.FragmentEmulationBinding import org.citra.citra_emu.display.PortraitScreenLayout import org.citra.citra_emu.display.ScreenAdjustmentUtil import org.citra.citra_emu.display.ScreenLayout +import org.citra.citra_emu.features.hotkeys.Hotkey import org.citra.citra_emu.features.settings.model.BooleanSetting import org.citra.citra_emu.features.settings.model.IntSetting import org.citra.citra_emu.features.settings.model.Settings @@ -809,7 +810,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram } R.id.menu_emulation_adjust_scale_button_combo -> { - showAdjustScaleDialog("controlScale-" + NativeLibrary.ButtonType.BUTTON_COMBO) + showAdjustScaleDialog("controlScale-" + Hotkey.COMBO_KEY.button) true } 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 bf0ef8ac6..002329dc9 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 @@ -8,26 +8,10 @@ import org.citra.citra_emu.NativeLibrary import org.citra.citra_emu.features.settings.model.IntListSetting object ComboHelper { - fun getButton(button: Int): Int { - when (button) { - 0 -> return NativeLibrary.ButtonType.BUTTON_A - 1 -> return NativeLibrary.ButtonType.BUTTON_B - 2 -> return NativeLibrary.ButtonType.BUTTON_X - 3 -> return NativeLibrary.ButtonType.BUTTON_Y - 4 -> return NativeLibrary.ButtonType.TRIGGER_L - 5 -> return NativeLibrary.ButtonType.TRIGGER_R - 6 -> return NativeLibrary.ButtonType.BUTTON_ZL - 7 -> return NativeLibrary.ButtonType.BUTTON_ZR - 8 -> return NativeLibrary.ButtonType.BUTTON_START - 9 -> return NativeLibrary.ButtonType.BUTTON_SELECT - } - return -1 - } fun comboActivate(buttonStatus: Int) { val comboArray = IntListSetting.COMBO_KEYS.list Log.info("Combo Array: $comboArray") - for (selectedButton in comboArray) { - val nativeButton = getButton(selectedButton) + for (nativeButton in comboArray) { Log.info("Native Button: $nativeButton") if (nativeButton == -1) { diff --git a/src/android/app/src/main/res/values/arrays.xml b/src/android/app/src/main/res/values/arrays.xml index 3a0e40050..39d0c810f 100644 --- a/src/android/app/src/main/res/values/arrays.xml +++ b/src/android/app/src/main/res/values/arrays.xml @@ -197,17 +197,18 @@ @string/button_select + - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 + 700 + 701 + 702 + 703 + 773 + 774 + 707 + 708 + 704 + 705 From bf2423e47103e461db5cb753ae54e07eaaa216f3 Mon Sep 17 00:00:00 2001 From: ADAS2024 Date: Sat, 9 May 2026 17:58:47 -0400 Subject: [PATCH 27/30] Commented out debug logging, added back missing TODO statement regarding magic numbers --- .../org/citra/citra_emu/features/hotkeys/HotkeyUtility.kt | 2 +- .../java/org/citra/citra_emu/fragments/EmulationFragment.kt | 1 + .../src/main/java/org/citra/citra_emu/utils/ComboHelper.kt | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/hotkeys/HotkeyUtility.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/hotkeys/HotkeyUtility.kt index d3f493ecd..7da3b17e0 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/hotkeys/HotkeyUtility.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/hotkeys/HotkeyUtility.kt @@ -110,7 +110,7 @@ class HotkeyUtility( } fun handleHotkeyRelease(bindedButton: Int): Boolean { - Log.debug("Handling hotkey button release: " + bindedButton) + // Log.debug("Handling hotkey button release: " + bindedButton) if (bindedButton == Hotkey.COMBO_KEY.button) { ComboHelper.comboActivate(NativeLibrary.ButtonState.RELEASED) } 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 517c3610a..7d669c873 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 @@ -1062,6 +1062,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram // Buttons that are disabled by default var defaultValue = true when (i) { + // TODO: Remove these magic numbers 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/utils/ComboHelper.kt b/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt index 002329dc9..c346b9b8a 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 @@ -10,9 +10,9 @@ import org.citra.citra_emu.features.settings.model.IntListSetting object ComboHelper { fun comboActivate(buttonStatus: Int) { val comboArray = IntListSetting.COMBO_KEYS.list - Log.info("Combo Array: $comboArray") + // Log.info("Combo Array: $comboArray") for (nativeButton in comboArray) { - Log.info("Native Button: $nativeButton") + // Log.info("Native Button: $nativeButton") if (nativeButton == -1) { // We don't want to parse any bad inputs here so we continue loop @@ -20,7 +20,7 @@ object ComboHelper { } else { - Log.debug("Handling combo button press: $nativeButton") + // Log.debug("Handling combo button press: $nativeButton") NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, nativeButton, buttonStatus) } } From 580986116f710d50f05212e272e99c1f79db9172 Mon Sep 17 00:00:00 2001 From: OpenSauce04 Date: Sun, 24 May 2026 12:10:20 +0100 Subject: [PATCH 28/30] Cleanup --- .../features/settings/model/IntListSetting.kt | 17 +++++------------ .../features/settings/model/Settings.kt | 3 +-- .../features/settings/ui/SettingsAdapter.kt | 3 --- .../settings/ui/SettingsFragmentPresenter.kt | 4 ++-- .../features/settings/utils/SettingsFile.kt | 2 +- .../org/citra/citra_emu/overlay/InputOverlay.kt | 1 - .../org/citra/citra_emu/utils/ComboHelper.kt | 14 ++------------ 7 files changed, 11 insertions(+), 33 deletions(-) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntListSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntListSetting.kt index 06f2ebd52..bef41fb34 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntListSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntListSetting.kt @@ -4,7 +4,8 @@ package org.citra.citra_emu.features.settings.model -import org.citra.citra_emu.NativeLibrary +import org.citra.citra_emu.CitraApplication +import org.citra.citra_emu.R enum class IntListSetting( override val key: String, @@ -14,17 +15,9 @@ enum class IntListSetting( ) : AbstractListSetting { LAYOUTS_TO_CYCLE("layouts_to_cycle", Settings.SECTION_LAYOUT, listOf(0, 1, 2, 3, 4, 5), canBeEmpty = false), - COMBO_KEYS("combo_keys", Settings.SECTION_CONTROLS, listOf - (NativeLibrary.ButtonType.BUTTON_A, - NativeLibrary.ButtonType.BUTTON_B, - NativeLibrary.ButtonType.BUTTON_X, - NativeLibrary.ButtonType.BUTTON_Y, - NativeLibrary.ButtonType.TRIGGER_L, - NativeLibrary.ButtonType.TRIGGER_R, - NativeLibrary.ButtonType.BUTTON_ZL, - NativeLibrary.ButtonType.BUTTON_ZR, - NativeLibrary.ButtonType.BUTTON_START, - NativeLibrary.ButtonType.BUTTON_SELECT), canBeEmpty = true); + COMBO_KEYS("combo_keys", Settings.SECTION_CONTROLS, + CitraApplication.appContext.resources.getIntArray(R.array.comboOptionValues).toCollection(ArrayList()), + canBeEmpty = true); private var backingList: List = defaultValue private var lastValidList : List = 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 2c2be85c2..54d2700c8 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 @@ -115,7 +115,6 @@ class Settings { const val SECTION_STORAGE = "Storage" const val SECTION_MISC = "Miscellaneous" - const val KEY_BUTTON_A = "button_a" const val KEY_BUTTON_B = "button_b" const val KEY_BUTTON_X = "button_x" @@ -255,4 +254,4 @@ class Settings { ) } } -} \ 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 81dbf597b..8603f4dcc 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 @@ -199,7 +199,6 @@ class SettingsAdapter( SettingsItem.TYPE_SINGLE_CHOICE -> { (oldItem as SingleChoiceSetting).isEnabled == (newItem as SingleChoiceSetting).isEnabled } - SettingsItem.TYPE_MULTI_CHOICE -> { (oldItem as MultiChoiceSetting).isEnabled == (newItem as MultiChoiceSetting).isEnabled } @@ -721,7 +720,6 @@ class SettingsAdapter( } } - private fun getSelectionForSingleChoiceValue(item: SingleChoiceSetting): Int { val value = item.selectedValue val valuesId = item.valuesId @@ -754,5 +752,4 @@ class SettingsAdapter( } return BooleanArray(1){false}; } - } 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 67d70b825..668023450 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 @@ -799,6 +799,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) onLongClick = { settingsAdapter.onLongClickAutoMap() } ) ) + add(HeaderSetting(R.string.generic_buttons)) Settings.buttonKeys.forEachIndexed { i: Int, key: String -> val button = getInputObject(key) @@ -839,6 +840,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) val button = getInputObject(key) add(InputBindingSetting(button, Settings.hotkeyTitles[i])) } + add(HeaderSetting(R.string.miscellaneous)) add( SwitchSetting( @@ -864,8 +866,6 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) } } - - private fun getInputObject(key: String): AbstractStringSetting { return object : AbstractStringSetting { override var string: String 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 fc75d9eeb..ef34520db 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 @@ -255,7 +255,7 @@ object SettingsFile { stringSetting.string = value return stringSetting } - + val intListSetting = IntListSetting.from(key) if (intListSetting != null) { intListSetting.list = value.split(", ").mapNotNull { it.toIntOrNull() } 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 85a04c741..45ead3d9d 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 @@ -159,7 +159,6 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex NativeLibrary.onTouchEvent(0f, 0f, false) break // Up and down actions shouldn't loop } - } var anyOverlayStateChanged = false 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 c346b9b8a..4c28696a1 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 @@ -10,23 +10,13 @@ import org.citra.citra_emu.features.settings.model.IntListSetting object ComboHelper { fun comboActivate(buttonStatus: Int) { val comboArray = IntListSetting.COMBO_KEYS.list - // Log.info("Combo Array: $comboArray") for (nativeButton in comboArray) { - // Log.info("Native Button: $nativeButton") - if (nativeButton == -1) - { + if (nativeButton == -1) { // We don't want to parse any bad inputs here so we continue loop continue - } - else - { - // Log.debug("Handling combo button press: $nativeButton") + } else { NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, nativeButton, buttonStatus) } } } - - - - } From 36f458552c1566144271cb6a6311fffcdc76acae Mon Sep 17 00:00:00 2001 From: ADAS2024 Date: Tue, 26 May 2026 15:27:59 -0400 Subject: [PATCH 29/30] Changed Combo Key to Combo Button in kotlin code (will need to test) --- .../org/citra/citra_emu/features/hotkeys/Hotkey.kt | 2 +- .../citra_emu/features/hotkeys/HotkeyUtility.kt | 5 ++--- .../features/settings/model/IntListSetting.kt | 2 +- .../settings/model/view/InputBindingSetting.kt | 2 +- .../settings/ui/SettingsFragmentPresenter.kt | 7 +++---- .../citra/citra_emu/fragments/EmulationFragment.kt | 4 +--- .../java/org/citra/citra_emu/overlay/InputOverlay.kt | 12 ++++++------ .../java/org/citra/citra_emu/utils/ComboHelper.kt | 2 +- 8 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/hotkeys/Hotkey.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/hotkeys/Hotkey.kt index 293017b31..1992e138b 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/hotkeys/Hotkey.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/hotkeys/Hotkey.kt @@ -13,5 +13,5 @@ enum class Hotkey(val button: Int) { QUICKLOAD(10006), TURBO_LIMIT(10007), ENABLE(10008), - COMBO_KEY(10009); + COMBO_BUTTON(10009); } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/hotkeys/HotkeyUtility.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/hotkeys/HotkeyUtility.kt index 7da3b17e0..e23864731 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/hotkeys/HotkeyUtility.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/hotkeys/HotkeyUtility.kt @@ -17,7 +17,6 @@ import org.citra.citra_emu.utils.ComboHelper import org.citra.citra_emu.display.ScreenAdjustmentUtil import org.citra.citra_emu.features.settings.model.view.InputBindingSetting import org.citra.citra_emu.features.settings.model.Settings -import org.citra.citra_emu.utils.Log class HotkeyUtility( private val screenAdjustmentUtil: ScreenAdjustmentUtil, @@ -111,7 +110,7 @@ class HotkeyUtility( fun handleHotkeyRelease(bindedButton: Int): Boolean { // Log.debug("Handling hotkey button release: " + bindedButton) - if (bindedButton == Hotkey.COMBO_KEY.button) { + if (bindedButton == Hotkey.COMBO_BUTTON.button) { ComboHelper.comboActivate(NativeLibrary.ButtonState.RELEASED) } return true @@ -145,7 +144,7 @@ class HotkeyUtility( Toast.LENGTH_SHORT ).show() } - Hotkey.COMBO_KEY.button -> { + Hotkey.COMBO_BUTTON.button -> { ComboHelper.comboActivate(NativeLibrary.ButtonState.PRESSED) } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntListSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntListSetting.kt index 3029b3e24..96b75ce90 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntListSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntListSetting.kt @@ -16,7 +16,7 @@ enum class IntListSetting( ) : AbstractListSetting { LAYOUTS_TO_CYCLE(SettingKeys.layouts_to_cycle(), Settings.SECTION_LAYOUT, listOf(0, 1, 2, 3, 4, 5), canBeEmpty = false), - COMBO_KEYS("combo_keys", Settings.SECTION_CONTROLS, + COMBO_BUTTONS("combo_buttons", Settings.SECTION_CONTROLS, CitraApplication.appContext.resources.getIntArray(R.array.comboOptionValues).toCollection(ArrayList()), canBeEmpty = true); 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 bf2a042ae..063a3436d 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 @@ -137,7 +137,7 @@ class InputBindingSetting( Settings.HOTKEY_QUICKSAVE -> Hotkey.QUICKSAVE.button Settings.HOTKEY_QUICKlOAD -> Hotkey.QUICKLOAD.button Settings.HOTKEY_TURBO_LIMIT -> Hotkey.TURBO_LIMIT.button - Settings.HOTKEY_BUTTON_COMBO -> Hotkey.COMBO_KEY.button + Settings.HOTKEY_BUTTON_COMBO -> Hotkey.COMBO_BUTTON.button else -> -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 668023450..12c920e3f 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 @@ -14,7 +14,6 @@ import android.os.Build import android.text.TextUtils import androidx.preference.PreferenceManager import com.google.android.material.dialog.MaterialAlertDialogBuilder -import kotlinx.serialization.builtins.IntArraySerializer import org.citra.citra_emu.CitraApplication import org.citra.citra_emu.R import org.citra.citra_emu.display.ScreenLayout @@ -854,13 +853,13 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) add( MultiChoiceSetting( - IntListSetting.COMBO_KEYS, + IntListSetting.COMBO_BUTTONS, R.string.combo_key_options, R.string.combo_key_description, R.array.comboOptions, R.array.comboOptionValues, - IntListSetting.COMBO_KEYS.key, - IntListSetting.COMBO_KEYS.defaultValue + IntListSetting.COMBO_BUTTONS.key, + IntListSetting.COMBO_BUTTONS.defaultValue ) ) } 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 7d669c873..760ba36f7 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 @@ -70,7 +70,6 @@ import org.citra.citra_emu.display.ScreenLayout import org.citra.citra_emu.features.hotkeys.Hotkey import org.citra.citra_emu.features.settings.model.BooleanSetting import org.citra.citra_emu.features.settings.model.IntSetting -import org.citra.citra_emu.features.settings.model.Settings import org.citra.citra_emu.features.settings.model.SettingsViewModel import org.citra.citra_emu.features.settings.ui.SettingsActivity import org.citra.citra_emu.features.settings.utils.SettingsFile @@ -79,7 +78,6 @@ import org.citra.citra_emu.utils.BuildUtil import org.citra.citra_emu.utils.DirectoryInitialization import org.citra.citra_emu.utils.DirectoryInitialization.DirectoryInitializationState import org.citra.citra_emu.utils.EmulationMenuSettings -import org.citra.citra_emu.utils.FileUtil import org.citra.citra_emu.utils.GameHelper import org.citra.citra_emu.utils.GameIconUtils import org.citra.citra_emu.utils.EmulationLifecycleUtil @@ -836,7 +834,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram } R.id.menu_emulation_adjust_scale_button_combo -> { - showAdjustScaleDialog("controlScale-" + Hotkey.COMBO_KEY.button) + showAdjustScaleDialog("controlScale-" + Hotkey.COMBO_BUTTON.button) true } 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 45ead3d9d..fec59f99f 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 @@ -177,7 +177,7 @@ 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 == Hotkey.COMBO_KEY.button && button.status == NativeLibrary.ButtonState.PRESSED) { + else if (button.id == Hotkey.COMBO_BUTTON.button && button.status == NativeLibrary.ButtonState.PRESSED) { ComboHelper.comboActivate(NativeLibrary.ButtonState.PRESSED) } @@ -580,7 +580,7 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex context, R.drawable.button_combo, R.drawable.button_combo_pressed, - Hotkey.COMBO_KEY.button, + Hotkey.COMBO_BUTTON.button, orientation ) ) @@ -799,11 +799,11 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex resources.getInteger(R.integer.N3DS_BUTTON_TURBO_Y).toFloat() / 1000 * maxY ) .putFloat( - Hotkey.COMBO_KEY.button.toString() + "-X", + Hotkey.COMBO_BUTTON.button.toString() + "-X", resources.getInteger(R.integer.N3DS_BUTTON_COMBO_X).toFloat() / 1000 * maxX ) .putFloat( - Hotkey.COMBO_KEY.button.toString() + "-Y", + Hotkey.COMBO_BUTTON.button.toString() + "-Y", resources.getInteger(R.integer.N3DS_BUTTON_COMBO_Y).toFloat() / 1000 * maxY ) .apply() @@ -958,11 +958,11 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex resources.getInteger(R.integer.N3DS_BUTTON_TURBO_PORTRAIT_Y).toFloat() / 1000 * maxY ) .putFloat( - Hotkey.COMBO_KEY.button.toString() + portrait + "-X", + Hotkey.COMBO_BUTTON.button.toString() + portrait + "-X", resources.getInteger(R.integer.N3DS_BUTTON_COMBO_PORTRAIT_X).toFloat() / 1000 * maxX ) .putFloat( - Hotkey.COMBO_KEY.button.toString() + portrait + "-Y", + Hotkey.COMBO_BUTTON.button.toString() + portrait + "-Y", resources.getInteger(R.integer.N3DS_BUTTON_COMBO_PORTRAIT_Y).toFloat() / 1000 * maxY ) .apply() 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 4c28696a1..533cf1b20 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 @@ -9,7 +9,7 @@ import org.citra.citra_emu.features.settings.model.IntListSetting object ComboHelper { fun comboActivate(buttonStatus: Int) { - val comboArray = IntListSetting.COMBO_KEYS.list + val comboArray = IntListSetting.COMBO_BUTTONS.list for (nativeButton in comboArray) { if (nativeButton == -1) { // We don't want to parse any bad inputs here so we continue loop From 1d7c8d64375464ff8a6af9d825e091b2d7e72008 Mon Sep 17 00:00:00 2001 From: ADAS2024 Date: Wed, 27 May 2026 01:10:29 -0400 Subject: [PATCH 30/30] Trying to integrate combo button as a SettingsKey setting. Running into issues with malformed/missing key --- CMakeModules/GenerateSettingKeys.cmake | 1 + .../java/org/citra/citra_emu/features/settings/SettingKeys.kt | 1 + .../citra/citra_emu/features/settings/model/IntListSetting.kt | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeModules/GenerateSettingKeys.cmake b/CMakeModules/GenerateSettingKeys.cmake index 7aff65db5..14b7d5072 100644 --- a/CMakeModules/GenerateSettingKeys.cmake +++ b/CMakeModules/GenerateSettingKeys.cmake @@ -238,6 +238,7 @@ if (ANDROID) "android_hide_images" "screen_orientation" "performance_overlay_position" + "combo_buttons" ) string(REPLACE "_" "_1" KEY_JNI_ESCAPED ${KEY}) set(SETTING_KEY_LIST "${SETTING_KEY_LIST}\n\"${KEY}\",") diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/SettingKeys.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/SettingKeys.kt index 56ffb6789..0a5b05960 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/SettingKeys.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/SettingKeys.kt @@ -141,4 +141,5 @@ object SettingKeys { external fun android_hide_images(): String external fun screen_orientation(): String external fun performance_overlay_position(): String + external fun combo_buttons(): String } \ No newline at end of file diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntListSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntListSetting.kt index 96b75ce90..8bfeb4df6 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntListSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/IntListSetting.kt @@ -16,7 +16,7 @@ enum class IntListSetting( ) : AbstractListSetting { LAYOUTS_TO_CYCLE(SettingKeys.layouts_to_cycle(), Settings.SECTION_LAYOUT, listOf(0, 1, 2, 3, 4, 5), canBeEmpty = false), - COMBO_BUTTONS("combo_buttons", Settings.SECTION_CONTROLS, + COMBO_BUTTONS(SettingKeys.combo_buttons(), Settings.SECTION_CONTROLS, CitraApplication.appContext.resources.getIntArray(R.array.comboOptionValues).toCollection(ArrayList()), canBeEmpty = true);