Merge pull request #12095 from t895/color-space-settings

Android: Expose color space settings
This commit is contained in:
Charles Lombardo 2023-08-30 10:07:07 -04:00 committed by GitHub
commit 5e5887a378
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 241 additions and 72 deletions

View File

@ -763,6 +763,18 @@ enum class BooleanSetting(
"ArbitraryMipmapDetection",
true
),
GFX_CC_CORRECT_COLOR_SPACE(
Settings.FILE_GFX,
Settings.SECTION_GFX_COLOR_CORRECTION,
"CorrectColorSpace",
false
),
GFX_CC_CORRECT_GAMMA(
Settings.FILE_GFX,
Settings.SECTION_GFX_COLOR_CORRECTION,
"CorrectGamma",
false
),
GFX_STEREO_SWAP_EYES(Settings.FILE_GFX, Settings.SECTION_STEREOSCOPY, "StereoSwapEyes", false),
GFX_HACK_EFB_ACCESS_ENABLE(
Settings.FILE_GFX,

View File

@ -10,7 +10,8 @@ enum class FloatSetting(
) : AbstractFloatSetting {
// These entries have the same names and order as in C++, just for consistency.
MAIN_EMULATION_SPEED(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "EmulationSpeed", 1.0f),
MAIN_OVERCLOCK(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "Overclock", 1.0f);
MAIN_OVERCLOCK(Settings.FILE_DOLPHIN, Settings.SECTION_INI_CORE, "Overclock", 1.0f),
GFX_CC_GAME_GAMMA(Settings.FILE_GFX, Settings.SECTION_GFX_COLOR_CORRECTION, "GameGamma", 2.35f);
override val isOverridden: Boolean
get() = NativeConfig.isOverridden(file, section, key)

View File

@ -119,6 +119,12 @@ enum class IntSetting(
"MaxAnisotropy",
0
),
GFX_CC_GAME_COLOR_SPACE(
Settings.FILE_GFX,
Settings.SECTION_GFX_COLOR_CORRECTION,
"GameColorSpace",
0
),
GFX_STEREO_MODE(Settings.FILE_GFX, Settings.SECTION_STEREOSCOPY, "StereoMode", 0),
GFX_STEREO_DEPTH(Settings.FILE_GFX, Settings.SECTION_STEREOSCOPY, "StereoDepth", 20),
GFX_STEREO_CONVERGENCE_PERCENTAGE(

View File

@ -135,6 +135,7 @@ class Settings : Closeable {
const val SECTION_LOGGER_OPTIONS = "Options"
const val SECTION_GFX_SETTINGS = "Settings"
const val SECTION_GFX_ENHANCEMENTS = "Enhancements"
const val SECTION_GFX_COLOR_CORRECTION = "ColorCorrection"
const val SECTION_GFX_HACKS = "Hacks"
const val SECTION_DEBUG = "Debug"
const val SECTION_EMULATED_USB_DEVICES = "EmulatedUSBDevices"

View File

@ -6,7 +6,8 @@ import android.content.Context
import org.dolphinemu.dolphinemu.features.settings.model.AbstractFloatSetting
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
import org.dolphinemu.dolphinemu.features.settings.model.Settings
import kotlin.math.roundToInt
import java.math.BigDecimal
import java.math.MathContext
open class FloatSliderSetting : SliderSetting {
var floatSetting: AbstractFloatSetting
@ -19,11 +20,12 @@ open class FloatSliderSetting : SliderSetting {
setting: AbstractFloatSetting,
titleId: Int,
descriptionId: Int,
min: Int,
max: Int,
min: Float,
max: Float,
units: String?,
stepSize: Int
) : super(context, titleId, descriptionId, min, max, units, stepSize) {
stepSize: Float,
showDecimal: Boolean
) : super(context, titleId, descriptionId, min, max, units, stepSize, showDecimal) {
floatSetting = setting
}
@ -31,17 +33,21 @@ open class FloatSliderSetting : SliderSetting {
setting: AbstractFloatSetting,
name: CharSequence,
description: CharSequence?,
min: Int,
max: Int,
units: String?
) : super(name, description, min, max, units) {
min: Float,
max: Float,
units: String?,
showDecimal: Boolean
) : super(name, description, min, max, units, showDecimal) {
floatSetting = setting
}
override val selectedValue: Int
get() = floatSetting.float.roundToInt()
override val selectedValue: Float
get() = floatSetting.float
open fun setSelectedValue(settings: Settings?, selection: Float) {
floatSetting.setFloat(settings!!, selection)
floatSetting.setFloat(
settings!!,
BigDecimal((selection).toDouble()).round(MathContext(3)).toFloat()
)
}
}

View File

@ -16,7 +16,7 @@ class IntSliderSetting(
max: Int,
units: String?,
stepSize: Int
) : SliderSetting(context, titleId, descriptionId, min, max, units, stepSize) {
) : SliderSetting(context, titleId, descriptionId, min, max, units, stepSize, false) {
override val setting: AbstractSetting
get() = intSetting

View File

@ -4,24 +4,38 @@ package org.dolphinemu.dolphinemu.features.settings.model.view
import android.content.Context
import org.dolphinemu.dolphinemu.features.settings.model.AbstractFloatSetting
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
import org.dolphinemu.dolphinemu.features.settings.model.Settings
import kotlin.math.roundToInt
import java.math.BigDecimal
import java.math.MathContext
class PercentSliderSetting(
context: Context,
override val setting: AbstractFloatSetting,
titleId: Int,
descriptionId: Int,
min: Int,
max: Int,
min: Float,
max: Float,
units: String?,
stepSize: Int
) : FloatSliderSetting(context, setting, titleId, descriptionId, min, max, units, stepSize) {
override val selectedValue: Int
get() = (floatSetting.float * 100).roundToInt()
stepSize: Float,
showDecimal: Boolean
) : FloatSliderSetting(
context,
setting,
titleId,
descriptionId,
min,
max,
units,
stepSize,
showDecimal
) {
override val selectedValue: Float
get() = (floatSetting.float * 100)
override fun setSelectedValue(settings: Settings?, selection: Float) {
floatSetting.setFloat(settings!!, selection / 100)
floatSetting.setFloat(
settings!!,
BigDecimal((selection / 100).toDouble()).round(MathContext(3)).toFloat()
)
}
}

View File

@ -4,44 +4,50 @@ package org.dolphinemu.dolphinemu.features.settings.model.view
import android.content.Context
abstract class SliderSetting : SettingsItem {
sealed class SliderSetting : SettingsItem {
override val type: Int = TYPE_SLIDER
var min: Int
var min: Any
private set
var max: Int
var max: Any
private set
var units: String?
private set
var stepSize = 0
var stepSize: Any = 0
private set
var showDecimal: Boolean = false
private set
constructor(
context: Context,
nameId: Int,
descriptionId: Int,
min: Int,
max: Int,
min: Any,
max: Any,
units: String?,
stepSize: Int
stepSize: Any,
showDecimal: Boolean
) : super(context, nameId, descriptionId) {
this.min = min
this.max = max
this.units = units
this.stepSize = stepSize
this.showDecimal = showDecimal
}
constructor(
name: CharSequence,
description: CharSequence?,
min: Int,
max: Int,
units: String?
min: Any,
max: Any,
units: String?,
showDecimal: Boolean
) : super(name, description) {
this.min = min
this.max = max
this.units = units
this.showDecimal = showDecimal
}
abstract val selectedValue: Int
abstract val selectedValue: Any
}

View File

@ -19,6 +19,7 @@ enum class MenuTag {
DEBUG("debug"),
GRAPHICS("graphics"),
ENHANCEMENTS("enhancements"),
COLOR_CORRECTION("color_correction"),
STEREOSCOPY("stereoscopy"),
HACKS("hacks"),
STATISTICS("statistics"),

View File

@ -51,7 +51,7 @@ class SettingsAdapter(
private var settingsList: ArrayList<SettingsItem>? = null
private var clickedItem: SettingsItem? = null
private var clickedPosition: Int = -1
private var seekbarProgress = 0
private var seekbarProgress: Float = 0f
private var dialog: AlertDialog? = null
private var textSliderValue: TextView? = null
@ -229,21 +229,37 @@ class SettingsAdapter(
fun onSliderClick(item: SliderSetting, position: Int) {
clickedItem = item
clickedPosition = position
seekbarProgress = item.selectedValue
seekbarProgress = when (item) {
is FloatSliderSetting -> item.selectedValue
is IntSliderSetting -> item.selectedValue.toFloat()
}
val inflater = LayoutInflater.from(fragmentView.fragmentActivity)
val binding = DialogSliderBinding.inflate(inflater)
textSliderValue = binding.textValue
textSliderValue!!.text = seekbarProgress.toString()
textSliderValue!!.text = if (item.showDecimal) {
String.format("%.2f", seekbarProgress)
} else {
seekbarProgress.toInt().toString()
}
binding.textUnits.text = item.units
val slider = binding.slider
slider.valueFrom = item.min.toFloat()
slider.valueTo = item.max.toFloat()
slider.value = seekbarProgress.toFloat()
slider.stepSize = item.stepSize.toFloat()
when (item) {
is FloatSliderSetting -> {
slider.valueFrom = item.min as Float
slider.valueTo = item.max as Float
slider.stepSize = item.stepSize as Float
}
is IntSliderSetting -> {
slider.valueFrom = (item.min as Int).toFloat()
slider.valueTo = (item.max as Int).toFloat()
slider.stepSize = (item.stepSize as Int).toFloat()
}
}
slider.value = seekbarProgress
slider.addOnChangeListener(this)
dialog = MaterialAlertDialogBuilder(fragmentView.fragmentActivity)
@ -480,8 +496,10 @@ class SettingsAdapter(
}
is IntSliderSetting -> {
val sliderSetting = clickedItem as IntSliderSetting
if (sliderSetting.selectedValue != seekbarProgress) fragmentView.onSettingChanged()
sliderSetting.setSelectedValue(settings, seekbarProgress)
if (sliderSetting.selectedValue != seekbarProgress.toInt()) {
fragmentView.onSettingChanged()
}
sliderSetting.setSelectedValue(settings, seekbarProgress.toInt())
closeDialog()
}
is FloatSliderSetting -> {
@ -489,13 +507,13 @@ class SettingsAdapter(
if (sliderSetting.selectedValue != seekbarProgress) fragmentView.onSettingChanged()
sliderSetting.setSelectedValue(settings, seekbarProgress.toFloat())
sliderSetting.setSelectedValue(settings, seekbarProgress)
closeDialog()
}
}
clickedItem = null
seekbarProgress = -1
seekbarProgress = -1f
}
fun closeDialog() {
@ -510,8 +528,12 @@ class SettingsAdapter(
}
override fun onValueChange(slider: Slider, progress: Float, fromUser: Boolean) {
seekbarProgress = progress.toInt()
textSliderValue!!.text = seekbarProgress.toString()
seekbarProgress = progress
textSliderValue!!.text = if ((clickedItem as SliderSetting).showDecimal) {
String.format("%.2f", seekbarProgress)
} else {
seekbarProgress.toInt().toString()
}
}
private fun getValueForSingleChoiceSelection(item: SingleChoiceSetting, which: Int): Int {

View File

@ -272,6 +272,7 @@ class SettingsFragment : Fragment(), SettingsFragmentView {
titles[MenuTag.DEBUG] = R.string.debug_submenu
titles[MenuTag.GRAPHICS] = R.string.graphics_settings
titles[MenuTag.ENHANCEMENTS] = R.string.enhancements_submenu
titles[MenuTag.COLOR_CORRECTION] = R.string.color_correction_submenu
titles[MenuTag.STEREOSCOPY] = R.string.stereoscopy_submenu
titles[MenuTag.HACKS] = R.string.hacks_submenu
titles[MenuTag.STATISTICS] = R.string.statistics_submenu

View File

@ -34,6 +34,7 @@ import org.dolphinemu.dolphinemu.model.GpuDriverMetadata
import org.dolphinemu.dolphinemu.ui.main.MainPresenter
import org.dolphinemu.dolphinemu.utils.*
import java.util.*
import kotlin.collections.ArrayList
import kotlin.math.ceil
import kotlin.math.floor
@ -72,9 +73,8 @@ class SettingsFragmentPresenter(
&& GpuDriverHelper.supportsCustomDriverLoading()
) {
this.gpuDriver =
GpuDriverHelper.getInstalledDriverMetadata() ?: GpuDriverHelper.getSystemDriverMetadata(
context.applicationContext
)
GpuDriverHelper.getInstalledDriverMetadata()
?: GpuDriverHelper.getSystemDriverMetadata(context.applicationContext)
}
}
@ -120,6 +120,7 @@ class SettingsFragmentPresenter(
MenuTag.GCPAD_TYPE -> addGcPadSettings(sl)
MenuTag.WIIMOTE -> addWiimoteSettings(sl)
MenuTag.ENHANCEMENTS -> addEnhanceSettings(sl)
MenuTag.COLOR_CORRECTION -> addColorCorrectionSettings(sl)
MenuTag.STEREOSCOPY -> addStereoSettings(sl)
MenuTag.HACKS -> addHackSettings(sl)
MenuTag.STATISTICS -> addStatisticsSettings(sl)
@ -250,10 +251,11 @@ class SettingsFragmentPresenter(
FloatSetting.MAIN_EMULATION_SPEED,
R.string.speed_limit,
0,
0,
200,
0f,
200f,
"%",
1
1f,
false
)
)
sl.add(
@ -713,12 +715,12 @@ class SettingsFragmentPresenter(
)
)
sl.add(
SwitchSetting(
context,
BooleanSetting.MAIN_WII_WIILINK_ENABLE,
R.string.wii_enable_wiilink,
R.string.wii_enable_wiilink_description
)
SwitchSetting(
context,
BooleanSetting.MAIN_WII_WIILINK_ENABLE,
R.string.wii_enable_wiilink,
R.string.wii_enable_wiilink_description
)
)
sl.add(
SingleChoiceSetting(
@ -1001,10 +1003,11 @@ class SettingsFragmentPresenter(
FloatSetting.MAIN_OVERCLOCK,
R.string.overclock_title,
R.string.overclock_title_description,
0,
400,
0f,
400f,
"%",
1
1f,
false
)
)
@ -1333,6 +1336,13 @@ class SettingsFragmentPresenter(
R.array.textureFilteringValues
)
)
sl.add(
SubmenuSetting(
context,
R.string.color_correction_submenu,
MenuTag.COLOR_CORRECTION
)
)
val stereoModeValue = IntSetting.GFX_STEREO_MODE.int
val anaglyphMode = 3
@ -1429,6 +1439,53 @@ class SettingsFragmentPresenter(
}
}
private fun addColorCorrectionSettings(sl: ArrayList<SettingsItem>) {
sl.apply {
add(HeaderSetting(context, R.string.color_space, 0))
add(
SwitchSetting(
context,
BooleanSetting.GFX_CC_CORRECT_COLOR_SPACE,
R.string.correct_color_space,
R.string.correct_color_space_description
)
)
add(
SingleChoiceSetting(
context,
IntSetting.GFX_CC_GAME_COLOR_SPACE,
R.string.game_color_space,
0,
R.array.colorSpaceEntries,
R.array.colorSpaceValues
)
)
add(HeaderSetting(context, R.string.gamma, 0))
add(
FloatSliderSetting(
context,
FloatSetting.GFX_CC_GAME_GAMMA,
R.string.game_gamma,
R.string.game_gamma_description,
2.2f,
2.8f,
"",
0.01f,
true
)
)
add(
SwitchSetting(
context,
BooleanSetting.GFX_CC_CORRECT_GAMMA,
R.string.correct_sdr_gamma,
0
)
)
}
}
private fun addHackSettings(sl: ArrayList<SettingsItem>) {
sl.add(HeaderSetting(context, R.string.embedded_frame_buffer, 0))
sl.add(
@ -2296,9 +2353,10 @@ class SettingsFragmentPresenter(
InputMappingDoubleSetting(setting),
setting.getUiName(),
"",
ceil(setting.getDoubleMin()).toInt(),
floor(setting.getDoubleMax()).toInt(),
setting.getUiSuffix()
ceil(setting.getDoubleMin()).toFloat(),
floor(setting.getDoubleMax()).toFloat(),
setting.getUiSuffix(),
false
)
)

View File

@ -7,6 +7,7 @@ import android.text.TextUtils
import android.view.View
import org.dolphinemu.dolphinemu.R
import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding
import org.dolphinemu.dolphinemu.features.settings.model.view.IntSliderSetting
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
import org.dolphinemu.dolphinemu.features.settings.model.view.SliderSetting
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
@ -14,7 +15,7 @@ import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
class SliderViewHolder(
private val binding: ListItemSettingBinding, adapter: SettingsAdapter?,
private val context: Context
) : SettingViewHolder(binding.getRoot(), adapter!!) {
) : SettingViewHolder(binding.root, adapter!!) {
private lateinit var setting: SliderSetting
override val item: SettingsItem
@ -28,11 +29,25 @@ class SliderViewHolder(
if (!TextUtils.isEmpty(item.description)) {
binding.textSettingDescription.text = item.description
} else {
binding.textSettingDescription.text = context.getString(
R.string.slider_setting_value,
setting.selectedValue,
setting.units
)
val selectedValue: Float = if (item is IntSliderSetting) {
(setting.selectedValue as Int).toFloat()
} else {
setting.selectedValue as Float
}
if (setting.showDecimal) {
binding.textSettingDescription.text = String.format(
context.getString(R.string.slider_setting_float_value),
selectedValue,
setting.units
)
} else {
binding.textSettingDescription.text = String.format(
context.getString(R.string.slider_setting_value),
selectedValue,
setting.units
)
}
}
setStyle(binding.textSettingName, setting)

View File

@ -732,4 +732,15 @@
<item>21</item>
<item>22</item>
</integer-array>
<string-array name="colorSpaceEntries">
<item>@string/ntscm_space</item>
<item>@string/ntscj_space</item>
<item>@string/pal_space</item>
</string-array>
<integer-array name="colorSpaceValues">
<item>0</item>
<item>1</item>
<item>2</item>
</integer-array>
</resources>

View File

@ -222,6 +222,20 @@
<string name="disable_copy_filter_description">Disables the blending of adjacent rows when copying the EFB. This is known in some games as \"deflickering\" or \"smoothing\". Disabling the filter is usually safe, and may result in a sharper image.</string>
<string name="arbitrary_mipmap_detection">Arbitrary Mipmap Detection</string>
<string name="arbitrary_mipmap_detection_description">Enables detection of arbitrary mipmaps, which some games use for special distance-based effects.\nMay have false positives that result in blurry textures at increased internal resolution, such as in games that use very low resolution mipmaps. Disabling this can also reduce stutter in games that frequently load new textures.\n\nIf unsure, leave this checked.</string>
<string name="color_correction_submenu">Color Correction</string>
<string name="color_space">Color Space</string>
<string name="correct_color_space">Correct Color Space</string>
<string name="correct_color_space_description">Converts the colors from the color spaces that GC/Wii were meant to work with to sRGB/Rec.709.</string>
<string name="game_color_space">Game Color Space</string>
<string name="ntscm_space">NTSC-M (SMPTE 170M)</string>
<string name="ntscj_space">NTSC-J (ARUB TR-89)</string>
<string name="pal_space">PAL (EBU)</string>
<string name="gamma">Gamma</string>
<string name="game_gamma">Game Gamma</string>
<string name="game_gamma_description">NTSC-M and NTSC-J target gamma ~2.2. PAL targets gamma ~2.8.\nNone of the two were necessarily followed by games or TVs. 2.35 is a good generic value for all regions.\nIf a game allows you to chose a gamma value, match it here.</string>
<string name="correct_sdr_gamma">Correct SDR Gamma</string>
<string name="sdr_display_gamma_target">SDR Display Gamma Target</string>
<string name="custom_gamma_target">Custom Gamma Target</string>
<string name="stereoscopy_submenu">Stereoscopy</string>
<string name="stereoscopy_submenu_description">Stereoscopy allows you to get a better feeling of depth if you have the necessary hardware.\nHeavily decreases emulation speed and sometimes causes issues</string>
<string name="wide_screen_hack">Widescreen Hack</string>
@ -619,7 +633,8 @@ It can efficiently compress both junk data and encrypted Wii data.
<!-- Misc -->
<string name="enabled">Enabled</string>
<string name="default_values">Default Values</string>
<string name="slider_setting_value">%1$d%2$s</string>
<string name="slider_setting_value">%.0f%2$s</string>
<string name="slider_setting_float_value">%.2f%2$s</string>
<string name="disc_number">Disc %1$d</string>
<string name="replug_gc_adapter">GameCube Adapter couldn\'t be opened. Please re-plug the device.</string>
<string name="disabled_gc_overlay_notice">The selected GameCube controller is set to \"None\"</string>