318 lines
9.4 KiB
C#
Raw Normal View History

2025-09-24 11:24:38 +05:00
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
namespace TPSBR.UI
{
public class UISettingsView : UICloseView
{
// PRIVATE MEMBERS
[SerializeField]
private UISlider _musicVolumeSlider;
[SerializeField]
private UISlider _effectsVolumeSlider;
[SerializeField]
private UISlider _sensitivitySlider;
[SerializeField]
private UISlider _aimSensitivitySlider;
[SerializeField]
private TMP_Dropdown _graphicsQuality;
[SerializeField]
private TMP_Dropdown _resolution;
[SerializeField]
private UIToggle _vSync;
[SerializeField]
private UIToggle _limitFPS;
[SerializeField]
private UISlider _targetFPS;
[SerializeField]
private int[] _targetFPSValues;
[SerializeField]
private UIToggle _windowed;
[SerializeField]
private UIButton _confirmButton;
[SerializeField]
private UIButton _resetButton;
private List<ResolutionData> _validResolutions = new List<ResolutionData>(32);
// UICloseView INTERFACE
protected override void OnInitialize()
{
base.OnInitialize();
_confirmButton.onClick.AddListener(OnConfirmButton);
_resetButton.onClick.AddListener(OnResetButton);
_musicVolumeSlider.onValueChanged.AddListener(OnVolumeChanged);
_effectsVolumeSlider.onValueChanged.AddListener(OnVolumeChanged);
_sensitivitySlider.onValueChanged.AddListener(OnSensitivityChanged);
_aimSensitivitySlider.onValueChanged.AddListener(OnSensitivityChanged);
_graphicsQuality.onValueChanged.AddListener(OnGraphicsChanged);
_resolution.onValueChanged.AddListener(OnGraphicsChanged);
_targetFPS.onValueChanged.AddListener(OnTargetFPSChanged);
_limitFPS.onValueChanged.AddListener(OnLimitFPSChanged);
_vSync.onValueChanged.AddListener(OnLimitFPSChanged);
_windowed.onValueChanged.AddListener(OnWindowedChanged);
}
protected override void OnDeinitialize()
{
_confirmButton.onClick.RemoveListener(OnConfirmButton);
_resetButton.onClick.RemoveListener(OnResetButton);
_musicVolumeSlider.onValueChanged.RemoveListener(OnVolumeChanged);
_effectsVolumeSlider.onValueChanged.RemoveListener(OnVolumeChanged);
_sensitivitySlider.onValueChanged.RemoveListener(OnSensitivityChanged);
_aimSensitivitySlider.onValueChanged.RemoveListener(OnSensitivityChanged);
_graphicsQuality.onValueChanged.RemoveListener(OnGraphicsChanged);
_resolution.onValueChanged.RemoveListener(OnGraphicsChanged);
_targetFPS.onValueChanged.RemoveListener(OnTargetFPSChanged);
_limitFPS.onValueChanged.RemoveListener(OnLimitFPSChanged);
_vSync.onValueChanged.RemoveListener(OnLimitFPSChanged);
_windowed.onValueChanged.RemoveListener(OnWindowedChanged);
base.OnDeinitialize();
}
protected override void OnOpen()
{
base.OnOpen();
PrepareResolutionDropdown();
LoadValues();
}
protected override void OnClose()
{
base.OnClose();
Context.RuntimeSettings.Options.DiscardChanges();
Context.Audio.UpdateVolume();
}
protected override void OnTick()
{
base.OnTick();
_confirmButton.interactable = Context.RuntimeSettings.Options.HasUnsavedChanges;
_limitFPS.SetActive(_vSync.isOn == false);
_targetFPS.SetActive(_vSync.isOn == false && _limitFPS.isOn);
}
// PRIVATE METHODS
private void LoadValues()
{
var runtimeSettings = Context.RuntimeSettings;
_musicVolumeSlider.SetOptionsValueFloat(runtimeSettings.Options.GetValue(RuntimeSettings.KEY_MUSIC_VOLUME));
_effectsVolumeSlider.SetOptionsValueFloat(runtimeSettings.Options.GetValue(RuntimeSettings.KEY_EFFECTS_VOLUME));
_sensitivitySlider.SetOptionsValueFloat(runtimeSettings.Options.GetValue(RuntimeSettings.KEY_SENSITIVITY));
_aimSensitivitySlider.SetOptionsValueFloat(runtimeSettings.Options.GetValue(RuntimeSettings.KEY_AIM_SENSITIVITY));
_windowed.SetIsOnWithoutNotify(runtimeSettings.Windowed);
_graphicsQuality.SetValueWithoutNotify(runtimeSettings.GraphicsQuality);
_resolution.SetValueWithoutNotify(_validResolutions.FindIndex(t => t.Index == runtimeSettings.Resolution));
_targetFPS.SetOptionsValueInt(runtimeSettings.Options.GetValue(RuntimeSettings.KEY_TARGET_FPS));
_limitFPS.SetIsOnWithoutNotify(runtimeSettings.LimitFPS);
_vSync.SetIsOnWithoutNotify(runtimeSettings.VSync);
}
private void OnConfirmButton()
{
Context.RuntimeSettings.Options.SaveChanges();
var runtimeSettings = Context.RuntimeSettings;
if (Application.isMobilePlatform == false || Application.isEditor == true)
{
var resolution = Screen.resolutions[runtimeSettings.Resolution < 0 ? Screen.resolutions.Length - 1 : runtimeSettings.Resolution];
Screen.SetResolution(resolution.width, resolution.height, _windowed.isOn == false);
}
QualitySettings.SetQualityLevel(runtimeSettings.GraphicsQuality);
Application.targetFrameRate = runtimeSettings.LimitFPS == true ? runtimeSettings.TargetFPS : -1;
QualitySettings.vSyncCount = runtimeSettings.VSync == true ? 1 : 0;
Close();
}
private void OnResetButton()
{
var options = Context.RuntimeSettings.Options;
options.ResetValueToDefault(RuntimeSettings.KEY_EFFECTS_VOLUME, false);
options.ResetValueToDefault(RuntimeSettings.KEY_MUSIC_VOLUME, false);
options.ResetValueToDefault(RuntimeSettings.KEY_GRAPHICS_QUALITY, false);
options.ResetValueToDefault(RuntimeSettings.KEY_RESOLUTION, false);
options.ResetValueToDefault(RuntimeSettings.KEY_WINDOWED, false);
options.ResetValueToDefault(RuntimeSettings.KEY_LIMIT_FPS, false);
options.ResetValueToDefault(RuntimeSettings.KEY_TARGET_FPS, false);
options.ResetValueToDefault(RuntimeSettings.KEY_SENSITIVITY, false);
options.ResetValueToDefault(RuntimeSettings.KEY_AIM_SENSITIVITY, false);
options.ResetValueToDefault(RuntimeSettings.KEY_VSYNC, false);
LoadValues();
Context.Audio.UpdateVolume();
}
private void OnVolumeChanged(float value)
{
Context.RuntimeSettings.MusicVolume = _musicVolumeSlider.value;
Context.RuntimeSettings.EffectsVolume = _effectsVolumeSlider.value;
Context.Audio.UpdateVolume();
}
private void OnSensitivityChanged(float value)
{
Context.RuntimeSettings.Sensitivity = _sensitivitySlider.value;
Context.RuntimeSettings.AimSensitivity = _aimSensitivitySlider.value;
}
private void OnLimitFPSChanged(bool value)
{
OnGraphicsChanged(-1);
}
private void OnTargetFPSChanged(float value)
{
OnGraphicsChanged(-1);
}
private void OnGraphicsChanged(int value)
{
var runtimeSettings = Context.RuntimeSettings;
runtimeSettings.GraphicsQuality = _graphicsQuality.value;
runtimeSettings.Resolution = _validResolutions[_resolution.value].Index;
runtimeSettings.TargetFPS = Mathf.RoundToInt(_targetFPS.value);
runtimeSettings.LimitFPS = _limitFPS.isOn;
runtimeSettings.VSync = _vSync.isOn;
}
private void OnWindowedChanged(bool value)
{
Context.RuntimeSettings.Windowed = value;
}
private void PrepareResolutionDropdown()
{
_validResolutions.Clear();
var resolutions = Screen.resolutions;
int defaultRefreshRate = Mathf.RoundToInt((float)resolutions[^1].refreshRateRatio.value);
// Add resolutions in reversed order
for (int i = resolutions.Length - 1; i >= 0; i--)
{
var resolution = resolutions[i];
if (Mathf.RoundToInt((float)resolution.refreshRateRatio.value) != defaultRefreshRate)
continue;
_validResolutions.Add(new ResolutionData(i, resolution));
}
var options = ListPool.Get<TMP_Dropdown.OptionData>(16);
for (int i = 0; i < _validResolutions.Count; i++)
{
var resolution = _validResolutions[i].Resolution;
options.Add(new TMP_Dropdown.OptionData($"{resolution.width} x {resolution.height}"));
}
_resolution.ClearOptions();
_resolution.AddOptions(options);
ListPool.Return(options);
}
// HELPERS
private struct ResolutionData
{
public int Index;
public Resolution Resolution;
public ResolutionData(int index, Resolution resolution)
{
Index = index;
Resolution = resolution;
}
}
}
public static class UISliderExtensions
{
public static void SetOptionsValueFloat(this UISlider slider, OptionsValue value)
{
if (value.Type != EOptionsValueType.Float)
{
slider.value = 0f;
return;
}
if (slider.minValue != value.FloatValue.MinValue || slider.maxValue != value.FloatValue.MaxValue)
{
// Setting min and max value will unfortunately always trigger onValueChanged
// so we need to removed this event data and reassign it again agterwards
Slider.SliderEvent onValueChanged = slider.onValueChanged;
slider.onValueChanged = new Slider.SliderEvent();
slider.minValue = value.FloatValue.MinValue;
slider.maxValue = value.FloatValue.MaxValue;
slider.onValueChanged = onValueChanged;
}
slider.SetValue(value.FloatValue.Value);
}
public static void SetOptionsValueInt(this UISlider slider, OptionsValue value)
{
if (value.Type != EOptionsValueType.Int)
{
slider.value = 0f;
return;
}
if (slider.minValue != value.IntValue.MinValue || slider.maxValue != value.IntValue.MaxValue)
{
// Setting min and max value will unfortunately always trigger onValueChanged
// so we need to removed this event data and reassign it again agterwards
Slider.SliderEvent onValueChanged = slider.onValueChanged;
slider.onValueChanged = new Slider.SliderEvent();
slider.minValue = value.IntValue.MinValue;
slider.maxValue = value.IntValue.MaxValue;
slider.onValueChanged = onValueChanged;
}
slider.SetValue(value.IntValue.Value);
}
}
}