using System; using System.IO; using UnityEngine; namespace UnityEditor.SettingsManagement { /// /// /// A settings repository that stores data local to a Unity project. /// [Serializable] public sealed class PackageSettingsRepository : ISettingsRepository { const string k_PackageSettingsDirectory = "ProjectSettings/Packages"; const bool k_PrettyPrintJson = true; bool m_Initialized; [SerializeField] string m_Name; [SerializeField] string m_Path; [SerializeField] SettingsDictionary m_Dictionary = new SettingsDictionary(); string m_cachedJson; /// /// Constructor sets the serialized data path. /// /// /// The package name. /// /// /// A name for this settings file. Settings are saved in `ProjectSettings/Packages/{package}/{name}.json`. /// public PackageSettingsRepository(string package, string name) { m_Name = name; m_Path = GetSettingsPath(package, name); m_Initialized = false; AssemblyReloadEvents.beforeAssemblyReload += Save; EditorApplication.quitting += Save; } void Init() { if (m_Initialized) return; m_Initialized = true; if (File.Exists(path)) { m_Dictionary = null; m_cachedJson = File.ReadAllText(path); EditorJsonUtility.FromJsonOverwrite(m_cachedJson, this); if (m_Dictionary == null) m_Dictionary = new SettingsDictionary(); } } /// /// This repository implementation is relevant to the Project scope. /// /// public SettingsScope scope { get { return SettingsScope.Project; } } /// /// The full path to the settings file. /// This corresponds to `Unity Project/Project Settings/Packages/com.unity.package/name`. /// /// public string path { get { return m_Path; } } /// /// The name of this settings file. /// public string name { get { return m_Name; } } // Cannot call FindFromAssembly from a constructor or field initializer // static string CreateSettingsPath(Assembly assembly, string name) // { // var info = PackageManager.PackageInfo.FindForAssembly(assembly); // return string.Format("{0}/{1}/{2}.json", k_PackageSettingsDirectory, info.name, name); // } /// /// Get a path for a settings file relative to the calling assembly package directory. /// /// The name of the package requesting this setting. /// An optional name for the settings file. Default is "Settings." /// A package-scoped path to the settings file within Project Settings. public static string GetSettingsPath(string packageName, string name = "Settings") { return string.Format("{0}/{1}/{2}.json", k_PackageSettingsDirectory, packageName, name); } /// /// Save all settings to their serialized state. /// /// public void Save() { Init(); if (!File.Exists(path)) { var directory = Path.GetDirectoryName(path); Directory.CreateDirectory(directory); } string newSettingsJson = EditorJsonUtility.ToJson(this, k_PrettyPrintJson); bool areJsonsEqual = newSettingsJson == m_cachedJson; #if UNITY_2019_3_OR_NEWER if (!AssetDatabase.IsOpenForEdit(path) && areJsonsEqual == false) { if (!AssetDatabase.MakeEditable(path)) { Debug.LogWarning($"Could not save package settings to {path}"); return; } } #endif try { if (!areJsonsEqual) { File.WriteAllText(path, newSettingsJson); m_cachedJson = newSettingsJson; } } catch (UnauthorizedAccessException) { Debug.LogWarning($"Could not save package settings to {path}"); } } /// /// Set a value for key of type T. /// /// The settings key. /// The value to set. Must be serializable. /// Type of value. /// public void Set(string key, T value) { Init(); m_Dictionary.Set(key, value); } /// /// Get a value with key of type T, or return the fallback value if no matching key is found. /// /// The settings key. /// If no key with a value of type T is found, this value is returned. /// Type of value to search for. /// public T Get(string key, T fallback = default(T)) { Init(); return m_Dictionary.Get(key, fallback); } /// /// Does the repository contain a setting with key and type. /// /// The settings key. /// The type of value to search for. /// True if a setting matching both key and type is found, false if no entry is found. /// public bool ContainsKey(string key) { Init(); return m_Dictionary.ContainsKey(key); } /// /// Remove a key value pair from the settings repository. /// /// /// /// public void Remove(string key) { Init(); m_Dictionary.Remove(key); } } }