mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2026-04-10 11:21:35 -06:00
Merge 485778be95 into 000530c028
This commit is contained in:
commit
7e4084c2aa
@ -962,6 +962,7 @@ object NativeLibrary {
|
||||
const val BUTTON_GPIO14 = 782
|
||||
const val BUTTON_SWAP = 800
|
||||
const val BUTTON_TURBO = 801
|
||||
const val BUTTON_COMBO = 802
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -56,7 +56,8 @@ 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);
|
||||
USE_INTEGER_SCALING(SettingKeys.use_integer_scaling(), Settings.SECTION_RENDERER, false),
|
||||
ENABLE_COMBO_KEY("enable_combo_key", Settings.SECTION_CONTROLS, true);
|
||||
|
||||
override var boolean: Boolean = defaultValue
|
||||
|
||||
|
||||
@ -115,6 +115,7 @@ 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"
|
||||
@ -130,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 +154,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 +164,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,
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
// 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<String>,
|
||||
val canBeEmpty: Boolean = true
|
||||
) : AbstractListSetting<String> {
|
||||
COMBO_KEYS("combo_keys", Settings.SECTION_CONTROLS, listOf("A", "B", "X", "Y", "L", "R", "ZL", "ZR", "Start", "Select"));
|
||||
|
||||
private var backingList: List<String> = defaultValue
|
||||
private var lastValidList : List<String> = defaultValue
|
||||
|
||||
override var list: List<String>
|
||||
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<StringListSetting> = listOf();
|
||||
|
||||
|
||||
fun from(key: String): StringListSetting? =
|
||||
values().firstOrNull { it.key == key }
|
||||
|
||||
fun clear() = values().forEach { it.list = it.defaultValue }
|
||||
}
|
||||
}
|
||||
@ -125,6 +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_UP -> NativeLibrary.ButtonType.DPAD_UP
|
||||
Settings.KEY_BUTTON_DOWN -> NativeLibrary.ButtonType.DPAD_DOWN
|
||||
Settings.KEY_BUTTON_LEFT -> NativeLibrary.ButtonType.DPAD_LEFT
|
||||
@ -522,6 +523,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
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
// 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<String>,
|
||||
val values: Array<String>?,
|
||||
val key: String? = null,
|
||||
private val defaultValue: List<String>? = 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<String>
|
||||
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<String>): StringListSetting {
|
||||
val stringSetting = setting as StringListSetting
|
||||
stringSetting.list = selection
|
||||
return stringSetting
|
||||
}
|
||||
}
|
||||
@ -44,6 +44,7 @@ import org.citra.citra_emu.features.settings.model.FloatSetting
|
||||
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.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.SettingsItem
|
||||
@ -51,6 +52,7 @@ 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
|
||||
@ -137,6 +139,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)
|
||||
@ -198,9 +204,14 @@ 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
|
||||
}
|
||||
|
||||
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
|
||||
@ -271,6 +282,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 {
|
||||
@ -571,15 +602,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()))
|
||||
fragmentView?.putSetting(setting)
|
||||
fragmentView?.onSettingChanged()
|
||||
}
|
||||
fragmentView.loadSettingsList()
|
||||
}
|
||||
}
|
||||
fragmentView.loadSettingsList()
|
||||
}
|
||||
}
|
||||
|
||||
@ -714,6 +764,7 @@ class SettingsAdapter(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun getSelectionForSingleChoiceValue(item: SingleChoiceSetting): Int {
|
||||
val value = item.selectedValue
|
||||
val valuesId = item.valuesId
|
||||
@ -746,4 +797,27 @@ 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 };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,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
|
||||
@ -41,6 +42,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
|
||||
@ -778,6 +780,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
|
||||
private fun addControlsSettings(sl: ArrayList<SettingsItem>) {
|
||||
settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_controls))
|
||||
|
||||
sl.apply {
|
||||
add(
|
||||
RunnableSetting(
|
||||
@ -839,9 +842,24 @@ 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(
|
||||
StringListSetting.COMBO_KEYS,
|
||||
R.string.combo_key_options,
|
||||
R.string.combo_key_description,
|
||||
buttons,
|
||||
buttons,
|
||||
StringListSetting.COMBO_KEYS.key,
|
||||
StringListSetting.COMBO_KEYS.defaultValue
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private fun getInputObject(key: String): AbstractStringSetting {
|
||||
return object : AbstractStringSetting {
|
||||
override var string: String
|
||||
|
||||
@ -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<String> = 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 {
|
||||
|
||||
@ -17,6 +17,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
|
||||
@ -256,6 +257,11 @@ object SettingsFile {
|
||||
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() }
|
||||
|
||||
@ -831,6 +831,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
|
||||
@ -1048,13 +1053,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) {
|
||||
// TODO: Remove these magic numbers
|
||||
6, 7, 12, 13, 14, 15 -> defaultValue = false
|
||||
6, 7, 12, 13, 14, 15, 16 -> defaultValue = false
|
||||
}
|
||||
enabledButtons[i] = preferences.getBoolean("buttonToggle$i", defaultValue)
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -157,6 +158,7 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex
|
||||
NativeLibrary.onTouchEvent(0f, 0f, false)
|
||||
break // Up and down actions shouldn't loop
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var anyOverlayStateChanged = false
|
||||
@ -175,6 +177,9 @@ 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) {
|
||||
ComboHelper.comboActivate(button)
|
||||
}
|
||||
|
||||
NativeLibrary.onGamePadEvent(
|
||||
NativeLibrary.TouchScreenDevice,
|
||||
@ -568,6 +573,18 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (preferences.getBoolean("buttonToggle16", false)) {
|
||||
overlayButtons.add(
|
||||
initializeOverlayButton(
|
||||
context,
|
||||
R.drawable.button_combo,
|
||||
R.drawable.button_combo_pressed,
|
||||
NativeLibrary.ButtonType.BUTTON_COMBO,
|
||||
orientation
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun refreshControls() {
|
||||
@ -781,6 +798,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()
|
||||
}
|
||||
|
||||
@ -932,6 +957,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_PORTRAIT_X).toFloat() / 1000 * maxX
|
||||
)
|
||||
.putFloat(
|
||||
NativeLibrary.ButtonType.BUTTON_COMBO.toString() + portrait + "-Y",
|
||||
resources.getInteger(R.integer.N3DS_BUTTON_COMBO_PORTRAIT_Y).toFloat() / 1000 * maxY
|
||||
)
|
||||
.apply()
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
// 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.NativeLibrary
|
||||
import org.citra.citra_emu.overlay.InputOverlayDrawableButton
|
||||
import org.citra.citra_emu.features.settings.model.StringListSetting
|
||||
|
||||
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) {
|
||||
val comboArray = StringListSetting.COMBO_KEYS.list
|
||||
for (selected_button in comboArray) {
|
||||
val native_button = getButton(selected_button)
|
||||
if (native_button == -1)
|
||||
{
|
||||
val cause = IllegalStateException("Button is not in bindable inputs.")
|
||||
throw IllegalArgumentException("Input must be non-negative.", cause)
|
||||
}
|
||||
else
|
||||
{
|
||||
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, native_button, button.status)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
32
src/android/app/src/main/res/drawable/button_combo.xml
Normal file
32
src/android/app/src/main/res/drawable/button_combo.xml
Normal file
@ -0,0 +1,32 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="100dp"
|
||||
android:height="100dp"
|
||||
android:viewportWidth="99.27"
|
||||
android:viewportHeight="99.27">
|
||||
|
||||
<!-- Outer circle -->
|
||||
<path
|
||||
android:fillAlpha="0.5"
|
||||
android:fillColor="#eaeaea"
|
||||
android:pathData="M49.64,49.64m-49.64,0a49.64,49.64 0,1 1,99.28 0a49.64,49.64 0,1 1,-99.28 0"
|
||||
android:strokeAlpha="0.5" />
|
||||
|
||||
<!-- Centered blocky "C" icon -->
|
||||
<path
|
||||
android:fillAlpha="0.75"
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M42,30
|
||||
H62
|
||||
V40
|
||||
H47
|
||||
V60
|
||||
H62
|
||||
V70
|
||||
H42
|
||||
V60
|
||||
H37
|
||||
V40
|
||||
H42
|
||||
Z"
|
||||
android:strokeAlpha="0.75" />
|
||||
</vector>
|
||||
@ -0,0 +1,28 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="100dp"
|
||||
android:height="100dp"
|
||||
android:viewportWidth="99.27"
|
||||
android:viewportHeight="99.27">
|
||||
<path
|
||||
android:fillAlpha="0.5"
|
||||
android:fillColor="#151515"
|
||||
android:pathData="M49.64,49.64m-49.64,0a49.64,49.64 0,1 1,99.28 0a49.64,49.64 0,1 1,-99.28 0"
|
||||
android:strokeAlpha="0.5" />
|
||||
<path
|
||||
android:fillAlpha="0.75"
|
||||
android:fillColor="#fff"
|
||||
android:pathData="M42,30
|
||||
H62
|
||||
V40
|
||||
H47
|
||||
V60
|
||||
H62
|
||||
V70
|
||||
H42
|
||||
V60
|
||||
H37
|
||||
V40
|
||||
H42
|
||||
Z"
|
||||
android:strokeAlpha="0.75" />
|
||||
</vector>
|
||||
@ -79,6 +79,9 @@
|
||||
<item
|
||||
android:id="@+id/menu_emulation_adjust_scale_button_swap"
|
||||
android:title="@string/button_swap" />
|
||||
<item
|
||||
android:id="@+id/menu_emulation_adjust_scale_button_combo"
|
||||
android:title="@string/button_combo" />
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
|
||||
@ -181,6 +181,7 @@
|
||||
<item>@string/button_home</item>
|
||||
<item>@string/button_swap</item>
|
||||
<item>@string/button_turbo</item>
|
||||
<item>@string/button_combo</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="cameraImageSourceNames">
|
||||
|
||||
@ -35,6 +35,8 @@
|
||||
<integer name="N3DS_BUTTON_SWAP_Y">850</integer>
|
||||
<integer name="N3DS_BUTTON_TURBO_X">630</integer>
|
||||
<integer name="N3DS_BUTTON_TURBO_Y">850</integer>
|
||||
<integer name="N3DS_BUTTON_COMBO_X">740</integer>
|
||||
<integer name="N3DS_BUTTON_COMBO_Y">480</integer>
|
||||
|
||||
<!-- Default N3DS portrait layout -->
|
||||
<integer name="N3DS_BUTTON_A_PORTRAIT_X">810</integer>
|
||||
@ -69,5 +71,7 @@
|
||||
<integer name="N3DS_BUTTON_SWAP_PORTRAIT_Y">675</integer>
|
||||
<integer name="N3DS_BUTTON_TURBO_PORTRAIT_X">453</integer>
|
||||
<integer name="N3DS_BUTTON_TURBO_PORTRAIT_Y">720</integer>
|
||||
<integer name="N3DS_BUTTON_COMBO_PORTRAIT_X">445</integer>
|
||||
<integer name="N3DS_BUTTON_COMBO_PORTRAIT_Y">925</integer>
|
||||
|
||||
</resources>
|
||||
|
||||
@ -156,6 +156,7 @@
|
||||
<string name="button_home">HOME</string>
|
||||
<string name="button_swap">Swap Screens</string>
|
||||
<string name="button_turbo">Turbo</string>
|
||||
<string name="button_combo">Combo Key</string>
|
||||
<string name="button_x" translatable="false">X</string>
|
||||
<string name="button_y" translatable="false">Y</string>
|
||||
<string name="button_l" translatable="false">L</string>
|
||||
@ -167,6 +168,10 @@
|
||||
<string name="turbo_limit_hotkey">Turbo Speed</string>
|
||||
<string name="turbo_enabled_toast">Turbo Speed Enabled</string>
|
||||
<string name="turbo_disabled_toast">Turbo Speed Disabled</string>
|
||||
<string name="combo_key_enable">Enable Combo Button</string>
|
||||
<string name="combo_key_options">Combo Key Settings</string>
|
||||
<string name="combo_key_description">Enable and Change Combo Button Bindings.</string>
|
||||
<string name="combo_key_submenu_description">Changes whether or not Combo Button can be displayed and used in game.</string>
|
||||
|
||||
<!-- System files strings -->
|
||||
<string name="setup_system_files">System Files</string>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user