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 } /// /// An interface that represents a user setting. /// Types implementing IUserSetting are eligible for use with , which enables /// fields to automatically populate the interface. /// public interface IUserSetting { /// /// Implement this property to get the key for this value. /// /// The key used to identify the settings entry. This is used along with the to uniquely identify the value. string key { get; } /// /// Implement this property to get the type of the stored value. /// /// The type of value. This is used along with the to uniquely identify the value. Type type { get; } /// /// Implement this property to get the location in the UI where this setting will appear. /// /// /// Indicates whether this is a setting /// or a preference. /// SettingsScope scope { get; } /// /// Implement this property to get the name of the that this setting should be associated with. /// If null, the first repository matching the is used. /// /// The bare filename of this repository. string settingsRepositoryName { get; } /// /// Implement this property to get the instance to save and load this setting from. /// /// A reference to instance. Settings settings { get; } /// /// Implement this method to return the stored settings value. /// If you are implementing IUserSetting, you should cache this value. /// /// /// The stored value. /// object GetValue(); /// /// Implement this method to return the the default value for this setting. /// /// /// The default value for this setting. /// object GetDefaultValue(); /// /// Implement this method to set the value for this setting. /// /// The new value. /// /// True to immediately serialize the that is backing this value; or false to postpone. /// If not serializing immediately, be sure to call . /// void SetValue(object value, bool saveProjectSettingsImmediately = false); /// /// Implement this method to explicitly update the that is backing this value. /// 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(); /// /// Implement this method to set the current value back to the default. /// /// True to immediately re-serialize project settings. By default, no values are updated. void Reset(bool saveProjectSettingsImmediately = false); /// /// Implement this method to delete the saved setting. This does not clear the current value. /// /// /// True to immediately re-serialize project settings. By default, no values are updated. void Delete(bool saveProjectSettingsImmediately = false); } /// /// A generic implementation of to use with a instance. This default /// implementation assumes that the instance contains two interfaces: /// - Project settings () /// - User preferences () /// /// Type of value. 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() { } /// /// Initializes and returns an instance of the UserSetting<T> type. /// /// The instance to save and load this setting from. /// The key for this value. /// The default value for this key. /// The scope for this setting. By default, the scope is the project. 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; } /// /// Initializes and returns an instance of the UserSetting<T> type using the specified repository. /// /// The instance to save and load this setting from. /// The name to save and load this setting from. Specify null to save to the first available instance. /// The key for this value. /// The default value for this key. /// The scope for this setting. By default, the scope is the project. 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; } /// /// Gets the key for this value. /// /// public string key { get { return m_Key; } } /// /// Gets the name of the repository that this setting is saved in. /// /// public string settingsRepositoryName { get { return m_Repository; } } /// /// Gets the type that this setting represents (<T>). /// /// public Type type { get { return typeof(T); } } /// /// Returns a copy of the default value. /// /// /// The default value. /// /// public object GetDefaultValue() { return defaultValue; } /// /// Returns the currently stored value. /// /// /// The value that is currently set. /// /// public object GetValue() { return value; } /// /// Gets the scope () where the instance saves /// its data. /// /// public SettingsScope scope { get { return m_Scope; } } /// /// Gets the instance to read from and save to. /// /// public Settings settings { get { return m_Settings; } } /// /// Sets the value for this setting from the specified object. /// /// The new value to set. /// /// Set this value to true if you want to immediately serialize the /// that is backing this value. By default, this is false. /// /// **Note**: If not serializing immediately, you need 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); } /// public void SetValue(T value, bool saveProjectSettingsImmediately = false) { Init(); m_Value = value; settings.Set(key, m_Value, m_Scope); if (saveProjectSettingsImmediately) settings.Save(); } /// /// Deletes the saved setting but doesn't clear the current value. /// /// /// Set this value to true if you want to immediately serialize the /// that is backing this value. By default, this is false. /// /// **Note**: If not serializing immediately, you need to call . /// /// /// 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; } /// /// Forces Unity to serialize the changed properties to the that is backing this value. /// When the inspected type is a reference value, it is possible to change properties without affecting the /// backing setting. /// /// public void ApplyModifiedProperties() { settings.Set(key, m_Value, m_Scope); settings.Save(); } /// /// Sets the current value back to the default. /// /// /// Set this value to true if you want to immediately serialize the /// that is backing this value. By default, this is false. /// /// **Note**: If not serializing immediately, you need to call . /// /// 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); } } /// /// Gets the default value for this setting. /// public T defaultValue { get { Init(); return ValueWrapper.DeepCopy(m_DefaultValue); } } /// /// Gets or sets the currently stored value. /// public T value { get { Init(); return m_Value; } set { SetValue(value); } } /// /// Implicit casts this setting to the backing type `T`. /// /// The UserSetting<T> to cast to `T`. /// /// The currently stored . /// public static implicit operator T(UserSetting pref) { return pref.value; } /// /// Returns a string representation of this setting. /// /// A string summary of this setting of format "[scope] setting. Key: [key] Value: [value]". public override string ToString() { return string.Format("{0} setting. Key: {1} Value: {2}", scope, key, value); } } }