mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2025-03-13 09:12:27 +01:00
[WIP] implement button-quickassignment
This commit is contained in:
parent
43dbe42b29
commit
c9cf901d1c
@ -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(
|
||||||
@ -329,5 +330,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,241 @@
|
|||||||
|
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.DialogControllerautomappingBinding
|
||||||
|
import org.citra.citra_emu.features.settings.model.view.InputBindingSetting
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
|
||||||
|
class ControllerAutomappingDialog(
|
||||||
|
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 automappingBinding = DialogControllerautomappingBinding.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(automappingBinding.root)
|
||||||
|
.setTitle("Automapper")
|
||||||
|
.setPositiveButton("Next") {_,_ -> }
|
||||||
|
.setNegativeButton("Close") { dialog, which ->
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog = builder.create()
|
||||||
|
dialog?.show()
|
||||||
|
|
||||||
|
dialog?.setOnKeyListener { _, _, event -> onKeyEvent(event) }
|
||||||
|
automappingBinding.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) {
|
||||||
|
dialog?.dismiss()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if(index>0) {
|
||||||
|
automappingBinding.lastMappingIcon.visibility = View.VISIBLE
|
||||||
|
automappingBinding.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.automapping_unassigned)
|
||||||
|
}
|
||||||
|
automappingBinding.lastMappingDescription.text = lastTitle
|
||||||
|
automappingBinding.lastMappingIcon.setImageDrawable(automappingBinding.currentMappingIcon.drawable)
|
||||||
|
setting = InputBindingSetting(button, currentTitleInt)
|
||||||
|
|
||||||
|
automappingBinding.currentMappingTitle.text = calculateTitle()
|
||||||
|
automappingBinding.currentMappingDescription.text = setting?.value
|
||||||
|
automappingBinding.currentMappingIcon.setImageDrawable(getIcon())
|
||||||
|
|
||||||
|
|
||||||
|
if (allButtons.size-1 < index) {
|
||||||
|
dialog?.getButton(AlertDialog.BUTTON_POSITIVE)?.text =
|
||||||
|
context.getString(R.string.automapping_dialog_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 fun onKeyEvent(event: KeyEvent): Boolean {
|
||||||
|
return when (event.action) {
|
||||||
|
KeyEvent.ACTION_UP -> {
|
||||||
|
if(System.currentTimeMillis()-debounceTimestamp < 500) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
debounceTimestamp = System.currentTimeMillis()
|
||||||
|
|
||||||
|
index++
|
||||||
|
setting?.onKeyInput(event)
|
||||||
|
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) return false
|
||||||
|
if (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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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.preferences
|
||||||
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,32 @@ class SettingsAdapter(
|
|||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onClickAutoconfigureControls() {
|
||||||
|
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
Settings.buttonTitles
|
||||||
|
ControllerAutomappingDialog(context, buttons, titles, preferences).show()
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
fun closeDialog() {
|
fun closeDialog() {
|
||||||
if (dialog != null) {
|
if (dialog != null) {
|
||||||
if (clickedPosition != -1) {
|
if (clickedPosition != -1) {
|
||||||
|
@ -646,44 +646,56 @@ 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(HeaderSetting(R.string.auto_configure))
|
||||||
|
|
||||||
|
add(
|
||||||
|
RunnableSetting(
|
||||||
|
R.string.auto_configure,
|
||||||
|
0,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
{ settingsAdapter.onClickAutoconfigureControls() }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
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 +711,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>
|
@ -169,6 +169,7 @@
|
|||||||
<string name="home_menu_warning_description">Due to how slow Android\'s storage access framework is for accessing Azahar\'s files, downloading multiple versions of system files can dramatically slow down loading for applications, save states, and the Applications list. Only download the files that you require to avoid any issues with loading speeds.</string>
|
<string name="home_menu_warning_description">Due to how slow Android\'s storage access framework is for accessing Azahar\'s files, downloading multiple versions of system files can dramatically slow down loading for applications, save states, and the Applications list. Only download the files that you require to avoid any issues with loading speeds.</string>
|
||||||
|
|
||||||
<!-- Generic buttons (Shared with lots of stuff) -->
|
<!-- Generic buttons (Shared with lots of stuff) -->
|
||||||
|
<string name="auto_configure">Auto Configuration</string>
|
||||||
<string name="generic_buttons">Buttons</string>
|
<string name="generic_buttons">Buttons</string>
|
||||||
<string name="button">Button</string>
|
<string name="button">Button</string>
|
||||||
|
|
||||||
@ -765,6 +766,8 @@
|
|||||||
<string name="artic_base_enter_address">Enter Artic Base server address</string>
|
<string name="artic_base_enter_address">Enter Artic Base server address</string>
|
||||||
<string name="delay_render_thread">Delay game render thread</string>
|
<string name="delay_render_thread">Delay game render thread</string>
|
||||||
<string name="delay_render_thread_description">Delay the game render thread when it submits data to the GPU. Helps with performance issues in the (very few) applications with dynamic framerates.</string>
|
<string name="delay_render_thread_description">Delay the game render thread when it submits data to the GPU. Helps with performance issues in the (very few) applications with dynamic framerates.</string>
|
||||||
|
<string name="automapping_dialog_finish">Finish</string>
|
||||||
|
<string name="automapping_unassigned">Unassigned</string>
|
||||||
|
|
||||||
<!-- Quickload&Save-->
|
<!-- Quickload&Save-->
|
||||||
<string name="emulation_quicksave_slot">Quicksave</string>
|
<string name="emulation_quicksave_slot">Quicksave</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user