using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Audio; namespace RR.Common.Settings { public enum SettingValueType { Bool, Int, Float, String, Button, // Кнопка - не хранит значение, только вызывает действие OptionPicker // Выбор из списка опций (enum-like) } // "Куда применять" — расширяется редко (не под каждую настройку) public enum ApplyTarget { None, // Audio AudioMixerFloat01ToDb, // float 0..1 -> dB и в AudioMixer parameter // Graphics / Performance QualityLevel, // int -> QualitySettings.SetQualityLevel VSync, // bool -> QualitySettings.vSyncCount TargetFps, // int -> Application.targetFrameRate Fullscreen, // bool -> Screen.fullScreen FullscreenMode, // int 0..3 -> Screen.fullScreenMode ResolutionIndex // int -> индекс в Screen.resolutions } [Serializable] public struct SettingValue { public SettingValueType type; public bool b; public int i; public float f; public string s; public static SettingValue Bool(bool v) => new() { type = SettingValueType.Bool, b = v }; public static SettingValue Int(int v) => new() { type = SettingValueType.Int, i = v }; public static SettingValue Float(float v) => new() { type = SettingValueType.Float, f = v }; public static SettingValue String(string v) => new() { type = SettingValueType.String, s = v }; } [Serializable] public class SettingEntry { public string key; public string displayName; [TextArea] public string description; public string group = "General"; public SettingValueType valueType; // Defaults public bool defaultBool = true; public int defaultInt = 0; public float defaultFloat = 1f; public string defaultString = ""; // Ranges (used for Int/Float) public int minInt = 0; public int maxInt = 10; public float minFloat = 0f; public float maxFloat = 1f; public ApplyTarget applyTarget = ApplyTarget.None; // AudioMixer params (used only for AudioMixerFloat01ToDb) public AudioMixer mixer; public string mixerParameter = "MasterVolumeDb"; public float minDb = -80f; public float maxDb = 0f; // Button params (для типа Button) [Header("Button Settings")] [Tooltip("Текст на кнопке (если не задан displayName)")] public string buttonText; [Tooltip("Дополнительные данные для кнопки (URL, имя сцены и т.д.)")] public string buttonData; [Tooltip("Цвет кнопки")] public Color buttonColor = Color.white; [Tooltip("Текстура/спрайт кнопки")] public Sprite buttonSprite; // OptionPicker params (для типа OptionPicker) [Header("Option Picker Settings")] [Tooltip("Список вариантов выбора")] public List options; [Tooltip("Индекс варианта по умолчанию")] public int defaultOptionIndex; public SettingValue DefaultValue => valueType switch { SettingValueType.Bool => SettingValue.Bool(defaultBool), SettingValueType.Int => SettingValue.Int(defaultInt), SettingValueType.Float => SettingValue.Float(defaultFloat), SettingValueType.String => SettingValue.String(defaultString ?? ""), SettingValueType.Button => default, // Кнопки не хранят значение SettingValueType.OptionPicker => SettingValue.Int(options != null && options.Count > 0 ? Mathf.Clamp(defaultOptionIndex, 0, options.Count - 1) : 0), _ => default }; public SettingValue Sanitize(SettingValue v) { if (v.type != valueType) return DefaultValue; // защита от кривых min/max int iMin = Mathf.Min(minInt, maxInt); int iMax = Mathf.Max(minInt, maxInt); float fMin = Mathf.Min(minFloat, maxFloat); float fMax = Mathf.Max(minFloat, maxFloat); return valueType switch { SettingValueType.Bool => SettingValue.Bool(v.b), SettingValueType.Int => SettingValue.Int(Mathf.Clamp(v.i, iMin, iMax)), SettingValueType.Float => SettingValue.Float(Mathf.Clamp(v.f, fMin, fMax)), SettingValueType.String => SettingValue.String(v.s ?? ""), SettingValueType.Button => default, SettingValueType.OptionPicker => SettingValue.Int(options != null && options.Count > 0 ? Mathf.Clamp(v.i, 0, options.Count - 1) : 0), _ => DefaultValue }; } } [CreateAssetMenu(menuName = "Settings/Database")] public class SettingsDatabase : ScriptableObject { public List entries = new(); public SettingEntry Find(string key) => entries.Find(e => string.Equals(e.key, key, StringComparison.Ordinal)); private void OnValidate() { var set = new HashSet(); foreach (var e in entries) { if (e == null) continue; if (string.IsNullOrWhiteSpace(e.key)) Debug.LogWarning($"[SettingsDatabase] Empty key in {name}", this); else if (!set.Add(e.key)) Debug.LogWarning($"[SettingsDatabase] Duplicate key '{e.key}' in {name}", this); } } } }