using System.IO; using UnityEngine; namespace E7.NotchSolution.Editor { /// /// Helper base class to handle IO between any Unity-serializable class and the ProjectSettings folder. /// Uses Unity with the class instance. A subclass of /// is not really needed but may increases compatibility with something like inspector editor code. /// /// /// I saw a public UnityEditor.ScriptableSingleton with almost identical purpose /// except that FilePathAttribute required for it is internal. WHY?? /// internal abstract class GenericProjectSettings where T : GenericProjectSettings, new() { private static T cachedSettings; private static T cachedDummy; /// /// Point this to a constant number. It allows you to deprecate the old serialized file and start over. /// If file loaded has lower than this, the loaded instance will be /// a new instance instead. /// protected abstract int DataVersion { get; } /// /// Point this to a field that is serialized. When loading back this can be used to compare with /// if we should trust the serialized file or not. /// protected abstract int SerializedVersion { get; set; } /// /// Overridable file name to use for the settings file. /// protected virtual string FileName => typeof(T).Name; private string settingsPath => "ProjectSettings/" + FileName + ".asset"; private static T dummy { get { if (cachedDummy == null) { cachedDummy = new T(); } return cachedDummy; } } /// /// A singleton of the saved settings file. Can create a new one automatically or return /// a cached instance in the case of repeated use. /// public static T Instance { get { if (cachedSettings != null && cachedSettings.SerializedVersion >= dummy.DataVersion) { return cachedSettings; } var settings = new T(); if (File.Exists(dummy.settingsPath)) { var assetJson = File.ReadAllText(dummy.settingsPath); JsonUtility.FromJsonOverwrite(assetJson, settings); if (settings.SerializedVersion < dummy.DataVersion) { settings = new T(); } } cachedSettings = settings; return settings; } } /// /// Return the settings to the initial state and save to disk. /// public void Reset() { cachedSettings = new T(); Save(); } /// /// Commit all changes of this instance to disk. /// public void Save() { if (cachedSettings != null) { SerializedVersion = dummy.DataVersion; File.WriteAllText(settingsPath, JsonUtility.ToJson(cachedSettings, true)); } } } }