summaryrefslogtreecommitdiff
path: root/src/android/app
diff options
context:
space:
mode:
Diffstat (limited to 'src/android/app')
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/input/model/PlayerInput.kt6
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt3
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt6
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/StringInputSetting.kt22
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt13
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsDialogFragment.kt23
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt16
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt5
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt5
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SliderViewHolder.kt5
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/StringInputViewHolder.kt45
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt5
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt2
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt13
-rw-r--r--src/android/app/src/main/jni/native.cpp3
-rw-r--r--src/android/app/src/main/jni/native_input.cpp76
-rw-r--r--src/android/app/src/main/res/values/strings.xml1
17 files changed, 184 insertions, 65 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/input/model/PlayerInput.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/input/model/PlayerInput.kt
index d35de80c4..a84ac77a2 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/input/model/PlayerInput.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/input/model/PlayerInput.kt
@@ -64,17 +64,17 @@ data class PlayerInput(
64 fun hasMapping(): Boolean { 64 fun hasMapping(): Boolean {
65 var hasMapping = false 65 var hasMapping = false
66 buttons.forEach { 66 buttons.forEach {
67 if (it != "[empty]") { 67 if (it != "[empty]" && it.isNotEmpty()) {
68 hasMapping = true 68 hasMapping = true
69 } 69 }
70 } 70 }
71 analogs.forEach { 71 analogs.forEach {
72 if (it != "[empty]") { 72 if (it != "[empty]" && it.isNotEmpty()) {
73 hasMapping = true 73 hasMapping = true
74 } 74 }
75 } 75 }
76 motions.forEach { 76 motions.forEach {
77 if (it != "[empty]") { 77 if (it != "[empty]" && it.isNotEmpty()) {
78 hasMapping = true 78 hasMapping = true
79 } 79 }
80 } 80 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt
index a0d8cfede..6f16cf5b1 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt
@@ -6,7 +6,8 @@ package org.yuzu.yuzu_emu.features.settings.model
6import org.yuzu.yuzu_emu.utils.NativeConfig 6import org.yuzu.yuzu_emu.utils.NativeConfig
7 7
8enum class StringSetting(override val key: String) : AbstractStringSetting { 8enum class StringSetting(override val key: String) : AbstractStringSetting {
9 DRIVER_PATH("driver_path"); 9 DRIVER_PATH("driver_path"),
10 DEVICE_NAME("device_name");
10 11
11 override fun getString(needsGlobal: Boolean): String = NativeConfig.getString(key, needsGlobal) 12 override fun getString(needsGlobal: Boolean): String = NativeConfig.getString(key, needsGlobal)
12 13
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt
index 8f724835e..5fdf98318 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt
@@ -16,6 +16,7 @@ import org.yuzu.yuzu_emu.features.settings.model.ByteSetting
16import org.yuzu.yuzu_emu.features.settings.model.IntSetting 16import org.yuzu.yuzu_emu.features.settings.model.IntSetting
17import org.yuzu.yuzu_emu.features.settings.model.LongSetting 17import org.yuzu.yuzu_emu.features.settings.model.LongSetting
18import org.yuzu.yuzu_emu.features.settings.model.ShortSetting 18import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
19import org.yuzu.yuzu_emu.features.settings.model.StringSetting
19import org.yuzu.yuzu_emu.utils.NativeConfig 20import org.yuzu.yuzu_emu.utils.NativeConfig
20 21
21/** 22/**
@@ -75,6 +76,9 @@ abstract class SettingsItem(
75 get() = NativeLibrary.isRunning() && !setting.global && 76 get() = NativeLibrary.isRunning() && !setting.global &&
76 !NativeConfig.isPerGameConfigLoaded() 77 !NativeConfig.isPerGameConfigLoaded()
77 78
79 val clearable: Boolean
80 get() = !setting.global && NativeConfig.isPerGameConfigLoaded()
81
78 companion object { 82 companion object {
79 const val TYPE_HEADER = 0 83 const val TYPE_HEADER = 0
80 const val TYPE_SWITCH = 1 84 const val TYPE_SWITCH = 1
@@ -87,6 +91,7 @@ abstract class SettingsItem(
87 const val TYPE_INPUT = 8 91 const val TYPE_INPUT = 8
88 const val TYPE_INT_SINGLE_CHOICE = 9 92 const val TYPE_INT_SINGLE_CHOICE = 9
89 const val TYPE_INPUT_PROFILE = 10 93 const val TYPE_INPUT_PROFILE = 10
94 const val TYPE_STRING_INPUT = 11
90 95
91 const val FASTMEM_COMBINED = "fastmem_combined" 96 const val FASTMEM_COMBINED = "fastmem_combined"
92 97
@@ -105,6 +110,7 @@ abstract class SettingsItem(
105 110
106 // List of all general 111 // List of all general
107 val settingsItems = HashMap<String, SettingsItem>().apply { 112 val settingsItems = HashMap<String, SettingsItem>().apply {
113 put(StringInputSetting(StringSetting.DEVICE_NAME, titleId = R.string.device_name))
108 put( 114 put(
109 SwitchSetting( 115 SwitchSetting(
110 BooleanSetting.RENDERER_USE_SPEED_LIMIT, 116 BooleanSetting.RENDERER_USE_SPEED_LIMIT,
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/StringInputSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/StringInputSetting.kt
new file mode 100644
index 000000000..1eb999416
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/StringInputSetting.kt
@@ -0,0 +1,22 @@
1// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4package org.yuzu.yuzu_emu.features.settings.model.view
5
6import androidx.annotation.StringRes
7import org.yuzu.yuzu_emu.features.settings.model.AbstractStringSetting
8
9class StringInputSetting(
10 setting: AbstractStringSetting,
11 @StringRes titleId: Int = 0,
12 titleString: String = "",
13 @StringRes descriptionId: Int = 0,
14 descriptionString: String = ""
15) : SettingsItem(setting, titleId, titleString, descriptionId, descriptionString) {
16 override val type = TYPE_STRING_INPUT
17
18 fun getSelectedValue(needsGlobal: Boolean = false) = setting.getValueAsString(needsGlobal)
19
20 fun setSelectedValue(selection: String) =
21 (setting as AbstractStringSetting).setString(selection)
22}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt
index 45c8faa10..500ac6e66 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt
@@ -85,6 +85,10 @@ class SettingsAdapter(
85 InputProfileViewHolder(ListItemSettingBinding.inflate(inflater), this) 85 InputProfileViewHolder(ListItemSettingBinding.inflate(inflater), this)
86 } 86 }
87 87
88 SettingsItem.TYPE_STRING_INPUT -> {
89 StringInputViewHolder(ListItemSettingBinding.inflate(inflater), this)
90 }
91
88 else -> { 92 else -> {
89 HeaderViewHolder(ListItemSettingsHeaderBinding.inflate(inflater), this) 93 HeaderViewHolder(ListItemSettingsHeaderBinding.inflate(inflater), this)
90 } 94 }
@@ -392,6 +396,15 @@ class SettingsAdapter(
392 popup.show() 396 popup.show()
393 } 397 }
394 398
399 fun onStringInputClick(item: StringInputSetting, position: Int) {
400 SettingsDialogFragment.newInstance(
401 settingsViewModel,
402 item,
403 SettingsItem.TYPE_STRING_INPUT,
404 position
405 ).show(fragment.childFragmentManager, SettingsDialogFragment.TAG)
406 }
407
395 fun onLongClick(item: SettingsItem, position: Int): Boolean { 408 fun onLongClick(item: SettingsItem, position: Int): Boolean {
396 SettingsDialogFragment.newInstance( 409 SettingsDialogFragment.newInstance(
397 settingsViewModel, 410 settingsViewModel,
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsDialogFragment.kt
index a81ff6b1a..7f562a1f4 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsDialogFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsDialogFragment.kt
@@ -14,6 +14,7 @@ import androidx.fragment.app.activityViewModels
14import com.google.android.material.dialog.MaterialAlertDialogBuilder 14import com.google.android.material.dialog.MaterialAlertDialogBuilder
15import com.google.android.material.slider.Slider 15import com.google.android.material.slider.Slider
16import org.yuzu.yuzu_emu.R 16import org.yuzu.yuzu_emu.R
17import org.yuzu.yuzu_emu.databinding.DialogEditTextBinding
17import org.yuzu.yuzu_emu.databinding.DialogSliderBinding 18import org.yuzu.yuzu_emu.databinding.DialogSliderBinding
18import org.yuzu.yuzu_emu.features.input.NativeInput 19import org.yuzu.yuzu_emu.features.input.NativeInput
19import org.yuzu.yuzu_emu.features.input.model.AnalogDirection 20import org.yuzu.yuzu_emu.features.input.model.AnalogDirection
@@ -23,6 +24,7 @@ import org.yuzu.yuzu_emu.features.settings.model.view.IntSingleChoiceSetting
23import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem 24import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
24import org.yuzu.yuzu_emu.features.settings.model.view.SingleChoiceSetting 25import org.yuzu.yuzu_emu.features.settings.model.view.SingleChoiceSetting
25import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting 26import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting
27import org.yuzu.yuzu_emu.features.settings.model.view.StringInputSetting
26import org.yuzu.yuzu_emu.features.settings.model.view.StringSingleChoiceSetting 28import org.yuzu.yuzu_emu.features.settings.model.view.StringSingleChoiceSetting
27import org.yuzu.yuzu_emu.utils.ParamPackage 29import org.yuzu.yuzu_emu.utils.ParamPackage
28import org.yuzu.yuzu_emu.utils.collect 30import org.yuzu.yuzu_emu.utils.collect
@@ -37,6 +39,7 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener
37 private val settingsViewModel: SettingsViewModel by activityViewModels() 39 private val settingsViewModel: SettingsViewModel by activityViewModels()
38 40
39 private lateinit var sliderBinding: DialogSliderBinding 41 private lateinit var sliderBinding: DialogSliderBinding
42 private lateinit var stringInputBinding: DialogEditTextBinding
40 43
41 override fun onCreate(savedInstanceState: Bundle?) { 44 override fun onCreate(savedInstanceState: Bundle?) {
42 super.onCreate(savedInstanceState) 45 super.onCreate(savedInstanceState)
@@ -131,6 +134,18 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener
131 .create() 134 .create()
132 } 135 }
133 136
137 SettingsItem.TYPE_STRING_INPUT -> {
138 stringInputBinding = DialogEditTextBinding.inflate(layoutInflater)
139 val item = settingsViewModel.clickedItem as StringInputSetting
140 stringInputBinding.editText.setText(item.getSelectedValue())
141 MaterialAlertDialogBuilder(requireContext())
142 .setTitle(item.title)
143 .setView(stringInputBinding.root)
144 .setPositiveButton(android.R.string.ok, this)
145 .setNegativeButton(android.R.string.cancel, defaultCancelListener)
146 .create()
147 }
148
134 SettingsItem.TYPE_STRING_SINGLE_CHOICE -> { 149 SettingsItem.TYPE_STRING_SINGLE_CHOICE -> {
135 val item = settingsViewModel.clickedItem as StringSingleChoiceSetting 150 val item = settingsViewModel.clickedItem as StringSingleChoiceSetting
136 MaterialAlertDialogBuilder(requireContext()) 151 MaterialAlertDialogBuilder(requireContext())
@@ -158,6 +173,7 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener
158 ): View? { 173 ): View? {
159 return when (type) { 174 return when (type) {
160 SettingsItem.TYPE_SLIDER -> sliderBinding.root 175 SettingsItem.TYPE_SLIDER -> sliderBinding.root
176 SettingsItem.TYPE_STRING_INPUT -> stringInputBinding.root
161 else -> super.onCreateView(inflater, container, savedInstanceState) 177 else -> super.onCreateView(inflater, container, savedInstanceState)
162 } 178 }
163 } 179 }
@@ -200,6 +216,13 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener
200 val sliderSetting = settingsViewModel.clickedItem as SliderSetting 216 val sliderSetting = settingsViewModel.clickedItem as SliderSetting
201 sliderSetting.setSelectedValue(settingsViewModel.sliderProgress.value) 217 sliderSetting.setSelectedValue(settingsViewModel.sliderProgress.value)
202 } 218 }
219
220 is StringInputSetting -> {
221 val stringInputSetting = settingsViewModel.clickedItem as StringInputSetting
222 stringInputSetting.setSelectedValue(
223 (stringInputBinding.editText.text ?: "").toString()
224 )
225 }
203 } 226 }
204 closeDialog() 227 closeDialog()
205 } 228 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
index e491c29a2..3ea5f5008 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
@@ -23,6 +23,7 @@ import org.yuzu.yuzu_emu.features.settings.model.LongSetting
23import org.yuzu.yuzu_emu.features.settings.model.Settings 23import org.yuzu.yuzu_emu.features.settings.model.Settings
24import org.yuzu.yuzu_emu.features.settings.model.Settings.MenuTag 24import org.yuzu.yuzu_emu.features.settings.model.Settings.MenuTag
25import org.yuzu.yuzu_emu.features.settings.model.ShortSetting 25import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
26import org.yuzu.yuzu_emu.features.settings.model.StringSetting
26import org.yuzu.yuzu_emu.features.settings.model.view.* 27import org.yuzu.yuzu_emu.features.settings.model.view.*
27import org.yuzu.yuzu_emu.utils.InputHandler 28import org.yuzu.yuzu_emu.utils.InputHandler
28import org.yuzu.yuzu_emu.utils.NativeConfig 29import org.yuzu.yuzu_emu.utils.NativeConfig
@@ -153,6 +154,7 @@ class SettingsFragmentPresenter(
153 154
154 private fun addSystemSettings(sl: ArrayList<SettingsItem>) { 155 private fun addSystemSettings(sl: ArrayList<SettingsItem>) {
155 sl.apply { 156 sl.apply {
157 add(StringSetting.DEVICE_NAME.key)
156 add(BooleanSetting.RENDERER_USE_SPEED_LIMIT.key) 158 add(BooleanSetting.RENDERER_USE_SPEED_LIMIT.key)
157 add(ShortSetting.RENDERER_SPEED_LIMIT.key) 159 add(ShortSetting.RENDERER_SPEED_LIMIT.key)
158 add(BooleanSetting.USE_DOCKED_MODE.key) 160 add(BooleanSetting.USE_DOCKED_MODE.key)
@@ -778,7 +780,7 @@ class SettingsFragmentPresenter(
778 playerIndex: Int, 780 playerIndex: Int,
779 paramName: String, 781 paramName: String,
780 stick: NativeAnalog, 782 stick: NativeAnalog,
781 defaultValue: Int 783 defaultValue: Float
782 ): AbstractIntSetting = 784 ): AbstractIntSetting =
783 object : AbstractIntSetting { 785 object : AbstractIntSetting {
784 val params get() = NativeInput.getStickParam(playerIndex, stick) 786 val params get() = NativeInput.getStickParam(playerIndex, stick)
@@ -786,7 +788,7 @@ class SettingsFragmentPresenter(
786 override val key = "" 788 override val key = ""
787 789
788 override fun getInt(needsGlobal: Boolean): Int = 790 override fun getInt(needsGlobal: Boolean): Int =
789 (params.get(paramName, 0.15f) * 100).toInt() 791 (params.get(paramName, defaultValue) * 100).toInt()
790 792
791 override fun setInt(value: Int) { 793 override fun setInt(value: Int) {
792 val tempParams = params 794 val tempParams = params
@@ -794,12 +796,12 @@ class SettingsFragmentPresenter(
794 NativeInput.setStickParam(playerIndex, stick, tempParams) 796 NativeInput.setStickParam(playerIndex, stick, tempParams)
795 } 797 }
796 798
797 override val defaultValue = defaultValue 799 override val defaultValue = (defaultValue * 100).toInt()
798 800
799 override fun getValueAsString(needsGlobal: Boolean): String = 801 override fun getValueAsString(needsGlobal: Boolean): String =
800 getInt(needsGlobal).toString() 802 getInt(needsGlobal).toString()
801 803
802 override fun reset() = setInt(defaultValue) 804 override fun reset() = setInt(this.defaultValue)
803 } 805 }
804 806
805 private fun getExtraStickSettings( 807 private fun getExtraStickSettings(
@@ -809,11 +811,11 @@ class SettingsFragmentPresenter(
809 val stickIsController = 811 val stickIsController =
810 NativeInput.isController(NativeInput.getStickParam(playerIndex, nativeAnalog)) 812 NativeInput.isController(NativeInput.getStickParam(playerIndex, nativeAnalog))
811 val modifierRangeSetting = 813 val modifierRangeSetting =
812 getStickIntSettingFromParam(playerIndex, "modifier_scale", nativeAnalog, 50) 814 getStickIntSettingFromParam(playerIndex, "modifier_scale", nativeAnalog, 0.5f)
813 val stickRangeSetting = 815 val stickRangeSetting =
814 getStickIntSettingFromParam(playerIndex, "range", nativeAnalog, 95) 816 getStickIntSettingFromParam(playerIndex, "range", nativeAnalog, 0.95f)
815 val stickDeadzoneSetting = 817 val stickDeadzoneSetting =
816 getStickIntSettingFromParam(playerIndex, "deadzone", nativeAnalog, 15) 818 getStickIntSettingFromParam(playerIndex, "deadzone", nativeAnalog, 0.15f)
817 819
818 val out = mutableListOf<SettingsItem>().apply { 820 val out = mutableListOf<SettingsItem>().apply {
819 if (stickIsController) { 821 if (stickIsController) {
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt
index 367db7fd2..0309fad59 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt
@@ -13,7 +13,6 @@ import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
13import org.yuzu.yuzu_emu.features.settings.model.view.DateTimeSetting 13import org.yuzu.yuzu_emu.features.settings.model.view.DateTimeSetting
14import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem 14import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
15import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter 15import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
16import org.yuzu.yuzu_emu.utils.NativeConfig
17import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible 16import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
18 17
19class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) : 18class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) :
@@ -32,9 +31,7 @@ class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
32 val dateFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM) 31 val dateFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
33 binding.textSettingValue.text = dateFormatter.format(zonedTime) 32 binding.textSettingValue.text = dateFormatter.format(zonedTime)
34 33
35 binding.buttonClear.setVisible( 34 binding.buttonClear.setVisible(setting.clearable)
36 !setting.setting.global || NativeConfig.isPerGameConfigLoaded()
37 )
38 binding.buttonClear.setOnClickListener { 35 binding.buttonClear.setOnClickListener {
39 adapter.onClearClick(setting, bindingAdapterPosition) 36 adapter.onClearClick(setting, bindingAdapterPosition)
40 } 37 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt
index e2fe0b072..489f55455 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt
@@ -10,7 +10,6 @@ import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
10import org.yuzu.yuzu_emu.features.settings.model.view.SingleChoiceSetting 10import org.yuzu.yuzu_emu.features.settings.model.view.SingleChoiceSetting
11import org.yuzu.yuzu_emu.features.settings.model.view.StringSingleChoiceSetting 11import org.yuzu.yuzu_emu.features.settings.model.view.StringSingleChoiceSetting
12import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter 12import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
13import org.yuzu.yuzu_emu.utils.NativeConfig
14import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible 13import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
15 14
16class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) : 15class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) :
@@ -48,9 +47,7 @@ class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Setti
48 binding.textSettingValue.setVisible(false) 47 binding.textSettingValue.setVisible(false)
49 } 48 }
50 49
51 binding.buttonClear.setVisible( 50 binding.buttonClear.setVisible(setting.clearable)
52 !setting.setting.global || NativeConfig.isPerGameConfigLoaded()
53 )
54 binding.buttonClear.setOnClickListener { 51 binding.buttonClear.setOnClickListener {
55 adapter.onClearClick(setting, bindingAdapterPosition) 52 adapter.onClearClick(setting, bindingAdapterPosition)
56 } 53 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SliderViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SliderViewHolder.kt
index a37b59b44..90a7138cb 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SliderViewHolder.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SliderViewHolder.kt
@@ -9,7 +9,6 @@ import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
9import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem 9import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
10import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting 10import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting
11import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter 11import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
12import org.yuzu.yuzu_emu.utils.NativeConfig
13import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible 12import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
14 13
15class SliderViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) : 14class SliderViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) :
@@ -28,9 +27,7 @@ class SliderViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAda
28 setting.units 27 setting.units
29 ) 28 )
30 29
31 binding.buttonClear.setVisible( 30 binding.buttonClear.setVisible(setting.clearable)
32 !setting.setting.global || NativeConfig.isPerGameConfigLoaded()
33 )
34 binding.buttonClear.setOnClickListener { 31 binding.buttonClear.setOnClickListener {
35 adapter.onClearClick(setting, bindingAdapterPosition) 32 adapter.onClearClick(setting, bindingAdapterPosition)
36 } 33 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/StringInputViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/StringInputViewHolder.kt
new file mode 100644
index 000000000..a4fd36f62
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/StringInputViewHolder.kt
@@ -0,0 +1,45 @@
1// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4package org.yuzu.yuzu_emu.features.settings.ui.viewholder
5
6import android.view.View
7import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
8import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
9import org.yuzu.yuzu_emu.features.settings.model.view.StringInputSetting
10import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
11import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
12
13class StringInputViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) :
14 SettingViewHolder(binding.root, adapter) {
15 private lateinit var setting: StringInputSetting
16
17 override fun bind(item: SettingsItem) {
18 setting = item as StringInputSetting
19 binding.textSettingName.text = setting.title
20 binding.textSettingDescription.setVisible(setting.description.isNotEmpty())
21 binding.textSettingDescription.text = setting.description
22 binding.textSettingValue.setVisible(true)
23 binding.textSettingValue.text = setting.getSelectedValue()
24
25 binding.buttonClear.setVisible(setting.clearable)
26 binding.buttonClear.setOnClickListener {
27 adapter.onClearClick(setting, bindingAdapterPosition)
28 }
29
30 setStyle(setting.isEditable, binding)
31 }
32
33 override fun onClick(clicked: View) {
34 if (setting.isEditable) {
35 adapter.onStringInputClick(setting, bindingAdapterPosition)
36 }
37 }
38
39 override fun onLongClick(clicked: View): Boolean {
40 if (setting.isEditable) {
41 return adapter.onLongClick(setting, bindingAdapterPosition)
42 }
43 return false
44 }
45}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt
index 53f7b301f..e5763264a 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt
@@ -9,7 +9,6 @@ import org.yuzu.yuzu_emu.databinding.ListItemSettingSwitchBinding
9import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem 9import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
10import org.yuzu.yuzu_emu.features.settings.model.view.SwitchSetting 10import org.yuzu.yuzu_emu.features.settings.model.view.SwitchSetting
11import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter 11import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
12import org.yuzu.yuzu_emu.utils.NativeConfig
13import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible 12import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
14 13
15class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter: SettingsAdapter) : 14class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter: SettingsAdapter) :
@@ -29,9 +28,7 @@ class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter
29 adapter.onBooleanClick(setting, binding.switchWidget.isChecked, bindingAdapterPosition) 28 adapter.onBooleanClick(setting, binding.switchWidget.isChecked, bindingAdapterPosition)
30 } 29 }
31 30
32 binding.buttonClear.setVisible( 31 binding.buttonClear.setVisible(setting.clearable)
33 !setting.setting.global || NativeConfig.isPerGameConfigLoaded()
34 )
35 binding.buttonClear.setOnClickListener { 32 binding.buttonClear.setOnClickListener {
36 adapter.onClearClick(setting, bindingAdapterPosition) 33 adapter.onClearClick(setting, bindingAdapterPosition)
37 } 34 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
index c3b2b11f8..bcc880e17 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
@@ -810,7 +810,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
810 } 810 }
811 } 811 }
812 } 812 }
813 binding.doneControlConfig.setVisible(false) 813 binding.doneControlConfig.setVisible(true)
814 binding.surfaceInputOverlay.setIsInEditMode(true) 814 binding.surfaceInputOverlay.setIsInEditMode(true)
815 } 815 }
816 816
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt
index 66907085a..737e03584 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt
@@ -28,6 +28,7 @@ import org.yuzu.yuzu_emu.features.input.NativeInput
28import org.yuzu.yuzu_emu.R 28import org.yuzu.yuzu_emu.R
29import org.yuzu.yuzu_emu.features.input.model.NativeAnalog 29import org.yuzu.yuzu_emu.features.input.model.NativeAnalog
30import org.yuzu.yuzu_emu.features.input.model.NativeButton 30import org.yuzu.yuzu_emu.features.input.model.NativeButton
31import org.yuzu.yuzu_emu.features.input.model.NpadStyleIndex
31import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting 32import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
32import org.yuzu.yuzu_emu.features.settings.model.IntSetting 33import org.yuzu.yuzu_emu.features.settings.model.IntSetting
33import org.yuzu.yuzu_emu.overlay.model.OverlayControl 34import org.yuzu.yuzu_emu.overlay.model.OverlayControl
@@ -99,12 +100,10 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
99 } 100 }
100 101
101 var shouldUpdateView = false 102 var shouldUpdateView = false
102 val playerIndex = 103 val playerIndex = when (NativeInput.getStyleIndex(0)) {
103 if (NativeInput.isHandheldOnly()) { 104 NpadStyleIndex.Handheld -> 8
104 NativeInput.ConsoleDevice 105 else -> 0
105 } else { 106 }
106 NativeInput.Player1Device
107 }
108 107
109 for (button in overlayButtons) { 108 for (button in overlayButtons) {
110 if (!button.updateStatus(event)) { 109 if (!button.updateStatus(event)) {
@@ -664,7 +663,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
664 663
665 val overlayControlData = NativeConfig.getOverlayControlData() 664 val overlayControlData = NativeConfig.getOverlayControlData()
666 overlayControlData.forEach { 665 overlayControlData.forEach {
667 it.enabled = OverlayControl.from(it.id)?.defaultVisibility == false 666 it.enabled = OverlayControl.from(it.id)?.defaultVisibility == true
668 } 667 }
669 NativeConfig.setOverlayControlData(overlayControlData) 668 NativeConfig.setOverlayControlData(overlayControlData)
670 669
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index fa2300ae6..5d484a85e 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -292,6 +292,9 @@ void EmulationSession::ShutdownEmulation() {
292 // Unload user input. 292 // Unload user input.
293 m_system.HIDCore().UnloadInputDevices(); 293 m_system.HIDCore().UnloadInputDevices();
294 294
295 // Enable all controllers
296 m_system.HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All});
297
295 // Shutdown the main emulated process 298 // Shutdown the main emulated process
296 if (m_load_result == Core::SystemResultStatus::Success) { 299 if (m_load_result == Core::SystemResultStatus::Success) {
297 m_system.DetachDebugger(); 300 m_system.DetachDebugger();
diff --git a/src/android/app/src/main/jni/native_input.cpp b/src/android/app/src/main/jni/native_input.cpp
index 37a65f2b8..4935a4607 100644
--- a/src/android/app/src/main/jni/native_input.cpp
+++ b/src/android/app/src/main/jni/native_input.cpp
@@ -102,8 +102,50 @@ void ApplyControllerConfig(size_t player_index,
102 } 102 }
103} 103}
104 104
105std::vector<s32> GetSupportedStyles(int player_index) {
106 auto& hid_core = EmulationSession::GetInstance().System().HIDCore();
107 const auto npad_style_set = hid_core.GetSupportedStyleTag();
108 std::vector<s32> supported_indexes;
109 if (npad_style_set.fullkey == 1) {
110 supported_indexes.push_back(static_cast<s32>(Core::HID::NpadStyleIndex::Fullkey));
111 }
112
113 if (npad_style_set.joycon_dual == 1) {
114 supported_indexes.push_back(static_cast<s32>(Core::HID::NpadStyleIndex::JoyconDual));
115 }
116
117 if (npad_style_set.joycon_left == 1) {
118 supported_indexes.push_back(static_cast<s32>(Core::HID::NpadStyleIndex::JoyconLeft));
119 }
120
121 if (npad_style_set.joycon_right == 1) {
122 supported_indexes.push_back(static_cast<s32>(Core::HID::NpadStyleIndex::JoyconRight));
123 }
124
125 if (player_index == 0 && npad_style_set.handheld == 1) {
126 supported_indexes.push_back(static_cast<s32>(Core::HID::NpadStyleIndex::Handheld));
127 }
128
129 if (npad_style_set.gamecube == 1) {
130 supported_indexes.push_back(static_cast<s32>(Core::HID::NpadStyleIndex::GameCube));
131 }
132
133 return supported_indexes;
134}
135
105void ConnectController(size_t player_index, bool connected) { 136void ConnectController(size_t player_index, bool connected) {
106 auto& hid_core = EmulationSession::GetInstance().System().HIDCore(); 137 auto& hid_core = EmulationSession::GetInstance().System().HIDCore();
138 ApplyControllerConfig(player_index, [&](Core::HID::EmulatedController* controller) {
139 auto supported_styles = GetSupportedStyles(player_index);
140 auto controller_style = controller->GetNpadStyleIndex(true);
141 auto style = std::find(supported_styles.begin(), supported_styles.end(),
142 static_cast<int>(controller_style));
143 if (style == supported_styles.end() && !supported_styles.empty()) {
144 controller->SetNpadStyleIndex(
145 static_cast<Core::HID::NpadStyleIndex>(supported_styles[0]));
146 }
147 });
148
107 if (player_index == 0) { 149 if (player_index == 0) {
108 auto* handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); 150 auto* handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
109 auto* player_one = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); 151 auto* player_one = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
@@ -522,36 +564,10 @@ jint Java_org_yuzu_yuzu_1emu_features_input_NativeInput_getButtonNameImpl(JNIEnv
522 564
523jintArray Java_org_yuzu_yuzu_1emu_features_input_NativeInput_getSupportedStyleTagsImpl( 565jintArray Java_org_yuzu_yuzu_1emu_features_input_NativeInput_getSupportedStyleTagsImpl(
524 JNIEnv* env, jobject j_obj, jint j_player_index) { 566 JNIEnv* env, jobject j_obj, jint j_player_index) {
525 auto& hid_core = EmulationSession::GetInstance().System().HIDCore(); 567 auto supported_styles = GetSupportedStyles(j_player_index);
526 const auto npad_style_set = hid_core.GetSupportedStyleTag(); 568 jintArray j_supported_indexes = env->NewIntArray(supported_styles.size());
527 std::vector<s32> supported_indexes; 569 env->SetIntArrayRegion(j_supported_indexes, 0, supported_styles.size(),
528 if (npad_style_set.fullkey == 1) { 570 supported_styles.data());
529 supported_indexes.push_back(static_cast<u32>(Core::HID::NpadStyleIndex::Fullkey));
530 }
531
532 if (npad_style_set.joycon_dual == 1) {
533 supported_indexes.push_back(static_cast<u32>(Core::HID::NpadStyleIndex::JoyconDual));
534 }
535
536 if (npad_style_set.joycon_left == 1) {
537 supported_indexes.push_back(static_cast<u32>(Core::HID::NpadStyleIndex::JoyconLeft));
538 }
539
540 if (npad_style_set.joycon_right == 1) {
541 supported_indexes.push_back(static_cast<u32>(Core::HID::NpadStyleIndex::JoyconRight));
542 }
543
544 if (j_player_index == 0 && npad_style_set.handheld == 1) {
545 supported_indexes.push_back(static_cast<u32>(Core::HID::NpadStyleIndex::Handheld));
546 }
547
548 if (npad_style_set.gamecube == 1) {
549 supported_indexes.push_back(static_cast<u32>(Core::HID::NpadStyleIndex::GameCube));
550 }
551
552 jintArray j_supported_indexes = env->NewIntArray(supported_indexes.size());
553 env->SetIntArrayRegion(j_supported_indexes, 0, supported_indexes.size(),
554 supported_indexes.data());
555 return j_supported_indexes; 571 return j_supported_indexes;
556} 572}
557 573
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index 6a631f664..f7f19cdad 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -209,6 +209,7 @@
209 <string name="value_with_units">%1$s%2$s</string> 209 <string name="value_with_units">%1$s%2$s</string>
210 210
211 <!-- System settings strings --> 211 <!-- System settings strings -->
212 <string name="device_name">Device name</string>
212 <string name="use_docked_mode">Docked Mode</string> 213 <string name="use_docked_mode">Docked Mode</string>
213 <string name="use_docked_mode_description">Increases resolution, decreasing performance. Handheld Mode is used when disabled, lowering resolution and increasing performance.</string> 214 <string name="use_docked_mode_description">Increases resolution, decreasing performance. Handheld Mode is used when disabled, lowering resolution and increasing performance.</string>
214 <string name="emulated_region">Emulated region</string> 215 <string name="emulated_region">Emulated region</string>