mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-09 21:47:56 +00:00
More adjustments to UI
This commit is contained in:
@@ -298,6 +298,7 @@ class QuickSettings(val emulationFragment: EmulationFragment) {
|
||||
steps: Int,
|
||||
selectedStep: Int,
|
||||
describe: (Int) -> String,
|
||||
onCommitted: (Int) -> Unit,
|
||||
onChanged: (Int) -> Unit
|
||||
) {
|
||||
val inflater = LayoutInflater.from(emulationFragment.requireContext())
|
||||
@@ -327,14 +328,20 @@ class QuickSettings(val emulationFragment: EmulationFragment) {
|
||||
}
|
||||
}
|
||||
|
||||
var pressedValue = slider.value
|
||||
|
||||
slider.setOnTouchListener { _, event ->
|
||||
val drawer = emulationFragment.view?.findViewById<DrawerLayout>(R.id.drawer_layout)
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
drawer?.requestDisallowInterceptTouchEvent(true)
|
||||
pressedValue = slider.value
|
||||
}
|
||||
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||
drawer?.requestDisallowInterceptTouchEvent(false)
|
||||
if (slider.value != pressedValue) {
|
||||
onCommitted(slider.value.toInt())
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
@@ -389,6 +396,8 @@ class QuickSettings(val emulationFragment: EmulationFragment) {
|
||||
fun addEffectPicker(
|
||||
container: ViewGroup,
|
||||
choices: List<String>,
|
||||
hasEffects: Boolean,
|
||||
onRemoveAll: () -> Unit,
|
||||
onPicked: (Int) -> Unit
|
||||
) {
|
||||
val context = emulationFragment.requireContext()
|
||||
@@ -398,6 +407,10 @@ class QuickSettings(val emulationFragment: EmulationFragment) {
|
||||
val button = itemView.findViewById<com.google.android.material.button.MaterialButton>(
|
||||
R.id.add_button
|
||||
)
|
||||
val removeButton =
|
||||
itemView.findViewById<com.google.android.material.button.MaterialButton>(
|
||||
R.id.remove_all_button
|
||||
)
|
||||
val choiceGroup = itemView.findViewById<RadioGroup>(R.id.add_choices)
|
||||
|
||||
choices.forEachIndexed { index, name ->
|
||||
@@ -413,22 +426,27 @@ class QuickSettings(val emulationFragment: EmulationFragment) {
|
||||
choiceGroup.addView(radioButton)
|
||||
}
|
||||
|
||||
val closedBackground = MaterialColors.getColor(
|
||||
button,
|
||||
com.google.android.material.R.attr.colorSecondaryContainer
|
||||
)
|
||||
val closedForeground = MaterialColors.getColor(
|
||||
button,
|
||||
com.google.android.material.R.attr.colorOnSecondaryContainer
|
||||
)
|
||||
val openBackground = MaterialColors.getColor(
|
||||
button,
|
||||
var closedLabel = R.string.post_processing_add
|
||||
if (hasEffects) {
|
||||
closedLabel = R.string.post_processing_open_list
|
||||
removeButton.visibility = View.VISIBLE
|
||||
}
|
||||
button.setText(closedLabel)
|
||||
|
||||
val removeBackground = MaterialColors.getColor(
|
||||
removeButton,
|
||||
com.google.android.material.R.attr.colorErrorContainer
|
||||
)
|
||||
val openForeground = MaterialColors.getColor(
|
||||
button,
|
||||
val removeForeground = MaterialColors.getColor(
|
||||
removeButton,
|
||||
com.google.android.material.R.attr.colorOnErrorContainer
|
||||
)
|
||||
removeButton.backgroundTintList = ColorStateList.valueOf(removeBackground)
|
||||
removeButton.setTextColor(removeForeground)
|
||||
removeButton.iconTint = ColorStateList.valueOf(removeForeground)
|
||||
removeButton.setOnClickListener {
|
||||
onRemoveAll()
|
||||
}
|
||||
|
||||
val slide = context.resources.displayMetrics.density * 24.0f
|
||||
|
||||
@@ -451,11 +469,8 @@ class QuickSettings(val emulationFragment: EmulationFragment) {
|
||||
}
|
||||
.start()
|
||||
|
||||
button.text = context.getString(R.string.post_processing_hide_effects)
|
||||
button.setText(R.string.post_processing_close_list)
|
||||
button.setIconResource(R.drawable.ic_clear)
|
||||
button.backgroundTintList = ColorStateList.valueOf(openBackground)
|
||||
button.setTextColor(openForeground)
|
||||
button.iconTint = ColorStateList.valueOf(openForeground)
|
||||
} else {
|
||||
choiceGroup.animate()
|
||||
.alpha(0.0f)
|
||||
@@ -466,11 +481,8 @@ class QuickSettings(val emulationFragment: EmulationFragment) {
|
||||
}
|
||||
.start()
|
||||
|
||||
button.text = context.getString(R.string.post_processing_add)
|
||||
button.setText(closedLabel)
|
||||
button.setIconResource(R.drawable.ic_add)
|
||||
button.backgroundTintList = ColorStateList.valueOf(closedBackground)
|
||||
button.setTextColor(closedForeground)
|
||||
button.iconTint = ColorStateList.valueOf(closedForeground)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -494,8 +506,9 @@ class QuickSettings(val emulationFragment: EmulationFragment) {
|
||||
|
||||
switchView.isChecked = NativePostProcessing.isEnabled()
|
||||
switchView.setOnCheckedChangeListener { _, checked ->
|
||||
NativePostProcessing.setEnabled(checked)
|
||||
saveSettings()
|
||||
emulationFragment.editPostProcessing {
|
||||
NativePostProcessing.setEnabled(checked)
|
||||
}
|
||||
}
|
||||
|
||||
container.addView(itemView)
|
||||
@@ -510,12 +523,21 @@ class QuickSettings(val emulationFragment: EmulationFragment) {
|
||||
val preset = NativePostProcessing.getActivePreset()
|
||||
if (preset.isNotEmpty()) {
|
||||
addDivider(container)
|
||||
var summary =
|
||||
YuzuApplication.appContext.getString(R.string.post_processing_preset_locked)
|
||||
|
||||
var summary = ""
|
||||
val described = NativePostProcessing.presets().firstOrNull { it.name == preset }
|
||||
if (described != null) {
|
||||
summary = described.description
|
||||
}
|
||||
if (summary.isEmpty()) {
|
||||
summary =
|
||||
YuzuApplication.appContext.getString(R.string.post_processing_preset_locked)
|
||||
}
|
||||
if (NativePostProcessing.isPresetModified()) {
|
||||
summary =
|
||||
YuzuApplication.appContext.getString(R.string.post_processing_preset_modified)
|
||||
}
|
||||
|
||||
addPresetBand(container, preset, summary)
|
||||
return
|
||||
}
|
||||
@@ -553,8 +575,9 @@ class QuickSettings(val emulationFragment: EmulationFragment) {
|
||||
}
|
||||
|
||||
val body = addShaderCard(title, summary, container) {
|
||||
NativePostProcessing.remove(index)
|
||||
NativePostProcessing.persistFor(emulationFragment.shouldUseCustom)
|
||||
emulationFragment.editPostProcessing {
|
||||
NativePostProcessing.remove(index)
|
||||
}
|
||||
onStructureChanged()
|
||||
}
|
||||
|
||||
@@ -565,9 +588,20 @@ class QuickSettings(val emulationFragment: EmulationFragment) {
|
||||
}
|
||||
}
|
||||
|
||||
addEffectPicker(container, labels) { picked ->
|
||||
NativePostProcessing.append(files[picked], techniques[picked])
|
||||
NativePostProcessing.persistFor(emulationFragment.shouldUseCustom)
|
||||
addEffectPicker(
|
||||
container,
|
||||
labels,
|
||||
chain.isNotEmpty(),
|
||||
{
|
||||
emulationFragment.editPostProcessing {
|
||||
NativePostProcessing.clearChain()
|
||||
}
|
||||
onStructureChanged()
|
||||
}
|
||||
) { picked ->
|
||||
emulationFragment.editPostProcessing {
|
||||
NativePostProcessing.append(files[picked], techniques[picked])
|
||||
}
|
||||
onStructureChanged()
|
||||
}
|
||||
}
|
||||
@@ -600,7 +634,8 @@ class QuickSettings(val emulationFragment: EmulationFragment) {
|
||||
container,
|
||||
steps,
|
||||
step,
|
||||
{ position -> describeUniform(uniform, position) }
|
||||
{ position -> describeUniform(uniform, position) },
|
||||
{ emulationFragment.persistPostProcessing() }
|
||||
) { position ->
|
||||
NativePostProcessing.setValue(
|
||||
index,
|
||||
@@ -608,7 +643,6 @@ class QuickSettings(val emulationFragment: EmulationFragment) {
|
||||
component,
|
||||
uniform.min + position * uniform.step
|
||||
)
|
||||
NativePostProcessing.persistFor(emulationFragment.shouldUseCustom)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.features.settings.model
|
||||
|
||||
class FxPresetNameSetting(private val onNamed: (String) -> Unit) : AbstractStringSetting {
|
||||
override val key: String
|
||||
get() = "fx_preset_name"
|
||||
|
||||
override val defaultValue: Any
|
||||
get() = ""
|
||||
|
||||
override val isRuntimeModifiable: Boolean
|
||||
get() = true
|
||||
|
||||
override val pairedSettingKey: String
|
||||
get() = ""
|
||||
|
||||
override val isSwitchable: Boolean
|
||||
get() = false
|
||||
|
||||
override val isSaveable: Boolean
|
||||
get() = true
|
||||
|
||||
override var global: Boolean
|
||||
get() = true
|
||||
set(_) {}
|
||||
|
||||
override fun getString(needsGlobal: Boolean): String = ""
|
||||
|
||||
override fun setString(value: String) = onNamed(value)
|
||||
|
||||
override fun getValueAsString(needsGlobal: Boolean): String = ""
|
||||
|
||||
override fun reset() {}
|
||||
}
|
||||
+4
-4
@@ -39,7 +39,7 @@ abstract class FxUniformSetting(
|
||||
|
||||
protected fun commit(value: Float) {
|
||||
NativePostProcessing.setValue(index, uniform.name, component, value)
|
||||
NativePostProcessing.persist()
|
||||
NativePostProcessing.store()
|
||||
}
|
||||
|
||||
override fun reset() = commit(uniform.defaultAt(component))
|
||||
@@ -92,11 +92,11 @@ class FxUniformBooleanSetting(
|
||||
override fun getBoolean(needsGlobal: Boolean): Boolean = currentValue() != 0f
|
||||
|
||||
override fun setBoolean(value: Boolean) {
|
||||
var scalar = 0f
|
||||
if (value) {
|
||||
commit(1f)
|
||||
return
|
||||
scalar = 1f
|
||||
}
|
||||
commit(0f)
|
||||
commit(scalar)
|
||||
}
|
||||
|
||||
override fun getValueAsString(needsGlobal: Boolean): String = getBoolean().toString()
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.features.settings.model.view
|
||||
|
||||
class FxPresetSetting(
|
||||
titleString: String,
|
||||
descriptionString: String = "",
|
||||
val deletable: Boolean = false,
|
||||
val onApply: () -> Unit,
|
||||
val onDelete: () -> Unit = {}
|
||||
) : SettingsItem(emptySetting, 0, titleString, 0, descriptionString) {
|
||||
override val type = TYPE_FX_PRESET
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.features.settings.model.view
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
|
||||
class FxToolbarSetting(
|
||||
@StringRes val addLabelId: Int,
|
||||
val listOpen: Boolean,
|
||||
val presetLabel: String,
|
||||
val hasEffects: Boolean,
|
||||
val createPreset: StringInputSetting,
|
||||
val onAdd: () -> Unit,
|
||||
val onPresets: () -> Unit,
|
||||
val onRemoveAll: () -> Unit
|
||||
) : SettingsItem(emptySetting, 0, "", 0, "") {
|
||||
override val type = TYPE_FX_TOOLBAR
|
||||
}
|
||||
+2
@@ -145,6 +145,8 @@ abstract class SettingsItem(
|
||||
const val TYPE_PATH = 14
|
||||
const val TYPE_GPU_UNSWIZZLE = 15
|
||||
const val TYPE_CARD = 16
|
||||
const val TYPE_FX_TOOLBAR = 17
|
||||
const val TYPE_FX_PRESET = 18
|
||||
|
||||
const val FASTMEM_COMBINED = "fastmem_combined"
|
||||
const val GPU_UNSWIZZLE_COMBINED = "gpu_unswizzle_combined"
|
||||
|
||||
+17
-1
@@ -24,6 +24,8 @@ import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.SettingsNavigationDirections
|
||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
|
||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingCardBinding
|
||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingFxPresetBinding
|
||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingFxToolbarBinding
|
||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingInputBinding
|
||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingSwitchBinding
|
||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingsHeaderBinding
|
||||
@@ -108,7 +110,21 @@ class SettingsAdapter(
|
||||
}
|
||||
|
||||
SettingsItem.TYPE_CARD -> {
|
||||
CardViewHolder(ListItemSettingCardBinding.inflate(inflater), this)
|
||||
CardViewHolder(ListItemSettingCardBinding.inflate(inflater, parent, false), this)
|
||||
}
|
||||
|
||||
SettingsItem.TYPE_FX_TOOLBAR -> {
|
||||
FxToolbarViewHolder(
|
||||
ListItemSettingFxToolbarBinding.inflate(inflater, parent, false),
|
||||
this
|
||||
)
|
||||
}
|
||||
|
||||
SettingsItem.TYPE_FX_PRESET -> {
|
||||
FxPresetViewHolder(
|
||||
ListItemSettingFxPresetBinding.inflate(inflater, parent, false),
|
||||
this
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
|
||||
+126
-89
@@ -18,6 +18,7 @@ import org.yuzu.yuzu_emu.features.input.model.NpadStyleIndex
|
||||
import org.yuzu.yuzu_emu.features.settings.model.AbstractBooleanSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.AbstractIntSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.FxPresetNameSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.FxUniformBooleanSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.FxUniformChoiceSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.FxUniformSliderSetting
|
||||
@@ -54,6 +55,8 @@ class SettingsFragmentPresenter(
|
||||
|
||||
private var presetPickerOpen = false
|
||||
|
||||
private var postProcessingSynced = false
|
||||
|
||||
private val context get() = YuzuApplication.appContext
|
||||
|
||||
// Extension for altering settings list based on each setting's properties
|
||||
@@ -202,6 +205,11 @@ class SettingsFragmentPresenter(
|
||||
}
|
||||
|
||||
private fun addPostProcessingSettings(sl: ArrayList<SettingsItem>) {
|
||||
if (!postProcessingSynced) {
|
||||
postProcessingSynced = true
|
||||
NativePostProcessing.reload()
|
||||
}
|
||||
|
||||
val usable = NativePostProcessing.catalog().filter { it.valid }
|
||||
|
||||
sl.apply {
|
||||
@@ -216,68 +224,6 @@ class SettingsFragmentPresenter(
|
||||
return@apply
|
||||
}
|
||||
|
||||
val active = NativePostProcessing.getActivePreset()
|
||||
var presetSummary = context.getString(R.string.post_processing_preset_none)
|
||||
if (active.isNotEmpty()) {
|
||||
presetSummary = active
|
||||
if (NativePostProcessing.isPresetModified()) {
|
||||
presetSummary = context.getString(R.string.post_processing_preset_modified)
|
||||
}
|
||||
}
|
||||
|
||||
add(
|
||||
CardSetting(
|
||||
titleId = R.string.post_processing_preset,
|
||||
descriptionString = presetSummary,
|
||||
expanded = presetPickerOpen
|
||||
) {
|
||||
presetPickerOpen = !presetPickerOpen
|
||||
settingsViewModel.setReloadListAndNotifyDataset(true)
|
||||
}
|
||||
)
|
||||
|
||||
if (presetPickerOpen) {
|
||||
add(
|
||||
RunnableSetting(
|
||||
titleId = R.string.post_processing_preset_none,
|
||||
isRunnable = true
|
||||
) {
|
||||
NativePostProcessing.clearPreset()
|
||||
presetPickerOpen = false
|
||||
settingsViewModel.setReloadListAndNotifyDataset(true)
|
||||
}
|
||||
)
|
||||
for (preset in NativePostProcessing.presets()) {
|
||||
add(
|
||||
RunnableSetting(
|
||||
titleString = preset.name,
|
||||
descriptionString = preset.description,
|
||||
isRunnable = true
|
||||
) {
|
||||
NativePostProcessing.applyPreset(preset.name)
|
||||
NativePostProcessing.store()
|
||||
presetPickerOpen = false
|
||||
expandedShaderSlots.clear()
|
||||
settingsViewModel.setReloadListAndNotifyDataset(true)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (active.isNotEmpty()) {
|
||||
add(
|
||||
RunnableSetting(
|
||||
titleId = R.string.post_processing_preset_reset,
|
||||
isRunnable = true
|
||||
) {
|
||||
NativePostProcessing.applyPreset(active)
|
||||
NativePostProcessing.store()
|
||||
expandedShaderSlots.clear()
|
||||
settingsViewModel.setReloadListAndNotifyDataset(true)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
val labels = mutableListOf<String>()
|
||||
val summaries = mutableListOf<String>()
|
||||
val files = mutableListOf<String>()
|
||||
@@ -296,6 +242,124 @@ class SettingsFragmentPresenter(
|
||||
}
|
||||
|
||||
val chain = NativePostProcessing.chain()
|
||||
val active = NativePostProcessing.getActivePreset()
|
||||
|
||||
var addLabel = R.string.post_processing_add
|
||||
if (chain.isNotEmpty()) {
|
||||
addLabel = R.string.post_processing_open_list
|
||||
}
|
||||
if (shaderPickerOpen) {
|
||||
addLabel = R.string.post_processing_close_list
|
||||
}
|
||||
|
||||
var presetLabel = context.getString(R.string.post_processing_presets)
|
||||
if (active.isNotEmpty()) {
|
||||
presetLabel = active
|
||||
}
|
||||
|
||||
val createPreset = StringInputSetting(
|
||||
setting = FxPresetNameSetting { name ->
|
||||
NativePostProcessing.savePreset(name, "")
|
||||
settingsViewModel.setReloadListAndNotifyDataset(true)
|
||||
},
|
||||
titleId = R.string.post_processing_preset_new,
|
||||
descriptionId = R.string.post_processing_preset_new_description,
|
||||
validator = { it != null && it.isNotBlank() && !it.contains('=') },
|
||||
errorId = R.string.post_processing_preset_name_invalid
|
||||
)
|
||||
|
||||
add(
|
||||
FxToolbarSetting(
|
||||
addLabelId = addLabel,
|
||||
listOpen = shaderPickerOpen,
|
||||
presetLabel = presetLabel,
|
||||
hasEffects = chain.isNotEmpty(),
|
||||
createPreset = createPreset,
|
||||
onAdd = {
|
||||
shaderPickerOpen = !shaderPickerOpen
|
||||
presetPickerOpen = false
|
||||
settingsViewModel.setReloadListAndNotifyDataset(true)
|
||||
},
|
||||
onPresets = {
|
||||
presetPickerOpen = !presetPickerOpen
|
||||
shaderPickerOpen = false
|
||||
settingsViewModel.setReloadListAndNotifyDataset(true)
|
||||
},
|
||||
onRemoveAll = {
|
||||
NativePostProcessing.clearChain()
|
||||
NativePostProcessing.clearPreset()
|
||||
NativePostProcessing.store()
|
||||
expandedShaderSlots.clear()
|
||||
shaderPickerOpen = false
|
||||
settingsViewModel.setReloadListAndNotifyDataset(true)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
if (shaderPickerOpen) {
|
||||
for (choice in labels.indices) {
|
||||
add(
|
||||
RunnableSetting(
|
||||
titleString = labels[choice],
|
||||
descriptionString = summaries[choice],
|
||||
isRunnable = true
|
||||
) {
|
||||
NativePostProcessing.append(files[choice], techniques[choice])
|
||||
NativePostProcessing.store()
|
||||
shaderPickerOpen = false
|
||||
settingsViewModel.setReloadListAndNotifyDataset(true)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (presetPickerOpen) {
|
||||
add(
|
||||
FxPresetSetting(
|
||||
titleString = context.getString(R.string.post_processing_preset_none),
|
||||
onApply = {
|
||||
NativePostProcessing.clearPreset()
|
||||
presetPickerOpen = false
|
||||
settingsViewModel.setReloadListAndNotifyDataset(true)
|
||||
}
|
||||
)
|
||||
)
|
||||
for (preset in NativePostProcessing.presets()) {
|
||||
add(
|
||||
FxPresetSetting(
|
||||
titleString = preset.name,
|
||||
descriptionString = preset.description,
|
||||
deletable = !preset.bundled,
|
||||
onApply = {
|
||||
NativePostProcessing.applyPreset(preset.name)
|
||||
NativePostProcessing.store()
|
||||
presetPickerOpen = false
|
||||
expandedShaderSlots.clear()
|
||||
settingsViewModel.setReloadListAndNotifyDataset(true)
|
||||
},
|
||||
onDelete = {
|
||||
NativePostProcessing.deletePreset(preset.name)
|
||||
settingsViewModel.setReloadListAndNotifyDataset(true)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (active.isNotEmpty()) {
|
||||
add(
|
||||
RunnableSetting(
|
||||
titleId = R.string.post_processing_preset_reset,
|
||||
isRunnable = true
|
||||
) {
|
||||
NativePostProcessing.applyPreset(active)
|
||||
NativePostProcessing.store()
|
||||
expandedShaderSlots.clear()
|
||||
settingsViewModel.setReloadListAndNotifyDataset(true)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
for (index in chain.indices) {
|
||||
val entry = chain[index]
|
||||
val effect = usable.firstOrNull { it.file == entry.file }
|
||||
@@ -385,33 +449,6 @@ class SettingsFragmentPresenter(
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
add(
|
||||
CardSetting(
|
||||
titleId = R.string.post_processing_add,
|
||||
expanded = shaderPickerOpen
|
||||
) {
|
||||
shaderPickerOpen = !shaderPickerOpen
|
||||
settingsViewModel.setReloadListAndNotifyDataset(true)
|
||||
}
|
||||
)
|
||||
|
||||
if (shaderPickerOpen) {
|
||||
for (choice in labels.indices) {
|
||||
add(
|
||||
RunnableSetting(
|
||||
titleString = labels[choice],
|
||||
descriptionString = summaries[choice],
|
||||
isRunnable = true
|
||||
) {
|
||||
NativePostProcessing.append(files[choice], techniques[choice])
|
||||
NativePostProcessing.store()
|
||||
shaderPickerOpen = false
|
||||
settingsViewModel.setReloadListAndNotifyDataset(true)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.features.settings.ui.viewholder
|
||||
|
||||
import android.view.View
|
||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingFxPresetBinding
|
||||
import org.yuzu.yuzu_emu.features.settings.model.view.FxPresetSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
||||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
|
||||
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
|
||||
|
||||
class FxPresetViewHolder(
|
||||
val binding: ListItemSettingFxPresetBinding,
|
||||
adapter: SettingsAdapter
|
||||
) : SettingViewHolder(binding.root, adapter) {
|
||||
private lateinit var setting: FxPresetSetting
|
||||
|
||||
override fun bind(item: SettingsItem) {
|
||||
setting = item as FxPresetSetting
|
||||
|
||||
binding.presetName.text = item.title
|
||||
binding.presetDescription.text = item.description
|
||||
binding.presetDescription.setVisible(item.description.isNotEmpty())
|
||||
|
||||
binding.presetRow.setOnClickListener { setting.onApply.invoke() }
|
||||
|
||||
binding.presetDelete.setVisible(setting.deletable)
|
||||
binding.presetDelete.setOnClickListener { setting.onDelete.invoke() }
|
||||
}
|
||||
|
||||
override fun onClick(clicked: View) {}
|
||||
|
||||
override fun onLongClick(clicked: View): Boolean = true
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.features.settings.ui.viewholder
|
||||
|
||||
import android.content.res.ColorStateList
|
||||
import android.view.View
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingFxToolbarBinding
|
||||
import org.yuzu.yuzu_emu.features.settings.model.view.FxToolbarSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
||||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
|
||||
|
||||
class FxToolbarViewHolder(
|
||||
val binding: ListItemSettingFxToolbarBinding,
|
||||
adapter: SettingsAdapter
|
||||
) : SettingViewHolder(binding.root, adapter) {
|
||||
private lateinit var setting: FxToolbarSetting
|
||||
|
||||
override fun bind(item: SettingsItem) {
|
||||
setting = item as FxToolbarSetting
|
||||
|
||||
binding.fxAdd.setText(setting.addLabelId)
|
||||
var addIcon = R.drawable.ic_add
|
||||
if (setting.listOpen) {
|
||||
addIcon = R.drawable.ic_clear
|
||||
}
|
||||
binding.fxAdd.setIconResource(addIcon)
|
||||
binding.fxAdd.setOnClickListener { setting.onAdd.invoke() }
|
||||
|
||||
binding.fxPresets.text = setting.presetLabel
|
||||
binding.fxPresets.setOnClickListener { setting.onPresets.invoke() }
|
||||
|
||||
binding.fxCreatePreset.isEnabled = setting.hasEffects
|
||||
binding.fxCreatePreset.setOnClickListener {
|
||||
adapter.onStringInputClick(setting.createPreset, bindingAdapterPosition)
|
||||
}
|
||||
|
||||
val removeBackground = MaterialColors.getColor(
|
||||
binding.fxRemoveAll,
|
||||
com.google.android.material.R.attr.colorErrorContainer
|
||||
)
|
||||
val removeForeground = MaterialColors.getColor(
|
||||
binding.fxRemoveAll,
|
||||
com.google.android.material.R.attr.colorOnErrorContainer
|
||||
)
|
||||
binding.fxRemoveAll.backgroundTintList = ColorStateList.valueOf(removeBackground)
|
||||
binding.fxRemoveAll.iconTint = ColorStateList.valueOf(removeForeground)
|
||||
binding.fxRemoveAll.isEnabled = setting.hasEffects
|
||||
binding.fxRemoveAll.setOnClickListener { setting.onRemoveAll.invoke() }
|
||||
}
|
||||
|
||||
override fun onClick(clicked: View) {}
|
||||
|
||||
override fun onLongClick(clicked: View): Boolean = true
|
||||
}
|
||||
@@ -94,6 +94,7 @@ import org.yuzu.yuzu_emu.utils.InputHandler
|
||||
import org.yuzu.yuzu_emu.utils.Log
|
||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
||||
import org.yuzu.yuzu_emu.utils.NativeFreedrenoConfig
|
||||
import org.yuzu.yuzu_emu.utils.NativePostProcessing
|
||||
import org.yuzu.yuzu_emu.utils.ViewUtils
|
||||
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
|
||||
import org.yuzu.yuzu_emu.utils.collect
|
||||
@@ -883,6 +884,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
if (shouldUseCustom) {
|
||||
SettingsFile.loadCustomConfig(game!!)
|
||||
}
|
||||
refreshPostProcessing()
|
||||
addQuickSettings()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1087,6 +1090,34 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
private fun withPerGameConfig(create: Boolean, action: () -> Unit) {
|
||||
val target = game
|
||||
var owned = false
|
||||
if (target != null && !NativeConfig.isPerGameConfigLoaded()) {
|
||||
if (create || SettingsFile.getCustomSettingsFile(target).exists()) {
|
||||
SettingsFile.loadCustomConfig(target)
|
||||
owned = true
|
||||
}
|
||||
}
|
||||
action()
|
||||
if (owned) {
|
||||
NativeConfig.unloadPerGameConfig()
|
||||
}
|
||||
}
|
||||
|
||||
fun refreshPostProcessing() = withPerGameConfig(false) {
|
||||
NativePostProcessing.reload()
|
||||
}
|
||||
|
||||
fun persistPostProcessing() = withPerGameConfig(true) {
|
||||
NativePostProcessing.persist()
|
||||
}
|
||||
|
||||
fun editPostProcessing(action: () -> Unit) = withPerGameConfig(true) {
|
||||
action()
|
||||
NativePostProcessing.persist()
|
||||
}
|
||||
|
||||
private fun addQuickSettings() {
|
||||
binding.quickSettingsSheet.apply {
|
||||
val container = binding.quickSettingsSheet.findViewById<ViewGroup>(R.id.quick_settings_container)
|
||||
|
||||
@@ -42,6 +42,10 @@ object NativePostProcessing {
|
||||
|
||||
external fun store()
|
||||
|
||||
external fun reload()
|
||||
|
||||
external fun clearChain()
|
||||
|
||||
external fun getPresetsJson(): String
|
||||
|
||||
external fun getActivePreset(): String
|
||||
@@ -63,11 +67,7 @@ object NativePostProcessing {
|
||||
external fun getPresetDirectory(): String
|
||||
|
||||
fun persist() {
|
||||
store()
|
||||
NativeConfig.saveGlobalConfig()
|
||||
}
|
||||
|
||||
fun persistFor(perGame: Boolean) {
|
||||
val perGame = NativeConfig.isPerGameConfigLoaded()
|
||||
store()
|
||||
if (perGame) {
|
||||
NativeConfig.savePerGameConfig()
|
||||
|
||||
@@ -15,10 +15,22 @@
|
||||
#include "frontend_common/config.h"
|
||||
#include "frontend_common/settings_generator.h"
|
||||
#include "native.h"
|
||||
#ifdef HAS_RESHADE
|
||||
#include "video_core/post_processing/fx_chain.h"
|
||||
#endif
|
||||
|
||||
std::unique_ptr<AndroidConfig> global_config;
|
||||
std::unique_ptr<AndroidConfig> per_game_config;
|
||||
|
||||
#ifdef HAS_RESHADE
|
||||
static void ResetFxChainToGlobal() {
|
||||
VideoCore::UseGlobalFxSettings();
|
||||
VideoCore::FxChain::Instance().LoadFromSettings();
|
||||
}
|
||||
#else
|
||||
static void ResetFxChainToGlobal() {}
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
Settings::Setting<T>* getSetting(JNIEnv* env, jstring jkey) {
|
||||
auto key = Common::Android::GetJString(env, jkey);
|
||||
@@ -39,6 +51,7 @@ extern "C" {
|
||||
void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_initializeGlobalConfig(JNIEnv* env, jobject obj) {
|
||||
global_config = std::make_unique<AndroidConfig>();
|
||||
FrontendCommon::GenerateSettings();
|
||||
ResetFxChainToGlobal();
|
||||
}
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_unloadGlobalConfig(JNIEnv* env, jobject obj) {
|
||||
@@ -47,6 +60,7 @@ void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_unloadGlobalConfig(JNIEnv* env,
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_reloadGlobalConfig(JNIEnv* env, jobject obj) {
|
||||
global_config->AndroidConfig::ReloadAllValues();
|
||||
ResetFxChainToGlobal();
|
||||
}
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_saveGlobalConfig(JNIEnv* env, jobject obj) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <jni.h>
|
||||
@@ -9,15 +10,29 @@
|
||||
|
||||
#include "common/android/android_common.h"
|
||||
#ifdef HAS_RESHADE
|
||||
#include "android_config.h"
|
||||
#include "video_core/post_processing/fx_chain.h"
|
||||
#include "common/settings.h"
|
||||
#include "video_core/post_processing/fx_effect.h"
|
||||
#include "video_core/post_processing/fx_preset.h"
|
||||
|
||||
extern std::unique_ptr<AndroidConfig> per_game_config;
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef HAS_RESHADE
|
||||
bool EditingPerGame() {
|
||||
return per_game_config != nullptr;
|
||||
}
|
||||
|
||||
void BeginFxEdit() {
|
||||
if (!EditingPerGame()) {
|
||||
return;
|
||||
}
|
||||
VideoCore::UsePerGameFxSettings();
|
||||
}
|
||||
|
||||
nlohmann::json SerializeUniform(const VideoCore::FxUniformDesc& uniform) {
|
||||
nlohmann::json out;
|
||||
out["name"] = uniform.name;
|
||||
@@ -201,10 +216,26 @@ void Java_org_yuzu_yuzu_1emu_utils_NativePostProcessing_setValue(JNIEnv* env, jo
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_utils_NativePostProcessing_store(JNIEnv* env, jobject obj) {
|
||||
#ifdef HAS_RESHADE
|
||||
BeginFxEdit();
|
||||
VideoCore::FxChain::Instance().StoreToSettings();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_utils_NativePostProcessing_reload(JNIEnv* env, jobject obj) {
|
||||
#ifdef HAS_RESHADE
|
||||
if (!EditingPerGame()) {
|
||||
VideoCore::UseGlobalFxSettings();
|
||||
}
|
||||
VideoCore::FxChain::Instance().LoadFromSettings();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_utils_NativePostProcessing_clearChain(JNIEnv* env, jobject obj) {
|
||||
#ifdef HAS_RESHADE
|
||||
VideoCore::FxChain::Instance().Clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
jstring Java_org_yuzu_yuzu_1emu_utils_NativePostProcessing_getShaderDirectory(JNIEnv* env,
|
||||
jobject obj) {
|
||||
#ifdef HAS_RESHADE
|
||||
@@ -252,6 +283,7 @@ jboolean Java_org_yuzu_yuzu_1emu_utils_NativePostProcessing_isPresetModified(JNI
|
||||
jboolean Java_org_yuzu_yuzu_1emu_utils_NativePostProcessing_applyPreset(JNIEnv* env, jobject obj,
|
||||
jstring jname) {
|
||||
#ifdef HAS_RESHADE
|
||||
BeginFxEdit();
|
||||
return static_cast<jboolean>(
|
||||
VideoCore::ApplyFxPreset(Common::Android::GetJString(env, jname)));
|
||||
#else
|
||||
@@ -263,6 +295,7 @@ jboolean Java_org_yuzu_yuzu_1emu_utils_NativePostProcessing_savePreset(JNIEnv* e
|
||||
jstring jname,
|
||||
jstring jdescription) {
|
||||
#ifdef HAS_RESHADE
|
||||
BeginFxEdit();
|
||||
return static_cast<jboolean>(
|
||||
VideoCore::SaveFxPreset(Common::Android::GetJString(env, jname),
|
||||
Common::Android::GetJString(env, jdescription)));
|
||||
@@ -274,6 +307,7 @@ jboolean Java_org_yuzu_yuzu_1emu_utils_NativePostProcessing_savePreset(JNIEnv* e
|
||||
jboolean Java_org_yuzu_yuzu_1emu_utils_NativePostProcessing_deletePreset(JNIEnv* env, jobject obj,
|
||||
jstring jname) {
|
||||
#ifdef HAS_RESHADE
|
||||
BeginFxEdit();
|
||||
return static_cast<jboolean>(
|
||||
VideoCore::DeleteFxPreset(Common::Android::GetJString(env, jname)));
|
||||
#else
|
||||
@@ -283,6 +317,7 @@ jboolean Java_org_yuzu_yuzu_1emu_utils_NativePostProcessing_deletePreset(JNIEnv*
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_utils_NativePostProcessing_clearPreset(JNIEnv* env, jobject obj) {
|
||||
#ifdef HAS_RESHADE
|
||||
BeginFxEdit();
|
||||
VideoCore::SetActiveFxPreset(std::string_view());
|
||||
#endif
|
||||
}
|
||||
@@ -298,6 +333,7 @@ jboolean Java_org_yuzu_yuzu_1emu_utils_NativePostProcessing_isEnabled(JNIEnv* en
|
||||
void Java_org_yuzu_yuzu_1emu_utils_NativePostProcessing_setEnabled(JNIEnv* env, jobject obj,
|
||||
jboolean enabled) {
|
||||
#ifdef HAS_RESHADE
|
||||
BeginFxEdit();
|
||||
Settings::values.post_shader_enabled.SetValue(enabled != JNI_FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -5,16 +5,35 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/add_button"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="@string/post_processing_add"
|
||||
app:icon="@drawable/ic_add" />
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/add_button"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/post_processing_add"
|
||||
app:icon="@drawable/ic_add" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/remove_all_button"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/post_processing_remove_all"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_delete" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/add_choices"
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:background="@drawable/shader_card_background"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/preset_row"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/preset_name"
|
||||
style="@style/TextAppearance.Material3.TitleSmall"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/preset_description"
|
||||
style="@style/TextAppearance.Material3.BodySmall"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:textColor="?attr/colorOnSurfaceVariant" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/preset_delete"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:contentDescription="@string/post_processing_preset_delete"
|
||||
android:focusable="true"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/ic_delete"
|
||||
android:visibility="gone"
|
||||
app:tint="?attr/colorOnSurfaceVariant" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/fx_add"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/post_processing_add"
|
||||
app:icon="@drawable/ic_add" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/fx_presets"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_weight="1.4"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/post_processing_presets"
|
||||
app:icon="@drawable/ic_dropdown_arrow"
|
||||
app:iconGravity="textEnd" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/fx_create_preset"
|
||||
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/post_processing_preset_new"
|
||||
app:icon="@drawable/ic_add" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/fx_remove_all"
|
||||
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/post_processing_remove_all"
|
||||
app:icon="@drawable/ic_delete" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -303,11 +303,17 @@
|
||||
<string name="post_processing_per_game_description">Configure the effect chain for this game</string>
|
||||
<string name="post_processing_add">Add effect</string>
|
||||
<string name="post_processing_remove">Remove</string>
|
||||
<string name="post_processing_hide_effects">Remove effects</string>
|
||||
<string name="post_processing_open_list">Open list</string>
|
||||
<string name="post_processing_close_list">Close list</string>
|
||||
<string name="post_processing_remove_all">Remove effects</string>
|
||||
<string name="post_processing_preset_locked">Preset active. Edit it in Post-Processing Effects before starting a game.</string>
|
||||
<string name="post_processing_preset_modified">Preset active, with your own changes.</string>
|
||||
<string name="post_processing_preset">Preset</string>
|
||||
<string name="post_processing_presets">Presets</string>
|
||||
<string name="post_processing_preset_new">New preset</string>
|
||||
<string name="post_processing_preset_new_description">Saves the effects you have loaded, with their current values, as a preset you can pick later.</string>
|
||||
<string name="post_processing_preset_name_invalid">Give the preset a name without an equals sign.</string>
|
||||
<string name="post_processing_preset_none">No preset</string>
|
||||
<string name="post_processing_preset_delete">Delete preset</string>
|
||||
<string name="post_processing_preset_reset">Reset preset values</string>
|
||||
<string name="post_processing_move_up">Move up</string>
|
||||
<string name="post_processing_move_down">Move down</string>
|
||||
|
||||
@@ -119,6 +119,26 @@ std::string SerializeFxChain(std::span<const FxChainEntry> entries) {
|
||||
return out;
|
||||
}
|
||||
|
||||
void UseGlobalFxSettings() {
|
||||
Settings::values.post_shader_chain.SetGlobal(true);
|
||||
Settings::values.post_shader_preset.SetGlobal(true);
|
||||
Settings::values.post_shader_enabled.SetGlobal(true);
|
||||
}
|
||||
|
||||
void UsePerGameFxSettings() {
|
||||
const std::string chain = Settings::values.post_shader_chain.GetValue();
|
||||
const std::string preset = Settings::values.post_shader_preset.GetValue();
|
||||
const bool enabled = Settings::values.post_shader_enabled.GetValue();
|
||||
|
||||
Settings::values.post_shader_chain.SetGlobal(false);
|
||||
Settings::values.post_shader_preset.SetGlobal(false);
|
||||
Settings::values.post_shader_enabled.SetGlobal(false);
|
||||
|
||||
Settings::values.post_shader_chain.SetValue(chain);
|
||||
Settings::values.post_shader_preset.SetValue(preset);
|
||||
Settings::values.post_shader_enabled.SetValue(enabled);
|
||||
}
|
||||
|
||||
FxChain& FxChain::Instance() {
|
||||
static FxChain instance;
|
||||
return instance;
|
||||
@@ -260,19 +280,11 @@ void FxChain::LoadFromSettings() {
|
||||
auto parsed = ParseFxChain(Settings::values.post_shader_chain.GetValue());
|
||||
|
||||
std::scoped_lock lock{mutex};
|
||||
entries = std::move(parsed);
|
||||
loaded = true;
|
||||
generation.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void FxChain::EnsureLoadedFromSettings() {
|
||||
{
|
||||
std::scoped_lock lock{mutex};
|
||||
if (loaded) {
|
||||
return;
|
||||
}
|
||||
if (entries == parsed) {
|
||||
return;
|
||||
}
|
||||
LoadFromSettings();
|
||||
entries = std::move(parsed);
|
||||
generation.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void FxChain::StoreToSettings() const {
|
||||
|
||||
@@ -20,6 +20,8 @@ struct FxChainEntry {
|
||||
std::string file;
|
||||
std::string technique;
|
||||
std::map<std::string, std::array<f32, 4>> values;
|
||||
|
||||
bool operator==(const FxChainEntry&) const = default;
|
||||
};
|
||||
|
||||
struct FxChainSnapshot {
|
||||
@@ -31,6 +33,10 @@ std::vector<FxChainEntry> ParseFxChain(std::string_view value);
|
||||
|
||||
std::string SerializeFxChain(std::span<const FxChainEntry> entries);
|
||||
|
||||
void UseGlobalFxSettings();
|
||||
|
||||
void UsePerGameFxSettings();
|
||||
|
||||
class FxChain {
|
||||
public:
|
||||
static FxChain& Instance();
|
||||
@@ -65,8 +71,6 @@ public:
|
||||
|
||||
void LoadFromSettings();
|
||||
|
||||
void EnsureLoadedFromSettings();
|
||||
|
||||
void StoreToSettings() const;
|
||||
|
||||
void DropUnknownEntries();
|
||||
@@ -76,7 +80,6 @@ private:
|
||||
|
||||
mutable std::mutex mutex;
|
||||
std::vector<FxChainEntry> entries;
|
||||
bool loaded{};
|
||||
std::atomic<u64> generation{1};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user