using System; using UnityEngine; namespace UnityEditor.SettingsManagement { [Flags] enum SettingVisibility { None = 0 << 0, /// /// Matches any static field implementing IUserSetting and tagged with [UserSettingAttribute(visibleInSettingsProvider = true)]. /// /// /// These fields are automatically scraped by the SettingsProvider and displayed. /// Visible = 1 << 0, /// /// Matches any static field implementing IUserSetting and tagged with [UserSettingAttribute(visibleInSettingsProvider = false)]. /// /// /// These fields will be reset by the "Reset All" menu in SettingsProvider, but are not shown in the interface. /// Typically these fields require some conditional formatting or data handling, and are shown in the /// SettingsProvider UI with a [UserSettingBlockAttribute]. /// Hidden = 1 << 1, /// /// A static or instance field tagged with [SettingsKeyAttribute]. /// /// /// Unlisted settings are not shown in the SettingsProvider, but are reset to default values by the "Reset All" /// context menu. /// Unlisted = 1 << 2, /// /// A static field implementing IUserSetting that is not marked with any setting attribute. /// /// /// Unregistered IUserSetting fields are not affected by the SettingsProvider. /// Unregistered = 1 << 3, All = Visible | Hidden | Unlisted | Unregistered } /// /// Types implementing IUserSetting are eligible for use with , which enables /// fields to automatically populate the interface. /// public interface IUserSetting { /// /// The key for this value. /// string key { get; } /// /// The type of the stored value. /// Type type { get; } /// /// At which scope this setting is saved. /// SettingsScope scope { get; } /// /// The name of the that this setting should be associated with. If null, the /// first repository matching the will be used. /// string settingsRepositoryName { get; } /// /// The instance that this setting should be saved and loaded from. /// Settings settings { get; } /// /// Get the stored value. /// If you are implementing IUserSetting it is recommended that you cache this value. /// /// /// The stored value. /// object GetValue(); /// /// Get the default value for this setting. /// /// /// The default value for this setting. /// object GetDefaultValue(); /// /// Set the value for this setting. /// /// The new value. /// /// True to immediately serialize the ISettingsRepository that is backing this value, or false to postpone. /// If not serializing immediately, be sure to call . /// void SetValue(object value, bool saveProjectSettingsImmediately = false); /// /// When the inspected type is a reference value, it is possible to change properties without affecting the /// backing setting. ApplyModifiedProperties provides a method to force serialize these changes. /// void ApplyModifiedProperties(); /// /// Set the current value back to the default. /// /// True to immediately re-serialize project settings. void Reset(bool saveProjectSettingsImmediately = false); /// /// Delete the saved setting. Does not clear the current value. /// /// /// True to immediately re-serialize project settings. void Delete(bool saveProjectSettingsImmediately = false); } /// /// A generic implementation of IUserSetting to be used with a instance. This default /// implementation assumes the instance contains two , one /// for and one for . /// /// /// public class UserSetting : IUserSetting { bool m_Initialized; string m_Key; string m_Repository; T m_Value; T m_DefaultValue; SettingsScope m_Scope; Settings m_Settings; UserSetting() {} /// /// Constructor for UserSetting{T} type. /// /// The instance that this setting should be saved and loaded from. /// The key for this value. /// The default value for this key. /// The scope at which to save this setting. public UserSetting(Settings settings, string key, T value, SettingsScope scope = SettingsScope.Project) { m_Key = key; m_Repository = null; m_Value = value; m_Scope = scope; m_Initialized = false; m_Settings = settings; } /// /// Constructor for UserSetting{T} type. /// /// The instance that this setting should be saved and loaded from. /// The name that this setting should be saved and loaded from. Pass null to save to first available instance. /// The key for this value. /// The default value for this key. /// The scope at which to save this setting. public UserSetting(Settings settings, string repository, string key, T value, SettingsScope scope = SettingsScope.Project) { m_Key = key; m_Repository = repository; m_Value = value; m_Scope = scope; m_Initialized = false; m_Settings = settings; } /// /// The key for this value. /// /// public string key { get { return m_Key; } } /// /// The name of the repository that this setting is saved in. /// /// public string settingsRepositoryName { get { return m_Repository; } } /// /// The type that this setting represents ({T}). /// /// public Type type { get { return typeof(T); } } /// /// Get a copy of the default value. /// /// /// The default value. /// /// public object GetDefaultValue() { return defaultValue; } /// /// Get the currently stored value. /// /// /// The value that is currently set. /// /// public object GetValue() { return value; } /// /// The scope affects which the instance will save /// it's data to. /// /// /// The scope at which to save this key and value. /// /// public SettingsScope scope { get { return m_Scope; } } /// /// The instance that this setting will be read from and saved to. /// /// public Settings settings { get { return m_Settings; } } /// /// Set the value for this setting. /// /// The new value. /// /// True to immediately serialize the ISettingsRepository that is backing this value, or false to postpone. /// If not serializing immediately, be sure to call . /// /// public void SetValue(object value, bool saveProjectSettingsImmediately = false) { // we do want to allow null values if (value != null && !(value is T)) throw new ArgumentException("Value must be of type " + typeof(T) + "\n" + key + " expecting value of type " + type + ", received " + value.GetType()); SetValue((T)value, saveProjectSettingsImmediately); } /// /// Set the value for this setting. /// /// The new value. /// /// True to immediately serialize the ISettingsRepository that is backing this value, or false to postpone. /// If not serializing immediately, be sure to call . /// public void SetValue(T value, bool saveProjectSettingsImmediately = false) { Init(); m_Value = value; settings.Set(key, m_Value, m_Scope); if (saveProjectSettingsImmediately) settings.Save(); } /// /// Delete the saved setting. Does not clear the current value. /// /// /// True to immediately re-serialize project settings. /// public void Delete(bool saveProjectSettingsImmediately = false) { settings.DeleteKey(key, scope); // Don't Init() because that will set the key again. We just want to reset the m_Value with default and // pretend that this field hasn't been initialised yet. m_Value = ValueWrapper.DeepCopy(m_DefaultValue); m_Initialized = false; } /// /// When the inspected type is a reference value, it is possible to change properties without affecting the /// backing setting. ApplyModifiedProperties provides a method to force serialize these changes. /// /// public void ApplyModifiedProperties() { settings.Set(key, m_Value, m_Scope); settings.Save(); } /// /// Set the current value back to the default. /// /// True to immediately re-serialize project settings. /// public void Reset(bool saveProjectSettingsImmediately = false) { SetValue(defaultValue, saveProjectSettingsImmediately); } void Init() { if (!m_Initialized) { if (m_Scope == SettingsScope.Project && settings == null) throw new Exception("UserSetting \"" + m_Key + "\" is attempting to access SettingsScope.Project setting with no Settings instance!"); m_Initialized = true; // DeepCopy uses EditorJsonUtility which is not permitted during construction m_DefaultValue = ValueWrapper.DeepCopy(m_Value); if (settings.ContainsKey(m_Key, m_Scope)) m_Value = settings.Get(m_Key, m_Scope); else settings.Set(m_Key, m_Value, m_Scope); } } /// /// The default value for this setting. /// public T defaultValue { get { Init(); return ValueWrapper.DeepCopy(m_DefaultValue); } } /// /// The currently stored value. /// public T value { get { Init(); return m_Value; } set { SetValue(value); } } /// /// Implicit cast to backing type. /// /// The UserSetting{T} to cast to {T}. /// /// The currently stored . /// public static implicit operator T(UserSetting pref) { return pref.value; } /// /// Get a summary of this setting. /// /// A string summary of this setting. public override string ToString() { return string.Format("{0} setting. Key: {1} Value: {2}", scope, key, value); } } }