278 lines
11 KiB
C#
278 lines
11 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Audio;
|
|
using UnityEngine.Events;
|
|
using Ashwild.Core;
|
|
|
|
namespace Ashwild.Settings
|
|
{
|
|
public class SettingsManager : MonoBehaviour
|
|
{
|
|
public static SettingsManager Instance { get; private set; }
|
|
|
|
[Header("Audio Mixer")]
|
|
[SerializeField] private AudioMixer audioMixer;
|
|
[SerializeField] private string masterParam = "MasterVol";
|
|
[SerializeField] private string musicParam = "MusicVol";
|
|
[SerializeField] private string sfxParam = "SfxVol";
|
|
|
|
[Header("Events")]
|
|
public UnityEvent onSettingsChanged;
|
|
|
|
// ── Display ─────────────────────────────────────────────────
|
|
public int ResolutionIndex { get; private set; }
|
|
public FullScreenMode FullscreenMode { get; private set; }
|
|
public int MonitorIndex { get; private set; }
|
|
public float Brightness { get; private set; }
|
|
|
|
// ── Audio ───────────────────────────────────────────────────
|
|
public float MasterVolume { get; private set; }
|
|
public float MusicVolume { get; private set; }
|
|
public float SfxVolume { get; private set; }
|
|
|
|
// ── Graphics ────────────────────────────────────────────────
|
|
public int QualityLevel { get; private set; }
|
|
public bool VSync { get; private set; }
|
|
public int TargetFps { get; private set; }
|
|
public float Fov { get; private set; }
|
|
|
|
// ── Controls ────────────────────────────────────────────────
|
|
public float Sensitivity { get; private set; }
|
|
public bool InvertY { get; private set; }
|
|
public bool CrosshairEnabled { get; private set; }
|
|
|
|
// ── PlayerPrefs keys ────────────────────────────────────────
|
|
private const string K_RESOLUTION = "settings.display.resolutionIndex";
|
|
private const string K_FULLSCREEN = "settings.display.fullscreenMode";
|
|
private const string K_MONITOR = "settings.display.monitorIndex";
|
|
private const string K_BRIGHTNESS = "settings.display.brightness";
|
|
private const string K_MASTER = "settings.audio.master";
|
|
private const string K_MUSIC = "settings.audio.music";
|
|
private const string K_SFX = "settings.audio.sfx";
|
|
private const string K_QUALITY = "settings.graphics.qualityLevel";
|
|
private const string K_VSYNC = "settings.graphics.vsync";
|
|
private const string K_TARGET_FPS = "settings.graphics.targetFps";
|
|
private const string K_FOV = "settings.graphics.fov";
|
|
private const string K_SENS = "settings.controls.sensitivity";
|
|
private const string K_INVERT_Y = "settings.controls.invertY";
|
|
private const string K_CROSSHAIR = "settings.controls.crosshair";
|
|
|
|
private void Awake()
|
|
{
|
|
if (Instance != null && Instance != this)
|
|
{
|
|
Destroy(gameObject);
|
|
return;
|
|
}
|
|
Instance = this;
|
|
Persistence.Persist(gameObject);
|
|
|
|
LoadAll();
|
|
ApplyAll();
|
|
}
|
|
|
|
// ── Public setters ──────────────────────────────────────────
|
|
|
|
public void SetResolution(int index)
|
|
{
|
|
Resolution[] resolutions = Screen.resolutions;
|
|
if (index < 0 || index >= resolutions.Length) return;
|
|
ResolutionIndex = index;
|
|
Resolution r = resolutions[index];
|
|
Screen.SetResolution(r.width, r.height, FullscreenMode, r.refreshRateRatio);
|
|
Save();
|
|
onSettingsChanged?.Invoke();
|
|
}
|
|
|
|
public void SetFullscreenMode(FullScreenMode mode)
|
|
{
|
|
FullscreenMode = mode;
|
|
Screen.fullScreenMode = mode;
|
|
Save();
|
|
onSettingsChanged?.Invoke();
|
|
}
|
|
|
|
public void SetMonitor(int index)
|
|
{
|
|
List<DisplayInfo> displays = new List<DisplayInfo>();
|
|
Screen.GetDisplayLayout(displays);
|
|
if (index < 0 || index >= displays.Count) return;
|
|
MonitorIndex = index;
|
|
Screen.MoveMainWindowTo(displays[index], Vector2Int.zero);
|
|
Save();
|
|
onSettingsChanged?.Invoke();
|
|
}
|
|
|
|
public void SetBrightness(float value)
|
|
{
|
|
Brightness = Mathf.Clamp(value, 0.5f, 1.5f);
|
|
Save();
|
|
onSettingsChanged?.Invoke();
|
|
}
|
|
|
|
public void SetMasterVolume(float value)
|
|
{
|
|
MasterVolume = Mathf.Clamp01(value);
|
|
ApplyMasterVolume();
|
|
Save();
|
|
onSettingsChanged?.Invoke();
|
|
}
|
|
|
|
public void SetMusicVolume(float value)
|
|
{
|
|
MusicVolume = Mathf.Clamp01(value);
|
|
ApplyMusicVolume();
|
|
Save();
|
|
onSettingsChanged?.Invoke();
|
|
}
|
|
|
|
public void SetSfxVolume(float value)
|
|
{
|
|
SfxVolume = Mathf.Clamp01(value);
|
|
ApplySfxVolume();
|
|
Save();
|
|
onSettingsChanged?.Invoke();
|
|
}
|
|
|
|
public void SetQualityLevel(int level)
|
|
{
|
|
QualityLevel = Mathf.Clamp(level, 0, QualitySettings.names.Length - 1);
|
|
QualitySettings.SetQualityLevel(QualityLevel, true);
|
|
Save();
|
|
onSettingsChanged?.Invoke();
|
|
}
|
|
|
|
public void SetVSync(bool enabled)
|
|
{
|
|
VSync = enabled;
|
|
QualitySettings.vSyncCount = enabled ? 1 : 0;
|
|
Save();
|
|
onSettingsChanged?.Invoke();
|
|
}
|
|
|
|
public void SetTargetFps(int fps)
|
|
{
|
|
TargetFps = Mathf.Clamp(fps, 30, 360);
|
|
Application.targetFrameRate = TargetFps;
|
|
Save();
|
|
onSettingsChanged?.Invoke();
|
|
}
|
|
|
|
public void SetFov(float fov)
|
|
{
|
|
Fov = Mathf.Clamp(fov, 60f, 110f);
|
|
Save();
|
|
onSettingsChanged?.Invoke();
|
|
}
|
|
|
|
public void SetSensitivity(float value)
|
|
{
|
|
Sensitivity = Mathf.Clamp(value, 0.05f, 2f);
|
|
Save();
|
|
onSettingsChanged?.Invoke();
|
|
}
|
|
|
|
public void SetInvertY(bool enabled)
|
|
{
|
|
InvertY = enabled;
|
|
Save();
|
|
onSettingsChanged?.Invoke();
|
|
}
|
|
|
|
public void SetCrosshairEnabled(bool enabled)
|
|
{
|
|
CrosshairEnabled = enabled;
|
|
Save();
|
|
onSettingsChanged?.Invoke();
|
|
}
|
|
|
|
// ── Load / Save / Apply ─────────────────────────────────────
|
|
|
|
private void LoadAll()
|
|
{
|
|
int defaultResolution = Mathf.Max(0, Screen.resolutions.Length - 1);
|
|
|
|
ResolutionIndex = PlayerPrefs.GetInt(K_RESOLUTION, defaultResolution);
|
|
FullscreenMode = (FullScreenMode)PlayerPrefs.GetInt(K_FULLSCREEN, (int)FullScreenMode.FullScreenWindow);
|
|
MonitorIndex = PlayerPrefs.GetInt(K_MONITOR, 0);
|
|
Brightness = PlayerPrefs.GetFloat(K_BRIGHTNESS, 1f);
|
|
|
|
MasterVolume = PlayerPrefs.GetFloat(K_MASTER, 1f);
|
|
MusicVolume = PlayerPrefs.GetFloat(K_MUSIC, 0.8f);
|
|
SfxVolume = PlayerPrefs.GetFloat(K_SFX, 1f);
|
|
|
|
QualityLevel = PlayerPrefs.GetInt(K_QUALITY, QualitySettings.GetQualityLevel());
|
|
VSync = PlayerPrefs.GetInt(K_VSYNC, 1) == 1;
|
|
TargetFps = PlayerPrefs.GetInt(K_TARGET_FPS, 144);
|
|
Fov = PlayerPrefs.GetFloat(K_FOV, 75f);
|
|
|
|
Sensitivity = PlayerPrefs.GetFloat(K_SENS, 0.15f);
|
|
InvertY = PlayerPrefs.GetInt(K_INVERT_Y, 0) == 1;
|
|
CrosshairEnabled = PlayerPrefs.GetInt(K_CROSSHAIR, 1) == 1;
|
|
}
|
|
|
|
private void Save()
|
|
{
|
|
PlayerPrefs.SetInt(K_RESOLUTION, ResolutionIndex);
|
|
PlayerPrefs.SetInt(K_FULLSCREEN, (int)FullscreenMode);
|
|
PlayerPrefs.SetInt(K_MONITOR, MonitorIndex);
|
|
PlayerPrefs.SetFloat(K_BRIGHTNESS, Brightness);
|
|
|
|
PlayerPrefs.SetFloat(K_MASTER, MasterVolume);
|
|
PlayerPrefs.SetFloat(K_MUSIC, MusicVolume);
|
|
PlayerPrefs.SetFloat(K_SFX, SfxVolume);
|
|
|
|
PlayerPrefs.SetInt(K_QUALITY, QualityLevel);
|
|
PlayerPrefs.SetInt(K_VSYNC, VSync ? 1 : 0);
|
|
PlayerPrefs.SetInt(K_TARGET_FPS, TargetFps);
|
|
PlayerPrefs.SetFloat(K_FOV, Fov);
|
|
|
|
PlayerPrefs.SetFloat(K_SENS, Sensitivity);
|
|
PlayerPrefs.SetInt(K_INVERT_Y, InvertY ? 1 : 0);
|
|
PlayerPrefs.SetInt(K_CROSSHAIR, CrosshairEnabled ? 1 : 0);
|
|
|
|
PlayerPrefs.Save();
|
|
}
|
|
|
|
private void ApplyAll()
|
|
{
|
|
// Display
|
|
Resolution[] resolutions = Screen.resolutions;
|
|
if (ResolutionIndex >= 0 && ResolutionIndex < resolutions.Length)
|
|
{
|
|
Resolution r = resolutions[ResolutionIndex];
|
|
Screen.SetResolution(r.width, r.height, FullscreenMode, r.refreshRateRatio);
|
|
}
|
|
if (MonitorIndex > 0)
|
|
{
|
|
List<DisplayInfo> displays = new List<DisplayInfo>();
|
|
Screen.GetDisplayLayout(displays);
|
|
if (MonitorIndex < displays.Count)
|
|
Screen.MoveMainWindowTo(displays[MonitorIndex], Vector2Int.zero);
|
|
}
|
|
|
|
// Audio
|
|
ApplyMasterVolume();
|
|
ApplyMusicVolume();
|
|
ApplySfxVolume();
|
|
|
|
// Graphics
|
|
QualitySettings.SetQualityLevel(QualityLevel, true);
|
|
QualitySettings.vSyncCount = VSync ? 1 : 0;
|
|
Application.targetFrameRate = TargetFps;
|
|
}
|
|
|
|
// ── Audio helpers ───────────────────────────────────────────
|
|
|
|
private void ApplyMasterVolume() => SetMixer(masterParam, MasterVolume);
|
|
private void ApplyMusicVolume() => SetMixer(musicParam, MusicVolume);
|
|
private void ApplySfxVolume() => SetMixer(sfxParam, SfxVolume);
|
|
|
|
private void SetMixer(string param, float linear)
|
|
{
|
|
if (audioMixer == null || string.IsNullOrEmpty(param)) return;
|
|
audioMixer.SetFloat(param, Mathf.Log10(Mathf.Max(linear, 0.0001f)) * 20f);
|
|
}
|
|
}
|
|
}
|