726 lines
23 KiB
C#
726 lines
23 KiB
C#
using System;
|
|
using System.Threading;
|
|
using BriarQueen.Framework.Coordinators.Events;
|
|
using BriarQueen.Framework.Managers.UI.Base;
|
|
using BriarQueen.Framework.Managers.UI.Events;
|
|
using BriarQueen.Framework.Services.Settings;
|
|
using BriarQueen.Framework.Services.Settings.Data;
|
|
using Cysharp.Threading.Tasks;
|
|
using PrimeTween;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.EventSystems;
|
|
using UnityEngine.UI;
|
|
using VContainer;
|
|
using AudioSettings = BriarQueen.Framework.Services.Settings.Data.AudioSettings;
|
|
|
|
namespace BriarQueen.UI.Menus
|
|
{
|
|
public class SettingsWindow : MonoBehaviour, IUIWindow
|
|
{
|
|
[Header("UI Elements")]
|
|
[SerializeField]
|
|
private CanvasGroup _canvasGroup;
|
|
|
|
[SerializeField]
|
|
private RectTransform _windowRect;
|
|
|
|
[Header("Buttons")]
|
|
[SerializeField]
|
|
private Button _applyButton;
|
|
|
|
[SerializeField]
|
|
private Button _backButton;
|
|
|
|
[Header("Game")]
|
|
[SerializeField]
|
|
private Slider _popupDisplayDurationSlider;
|
|
|
|
[SerializeField]
|
|
private TextMeshProUGUI _popupDisplayDurationText;
|
|
|
|
[SerializeField]
|
|
private Toggle _tutorialsEnabledToggle;
|
|
|
|
[SerializeField]
|
|
private Toggle _tooltipsEnabledToggle;
|
|
|
|
[SerializeField]
|
|
private Toggle _autoUseToolsToggle;
|
|
|
|
[Header("Visual")]
|
|
[SerializeField]
|
|
private Toggle _fullscreenToggle;
|
|
|
|
[Tooltip("0 = VSync Off, 1 = Every V-Blank, 2 = Every 2nd V-Blank")]
|
|
[SerializeField]
|
|
private Slider _vsyncSlider;
|
|
|
|
[SerializeField]
|
|
private TextMeshProUGUI _vsyncValueText;
|
|
|
|
[SerializeField]
|
|
private Slider _maxFramerateSlider;
|
|
|
|
[SerializeField]
|
|
private TextMeshProUGUI _maxFramerateValueText;
|
|
|
|
[Header("Audio")]
|
|
[SerializeField]
|
|
private Slider _masterVolumeSlider;
|
|
|
|
[SerializeField]
|
|
private TextMeshProUGUI _masterVolumeText;
|
|
|
|
[SerializeField]
|
|
private Slider _musicVolumeSlider;
|
|
|
|
[SerializeField]
|
|
private TextMeshProUGUI _musicVolumeText;
|
|
|
|
[SerializeField]
|
|
private Slider _sfxVolumeSlider;
|
|
|
|
[SerializeField]
|
|
private TextMeshProUGUI _sfxVolumeText;
|
|
|
|
[SerializeField]
|
|
private Slider _voiceVolumeSlider;
|
|
|
|
[SerializeField]
|
|
private TextMeshProUGUI _voiceVolumeText;
|
|
|
|
[SerializeField]
|
|
private Slider _ambienceVolumeSlider;
|
|
|
|
[SerializeField]
|
|
private TextMeshProUGUI _ambienceVolumeText;
|
|
|
|
[SerializeField]
|
|
private Slider _uiVolumeSlider;
|
|
|
|
[SerializeField]
|
|
private TextMeshProUGUI _uiVolumeText;
|
|
|
|
[SerializeField]
|
|
private Toggle _muteWhenUnfocusedToggle;
|
|
|
|
[Header("Unsaved Changes Warning")]
|
|
[SerializeField]
|
|
private TMP_Text _pendingChangesText;
|
|
|
|
[SerializeField]
|
|
private string _pendingChangesMessage = "You have unsaved changes.";
|
|
|
|
[Header("Tween Settings")]
|
|
[SerializeField]
|
|
private TweenSettings _tweenSettings = new()
|
|
{
|
|
duration = 0.25f,
|
|
ease = Ease.InOutSine,
|
|
useUnscaledTime = true
|
|
};
|
|
|
|
[Header("Scale")]
|
|
[SerializeField]
|
|
private float _hiddenScale = 0.85f;
|
|
|
|
[Header("Selection")]
|
|
[SerializeField]
|
|
private Selectable _firstSelectedOnOpen;
|
|
|
|
[Header("Game Slider Ranges")]
|
|
[SerializeField]
|
|
private float _popupDisplayDurationMin = 1f;
|
|
|
|
[SerializeField]
|
|
private float _popupDisplayDurationMax = 10f;
|
|
|
|
[Header("Visual Slider Ranges")]
|
|
[SerializeField]
|
|
private int _maxFramerateMin = 30;
|
|
|
|
[SerializeField]
|
|
private int _maxFramerateMax = 240;
|
|
|
|
private CancellationTokenSource _cts;
|
|
|
|
private AudioSettings _draftAudio;
|
|
private GameSettings _draftGameSettings;
|
|
private VisualSettings _draftVisual;
|
|
private EventCoordinator _eventCoordinator;
|
|
|
|
private bool _ignoreUiCallbacks;
|
|
|
|
private AudioSettings _loadedAudio;
|
|
private GameSettings _loadedGameSettings;
|
|
private VisualSettings _loadedVisual;
|
|
|
|
private Sequence _sequence;
|
|
|
|
private SettingsService _settingsService;
|
|
private bool _waitingChanges;
|
|
|
|
public bool IsModal => true;
|
|
public WindowType WindowType => WindowType.SettingsWindow;
|
|
|
|
private void Awake()
|
|
{
|
|
if (_applyButton != null) _applyButton.onClick.AddListener(OnApplyClicked);
|
|
if (_backButton != null) _backButton.onClick.AddListener(OnBackClicked);
|
|
|
|
HookSlider(_masterVolumeSlider, _masterVolumeText, v => _draftAudio.MasterVolume = v);
|
|
HookSlider(_musicVolumeSlider, _musicVolumeText, v => _draftAudio.MusicVolume = v);
|
|
HookSlider(_sfxVolumeSlider, _sfxVolumeText, v => _draftAudio.SfxVolume = v);
|
|
HookSlider(_voiceVolumeSlider, _voiceVolumeText, v => _draftAudio.VoiceVolume = v);
|
|
HookSlider(_ambienceVolumeSlider, _ambienceVolumeText, v => _draftAudio.AmbienceVolume = v);
|
|
HookSlider(_uiVolumeSlider, _uiVolumeText, v => _draftAudio.UIVolume = v);
|
|
|
|
SetupGameSliders();
|
|
|
|
if (_popupDisplayDurationSlider != null)
|
|
_popupDisplayDurationSlider.onValueChanged.AddListener(OnPopupDisplayDurationChanged);
|
|
|
|
if (_tutorialsEnabledToggle != null)
|
|
_tutorialsEnabledToggle.onValueChanged.AddListener(OnTutorialsToggleChanged);
|
|
|
|
if (_tooltipsEnabledToggle != null)
|
|
_tooltipsEnabledToggle.onValueChanged.AddListener(OnTooltipsToggleChanged);
|
|
|
|
if(_autoUseToolsToggle != null)
|
|
_autoUseToolsToggle.onValueChanged.AddListener(OnAutoToolsToggleChanged);
|
|
|
|
if (_muteWhenUnfocusedToggle != null)
|
|
_muteWhenUnfocusedToggle.onValueChanged.AddListener(OnMuteWhenUnfocusedChanged);
|
|
|
|
if (_fullscreenToggle != null)
|
|
_fullscreenToggle.onValueChanged.AddListener(OnFullscreenToggleChanged);
|
|
|
|
SetupVsyncSlider();
|
|
|
|
if (_vsyncSlider != null)
|
|
_vsyncSlider.onValueChanged.AddListener(OnVsyncSliderChanged);
|
|
|
|
SetupMaxFramerateSlider();
|
|
|
|
if (_maxFramerateSlider != null)
|
|
_maxFramerateSlider.onValueChanged.AddListener(OnMaxFramerateSliderChanged);
|
|
|
|
SetPendingChangesVisible(false);
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
StopAndResetCancellation();
|
|
|
|
if (_sequence.isAlive)
|
|
_sequence.Stop();
|
|
|
|
if (_applyButton != null) _applyButton.onClick.RemoveListener(OnApplyClicked);
|
|
if (_backButton != null) _backButton.onClick.RemoveListener(OnBackClicked);
|
|
|
|
if (_popupDisplayDurationSlider != null)
|
|
_popupDisplayDurationSlider.onValueChanged.RemoveListener(OnPopupDisplayDurationChanged);
|
|
|
|
if (_tutorialsEnabledToggle != null)
|
|
_tutorialsEnabledToggle.onValueChanged.RemoveListener(OnTutorialsToggleChanged);
|
|
|
|
if (_tooltipsEnabledToggle != null)
|
|
_tooltipsEnabledToggle.onValueChanged.RemoveListener(OnTooltipsToggleChanged);
|
|
|
|
if (_muteWhenUnfocusedToggle != null)
|
|
_muteWhenUnfocusedToggle.onValueChanged.RemoveListener(OnMuteWhenUnfocusedChanged);
|
|
|
|
if (_fullscreenToggle != null)
|
|
_fullscreenToggle.onValueChanged.RemoveListener(OnFullscreenToggleChanged);
|
|
|
|
if (_vsyncSlider != null)
|
|
_vsyncSlider.onValueChanged.RemoveListener(OnVsyncSliderChanged);
|
|
|
|
if (_maxFramerateSlider != null)
|
|
_maxFramerateSlider.onValueChanged.RemoveListener(OnMaxFramerateSliderChanged);
|
|
}
|
|
|
|
public async UniTask Show()
|
|
{
|
|
if (_settingsService != null)
|
|
LoadSettings(_settingsService.Audio, _settingsService.Visual, _settingsService.Game);
|
|
|
|
StopAndResetCancellation();
|
|
|
|
gameObject.SetActive(true);
|
|
|
|
_windowRect.localScale = Vector3.one * _hiddenScale;
|
|
_canvasGroup.alpha = 0f;
|
|
_canvasGroup.blocksRaycasts = false;
|
|
_canvasGroup.interactable = false;
|
|
|
|
var alpha = new TweenSettings<float>
|
|
{
|
|
startValue = 0f,
|
|
endValue = 1f,
|
|
settings = _tweenSettings
|
|
};
|
|
|
|
var scale = new TweenSettings<Vector3>
|
|
{
|
|
startValue = Vector3.one * _hiddenScale,
|
|
endValue = Vector3.one,
|
|
settings = _tweenSettings
|
|
};
|
|
|
|
_sequence = Sequence.Create(useUnscaledTime: true)
|
|
.Group(Tween.Alpha(_canvasGroup, alpha))
|
|
.Group(Tween.Scale(_windowRect, scale));
|
|
|
|
try
|
|
{
|
|
await _sequence.ToUniTask(cancellationToken: _cts.Token);
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_canvasGroup.blocksRaycasts = true;
|
|
_canvasGroup.interactable = true;
|
|
|
|
SelectDefault();
|
|
}
|
|
|
|
public async UniTask Hide()
|
|
{
|
|
StopAndResetCancellation();
|
|
|
|
_canvasGroup.blocksRaycasts = false;
|
|
_canvasGroup.interactable = false;
|
|
|
|
var alpha = new TweenSettings<float>
|
|
{
|
|
startValue = _canvasGroup.alpha,
|
|
endValue = 0f,
|
|
settings = _tweenSettings
|
|
};
|
|
|
|
var scale = new TweenSettings<Vector3>
|
|
{
|
|
startValue = _windowRect.localScale,
|
|
endValue = Vector3.one * _hiddenScale,
|
|
settings = _tweenSettings
|
|
};
|
|
|
|
_sequence = Sequence.Create(useUnscaledTime: true)
|
|
.Group(Tween.Alpha(_canvasGroup, alpha))
|
|
.Group(Tween.Scale(_windowRect, scale));
|
|
|
|
try
|
|
{
|
|
await _sequence.ToUniTask(cancellationToken: _cts.Token);
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
return;
|
|
}
|
|
|
|
gameObject.SetActive(false);
|
|
}
|
|
|
|
[Inject]
|
|
public void Construct(SettingsService settingsService, EventCoordinator eventCoordinator)
|
|
{
|
|
_settingsService = settingsService;
|
|
_eventCoordinator = eventCoordinator;
|
|
}
|
|
|
|
private void OnTutorialsToggleChanged(bool value)
|
|
{
|
|
if (_ignoreUiCallbacks) return;
|
|
|
|
_draftGameSettings.TutorialsEnabled = value;
|
|
MarkDirty();
|
|
}
|
|
|
|
private void OnTooltipsToggleChanged(bool value)
|
|
{
|
|
if (_ignoreUiCallbacks) return;
|
|
|
|
_draftGameSettings.TooltipsEnabled = value;
|
|
MarkDirty();
|
|
}
|
|
|
|
private void OnAutoToolsToggleChanged(bool value)
|
|
{
|
|
if (_ignoreUiCallbacks)
|
|
return;
|
|
|
|
_draftGameSettings.AutoUseTools = value;
|
|
MarkDirty();
|
|
}
|
|
|
|
private void OnPopupDisplayDurationChanged(float value)
|
|
{
|
|
if (_ignoreUiCallbacks) return;
|
|
|
|
_draftGameSettings.PopupDisplayDuration =
|
|
Mathf.Clamp(value, _popupDisplayDurationMin, _popupDisplayDurationMax);
|
|
|
|
UpdateSecondsLabel(_popupDisplayDurationText, _draftGameSettings.PopupDisplayDuration);
|
|
MarkDirty();
|
|
}
|
|
|
|
private void OnMuteWhenUnfocusedChanged(bool value)
|
|
{
|
|
if (_ignoreUiCallbacks) return;
|
|
|
|
_draftAudio.MuteWhenUnfocused = value;
|
|
MarkDirty();
|
|
}
|
|
|
|
private void OnFullscreenToggleChanged(bool isFullscreen)
|
|
{
|
|
if (_ignoreUiCallbacks) return;
|
|
|
|
_draftVisual.FullScreenMode = isFullscreen
|
|
? FullScreenMode.FullScreenWindow
|
|
: FullScreenMode.Windowed;
|
|
|
|
MarkDirty();
|
|
}
|
|
|
|
private void OnVsyncSliderChanged(float value)
|
|
{
|
|
if (_ignoreUiCallbacks) return;
|
|
|
|
var v = Mathf.Clamp(Mathf.RoundToInt(value), 0, 2);
|
|
_draftVisual.VSyncCount = v;
|
|
|
|
UpdateVsyncLabel(v);
|
|
MarkDirty();
|
|
}
|
|
|
|
private void OnMaxFramerateSliderChanged(float value)
|
|
{
|
|
if (_ignoreUiCallbacks) return;
|
|
|
|
var fps = Mathf.Clamp(Mathf.RoundToInt(value), _maxFramerateMin, _maxFramerateMax);
|
|
_draftVisual.MaxFramerate = fps;
|
|
|
|
UpdateMaxFramerateLabel(fps);
|
|
MarkDirty();
|
|
}
|
|
|
|
private void OnApplyClicked()
|
|
{
|
|
_loadedAudio = CloneAudio(_draftAudio);
|
|
_loadedVisual = CloneVisual(_draftVisual);
|
|
_loadedGameSettings = CloneGameSettings(_draftGameSettings);
|
|
|
|
_settingsService.Apply(_loadedAudio, _loadedVisual, _loadedGameSettings);
|
|
|
|
_waitingChanges = false;
|
|
SetPendingChangesVisible(false);
|
|
}
|
|
|
|
private void OnBackClicked()
|
|
{
|
|
if (HasUnappliedChanges())
|
|
{
|
|
_draftAudio = CloneAudio(_loadedAudio);
|
|
_draftVisual = CloneVisual(_loadedVisual);
|
|
_draftGameSettings = CloneGameSettings(_loadedGameSettings);
|
|
|
|
ApplySettingsToUI();
|
|
}
|
|
|
|
_eventCoordinator.PublishImmediate(new UIToggleSettingsWindow(false));
|
|
}
|
|
|
|
private void StopAndResetCancellation()
|
|
{
|
|
if (_sequence.isAlive)
|
|
_sequence.Stop();
|
|
|
|
if (_cts != null)
|
|
{
|
|
try
|
|
{
|
|
_cts.Cancel();
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
|
|
_cts.Dispose();
|
|
}
|
|
|
|
_cts = new CancellationTokenSource();
|
|
}
|
|
|
|
private void SelectDefault()
|
|
{
|
|
if (EventSystem.current == null) return;
|
|
|
|
if (_firstSelectedOnOpen != null)
|
|
EventSystem.current.SetSelectedGameObject(_firstSelectedOnOpen.gameObject);
|
|
else if (_applyButton != null)
|
|
EventSystem.current.SetSelectedGameObject(_applyButton.gameObject);
|
|
}
|
|
|
|
private void SetupGameSliders()
|
|
{
|
|
if (_popupDisplayDurationSlider == null) return;
|
|
|
|
_popupDisplayDurationSlider.minValue = _popupDisplayDurationMin;
|
|
_popupDisplayDurationSlider.maxValue = _popupDisplayDurationMax;
|
|
_popupDisplayDurationSlider.wholeNumbers = false;
|
|
}
|
|
|
|
private void SetupVsyncSlider()
|
|
{
|
|
if (_vsyncSlider == null) return;
|
|
|
|
_vsyncSlider.minValue = 0;
|
|
_vsyncSlider.maxValue = 2;
|
|
_vsyncSlider.wholeNumbers = true;
|
|
|
|
UpdateVsyncLabel((int)_vsyncSlider.value);
|
|
}
|
|
|
|
private void SetupMaxFramerateSlider()
|
|
{
|
|
if (_maxFramerateSlider == null) return;
|
|
|
|
_maxFramerateSlider.minValue = _maxFramerateMin;
|
|
_maxFramerateSlider.maxValue = _maxFramerateMax;
|
|
_maxFramerateSlider.wholeNumbers = true;
|
|
|
|
UpdateMaxFramerateLabel(Mathf.RoundToInt(_maxFramerateSlider.value));
|
|
}
|
|
|
|
private void HookSlider(Slider slider, TextMeshProUGUI label, Action<float> assignToDraft)
|
|
{
|
|
if (slider == null) return;
|
|
|
|
slider.minValue = 0f;
|
|
slider.maxValue = 1f;
|
|
|
|
slider.onValueChanged.AddListener(v =>
|
|
{
|
|
if (_ignoreUiCallbacks) return;
|
|
|
|
var clamped = Mathf.Clamp01(v);
|
|
assignToDraft?.Invoke(clamped);
|
|
UpdatePercentLabel(label, clamped);
|
|
|
|
MarkDirty();
|
|
});
|
|
}
|
|
|
|
private void LoadSettings(AudioSettings audio, VisualSettings visual, GameSettings game)
|
|
{
|
|
_loadedAudio = CloneAudio(audio ?? new AudioSettings());
|
|
_loadedVisual = CloneVisual(visual ?? new VisualSettings());
|
|
_loadedGameSettings = CloneGameSettings(game ?? new GameSettings());
|
|
|
|
_draftAudio = CloneAudio(_loadedAudio);
|
|
_draftVisual = CloneVisual(_loadedVisual);
|
|
_draftGameSettings = CloneGameSettings(_loadedGameSettings);
|
|
|
|
ApplySettingsToUI();
|
|
}
|
|
|
|
private void ApplySettingsToUI()
|
|
{
|
|
_ignoreUiCallbacks = true;
|
|
|
|
SetSlider(_masterVolumeSlider, _masterVolumeText, _draftAudio.MasterVolume);
|
|
SetSlider(_musicVolumeSlider, _musicVolumeText, _draftAudio.MusicVolume);
|
|
SetSlider(_sfxVolumeSlider, _sfxVolumeText, _draftAudio.SfxVolume);
|
|
SetSlider(_voiceVolumeSlider, _voiceVolumeText, _draftAudio.VoiceVolume);
|
|
SetSlider(_ambienceVolumeSlider, _ambienceVolumeText, _draftAudio.AmbienceVolume);
|
|
SetSlider(_uiVolumeSlider, _uiVolumeText, _draftAudio.UIVolume);
|
|
|
|
if (_tutorialsEnabledToggle != null)
|
|
_tutorialsEnabledToggle.isOn = _draftGameSettings.TutorialsEnabled;
|
|
|
|
if (_tooltipsEnabledToggle != null)
|
|
_tooltipsEnabledToggle.isOn = _draftGameSettings.TooltipsEnabled;
|
|
|
|
if(_autoUseToolsToggle != null)
|
|
_autoUseToolsToggle.isOn = _draftGameSettings.AutoUseTools;
|
|
|
|
if (_muteWhenUnfocusedToggle != null)
|
|
_muteWhenUnfocusedToggle.isOn = _draftAudio.MuteWhenUnfocused;
|
|
|
|
if (_fullscreenToggle != null)
|
|
_fullscreenToggle.isOn = _draftVisual.FullScreenMode != FullScreenMode.Windowed;
|
|
|
|
if (_vsyncSlider != null)
|
|
{
|
|
_vsyncSlider.value = Mathf.Clamp(_draftVisual.VSyncCount, 0, 2);
|
|
UpdateVsyncLabel(_draftVisual.VSyncCount);
|
|
}
|
|
|
|
if (_maxFramerateSlider != null)
|
|
{
|
|
var fps = Mathf.Clamp(_draftVisual.MaxFramerate, _maxFramerateMin, _maxFramerateMax);
|
|
_maxFramerateSlider.value = fps;
|
|
UpdateMaxFramerateLabel(fps);
|
|
}
|
|
|
|
if (_popupDisplayDurationSlider != null)
|
|
{
|
|
_popupDisplayDurationSlider.value = _draftGameSettings.PopupDisplayDuration;
|
|
UpdateSecondsLabel(_popupDisplayDurationText, _draftGameSettings.PopupDisplayDuration);
|
|
}
|
|
|
|
_ignoreUiCallbacks = false;
|
|
|
|
_waitingChanges = HasUnappliedChanges();
|
|
SetPendingChangesVisible(_waitingChanges);
|
|
}
|
|
|
|
private void SetSlider(Slider slider, TextMeshProUGUI label, float value)
|
|
{
|
|
if (slider != null)
|
|
slider.value = Mathf.Clamp01(value);
|
|
|
|
UpdatePercentLabel(label, value);
|
|
}
|
|
|
|
private void UpdatePercentLabel(TextMeshProUGUI label, float value)
|
|
{
|
|
if (label == null) return;
|
|
label.text = $"{Mathf.RoundToInt(value * 100f)}%";
|
|
}
|
|
|
|
private void UpdateSecondsLabel(TextMeshProUGUI label, float value)
|
|
{
|
|
if (label == null) return;
|
|
label.text = $"{value:0.0}s";
|
|
}
|
|
|
|
private void UpdateVsyncLabel(int v)
|
|
{
|
|
if (_vsyncValueText == null) return;
|
|
|
|
_vsyncValueText.text = v switch
|
|
{
|
|
0 => "Off",
|
|
1 => "On",
|
|
2 => "Half",
|
|
_ => "On"
|
|
};
|
|
}
|
|
|
|
private void UpdateMaxFramerateLabel(int fps)
|
|
{
|
|
if (_maxFramerateValueText == null) return;
|
|
_maxFramerateValueText.text = $"{fps} FPS";
|
|
}
|
|
|
|
private void MarkDirty()
|
|
{
|
|
if (_ignoreUiCallbacks) return;
|
|
|
|
_waitingChanges = HasUnappliedChanges();
|
|
SetPendingChangesVisible(_waitingChanges);
|
|
}
|
|
|
|
private bool HasUnappliedChanges()
|
|
{
|
|
return !AudioEquals(_draftAudio, _loadedAudio) ||
|
|
!VisualEquals(_draftVisual, _loadedVisual) ||
|
|
!GameEquals(_draftGameSettings, _loadedGameSettings);
|
|
}
|
|
|
|
private void SetPendingChangesVisible(bool visible)
|
|
{
|
|
if (_pendingChangesText == null) return;
|
|
|
|
_pendingChangesText.gameObject.SetActive(visible);
|
|
if (visible)
|
|
_pendingChangesText.text = _pendingChangesMessage;
|
|
}
|
|
|
|
private static bool AudioEquals(AudioSettings a, AudioSettings b)
|
|
{
|
|
if (ReferenceEquals(a, b)) return true;
|
|
if (a == null || b == null) return false;
|
|
|
|
const float eps = 0.0001f;
|
|
|
|
return Mathf.Abs(a.MasterVolume - b.MasterVolume) < eps &&
|
|
Mathf.Abs(a.MusicVolume - b.MusicVolume) < eps &&
|
|
Mathf.Abs(a.SfxVolume - b.SfxVolume) < eps &&
|
|
Mathf.Abs(a.VoiceVolume - b.VoiceVolume) < eps &&
|
|
Mathf.Abs(a.AmbienceVolume - b.AmbienceVolume) < eps &&
|
|
Mathf.Abs(a.UIVolume - b.UIVolume) < eps &&
|
|
a.MuteWhenUnfocused == b.MuteWhenUnfocused;
|
|
}
|
|
|
|
private static bool VisualEquals(VisualSettings a, VisualSettings b)
|
|
{
|
|
if (ReferenceEquals(a, b)) return true;
|
|
if (a == null || b == null) return false;
|
|
|
|
return a.FullScreenMode == b.FullScreenMode &&
|
|
a.VSyncCount == b.VSyncCount &&
|
|
a.MaxFramerate == b.MaxFramerate;
|
|
}
|
|
|
|
private static bool GameEquals(GameSettings a, GameSettings b)
|
|
{
|
|
if (ReferenceEquals(a, b)) return true;
|
|
if (a == null || b == null) return false;
|
|
|
|
const float eps = 0.0001f;
|
|
|
|
return Mathf.Abs(a.PopupDisplayDuration - b.PopupDisplayDuration) < eps &&
|
|
a.TutorialsEnabled == b.TutorialsEnabled &&
|
|
a.TooltipsEnabled == b.TooltipsEnabled &&
|
|
a.AutoUseTools == b.AutoUseTools;
|
|
}
|
|
|
|
private static AudioSettings CloneAudio(AudioSettings a)
|
|
{
|
|
if (a == null) a = new AudioSettings();
|
|
|
|
return new AudioSettings
|
|
{
|
|
MasterVolume = a.MasterVolume,
|
|
MusicVolume = a.MusicVolume,
|
|
SfxVolume = a.SfxVolume,
|
|
VoiceVolume = a.VoiceVolume,
|
|
AmbienceVolume = a.AmbienceVolume,
|
|
UIVolume = a.UIVolume,
|
|
MuteWhenUnfocused = a.MuteWhenUnfocused
|
|
};
|
|
}
|
|
|
|
private static VisualSettings CloneVisual(VisualSettings v)
|
|
{
|
|
if (v == null) v = new VisualSettings();
|
|
|
|
return new VisualSettings
|
|
{
|
|
FullScreenMode = v.FullScreenMode,
|
|
VSyncCount = v.VSyncCount,
|
|
MaxFramerate = v.MaxFramerate <= 0 ? 120 : v.MaxFramerate
|
|
};
|
|
}
|
|
|
|
private static GameSettings CloneGameSettings(GameSettings g)
|
|
{
|
|
if (g == null) g = new GameSettings();
|
|
|
|
return new GameSettings
|
|
{
|
|
PopupDisplayDuration = g.PopupDisplayDuration,
|
|
TutorialsEnabled = g.TutorialsEnabled,
|
|
TooltipsEnabled = g.TooltipsEnabled,
|
|
AutoUseTools = g.AutoUseTools,
|
|
};
|
|
}
|
|
}
|
|
} |