Added "Small Screen Position" feature
* error checking for layout value from older config * rename enum and update aspect ratio code * rewrite LargeFrameLayout to support multiple positions * add settings for smallscreenposition, fix minsize function * fixed framebuffer from res scale (screenshots) * add desktop UI for small screen position * small screen position submenu on desktop * fix int-float conversion warning * rename Above and Below to hopefully fix linux issue * Add Small Screen Position Setting to android settings menu * fix sliders to work with floats, mostly * fix android slider textinput ui * change None enums in settings and cam_params * Apply clang-format-18 * SettingsAdapter.kt: Make more null pointer exception resistant * Updated license headers * Code formatting nitpicks * fix bug in main.ui that was hiding menu * replace default layout with a special call to LargeFrame (like SideBySide does) * fix bug when "large screen" is actually narrower * edit documentation for LargeScreenLayout * update PortraitTopFullFrameLayout to use LargeFrameLayout * fix unary minus on unsigned int bug * Applied formatting correction * Added `const`s where appropriate * android: Add mention of the bottom-right small screen position being the default * review fixes + more constants * refactor all Upright calculations to a reverseLayout method, simplifying code and reducing bugs * Removed stray extra newline * SettingsAdapter.kt: Fixed some strange indentation * Removed unnecessary `if` in favour of direct value usage --------- Co-authored-by: Reg Tiangha <rtiangha@users.noreply.github.com> Co-authored-by: OpenSauce04 <opensauce04@gmail.com>
This commit is contained in:
committed by
OpenSauce04
parent
0a3cb3a4dc
commit
43c4d3981d
@@ -21,6 +21,23 @@ enum class ScreenLayout(val int: Int) {
|
||||
}
|
||||
}
|
||||
|
||||
enum class SmallScreenPosition(val int: Int) {
|
||||
TOP_RIGHT(0),
|
||||
MIDDLE_RIGHT(1),
|
||||
BOTTOM_RIGHT(2),
|
||||
TOP_LEFT(3),
|
||||
MIDDLE_LEFT(4),
|
||||
BOTTOM_LEFT(5),
|
||||
ABOVE(6),
|
||||
BELOW(7);
|
||||
|
||||
companion object {
|
||||
fun from(int: Int): SmallScreenPosition {
|
||||
return entries.firstOrNull { it.int == int } ?: TOP_RIGHT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class PortraitScreenLayout(val int: Int) {
|
||||
// These must match what is defined in src/common/settings.h
|
||||
TOP_FULL_WIDTH(0),
|
||||
@@ -28,7 +45,7 @@ enum class PortraitScreenLayout(val int: Int) {
|
||||
|
||||
companion object {
|
||||
fun from(int: Int): PortraitScreenLayout {
|
||||
return entries.firstOrNull { it.int == int } ?: TOP_FULL_WIDTH;
|
||||
return entries.firstOrNull { it.int == int } ?: TOP_FULL_WIDTH
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2023 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Lime3DS Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
@@ -9,7 +9,7 @@ enum class FloatSetting(
|
||||
override val section: String,
|
||||
override val defaultValue: Float
|
||||
) : AbstractFloatSetting {
|
||||
// There are no float settings currently
|
||||
LARGE_SCREEN_PROPORTION("large_screen_proportion",Settings.SECTION_LAYOUT,2.25f),
|
||||
EMPTY_SETTING("", "", 0.0f);
|
||||
|
||||
override var float: Float = defaultValue
|
||||
|
||||
@@ -24,6 +24,7 @@ enum class IntSetting(
|
||||
CARDBOARD_X_SHIFT("cardboard_x_shift", Settings.SECTION_LAYOUT, 0),
|
||||
CARDBOARD_Y_SHIFT("cardboard_y_shift", Settings.SECTION_LAYOUT, 0),
|
||||
SCREEN_LAYOUT("layout_option", Settings.SECTION_LAYOUT, 0),
|
||||
SMALL_SCREEN_POSITION("small_screen_position",Settings.SECTION_LAYOUT,0),
|
||||
LANDSCAPE_TOP_X("custom_top_x",Settings.SECTION_LAYOUT,0),
|
||||
LANDSCAPE_TOP_Y("custom_top_y",Settings.SECTION_LAYOUT,0),
|
||||
LANDSCAPE_TOP_WIDTH("custom_top_width",Settings.SECTION_LAYOUT,800),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2023 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Lime3DS Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
@@ -39,5 +39,6 @@ abstract class SettingsItem(
|
||||
const val TYPE_RUNNABLE = 7
|
||||
const val TYPE_INPUT_BINDING = 8
|
||||
const val TYPE_STRING_INPUT = 9
|
||||
const val TYPE_FLOAT_INPUT = 10
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2023 Citra Emulator Project
|
||||
// Copyright Citra Emulator Project / Lime3DS Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
@@ -23,17 +23,16 @@ class SliderSetting(
|
||||
val defaultValue: Float? = null
|
||||
) : SettingsItem(setting, titleId, descriptionId) {
|
||||
override val type = TYPE_SLIDER
|
||||
|
||||
val selectedValue: Int
|
||||
val selectedFloat: Float
|
||||
get() {
|
||||
val setting = setting ?: return defaultValue!!.toInt()
|
||||
val setting = setting ?: return defaultValue!!.toFloat()
|
||||
return when (setting) {
|
||||
is AbstractIntSetting -> setting.int
|
||||
is FloatSetting -> setting.float.roundToInt()
|
||||
is ScaledFloatSetting -> setting.float.roundToInt()
|
||||
is AbstractIntSetting -> setting.int.toFloat()
|
||||
is FloatSetting -> setting.float
|
||||
is ScaledFloatSetting -> setting.float
|
||||
else -> {
|
||||
Log.error("[SliderSetting] Error casting setting type.")
|
||||
-1
|
||||
-1f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import android.icu.util.Calendar
|
||||
import android.icu.util.TimeZone
|
||||
import android.text.Editable
|
||||
import android.text.InputFilter
|
||||
import android.text.InputType
|
||||
import android.text.TextWatcher
|
||||
import android.text.format.DateFormat
|
||||
import android.view.LayoutInflater
|
||||
@@ -68,6 +69,7 @@ import org.citra.citra_emu.utils.SystemSaveGame
|
||||
import java.lang.IllegalStateException
|
||||
import java.lang.NumberFormatException
|
||||
import java.text.SimpleDateFormat
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class SettingsAdapter(
|
||||
private val fragmentView: SettingsFragmentView,
|
||||
@@ -77,7 +79,7 @@ class SettingsAdapter(
|
||||
private var clickedItem: SettingsItem? = null
|
||||
private var clickedPosition: Int
|
||||
private var dialog: AlertDialog? = null
|
||||
private var sliderProgress = 0
|
||||
private var sliderProgress = 0f
|
||||
private var textSliderValue: TextInputEditText? = null
|
||||
private var textInputLayout: TextInputLayout? = null
|
||||
private var textInputValue: String = ""
|
||||
@@ -136,27 +138,23 @@ class SettingsAdapter(
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: SettingViewHolder, position: Int) {
|
||||
holder.bind(getItem(position))
|
||||
getItem(position)?.let { holder.bind(it) }
|
||||
}
|
||||
|
||||
private fun getItem(position: Int): SettingsItem {
|
||||
return settings!![position]
|
||||
private fun getItem(position: Int): SettingsItem? {
|
||||
return settings?.get(position)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return if (settings != null) {
|
||||
settings!!.size
|
||||
} else {
|
||||
0
|
||||
}
|
||||
return settings?.size ?: 0
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return getItem(position).type
|
||||
return getItem(position)?.type ?: -1
|
||||
}
|
||||
|
||||
fun setSettingsList(settings: ArrayList<SettingsItem>?) {
|
||||
this.settings = settings
|
||||
this.settings = settings ?: arrayListOf()
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
@@ -182,10 +180,12 @@ class SettingsAdapter(
|
||||
|
||||
private fun onStringSingleChoiceClick(item: StringSingleChoiceSetting) {
|
||||
clickedItem = item
|
||||
dialog = MaterialAlertDialogBuilder(context)
|
||||
.setTitle(item.nameId)
|
||||
.setSingleChoiceItems(item.choices, item.selectValueIndex, this)
|
||||
.show()
|
||||
dialog = context?.let {
|
||||
MaterialAlertDialogBuilder(it)
|
||||
.setTitle(item.nameId)
|
||||
.setSingleChoiceItems(item.choices, item.selectValueIndex, this)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
fun onStringSingleChoiceClick(item: StringSingleChoiceSetting, position: Int) {
|
||||
@@ -231,10 +231,10 @@ class SettingsAdapter(
|
||||
.build()
|
||||
|
||||
datePicker.addOnPositiveButtonClickListener {
|
||||
timePicker.show(
|
||||
(fragmentView.activityView as AppCompatActivity).supportFragmentManager,
|
||||
"TimePicker"
|
||||
)
|
||||
val activity = fragmentView.activityView as? AppCompatActivity
|
||||
activity?.supportFragmentManager?.let { fragmentManager ->
|
||||
timePicker.show(fragmentManager, "TimePicker")
|
||||
}
|
||||
}
|
||||
timePicker.addOnPositiveButtonClickListener {
|
||||
var epochTime: Long = datePicker.selection!! / 1000
|
||||
@@ -258,38 +258,62 @@ class SettingsAdapter(
|
||||
fun onSliderClick(item: SliderSetting, position: Int) {
|
||||
clickedItem = item
|
||||
clickedPosition = position
|
||||
sliderProgress = item.selectedValue
|
||||
sliderProgress = (item.selectedFloat * 100f).roundToInt() / 100f
|
||||
|
||||
|
||||
val inflater = LayoutInflater.from(context)
|
||||
val sliderBinding = DialogSliderBinding.inflate(inflater)
|
||||
textInputLayout = sliderBinding.textInput
|
||||
textSliderValue = sliderBinding.textValue
|
||||
textSliderValue!!.setText(sliderProgress.toString())
|
||||
textInputLayout!!.suffixText = item.units
|
||||
if (item.setting is FloatSetting) {
|
||||
textSliderValue?.let {
|
||||
it.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
|
||||
it.setText(sliderProgress.toString())
|
||||
}
|
||||
} else {
|
||||
textSliderValue?.setText(sliderProgress.roundToInt().toString())
|
||||
}
|
||||
|
||||
textInputLayout?.suffixText = item.units
|
||||
|
||||
sliderBinding.slider.apply {
|
||||
valueFrom = item.min.toFloat()
|
||||
valueTo = item.max.toFloat()
|
||||
value = sliderProgress.toFloat()
|
||||
textSliderValue!!.addTextChangedListener( object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
val textValue = s.toString().toIntOrNull();
|
||||
if (textValue == null || textValue < valueFrom || textValue > valueTo) {
|
||||
textInputLayout!!.error ="Inappropriate value"
|
||||
} else {
|
||||
textInputLayout!!.error = null
|
||||
value = textValue.toFloat();
|
||||
}
|
||||
value = sliderProgress
|
||||
textSliderValue?.addTextChangedListener(object : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
var textValue = s.toString().toFloatOrNull();
|
||||
if (item.setting !is FloatSetting) {
|
||||
textValue = textValue?.roundToInt()?.toFloat();
|
||||
}
|
||||
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||
})
|
||||
if (textValue == null || textValue < valueFrom || textValue > valueTo) {
|
||||
textInputLayout?.error = "Inappropriate value"
|
||||
} else {
|
||||
textInputLayout?.error = null
|
||||
value = textValue
|
||||
}
|
||||
}
|
||||
|
||||
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||
})
|
||||
|
||||
addOnChangeListener { _: Slider, value: Float, _: Boolean ->
|
||||
sliderProgress = value.toInt()
|
||||
if (textSliderValue!!.text.toString() != value.toInt().toString()) {
|
||||
textSliderValue!!.setText(value.toInt().toString())
|
||||
textSliderValue!!.setSelection(textSliderValue!!.length())
|
||||
sliderProgress = (value * 100).roundToInt().toFloat() / 100f
|
||||
var sliderString = sliderProgress.toString()
|
||||
if (item.setting !is FloatSetting) {
|
||||
sliderString = sliderProgress.roundToInt().toString()
|
||||
if (textSliderValue?.text.toString() != sliderString) {
|
||||
textSliderValue?.setText(sliderString)
|
||||
textSliderValue?.setSelection(textSliderValue?.length() ?: 0 )
|
||||
}
|
||||
} else {
|
||||
val currentText = textSliderValue?.text.toString()
|
||||
val currentTextValue = currentText.toFloat()
|
||||
if (currentTextValue != sliderProgress) {
|
||||
textSliderValue?.setText(sliderString)
|
||||
textSliderValue?.setSelection(textSliderValue?.length() ?: 0 )
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -300,14 +324,14 @@ class SettingsAdapter(
|
||||
.setPositiveButton(android.R.string.ok, this)
|
||||
.setNegativeButton(android.R.string.cancel, defaultCancelListener)
|
||||
.setNeutralButton(R.string.slider_default) { dialog: DialogInterface, which: Int ->
|
||||
sliderBinding.slider.value = when (item.setting) {
|
||||
sliderBinding.slider?.value = when (item.setting) {
|
||||
is ScaledFloatSetting -> {
|
||||
val scaledSetting = item.setting as ScaledFloatSetting
|
||||
scaledSetting.defaultValue * scaledSetting.scale
|
||||
}
|
||||
|
||||
is FloatSetting -> (item.setting as FloatSetting).defaultValue
|
||||
else -> item.defaultValue!!
|
||||
else -> item.defaultValue ?: 0f
|
||||
}
|
||||
onClick(dialog, which)
|
||||
}
|
||||
@@ -358,85 +382,89 @@ class SettingsAdapter(
|
||||
override fun onClick(dialog: DialogInterface, which: Int) {
|
||||
when (clickedItem) {
|
||||
is SingleChoiceSetting -> {
|
||||
val scSetting = clickedItem as SingleChoiceSetting
|
||||
val setting = when (scSetting.setting) {
|
||||
is AbstractIntSetting -> {
|
||||
val value = getValueForSingleChoiceSelection(scSetting, which)
|
||||
if (scSetting.selectedValue != value) {
|
||||
fragmentView.onSettingChanged()
|
||||
val scSetting = clickedItem as? SingleChoiceSetting
|
||||
scSetting?.let {
|
||||
val setting = when (it.setting) {
|
||||
is AbstractIntSetting -> {
|
||||
val value = getValueForSingleChoiceSelection(it, which)
|
||||
if (it.selectedValue != value) {
|
||||
fragmentView?.onSettingChanged()
|
||||
}
|
||||
it.setSelectedValue(value)
|
||||
}
|
||||
scSetting.setSelectedValue(value)
|
||||
}
|
||||
|
||||
is AbstractShortSetting -> {
|
||||
val value = getValueForSingleChoiceSelection(scSetting, which).toShort()
|
||||
if (scSetting.selectedValue.toShort() != value) {
|
||||
fragmentView.onSettingChanged()
|
||||
is AbstractShortSetting -> {
|
||||
val value = getValueForSingleChoiceSelection(it, which).toShort()
|
||||
if (it.selectedValue.toShort() != value) {
|
||||
fragmentView?.onSettingChanged()
|
||||
}
|
||||
it.setSelectedValue(value)
|
||||
}
|
||||
scSetting.setSelectedValue(value)
|
||||
else -> throw IllegalStateException("Unrecognized type used for SingleChoiceSetting!")
|
||||
}
|
||||
|
||||
else -> throw IllegalStateException("Unrecognized type used for SingleChoiceSetting!")
|
||||
fragmentView?.putSetting(setting)
|
||||
closeDialog()
|
||||
}
|
||||
|
||||
fragmentView.putSetting(setting)
|
||||
closeDialog()
|
||||
}
|
||||
|
||||
is StringSingleChoiceSetting -> {
|
||||
val scSetting = clickedItem as StringSingleChoiceSetting
|
||||
val setting = when (scSetting.setting) {
|
||||
is AbstractStringSetting -> {
|
||||
val value = scSetting.getValueAt(which)
|
||||
if (scSetting.selectedValue != value) fragmentView.onSettingChanged()
|
||||
scSetting.setSelectedValue(value!!)
|
||||
val scSetting = clickedItem as? StringSingleChoiceSetting
|
||||
scSetting?.let {
|
||||
val setting = when (it.setting) {
|
||||
is AbstractStringSetting -> {
|
||||
val value = it.getValueAt(which)
|
||||
if (it.selectedValue != value) fragmentView?.onSettingChanged()
|
||||
it.setSelectedValue(value ?: "")
|
||||
}
|
||||
|
||||
is AbstractShortSetting -> {
|
||||
if (it.selectValueIndex != which) fragmentView?.onSettingChanged()
|
||||
it.setSelectedValue(it.getValueAt(which)?.toShort() ?: 1)
|
||||
}
|
||||
|
||||
else -> throw IllegalStateException("Unrecognized type used for StringSingleChoiceSetting!")
|
||||
}
|
||||
|
||||
is AbstractShortSetting -> {
|
||||
if (scSetting.selectValueIndex != which) fragmentView.onSettingChanged()
|
||||
scSetting.setSelectedValue(scSetting.getValueAt(which)?.toShort() ?: 1)
|
||||
}
|
||||
|
||||
else -> throw IllegalStateException("Unrecognized type used for StringSingleChoiceSetting!")
|
||||
fragmentView?.putSetting(setting)
|
||||
closeDialog()
|
||||
}
|
||||
|
||||
fragmentView.putSetting(setting)
|
||||
closeDialog()
|
||||
}
|
||||
|
||||
is SliderSetting -> {
|
||||
val sliderSetting = clickedItem as SliderSetting
|
||||
if (sliderSetting.selectedValue != sliderProgress) {
|
||||
fragmentView.onSettingChanged()
|
||||
}
|
||||
when (sliderSetting.setting) {
|
||||
is FloatSetting,
|
||||
is ScaledFloatSetting -> {
|
||||
val value = sliderProgress.toFloat()
|
||||
val setting = sliderSetting.setSelectedValue(value)
|
||||
fragmentView.putSetting(setting)
|
||||
}
|
||||
|
||||
else -> {
|
||||
val setting = sliderSetting.setSelectedValue(sliderProgress)
|
||||
fragmentView.putSetting(setting)
|
||||
val sliderSetting = clickedItem as? SliderSetting
|
||||
sliderSetting?.let {
|
||||
val sliderval = (it.selectedFloat * 100).roundToInt().toFloat() / 100
|
||||
if (sliderval != sliderProgress) {
|
||||
fragmentView?.onSettingChanged()
|
||||
}
|
||||
when (it.setting) {
|
||||
is AbstractIntSetting -> {
|
||||
val value = sliderProgress.roundToInt()
|
||||
val setting = it.setSelectedValue(value)
|
||||
fragmentView?.putSetting(setting)
|
||||
}
|
||||
else -> {
|
||||
val setting = it.setSelectedValue(sliderProgress)
|
||||
fragmentView?.putSetting(setting)
|
||||
}
|
||||
}
|
||||
closeDialog()
|
||||
}
|
||||
closeDialog()
|
||||
}
|
||||
|
||||
is StringInputSetting -> {
|
||||
val inputSetting = clickedItem as StringInputSetting
|
||||
if (inputSetting.selectedValue != textInputValue) {
|
||||
fragmentView.onSettingChanged()
|
||||
}
|
||||
val setting = inputSetting.setSelectedValue(textInputValue)
|
||||
fragmentView.putSetting(setting)
|
||||
closeDialog()
|
||||
val inputSetting = clickedItem as? StringInputSetting
|
||||
inputSetting?.let {
|
||||
if (it.selectedValue != textInputValue) {
|
||||
fragmentView?.onSettingChanged()
|
||||
}
|
||||
val setting = it.setSelectedValue(textInputValue ?: "")
|
||||
fragmentView?.putSetting(setting)
|
||||
closeDialog()
|
||||
}
|
||||
}
|
||||
}
|
||||
clickedItem = null
|
||||
sliderProgress = -1
|
||||
sliderProgress = -1f
|
||||
textInputValue = ""
|
||||
}
|
||||
|
||||
|
||||
@@ -16,16 +16,19 @@ import androidx.preference.PreferenceManager
|
||||
import kotlin.math.min
|
||||
import org.citra.citra_emu.CitraApplication
|
||||
import org.citra.citra_emu.R
|
||||
import org.citra.citra_emu.display.PortraitScreenLayout
|
||||
import org.citra.citra_emu.display.ScreenLayout
|
||||
import org.citra.citra_emu.features.settings.model.AbstractBooleanSetting
|
||||
import org.citra.citra_emu.features.settings.model.AbstractIntSetting
|
||||
import org.citra.citra_emu.features.settings.model.AbstractSetting
|
||||
import org.citra.citra_emu.features.settings.model.AbstractShortSetting
|
||||
import org.citra.citra_emu.features.settings.model.AbstractStringSetting
|
||||
import org.citra.citra_emu.features.settings.model.BooleanSetting
|
||||
import org.citra.citra_emu.features.settings.model.FloatSetting
|
||||
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.Settings
|
||||
import org.citra.citra_emu.features.settings.model.StringSetting
|
||||
import org.citra.citra_emu.features.settings.model.AbstractShortSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.DateTimeSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.HeaderSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.InputBindingSetting
|
||||
@@ -962,6 +965,29 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
IntSetting.PORTRAIT_SCREEN_LAYOUT.defaultValue
|
||||
)
|
||||
)
|
||||
add(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.SMALL_SCREEN_POSITION,
|
||||
R.string.emulation_small_screen_position,
|
||||
R.string.small_screen_position_description,
|
||||
R.array.smallScreenPositions,
|
||||
R.array.smallScreenPositionValues,
|
||||
IntSetting.SMALL_SCREEN_POSITION.key,
|
||||
IntSetting.SMALL_SCREEN_POSITION.defaultValue
|
||||
)
|
||||
)
|
||||
add(
|
||||
SliderSetting(
|
||||
FloatSetting.LARGE_SCREEN_PROPORTION,
|
||||
R.string.large_screen_proportion,
|
||||
R.string.large_screen_proportion_description,
|
||||
1,
|
||||
5,
|
||||
"",
|
||||
FloatSetting.LARGE_SCREEN_PROPORTION.key,
|
||||
FloatSetting.LARGE_SCREEN_PROPORTION.defaultValue
|
||||
)
|
||||
)
|
||||
add(
|
||||
SubmenuSetting(
|
||||
R.string.emulation_landscape_custom_layout,
|
||||
@@ -978,8 +1004,6 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
||||
Settings.SECTION_CUSTOM_PORTRAIT
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -182,10 +182,11 @@ void Config::ReadValues() {
|
||||
layoutInt = static_cast<int>(Settings::LayoutOption::LargeScreen);
|
||||
}
|
||||
Settings::values.layout_option = static_cast<Settings::LayoutOption>(layoutInt);
|
||||
|
||||
Settings::values.large_screen_proportion =
|
||||
static_cast<float>(sdl2_config->GetReal("Layout", "large_screen_proportion", 2.25));
|
||||
|
||||
Settings::values.small_screen_position = static_cast<Settings::SmallScreenPosition>(
|
||||
sdl2_config->GetInteger("Layout", "small_screen_position",
|
||||
static_cast<int>(Settings::SmallScreenPosition::TopRight)));
|
||||
ReadSetting("Layout", Settings::values.custom_top_x);
|
||||
ReadSetting("Layout", Settings::values.custom_top_y);
|
||||
ReadSetting("Layout", Settings::values.custom_top_width);
|
||||
|
||||
@@ -184,15 +184,26 @@ delay_game_render_thread_us =
|
||||
|
||||
[Layout]
|
||||
# Layout for the screen inside the render window, landscape mode
|
||||
# 0: Top/Bottom *currently unsupported on android*
|
||||
# 0: Original (screens vertically aligned)
|
||||
# 1: Single Screen Only,
|
||||
# 2: *currently unsupported on android*
|
||||
# 2: Large Screen (Default on android)
|
||||
# 3: Side by Side
|
||||
# 4: Hybrid
|
||||
# 5: Custom Layout
|
||||
# 6: (default) Large screen / small screen
|
||||
layout_option =
|
||||
|
||||
# Large Screen Proportion - Relative size of large:small in large screen mode
|
||||
# Default value is 2.25
|
||||
large_screen_proportion =
|
||||
|
||||
# Small Screen Position - where is the small screen relative to the large
|
||||
# Default value is 0
|
||||
# 0: Top Right 1: Middle Right 2: Bottom Right
|
||||
# 3: Top Left 4: Middle left 5: Bottom Left
|
||||
# 6: Above the large screen 7: Below the large screen
|
||||
small_screen_position =
|
||||
|
||||
|
||||
# Screen placement when using Custom layout option
|
||||
# 0x, 0y is the top left corner of the render window.
|
||||
# suggested aspect ratio for top screen is 5:3
|
||||
|
||||
@@ -39,6 +39,28 @@
|
||||
<item>1</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="smallScreenPositions">
|
||||
<item>@string/small_screen_position_top_right</item>
|
||||
<item>@string/small_screen_position_middle_right</item>
|
||||
<item>@string/small_screen_position_bottom_right</item>
|
||||
<item>@string/small_screen_position_top_left</item>
|
||||
<item>@string/small_screen_position_middle_left</item>
|
||||
<item>@string/small_screen_position_bottom_left</item>
|
||||
<item>@string/small_screen_position_above</item>
|
||||
<item>@string/small_screen_position_below</item>
|
||||
</string-array>
|
||||
|
||||
<integer-array name="smallScreenPositionValues">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
<item>4</item>
|
||||
<item>5</item>
|
||||
<item>6</item>
|
||||
<item>7</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="regionNames">
|
||||
<item>@string/auto_select</item>
|
||||
<item>@string/system_region_jpn</item>
|
||||
|
||||
@@ -384,6 +384,18 @@
|
||||
<string name="emulation_screen_layout_original">Original</string>
|
||||
<string name="emulation_portrait_layout_top_full">Default</string>
|
||||
<string name="emulation_screen_layout_custom">Custom Layout</string>
|
||||
<string name="emulation_small_screen_position">Small Screen Position</string>
|
||||
<string name="small_screen_position_description">Where should the small screen appear relative to the large one in Large Screen Layout?</string>
|
||||
<string name="small_screen_position_top_right">Top Right</string>
|
||||
<string name="small_screen_position_middle_right">Middle Right</string>
|
||||
<string name="small_screen_position_bottom_right">Bottom Right (Default)</string>
|
||||
<string name="small_screen_position_top_left">Top Left</string>
|
||||
<string name="small_screen_position_middle_left">Middle Left</string>
|
||||
<string name="small_screen_position_bottom_left">Bottom Left</string>
|
||||
<string name="small_screen_position_above">Above</string>
|
||||
<string name="small_screen_position_below">Below</string>
|
||||
<string name="large_screen_proportion">Large Screen Proportion</string>
|
||||
<string name="large_screen_proportion_description">How many times larger is the large screen than the small screen in Large Screen layout?</string>
|
||||
<string name="emulation_adjust_custom_layout">Adjust Custom Layout in Settings</string>
|
||||
<string name="emulation_landscape_custom_layout">Landscape Custom Layout</string>
|
||||
<string name="emulation_portrait_custom_layout">Portrait Custom Layout</string>
|
||||
|
||||
Reference in New Issue
Block a user