mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2025-03-14 01:32:25 +01:00
Merge c7f6d2d679ff600942b388ddebacd8fdd2b51bcb into 26ce7e4f2844a445bf77b4b14977d62e6434df08
This commit is contained in:
commit
5e57417ebf
@ -16,6 +16,7 @@ import org.citra.citra_emu.NativeLibrary
|
|||||||
import org.citra.citra_emu.R
|
import org.citra.citra_emu.R
|
||||||
import org.citra.citra_emu.features.hotkeys.Hotkey
|
import org.citra.citra_emu.features.hotkeys.Hotkey
|
||||||
import org.citra.citra_emu.features.settings.model.AbstractSetting
|
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.Settings
|
import org.citra.citra_emu.features.settings.model.Settings
|
||||||
|
|
||||||
class InputBindingSetting(
|
class InputBindingSetting(
|
||||||
@ -34,6 +35,8 @@ class InputBindingSetting(
|
|||||||
.apply()
|
.apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var key: String = ""
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this key is for the 3DS Circle Pad
|
* Returns true if this key is for the 3DS Circle Pad
|
||||||
*/
|
*/
|
||||||
@ -229,6 +232,29 @@ class InputBindingSetting(
|
|||||||
value = uiString
|
value = uiString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the provided key input setting as an Android preference.
|
||||||
|
* Only gets applied when apply(); is called.
|
||||||
|
*
|
||||||
|
* @param keyEvent KeyEvent of this key press.
|
||||||
|
*/
|
||||||
|
fun onKeyInputDeferred(keyEvent: KeyEvent) {
|
||||||
|
if (!isButtonMappingSupported()) {
|
||||||
|
Toast.makeText(context, R.string.input_message_analog_only, Toast.LENGTH_LONG).show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
key = getInputButtonKey(keyEvent.keyCode)
|
||||||
|
val uiString = "${keyEvent.device.name}: Button ${keyEvent.keyCode}"
|
||||||
|
value = uiString
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the provided key input setting as an Android preference.
|
||||||
|
*/
|
||||||
|
fun applyMapping() {
|
||||||
|
writeButtonMapping(key)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the provided motion input setting as an Android preference.
|
* Saves the provided motion input setting as an Android preference.
|
||||||
*
|
*
|
||||||
@ -329,5 +355,22 @@ class InputBindingSetting(
|
|||||||
event.keyCode
|
event.keyCode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getInputObject(key: String, preferences: SharedPreferences): AbstractStringSetting {
|
||||||
|
return object : AbstractStringSetting {
|
||||||
|
override var string: String
|
||||||
|
get() = preferences.getString(key, "")!!
|
||||||
|
set(value) {
|
||||||
|
preferences.edit()
|
||||||
|
.putString(key, value)
|
||||||
|
.apply()
|
||||||
|
}
|
||||||
|
override val key = key
|
||||||
|
override val section = Settings.SECTION_CONTROLS
|
||||||
|
override val isRuntimeEditable = true
|
||||||
|
override val valueAsString = preferences.getString(key, "")!!
|
||||||
|
override val defaultValue = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,237 @@
|
|||||||
|
package org.citra.citra_emu.features.settings.ui
|
||||||
|
|
||||||
|
import android.app.AlertDialog
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.view.InputDevice
|
||||||
|
import android.view.KeyEvent
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.View
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import org.citra.citra_emu.R
|
||||||
|
import org.citra.citra_emu.databinding.DialogControllerQuickConfigBinding
|
||||||
|
import org.citra.citra_emu.features.settings.model.view.InputBindingSetting
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
|
||||||
|
class ControllerQuickConfigDialog(
|
||||||
|
private var context: Context,
|
||||||
|
buttons: ArrayList<List<String>>,
|
||||||
|
titles: ArrayList<List<Int>>,
|
||||||
|
private var preferences: SharedPreferences
|
||||||
|
) {
|
||||||
|
private var index = 0
|
||||||
|
val inflater = LayoutInflater.from(context)
|
||||||
|
val quickConfigBinding = DialogControllerQuickConfigBinding.inflate(inflater)
|
||||||
|
var dialog: AlertDialog? = null
|
||||||
|
|
||||||
|
var allButtons = arrayListOf<String>()
|
||||||
|
var allTitles = arrayListOf<Int>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
buttons.forEach {group ->
|
||||||
|
group.forEach {button ->
|
||||||
|
allButtons.add(button)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
titles.forEach {group ->
|
||||||
|
group.forEach {title ->
|
||||||
|
allTitles.add(title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun show() {
|
||||||
|
val builder: AlertDialog.Builder = AlertDialog.Builder(context)
|
||||||
|
builder
|
||||||
|
.setView(quickConfigBinding.root)
|
||||||
|
.setTitle(context.getString(R.string.controller_quick_config))
|
||||||
|
.setPositiveButton(context.getString(R.string.controller_quick_config_next)) {_,_ -> }
|
||||||
|
.setNegativeButton(context.getString(R.string.controller_quick_config_close)) { dialog, which ->
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog = builder.create()
|
||||||
|
dialog?.show()
|
||||||
|
|
||||||
|
dialog?.setOnKeyListener { _, _, event -> onKeyEvent(event) }
|
||||||
|
quickConfigBinding.root.setOnGenericMotionListener { _, event -> onMotionEvent(event) }
|
||||||
|
|
||||||
|
// Prepare the first element
|
||||||
|
prepareUIforIndex(index)
|
||||||
|
|
||||||
|
val nextButton = dialog?.getButton(AlertDialog.BUTTON_POSITIVE)
|
||||||
|
nextButton?.setOnClickListener {
|
||||||
|
// Skip to next:
|
||||||
|
prepareUIforIndex(index++)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun prepareUIforIndex(i: Int) {
|
||||||
|
if (allButtons.size-1 < i) {
|
||||||
|
settingsList.forEach { it.applyMapping() }
|
||||||
|
dialog?.dismiss()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index>0) {
|
||||||
|
quickConfigBinding.lastMappingIcon.visibility = View.VISIBLE
|
||||||
|
quickConfigBinding.lastMappingDescription.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
val currentButton = allButtons[i]
|
||||||
|
val currentTitleInt = allTitles[i]
|
||||||
|
|
||||||
|
val button = InputBindingSetting.getInputObject(currentButton, preferences)
|
||||||
|
|
||||||
|
var lastTitle = setting?.value ?: ""
|
||||||
|
if (lastTitle.isBlank()) {
|
||||||
|
lastTitle = context.getString(R.string.controller_quick_config_unassigned)
|
||||||
|
}
|
||||||
|
quickConfigBinding.lastMappingDescription.text = lastTitle
|
||||||
|
quickConfigBinding.lastMappingIcon.setImageDrawable(quickConfigBinding.currentMappingIcon.drawable)
|
||||||
|
|
||||||
|
setting = InputBindingSetting(button, currentTitleInt)
|
||||||
|
quickConfigBinding.currentMappingTitle.text = calculateTitle()
|
||||||
|
quickConfigBinding.currentMappingDescription.text = setting?.value
|
||||||
|
quickConfigBinding.currentMappingIcon.setImageDrawable(getIcon())
|
||||||
|
|
||||||
|
if (allButtons.size-1 < index) {
|
||||||
|
dialog?.getButton(AlertDialog.BUTTON_POSITIVE)?.text =
|
||||||
|
context.getString(R.string.controller_quick_config_finish)
|
||||||
|
dialog?.getButton(AlertDialog.BUTTON_NEGATIVE)?.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun calculateTitle(): String {
|
||||||
|
val inputTypeId = when {
|
||||||
|
setting!!.isCirclePad() -> R.string.controller_circlepad
|
||||||
|
setting!!.isCStick() -> R.string.controller_c
|
||||||
|
setting!!.isDPad() -> R.string.controller_dpad
|
||||||
|
setting!!.isTrigger() -> R.string.controller_trigger
|
||||||
|
else -> R.string.button
|
||||||
|
}
|
||||||
|
|
||||||
|
val nameId = setting?.nameId?.let { context.getString(it) }
|
||||||
|
|
||||||
|
return String.format(
|
||||||
|
context.getString(R.string.input_dialog_title),
|
||||||
|
context.getString(inputTypeId),
|
||||||
|
nameId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getIcon(): Drawable? {
|
||||||
|
val id = when {
|
||||||
|
setting!!.isCirclePad() -> R.drawable.stick_main
|
||||||
|
setting!!.isCStick() -> R.drawable.stick_c
|
||||||
|
setting!!.isDPad() -> R.drawable.dpad
|
||||||
|
else -> {
|
||||||
|
val resourceTitle = context.resources.getResourceEntryName(setting!!.nameId)
|
||||||
|
if (resourceTitle.startsWith("direction")) {
|
||||||
|
R.drawable.dpad
|
||||||
|
} else {
|
||||||
|
context.resources.getIdentifier(resourceTitle, "drawable", context.packageName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ContextCompat.getDrawable(context, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val previousValues = ArrayList<Float>()
|
||||||
|
private var prevDeviceId = 0
|
||||||
|
private var waitingForEvent = true
|
||||||
|
private var setting: InputBindingSetting? = null
|
||||||
|
private var debounceTimestamp = System.currentTimeMillis()
|
||||||
|
|
||||||
|
private var settingsList = arrayListOf<InputBindingSetting>()
|
||||||
|
|
||||||
|
private fun onKeyEvent(event: KeyEvent): Boolean {
|
||||||
|
return when (event.action) {
|
||||||
|
KeyEvent.ACTION_UP -> {
|
||||||
|
if (System.currentTimeMillis()-debounceTimestamp < DEBOUNCE_TIMER) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
debounceTimestamp = System.currentTimeMillis()
|
||||||
|
index++
|
||||||
|
setting?.let {
|
||||||
|
it.onKeyInputDeferred(event)
|
||||||
|
settingsList.add(it)
|
||||||
|
}
|
||||||
|
prepareUIforIndex(index)
|
||||||
|
// Even if we ignore the key, we still consume it. Thus return true regardless.
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onMotionEvent(event: MotionEvent): Boolean {
|
||||||
|
if ((event.source and InputDevice.SOURCE_CLASS_JOYSTICK == 0) ||
|
||||||
|
event.action != MotionEvent.ACTION_MOVE) return false
|
||||||
|
|
||||||
|
val input = event.device
|
||||||
|
val motionRanges = input.motionRanges
|
||||||
|
|
||||||
|
if (input.id != prevDeviceId) {
|
||||||
|
previousValues.clear()
|
||||||
|
}
|
||||||
|
prevDeviceId = input.id
|
||||||
|
val firstEvent = previousValues.isEmpty()
|
||||||
|
|
||||||
|
var numMovedAxis = 0
|
||||||
|
var axisMoveValue = 0.0f
|
||||||
|
var lastMovedRange: InputDevice.MotionRange? = null
|
||||||
|
var lastMovedDir = '?'
|
||||||
|
if (waitingForEvent) {
|
||||||
|
for (i in motionRanges.indices) {
|
||||||
|
val range = motionRanges[i]
|
||||||
|
val axis = range.axis
|
||||||
|
val origValue = event.getAxisValue(axis)
|
||||||
|
if (firstEvent) {
|
||||||
|
previousValues.add(origValue)
|
||||||
|
} else {
|
||||||
|
val previousValue = previousValues[i]
|
||||||
|
|
||||||
|
// Only handle the axes that are not neutral (more than 0.5)
|
||||||
|
// but ignore any axis that has a constant value (e.g. always 1)
|
||||||
|
if (abs(origValue) > 0.5f && origValue != previousValue) {
|
||||||
|
// It is common to have multiple axes with the same physical input. For example,
|
||||||
|
// shoulder butters are provided as both AXIS_LTRIGGER and AXIS_BRAKE.
|
||||||
|
// To handle this, we ignore an axis motion that's the exact same as a motion
|
||||||
|
// we already saw. This way, we ignore axes with two names, but catch the case
|
||||||
|
// where a joystick is moved in two directions.
|
||||||
|
// ref: bottom of https://developer.android.com/training/game-controllers/controller-input.html
|
||||||
|
if (origValue != axisMoveValue) {
|
||||||
|
axisMoveValue = origValue
|
||||||
|
numMovedAxis++
|
||||||
|
lastMovedRange = range
|
||||||
|
lastMovedDir = if (origValue < 0.0f) '-' else '+'
|
||||||
|
}
|
||||||
|
} else if (abs(origValue) < 0.25f && abs(previousValue) > 0.75f) {
|
||||||
|
// Special case for d-pads (axis value jumps between 0 and 1 without any values
|
||||||
|
// in between). Without this, the user would need to press the d-pad twice
|
||||||
|
// due to the first press being caught by the "if (firstEvent)" case further up.
|
||||||
|
numMovedAxis++
|
||||||
|
lastMovedRange = range
|
||||||
|
lastMovedDir = if (previousValue < 0.0f) '-' else '+'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
previousValues[i] = origValue
|
||||||
|
}
|
||||||
|
// If only one axis moved, that's the winner.
|
||||||
|
if (numMovedAxis == 1) {
|
||||||
|
waitingForEvent = false
|
||||||
|
setting?.onMotionInput(input, lastMovedRange!!, lastMovedDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val DEBOUNCE_TIMER = 100
|
||||||
|
}
|
||||||
|
}
|
@ -44,6 +44,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.FloatSetting
|
||||||
import org.citra.citra_emu.features.settings.model.ScaledFloatSetting
|
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.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.DateTimeSetting
|
||||||
import org.citra.citra_emu.features.settings.model.view.InputBindingSetting
|
import org.citra.citra_emu.features.settings.model.view.InputBindingSetting
|
||||||
import org.citra.citra_emu.features.settings.model.view.SettingsItem
|
import org.citra.citra_emu.features.settings.model.view.SettingsItem
|
||||||
@ -65,6 +66,7 @@ import org.citra.citra_emu.features.settings.ui.viewholder.SubmenuViewHolder
|
|||||||
import org.citra.citra_emu.features.settings.ui.viewholder.SwitchSettingViewHolder
|
import org.citra.citra_emu.features.settings.ui.viewholder.SwitchSettingViewHolder
|
||||||
import org.citra.citra_emu.fragments.MessageDialogFragment
|
import org.citra.citra_emu.fragments.MessageDialogFragment
|
||||||
import org.citra.citra_emu.fragments.MotionBottomSheetDialogFragment
|
import org.citra.citra_emu.fragments.MotionBottomSheetDialogFragment
|
||||||
|
import org.citra.citra_emu.utils.PermissionsHandler
|
||||||
import org.citra.citra_emu.utils.SystemSaveGame
|
import org.citra.citra_emu.utils.SystemSaveGame
|
||||||
import java.lang.IllegalStateException
|
import java.lang.IllegalStateException
|
||||||
import java.lang.NumberFormatException
|
import java.lang.NumberFormatException
|
||||||
@ -514,6 +516,28 @@ class SettingsAdapter(
|
|||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onClickControllerQuickConfig() {
|
||||||
|
val buttons = arrayListOf(
|
||||||
|
Settings.buttonKeys,
|
||||||
|
Settings.circlePadKeys,
|
||||||
|
Settings.cStickKeys,
|
||||||
|
Settings.dPadAxisKeys,
|
||||||
|
Settings.dPadButtonKeys,
|
||||||
|
Settings.triggerKeys
|
||||||
|
)
|
||||||
|
|
||||||
|
val titles = arrayListOf(
|
||||||
|
Settings.buttonTitles,
|
||||||
|
Settings.axisTitles,
|
||||||
|
Settings.axisTitles,
|
||||||
|
Settings.axisTitles,
|
||||||
|
Settings.dPadTitles,
|
||||||
|
Settings.triggerTitles
|
||||||
|
)
|
||||||
|
|
||||||
|
ControllerQuickConfigDialog(context, buttons, titles, PermissionsHandler.preferences).show()
|
||||||
|
}
|
||||||
|
|
||||||
fun closeDialog() {
|
fun closeDialog() {
|
||||||
if (dialog != null) {
|
if (dialog != null) {
|
||||||
if (clickedPosition != -1) {
|
if (clickedPosition != -1) {
|
||||||
|
@ -646,44 +646,54 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
|||||||
private fun addControlsSettings(sl: ArrayList<SettingsItem>) {
|
private fun addControlsSettings(sl: ArrayList<SettingsItem>) {
|
||||||
settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_controls))
|
settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_controls))
|
||||||
sl.apply {
|
sl.apply {
|
||||||
|
add(
|
||||||
|
RunnableSetting(
|
||||||
|
R.string.controller_quick_config,
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
{ settingsAdapter.onClickControllerQuickConfig() }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
add(HeaderSetting(R.string.generic_buttons))
|
add(HeaderSetting(R.string.generic_buttons))
|
||||||
Settings.buttonKeys.forEachIndexed { i: Int, key: String ->
|
Settings.buttonKeys.forEachIndexed { i: Int, key: String ->
|
||||||
val button = getInputObject(key)
|
val button = InputBindingSetting.getInputObject(key, preferences)
|
||||||
add(InputBindingSetting(button, Settings.buttonTitles[i]))
|
add(InputBindingSetting(button, Settings.buttonTitles[i]))
|
||||||
}
|
}
|
||||||
|
|
||||||
add(HeaderSetting(R.string.controller_circlepad))
|
add(HeaderSetting(R.string.controller_circlepad))
|
||||||
Settings.circlePadKeys.forEachIndexed { i: Int, key: String ->
|
Settings.circlePadKeys.forEachIndexed { i: Int, key: String ->
|
||||||
val button = getInputObject(key)
|
val button = InputBindingSetting.getInputObject(key, preferences)
|
||||||
add(InputBindingSetting(button, Settings.axisTitles[i]))
|
add(InputBindingSetting(button, Settings.axisTitles[i]))
|
||||||
}
|
}
|
||||||
|
|
||||||
add(HeaderSetting(R.string.controller_c))
|
add(HeaderSetting(R.string.controller_c))
|
||||||
Settings.cStickKeys.forEachIndexed { i: Int, key: String ->
|
Settings.cStickKeys.forEachIndexed { i: Int, key: String ->
|
||||||
val button = getInputObject(key)
|
val button = InputBindingSetting.getInputObject(key, preferences)
|
||||||
add(InputBindingSetting(button, Settings.axisTitles[i]))
|
add(InputBindingSetting(button, Settings.axisTitles[i]))
|
||||||
}
|
}
|
||||||
|
|
||||||
add(HeaderSetting(R.string.controller_dpad_axis,R.string.controller_dpad_axis_description))
|
add(HeaderSetting(R.string.controller_dpad_axis,R.string.controller_dpad_axis_description))
|
||||||
Settings.dPadAxisKeys.forEachIndexed { i: Int, key: String ->
|
Settings.dPadAxisKeys.forEachIndexed { i: Int, key: String ->
|
||||||
val button = getInputObject(key)
|
val button = InputBindingSetting.getInputObject(key, preferences)
|
||||||
add(InputBindingSetting(button, Settings.axisTitles[i]))
|
add(InputBindingSetting(button, Settings.axisTitles[i]))
|
||||||
}
|
}
|
||||||
add(HeaderSetting(R.string.controller_dpad_button,R.string.controller_dpad_button_description))
|
add(HeaderSetting(R.string.controller_dpad_button,R.string.controller_dpad_button_description))
|
||||||
Settings.dPadButtonKeys.forEachIndexed { i: Int, key: String ->
|
Settings.dPadButtonKeys.forEachIndexed { i: Int, key: String ->
|
||||||
val button = getInputObject(key)
|
val button = InputBindingSetting.getInputObject(key, preferences)
|
||||||
add(InputBindingSetting(button, Settings.dPadTitles[i]))
|
add(InputBindingSetting(button, Settings.dPadTitles[i]))
|
||||||
}
|
}
|
||||||
|
|
||||||
add(HeaderSetting(R.string.controller_triggers))
|
add(HeaderSetting(R.string.controller_triggers))
|
||||||
Settings.triggerKeys.forEachIndexed { i: Int, key: String ->
|
Settings.triggerKeys.forEachIndexed { i: Int, key: String ->
|
||||||
val button = getInputObject(key)
|
val button = InputBindingSetting.getInputObject(key, preferences)
|
||||||
add(InputBindingSetting(button, Settings.triggerTitles[i]))
|
add(InputBindingSetting(button, Settings.triggerTitles[i]))
|
||||||
}
|
}
|
||||||
|
|
||||||
add(HeaderSetting(R.string.controller_hotkeys))
|
add(HeaderSetting(R.string.controller_hotkeys))
|
||||||
Settings.hotKeys.forEachIndexed { i: Int, key: String ->
|
Settings.hotKeys.forEachIndexed { i: Int, key: String ->
|
||||||
val button = getInputObject(key)
|
val button = InputBindingSetting.getInputObject(key, preferences)
|
||||||
add(InputBindingSetting(button, Settings.hotkeyTitles[i]))
|
add(InputBindingSetting(button, Settings.hotkeyTitles[i]))
|
||||||
}
|
}
|
||||||
add(HeaderSetting(R.string.miscellaneous))
|
add(HeaderSetting(R.string.miscellaneous))
|
||||||
@ -699,23 +709,6 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getInputObject(key: String): AbstractStringSetting {
|
|
||||||
return object : AbstractStringSetting {
|
|
||||||
override var string: String
|
|
||||||
get() = preferences.getString(key, "")!!
|
|
||||||
set(value) {
|
|
||||||
preferences.edit()
|
|
||||||
.putString(key, value)
|
|
||||||
.apply()
|
|
||||||
}
|
|
||||||
override val key = key
|
|
||||||
override val section = Settings.SECTION_CONTROLS
|
|
||||||
override val isRuntimeEditable = true
|
|
||||||
override val valueAsString = preferences.getString(key, "")!!
|
|
||||||
override val defaultValue = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addGraphicsSettings(sl: ArrayList<SettingsItem>) {
|
private fun addGraphicsSettings(sl: ArrayList<SettingsItem>) {
|
||||||
settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_graphics))
|
settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_graphics))
|
||||||
sl.apply {
|
sl.apply {
|
||||||
|
@ -0,0 +1,73 @@
|
|||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/linearLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/lastMappingIcon"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginTop="32dp"
|
||||||
|
android:scaleType="centerInside"
|
||||||
|
android:src="@drawable/button_a"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/currentMappingIcon"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/currentMappingIcon"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_chainStyle="packed" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/lastMappingDescription"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginEnd="32dp"
|
||||||
|
android:enabled="false"
|
||||||
|
android:text="TextView"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/lastMappingIcon"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/lastMappingIcon"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/lastMappingIcon" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/currentMappingIcon"
|
||||||
|
android:layout_width="64dp"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/lastMappingIcon"
|
||||||
|
app:srcCompat="@drawable/button_b" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/currentMappingTitle"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="32dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginEnd="32dp"
|
||||||
|
android:text="TextView"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/currentMappingIcon"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/currentMappingIcon" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/currentMappingDescription"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="32dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginEnd="32dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:enabled="false"
|
||||||
|
android:text="TextView"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/currentMappingIcon"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/currentMappingTitle" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -140,6 +140,11 @@
|
|||||||
<string name="button_zr" translatable="false">ZR</string>
|
<string name="button_zr" translatable="false">ZR</string>
|
||||||
<string name="input_message_analog_only">This control must be bound to a gamepad analog stick or D-pad axis!</string>
|
<string name="input_message_analog_only">This control must be bound to a gamepad analog stick or D-pad axis!</string>
|
||||||
<string name="input_message_button_only">This control must be bound to a gamepad button!</string>
|
<string name="input_message_button_only">This control must be bound to a gamepad button!</string>
|
||||||
|
<string name="controller_quick_config">Quick Configure</string>
|
||||||
|
<string name="controller_quick_config_finish">Finish</string>
|
||||||
|
<string name="controller_quick_config_unassigned">Unassigned</string>
|
||||||
|
<string name="controller_quick_config_next">Next</string>
|
||||||
|
<string name="controller_quick_config_close">Close</string>
|
||||||
|
|
||||||
<!-- System files strings -->
|
<!-- System files strings -->
|
||||||
<string name="system_files">System Files</string>
|
<string name="system_files">System Files</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user