using System;
using Cielonos.MainGame.UI;
using SLSUtilities.General;
using SLSUtilities.UI;
using SLSUtilities.WwiseAssistance;
using UnityEngine;
using UnityEngine.Localization.Settings;
namespace Cielonos.Settings
{
///
/// 游戏设置的 Singleton 管理器。
///
/// 数据流:
/// 字段初始化器提供编译期默认值 →
/// 中通过 ES3 加载磁盘数据覆盖 →
/// 中调用 推送到各子系统。
///
///
/// 扩展方式:直接在对应 Settings 类(
/// / /
/// / )中添加带默认值的新字段。
/// ES3 反序列化时,旧存档缺失的字段自动获取字段初始化器的默认值。
/// 然后在对应的 Apply 方法中添加新字段的应用逻辑即可。
///
///
public class GameSettingsManager : Singleton
{
// ──────────────────────── 持久化常量 ────────────────────────
private const string SaveFileName = "GameSettings.es3";
private const string KeyGameplay = "gameplay";
private const string KeyGraphics = "graphics";
private const string KeySound = "sound";
private const string KeyControls = "controls";
// ──────────────────────── Wwise RTPC 名称 ──────────────────
private const string RtpcMasterVolume = "MasterVolume";
private const string RtpcMusicVolume = "MusicVolume";
private const string RtpcSfxVolume = "SFXVolume";
// ──────────────────────── 运行时数据 ───────────────────────
public GameplaySettings gameplay = new();
public GraphicsSettings graphics = new();
public SoundSettings sound = new();
public ControlsSettings controls = new();
// ──────────────────────── 事件 ─────────────────────────────
/// Gameplay 设置被应用后触发。
public static event Action OnGameplaySettingsApplied;
/// Graphics 设置被应用后触发。
public static event Action OnGraphicsSettingsApplied;
/// Sound 设置被应用后触发。
public static event Action OnSoundSettingsApplied;
/// Controls 设置被应用后触发。
public static event Action OnControlsSettingsApplied;
// ──────────────────────── 生命周期 ─────────────────────────
protected override void Awake()
{
base.Awake();
Load();
}
private void Start()
{
ApplyAll();
}
// ──────────────────────── 持久化 ───────────────────────────
///
/// 将所有设置分类保存到磁盘。每个分类使用独立的 ES3 Key,
/// 某个分类数据损坏时不影响其他分类。
///
public void Save()
{
try
{
ES3.Save(KeyGameplay, gameplay, SaveFileName);
ES3.Save(KeyGraphics, graphics, SaveFileName);
ES3.Save(KeySound, sound, SaveFileName);
ES3.Save(KeyControls, controls, SaveFileName);
Debug.Log("[GameSettingsManager] Settings saved.");
}
catch (Exception e)
{
Debug.LogError($"[GameSettingsManager] Save failed: {e.Message}");
}
}
///
/// 从磁盘加载设置。每个分类独立加载,某个分类缺失或损坏时
/// 保留字段初始化器的默认值。
///
public void Load()
{
try
{
if (!ES3.FileExists(SaveFileName)) return;
if (ES3.KeyExists(KeyGameplay, SaveFileName))
gameplay = ES3.Load(KeyGameplay, SaveFileName);
if (ES3.KeyExists(KeyGraphics, SaveFileName))
graphics = ES3.Load(KeyGraphics, SaveFileName);
if (ES3.KeyExists(KeySound, SaveFileName))
sound = ES3.Load(KeySound, SaveFileName);
if (ES3.KeyExists(KeyControls, SaveFileName))
controls = ES3.Load(KeyControls, SaveFileName);
}
catch (Exception e)
{
Debug.LogError($"[GameSettingsManager] Load failed: {e.Message}");
}
}
///
/// 删除设置存档文件。
///
public void DeleteSaveFile()
{
try
{
if (ES3.FileExists(SaveFileName))
{
ES3.DeleteFile(SaveFileName);
Debug.Log("[GameSettingsManager] Save file deleted.");
}
}
catch (Exception e)
{
Debug.LogError($"[GameSettingsManager] Delete save failed: {e.Message}");
}
}
// ──────────────────────── Apply ────────────────────────────
///
/// 应用所有分类的设置到对应系统。
///
public void ApplyAll()
{
ApplyGameplay();
ApplyGraphics();
ApplySound();
ApplyControls();
}
///
/// 应用 Gameplay 设置。
///
public void ApplyGameplay()
{
// Locale
var availableLocales = LocalizationSettings.AvailableLocales;
if (availableLocales != null)
{
var locale = availableLocales.GetLocale(gameplay.locale);
if (locale != null)
LocalizationSettings.SelectedLocale = locale;
}
// FPS 显示
if (PlayerCanvas.Instance != null)
PlayerCanvas.Instance.frameRateText.gameObject.SetActive(gameplay.showFPS);
OnGameplaySettingsApplied?.Invoke();
}
///
/// 应用 Graphics 设置。
///
public void ApplyGraphics()
{
// 分辨率与全屏模式
if (graphics.resolutionWidth > 0 && graphics.resolutionHeight > 0)
{
Screen.SetResolution(
graphics.resolutionWidth,
graphics.resolutionHeight,
graphics.fullscreenMode
);
}
else
{
Screen.fullScreenMode = graphics.fullscreenMode;
}
// 画质预设
if (graphics.qualityLevel >= 0)
QualitySettings.SetQualityLevel(graphics.qualityLevel, applyExpensiveChanges: true);
// VSync
QualitySettings.vSyncCount = graphics.vSync ? 1 : 0;
// 帧率上限
Application.targetFrameRate = graphics.targetFrameRate;
OnGraphicsSettingsApplied?.Invoke();
}
///
/// 应用 Sound 设置(通过 Wwise RTPC)。
///
public void ApplySound()
{
if (AudioManager.Instance == null) return;
AudioManager.Instance.SetRTPC(RtpcMasterVolume, sound.masterVolume);
AudioManager.Instance.SetRTPC(RtpcMusicVolume, sound.musicVolume);
AudioManager.Instance.SetRTPC(RtpcSfxVolume, sound.sfxVolume);
OnSoundSettingsApplied?.Invoke();
}
///
/// 应用 Controls 设置。
///
/// 按键绑定覆盖由 PlayerInputSubcontroller 消费:
/// 在其 Initialize() 中读取 .
/// 并调用 InputActionAsset.LoadBindingOverridesFromJson(),
/// 然后重新初始化 。
///
///
public void ApplyControls()
{
OnControlsSettingsApplied?.Invoke();
}
// ──────────────────────── Reset ────────────────────────────
///
/// 重置所有设置为默认值并立即应用。
///
public void ResetAllToDefault()
{
gameplay = new GameplaySettings();
graphics = new GraphicsSettings();
sound = new SoundSettings();
controls = new ControlsSettings();
ApplyAll();
}
///
/// 重置 Gameplay 设置为默认值并立即应用。
///
public void ResetGameplayToDefault()
{
gameplay = new GameplaySettings();
ApplyGameplay();
}
///
/// 重置 Graphics 设置为默认值并立即应用。
///
public void ResetGraphicsToDefault()
{
graphics = new GraphicsSettings();
ApplyGraphics();
}
///
/// 重置 Sound 设置为默认值并立即应用。
///
public void ResetSoundToDefault()
{
sound = new SoundSettings();
ApplySound();
}
///
/// 重置 Controls 设置为默认值并立即应用。
///
public void ResetControlsToDefault()
{
controls = new ControlsSettings();
ApplyControls();
}
}
}