first commit
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.SettingsManagement
|
||||
{
|
||||
/// <summary>
|
||||
/// A custom attribute for registering a static field of type <see cref="IUserSetting"/> for the <see cref="UserSettingsProvider"/> window.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public sealed class UserSettingAttribute : Attribute
|
||||
{
|
||||
string m_Category;
|
||||
GUIContent m_Title;
|
||||
bool m_VisibleInSettingsProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the group (category) to assign this settings value to.
|
||||
/// When Unity finds settings values in assemblies, it displays them in groups, organized by category.
|
||||
/// </summary>
|
||||
/// <value>The group or category where this setting appears in the UI.</value>
|
||||
public string category
|
||||
{
|
||||
get { return m_Category; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the label to show for this setting.
|
||||
/// </summary>
|
||||
/// <value>The label that appears beside this setting in the UI.</value>
|
||||
public GUIContent title
|
||||
{
|
||||
get { return m_Title; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True to show this field in the <see cref="UserSettingsProvider"/> interface; false if not.
|
||||
/// </summary>
|
||||
public bool visibleInSettingsProvider
|
||||
{
|
||||
get { return m_VisibleInSettingsProvider; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a static field as a setting. Fields must be of a type that implements <see cref="IUserSetting"/>.
|
||||
/// </summary>
|
||||
public UserSettingAttribute()
|
||||
{
|
||||
m_VisibleInSettingsProvider = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a static field as a setting and creates an entry in the UI. The field must be of a type that implements <see cref="IUserSetting"/>.
|
||||
/// </summary>
|
||||
/// <param name="category">The category to assign this setting to.</param>
|
||||
/// <param name="title">The display text for this setting in the UI.</param>
|
||||
/// <param name="tooltip">Optional. The tooltip for this setting.</param>
|
||||
public UserSettingAttribute(string category, string title, string tooltip = null)
|
||||
{
|
||||
m_Category = category;
|
||||
m_Title = new GUIContent(title, tooltip);
|
||||
m_VisibleInSettingsProvider = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A custom attribute for registering a field with <see cref="Settings"/>, but without automatically creating
|
||||
/// a property field in the <see cref="SettingsProvider"/>.
|
||||
/// Unlike <see cref="UserSettingAttribute"/>, this attribute is valid for instance properties as well as static. These values
|
||||
/// don't appear in the SettingsProvider. Unity clears their stored values when "Reset All" is invoked.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public sealed class SettingsKeyAttribute : Attribute
|
||||
{
|
||||
string m_Key;
|
||||
SettingsScope m_Scope;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the key for this value.
|
||||
/// </summary>
|
||||
/// <value>The key used to identify this settings value from the repository.</value>
|
||||
public string key
|
||||
{
|
||||
get { return m_Key; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the location where this setting is serialized.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Indicates whether this is a <see cref="UnityEditor.SettingsScope.Project"/> setting
|
||||
/// or a <see cref="UnityEditor.SettingsScope.User"/> preference.
|
||||
/// </value>
|
||||
public SettingsScope scope
|
||||
{
|
||||
get { return m_Scope; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a field as a setting. This allows the <see cref="UserSettingsProvider"/> to reset its value and display it
|
||||
/// in debugging modes.
|
||||
/// </summary>
|
||||
/// <param name="key">The key for this setting.</param>
|
||||
/// <param name="scope">The scope in which this setting is serialized.</param>
|
||||
public SettingsKeyAttribute(string key, SettingsScope scope = SettingsScope.Project)
|
||||
{
|
||||
m_Key = key;
|
||||
m_Scope = scope;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A custom attribute for adding a section of settings to a category.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public sealed class UserSettingBlockAttribute : Attribute
|
||||
{
|
||||
string m_Category;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the title for the settings group.
|
||||
/// When Unity finds settings values in assemblies, it displays them in groups, organized by category.
|
||||
/// </summary>
|
||||
/// <value>The group or category where this setting appears in the UI.</value>
|
||||
public string category
|
||||
{
|
||||
get { return m_Category; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a static method for a callback in the <see cref="UserSettingsProvider"/> Editor window under a category.
|
||||
/// <code><![CDATA[
|
||||
/// [UserSettingBlock("General")]
|
||||
/// static void GeneralSettings(string[] searchContext) {}
|
||||
/// ]]></code>
|
||||
/// </summary>
|
||||
/// <param name="category">Specify the title of the group of settings under which this setting appears in the UI.</param>
|
||||
public UserSettingBlockAttribute(string category)
|
||||
{
|
||||
m_Category = category;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ea67431821494cfca380c0e07258751
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,215 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.SettingsManagement
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a settings repository that stores data serialized to a JSON file.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class FileSettingsRepository : ISettingsRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// Location of where the package settings are saved under the `ProjectSettings` directory.
|
||||
/// </summary>
|
||||
/// <returns>The folder where package settings are saved under the `ProjectSettings` directory.</returns>
|
||||
protected const string k_PackageSettingsDirectory = "ProjectSettings/Packages";
|
||||
|
||||
/// <summary>
|
||||
/// Location of where the package settings are saved under the `UserSettings` directory.
|
||||
/// </summary>
|
||||
/// <returns>Per-project user settings directory. </returns>
|
||||
protected const string k_UserProjectSettingsDirectory = "UserSettings/Packages";
|
||||
|
||||
const bool k_PrettyPrintJson = true;
|
||||
|
||||
bool m_Initialized;
|
||||
string m_Path;
|
||||
[SerializeField]
|
||||
SettingsDictionary m_Dictionary = new SettingsDictionary();
|
||||
Hash128 m_JsonHash;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes and returns an instance of the FileSettingsRepository
|
||||
/// with the serialized data location set to the specified path.
|
||||
/// </summary>
|
||||
/// <param name="path">The project-relative path to save settings to.</param>
|
||||
public FileSettingsRepository(string path)
|
||||
{
|
||||
m_Path = path;
|
||||
m_Initialized = false;
|
||||
AssemblyReloadEvents.beforeAssemblyReload += Save;
|
||||
EditorApplication.quitting += Save;
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
if (m_Initialized)
|
||||
return;
|
||||
|
||||
m_Initialized = true;
|
||||
|
||||
if (TryLoadSavedJson(out string json))
|
||||
{
|
||||
m_Dictionary = null;
|
||||
m_JsonHash = Hash128.Compute(json);
|
||||
EditorJsonUtility.FromJsonOverwrite(json, this);
|
||||
}
|
||||
|
||||
if (m_Dictionary == null)
|
||||
m_Dictionary = new SettingsDictionary();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="SettingsScope"/> this repository applies to.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default, this repository implementation is relevant to the Project scope, but any implementations
|
||||
/// that override this method can choose to store this serialized data at a user scope instead.
|
||||
/// </remarks>
|
||||
/// <value>
|
||||
/// <see cref="SettingsScope.Project"/>, meaning that this setting applies to project settings (the default);
|
||||
/// or <see cref="SettingsScope.User"/>, meaning that this setting applies to user preferences.
|
||||
/// </value>
|
||||
/// <seealso cref="ISettingsRepository.scope"/>
|
||||
public virtual SettingsScope scope => SettingsScope.Project;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full path to the file containing the serialized settings data.
|
||||
/// </summary>
|
||||
/// <value>The location stored for this repository.</value>
|
||||
/// <seealso cref="ISettingsRepository.path"/>
|
||||
public string path
|
||||
{
|
||||
get { return m_Path; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the name of file containing the serialized settings data.
|
||||
/// </summary>
|
||||
/// <value>The bare filename of the settings file.</value>
|
||||
public string name => Path.GetFileNameWithoutExtension(path);
|
||||
|
||||
/// <summary>
|
||||
/// Loads the JSON file that stores the values for this settings object.
|
||||
/// </summary>
|
||||
/// <param name="json">The full path to the JSON file to load.</param>
|
||||
/// <returns>True if the file exists; false if it doesn't.</returns>
|
||||
public bool TryLoadSavedJson(out string json)
|
||||
{
|
||||
json = string.Empty;
|
||||
if (!File.Exists(path))
|
||||
return false;
|
||||
json = File.ReadAllText(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves all settings to their serialized state.
|
||||
/// </summary>
|
||||
/// <seealso cref="ISettingsRepository.Save"/>
|
||||
public void Save()
|
||||
{
|
||||
Init();
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
var directory = Path.GetDirectoryName(path);
|
||||
|
||||
if (string.IsNullOrEmpty(directory))
|
||||
{
|
||||
Debug.LogError(
|
||||
$"Settings file {name} is saved to an invalid path: {path}. Settings will not be saved.");
|
||||
return;
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
string json = EditorJsonUtility.ToJson(this, k_PrettyPrintJson);
|
||||
|
||||
// While unlikely, a hash collision is possible. Always test the actual saved contents before early exit.
|
||||
if (m_JsonHash == Hash128.Compute(json)
|
||||
&& TryLoadSavedJson(out string existing)
|
||||
&& existing.Equals(json))
|
||||
return;
|
||||
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
// AssetDatabase.IsOpenForEdit can be a very slow synchronous blocking call when Unity is connected to
|
||||
// Perforce Version Control. Especially if it's called repeatedly with every EditorGUI redraw.
|
||||
if (File.Exists(path) && !AssetDatabase.IsOpenForEdit(path))
|
||||
{
|
||||
if (!AssetDatabase.MakeEditable(path))
|
||||
{
|
||||
Debug.LogWarning($"Could not save package settings to {path}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
m_JsonHash = Hash128.Compute(json);
|
||||
File.WriteAllText(path, json);
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
Debug.LogWarning($"Could not save package settings to {path}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a value for a settings entry with a matching key and type `T`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <param name="value">The value to set. This value must be serializable.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
/// <seealso cref="ISettingsRepository.Set{T}"/>
|
||||
public void Set<T>(string key, T value)
|
||||
{
|
||||
Init();
|
||||
m_Dictionary.Set<T>(key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value with key of type `T`, or the fallback value if no matching key is found.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <param name="fallback">Specify the value of type `T` to return if the entry can't be found.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
/// <returns>The settings value if a match is found; otherwise, it returns the default (fallback) value.</returns>
|
||||
/// <seealso cref="ISettingsRepository.Get{T}"/>
|
||||
public T Get<T>(string key, T fallback = default(T))
|
||||
{
|
||||
Init();
|
||||
return m_Dictionary.Get<T>(key, fallback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this repository contains a settings entry that matches the specified key and is of type `T`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
/// <returns>True if a match is found for both key and type; false if no entry is found.</returns>
|
||||
/// <seealso cref="ISettingsRepository.ContainsKey{T}"/>
|
||||
public bool ContainsKey<T>(string key)
|
||||
{
|
||||
Init();
|
||||
return m_Dictionary.ContainsKey<T>(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a key-value pair from the settings repository. This method identifies the settings entry to remove
|
||||
/// by matching the specified key for a value of type `T`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
/// <seealso cref="ISettingsRepository.Remove{T}"/>
|
||||
public void Remove<T>(string key)
|
||||
{
|
||||
Init();
|
||||
m_Dictionary.Remove<T>(key);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0846ad73a5274e88951b2645bf7dac6c
|
||||
timeCreated: 1604852136
|
@@ -0,0 +1,67 @@
|
||||
namespace UnityEditor.SettingsManagement
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface that represents a settings repository, which is responsible for implementing the saving and loading of values.
|
||||
/// </summary>
|
||||
public interface ISettingsRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// Implement this property to get the <see cref="SettingsScope"/> this repository applies to.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Indicates whether this is a <see cref="UnityEditor.SettingsScope.Project"/> setting
|
||||
/// or a <see cref="UnityEditor.SettingsScope.User"/> preference.
|
||||
/// </value>
|
||||
SettingsScope scope { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Implement this property to get the name to identify this repository.
|
||||
/// </summary>
|
||||
/// <value>The bare filename of this repository.</value>
|
||||
string name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Implement this property to get the file path to the serialized settings data.
|
||||
/// </summary>
|
||||
/// <value>Full path to the JSON file containing the settings data.</value>
|
||||
string path { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Implement this method to save all settings to their serialized state.
|
||||
/// </summary>
|
||||
void Save();
|
||||
|
||||
/// <summary>
|
||||
/// Implement this method to set a value for a settings entry with a matching key and type `T`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <param name="value">The value to set. Must be serializable.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
void Set<T>(string key, T value);
|
||||
|
||||
/// <summary>
|
||||
/// Implement this method to get a value for a settings entry with a matching key and type `T`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <param name="fallback">Specify the value of type `T` to return if the entry can't be found.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
/// <returns>The value matching both `key` and type `T`. If there was no match, this returns the `fallback` value.</returns>
|
||||
T Get<T>(string key, T fallback = default(T));
|
||||
|
||||
/// <summary>
|
||||
/// Implement this method to evaluate whether the repository contains a settings entry that matches the specified key and is of type `T`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
/// <returns>True if a settings entry matches both `key` and type `T`; false if no entry is found.</returns>
|
||||
bool ContainsKey<T>(string key);
|
||||
|
||||
/// <summary>
|
||||
/// Implement this method to remove a key-value pair from the settings repository. This method identifies the settings entry to remove
|
||||
/// by matching the specified key for a value of type `T`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
void Remove<T>(string key);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8707cf6fb25b1438b9a0f476f93a76fe
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
|
||||
namespace UnityEditor.SettingsManagement
|
||||
{
|
||||
/// <summary>
|
||||
/// A settings repository that stores data local to a Unity project relative to a package.
|
||||
/// The settings data is serialized to a JSON file.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public sealed class PackageSettingsRepository : FileSettingsRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes and returns an instance of the PackageSettingsRepository with the
|
||||
/// serialized data location set to a path defined by the specified `package` and
|
||||
/// `name` values relative to the `ProjectSettings` directory. For example:
|
||||
/// `MyUnityProject/ProjectSettings/Packages/com.example.my-package/Settings.json`.
|
||||
/// </summary>
|
||||
/// <param name="package">The name of the package to store the serialized data under.</param>
|
||||
/// <param name="name">The base filename to use for the serialized data location.</param>
|
||||
public PackageSettingsRepository(string package, string name) : base(GetSettingsPath(package, 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);
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Builds and returns a path for a settings file relative to the calling assembly's package directory.
|
||||
/// This method constructs the location from the specified `package` and (filename) `name` under the `ProjectSettings` folder.
|
||||
/// </summary>
|
||||
/// <param name="packageName">The name of the package requesting this setting.</param>
|
||||
/// <param name="name">An optional name for the settings file. Default is "Settings."</param>
|
||||
/// <returns>A package-scoped path to the settings file inside the project's `ProjectSettings`.</returns>
|
||||
public static string GetSettingsPath(string packageName, string name = "Settings")
|
||||
{
|
||||
return string.Format("{0}/{1}/{2}.json", k_PackageSettingsDirectory, packageName, name);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8e2e054ed623847d29efb1262605e8ef
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
|
||||
namespace UnityEditor.SettingsManagement
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a settings repository that stores data local to a Unity project.
|
||||
/// The settings data is serialized to a JSON file.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class ProjectUserSettings : FileSettingsRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes and returns an instance of the ProjectUserSettings repository with the
|
||||
/// serialized data location set to a path defined by the specified `package` and
|
||||
/// `name` values relative to the `UserSettings` directory. For example:
|
||||
/// `MyUnityProject/UserSettings/Packages/com.example.my-package/Settings.json`.
|
||||
/// </summary>
|
||||
/// <param name="package">The name of the package to store the serialized data under.</param>
|
||||
/// <param name="name">The base filename to use for the serialized data location (defaults to "Settings").</param>
|
||||
public ProjectUserSettings(string package, string name = "Settings") : base(GetUserSettingsPath(package, name))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds and returns a path for a settings file relative to the calling assembly's package directory.
|
||||
/// This method constructs the location from the specified `package` and (filename) `name` under the `UserSettings` folder.
|
||||
/// </summary>
|
||||
/// <param name="package">The name of the package requesting this setting.</param>
|
||||
/// <param name="name">An optional name for the settings file. Default is "Settings."</param>
|
||||
/// <returns>A package-scoped path to the settings file inside the project's `UserSettings` folder.</returns>
|
||||
public static string GetUserSettingsPath(string package, string name)
|
||||
{
|
||||
return string.Format("{0}/{1}/{2}.json", k_UserProjectSettingsDirectory, package, name);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 30e7b5764902497297f0c9ca80bb179a
|
||||
timeCreated: 1604851389
|
@@ -0,0 +1,311 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.SettingsManagement
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a collection of objects that implement <see cref="ISettingsRepository"/>.
|
||||
/// </summary>
|
||||
public sealed class Settings
|
||||
{
|
||||
ISettingsRepository[] m_SettingsRepositories;
|
||||
|
||||
/// <summary>
|
||||
/// Called prior to when an instance of <see cref="ISettingsRepository"/> serializes its current state.
|
||||
/// </summary>
|
||||
public event Action beforeSettingsSaved;
|
||||
|
||||
/// <summary>
|
||||
/// Called immediately after an instance of <see cref="ISettingsRepository"/> serializes its current state.
|
||||
/// </summary>
|
||||
public event Action afterSettingsSaved;
|
||||
|
||||
Settings()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new Settings instance with a <see cref="UserSettingsRepository"/> and <see cref="PackageSettingsRepository"/>.
|
||||
/// </summary>
|
||||
/// <param name="package">The package name, such as `com.example.my-package`.</param>
|
||||
/// <param name="settingsFileName">The name of the settings file. The default value is `Settings`.</param>
|
||||
public Settings(string package, string settingsFileName = "Settings")
|
||||
{
|
||||
m_SettingsRepositories = new ISettingsRepository[]
|
||||
{
|
||||
new PackageSettingsRepository(package, settingsFileName),
|
||||
new UserSettingsRepository()
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new Settings instance with a collection of objects that implement <see cref="ISettingsRepository"/>.
|
||||
/// </summary>
|
||||
/// <param name="repositories">The repositories to populate the Settings instance with.</param>
|
||||
public Settings(IEnumerable<ISettingsRepository> repositories)
|
||||
{
|
||||
m_SettingsRepositories = repositories.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds and returns a settings repository that matches the specified scope.
|
||||
/// </summary>
|
||||
/// <param name="scope">The <see cref="SettingsScope">scope</see> of the settings repository to match.</param>
|
||||
/// <returns>
|
||||
/// An <see cref="ISettingsRepository"/> instance that implements the requested scope; or null if no
|
||||
/// matching repository is found.
|
||||
/// </returns>
|
||||
public ISettingsRepository GetRepository(SettingsScope scope)
|
||||
{
|
||||
foreach (var repo in m_SettingsRepositories)
|
||||
if (repo.scope == scope)
|
||||
return repo;
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds and returns a settings repository that matches the specified scope and name.
|
||||
/// </summary>
|
||||
/// <param name="scope">The <see cref="SettingsScope">scope</see> of the settings repository to match.</param>
|
||||
/// <param name="name">The name of the <see cref="ISettingsRepository"/> to match.</param>
|
||||
/// <returns>
|
||||
/// An <see cref="ISettingsRepository"/> instance that implements the specified scope and matches the name; or
|
||||
/// null if no matching repository is found.
|
||||
/// </returns>
|
||||
public ISettingsRepository GetRepository(SettingsScope scope, string name)
|
||||
{
|
||||
foreach (var repo in m_SettingsRepositories)
|
||||
if (repo.scope == scope && string.Equals(repo.name, name))
|
||||
return repo;
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the state of all settings repositories.
|
||||
/// </summary>
|
||||
public void Save()
|
||||
{
|
||||
if (beforeSettingsSaved != null)
|
||||
beforeSettingsSaved();
|
||||
|
||||
foreach (var repo in m_SettingsRepositories)
|
||||
repo.Save();
|
||||
|
||||
if (afterSettingsSaved != null)
|
||||
afterSettingsSaved();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a value for a settings entry with a matching key and type `T`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <param name="value">The value to set. This must be serializable.</param>
|
||||
/// <param name="scope">The <see cref="SettingsScope">scope</see> of the settings repository to match.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
public void Set<T>(string key, T value, SettingsScope scope = SettingsScope.Project)
|
||||
{
|
||||
if (scope == SettingsScope.Project)
|
||||
Set<T, PackageSettingsRepository>(key, value);
|
||||
Set<T, UserSettingsRepository>(key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a value for a settings entry with a matching key and type `T` from the specified repository.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <param name="value">The value to set. This must be serializable.</param>
|
||||
/// <param name="repositoryName">Optional. The name of the repository to set this value in.</param>
|
||||
/// <param name="scope">The <see cref="SettingsScope">scope</see> of the settings repository to match.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
public void Set<T>(string key, T value, string repositoryName, SettingsScope scope = SettingsScope.Project)
|
||||
{
|
||||
if (scope == SettingsScope.Project)
|
||||
Set<T, PackageSettingsRepository>(key, value, repositoryName);
|
||||
Set<T, UserSettingsRepository>(key, value, repositoryName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a value for a settings entry with a matching key and type `T` from the specified repository of type `K`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <param name="value">The value to set. This must be serializable.</param>
|
||||
/// <param name="repositoryName">Optional. The name of the repository to set this value in.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
/// <typeparam name="K">The type of repository to search for matching keys.</typeparam>
|
||||
public void Set<T, K>(string key, T value, string repositoryName = null) where K : ISettingsRepository
|
||||
{
|
||||
bool foundScopeRepository = false;
|
||||
|
||||
foreach (var repo in m_SettingsRepositories)
|
||||
{
|
||||
if (repo is K && (string.IsNullOrEmpty(repositoryName) || repo.name == repositoryName))
|
||||
{
|
||||
repo.Set<T>(key, value);
|
||||
foundScopeRepository = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundScopeRepository)
|
||||
Debug.LogWarning($"No repository with type {typeof(K)} found.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value for a settings entry with a matching key and type `T`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <param name="scope">The <see cref="SettingsScope">scope</see> of the settings repository to match.</param>
|
||||
/// <param name="fallback">Specify the value of type `T` to return if the entry can't be found.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
/// <returns>The value from a matching settings entry; or the default value if not found.</returns>
|
||||
public T Get<T>(string key, SettingsScope scope = SettingsScope.Project, T fallback = default(T))
|
||||
{
|
||||
if (scope == SettingsScope.Project)
|
||||
return Get<T, PackageSettingsRepository>(key, fallback);
|
||||
return Get<T, UserSettingsRepository>(key, fallback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value for a settings entry with a matching key and type `T`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <param name="repositoryName">The repository name to match.</param>
|
||||
/// <param name="scope">The <see cref="SettingsScope">scope</see> of the settings repository to match.</param>
|
||||
/// <param name="fallback">Specify the value of type `T` to return if the entry can't be found.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
/// <returns>The value from a matching settings entry; or the default value if not found.</returns>
|
||||
public T Get<T>(string key, string repositoryName, SettingsScope scope = SettingsScope.Project, T fallback = default(T))
|
||||
{
|
||||
if (scope == SettingsScope.Project)
|
||||
return Get<T, PackageSettingsRepository>(key, fallback, repositoryName);
|
||||
return Get<T, UserSettingsRepository>(key, fallback, repositoryName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value for a settings entry with a matching key and type `T` from the specified repository of type `K`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <param name="fallback">Specify the value of type `T` to return if the entry can't be found.</param>
|
||||
/// <param name="repositoryName">If provided, only repositories with a matching name will be searched for the key.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
/// <typeparam name="K">The type of repository to search for matching keys.</typeparam>
|
||||
/// <returns>The value from a matching settings entry; or the default value if not found.</returns>
|
||||
public T Get<T, K>(string key, T fallback = default(T), string repositoryName = null) where K : ISettingsRepository
|
||||
{
|
||||
foreach (var repo in m_SettingsRepositories)
|
||||
{
|
||||
if (repo is K && (string.IsNullOrEmpty(repositoryName) || repo.name == repositoryName))
|
||||
return repo.Get<T>(key, fallback);
|
||||
}
|
||||
|
||||
Debug.LogWarning($"No repository with type {typeof(K)} found.");
|
||||
return fallback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the repository in the specified <see cref="SettingsScope">scope</see> contains a settings entry
|
||||
/// that matches the specified key and is of type `T`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <param name="scope">The <see cref="SettingsScope">scope</see> of the settings repository to match.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
/// <returns>True if a setting matching both key and type is found; false if no entry is found.</returns>
|
||||
public bool ContainsKey<T>(string key, SettingsScope scope = SettingsScope.Project)
|
||||
{
|
||||
if (scope == SettingsScope.Project)
|
||||
return ContainsKey<T, PackageSettingsRepository>(key);
|
||||
return ContainsKey<T, UserSettingsRepository>(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified repository contains a settings entry that matches the specified key and is of type `T`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <param name="repositoryName">The repository name to match.</param>
|
||||
/// <param name="scope">The <see cref="SettingsScope">scope</see> of the settings repository to match.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
/// <returns>True if a setting matching both key and type is found; false if no entry is found.</returns>
|
||||
public bool ContainsKey<T>(string key, string repositoryName, SettingsScope scope = SettingsScope.Project)
|
||||
{
|
||||
if (scope == SettingsScope.Project)
|
||||
return ContainsKey<T, PackageSettingsRepository>(key, repositoryName);
|
||||
return ContainsKey<T, UserSettingsRepository>(key, repositoryName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified repository of type `K` contains a settings entry that matches the specified key and is of type `T`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <param name="repositoryName">The repository name to match.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
/// <typeparam name="K">The type of repository to search for matching keys.</typeparam>
|
||||
/// <returns>True if a setting matching both key and type is found; false if no entry is found.</returns>
|
||||
public bool ContainsKey<T, K>(string key, string repositoryName = null) where K : ISettingsRepository
|
||||
{
|
||||
foreach (var repo in m_SettingsRepositories)
|
||||
{
|
||||
if (repo is K && (string.IsNullOrEmpty(repositoryName) || repositoryName == repo.name))
|
||||
return repo.ContainsKey<T>(key);
|
||||
}
|
||||
|
||||
Debug.LogWarning($"No repository with type {typeof(K)} found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a key-value pair from a settings repository. This method identifies the settings entry to remove
|
||||
/// from any repository in the specified <see cref="SettingsScope">scope</see> by matching the specified key
|
||||
/// for a value of type `T`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <param name="scope">The <see cref="SettingsScope">scope</see> of the settings repository to match.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
public void DeleteKey<T>(string key, SettingsScope scope = SettingsScope.Project)
|
||||
{
|
||||
if (scope == SettingsScope.Project)
|
||||
DeleteKey<T, PackageSettingsRepository>(key);
|
||||
DeleteKey<T, UserSettingsRepository>(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a key-value pair from a settings repository. This method identifies the settings entry to remove
|
||||
/// from the specified repository by matching the specified key for a value of type `T`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <param name="repositoryName">The repository name to match.</param>
|
||||
/// <param name="scope">The <see cref="SettingsScope">scope</see> of the settings repository to match.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
public void DeleteKey<T>(string key, string repositoryName, SettingsScope scope = SettingsScope.Project)
|
||||
{
|
||||
if (scope == SettingsScope.Project)
|
||||
DeleteKey<T, PackageSettingsRepository>(key, repositoryName);
|
||||
DeleteKey<T, UserSettingsRepository>(key, repositoryName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a key-value pair from a settings repository. This method identifies the settings entry to remove
|
||||
/// from the specified repository of type `K` by matching the specified key for a value of type `T`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <param name="repositoryName">The repository name to match.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
/// <typeparam name="K">The type of repository to search for matching keys.</typeparam>
|
||||
public void DeleteKey<T, K>(string key, string repositoryName = null) where K : ISettingsRepository
|
||||
{
|
||||
bool foundScopeRepository = false;
|
||||
|
||||
foreach (var repo in m_SettingsRepositories)
|
||||
{
|
||||
if (repo is K && (string.IsNullOrEmpty(repositoryName) || repositoryName == repo.name))
|
||||
{
|
||||
foundScopeRepository = true;
|
||||
repo.Remove<T>(key);
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundScopeRepository)
|
||||
Debug.LogWarning($"No repository with type {typeof(K)} found.");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d3c815396f3a64c2d925a2100e08e093
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,151 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.SettingsManagement
|
||||
{
|
||||
[Serializable]
|
||||
sealed class SettingsDictionary : ISerializationCallbackReceiver
|
||||
{
|
||||
[Serializable]
|
||||
struct SettingsKeyValuePair
|
||||
{
|
||||
public string type;
|
||||
public string key;
|
||||
public string value;
|
||||
}
|
||||
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
List<SettingsKeyValuePair> m_DictionaryValues = new List<SettingsKeyValuePair>();
|
||||
#pragma warning restore 0649
|
||||
|
||||
internal Dictionary<Type, Dictionary<string, string>> dictionary = new Dictionary<Type, Dictionary<string, string>>();
|
||||
|
||||
public bool ContainsKey<T>(string key)
|
||||
{
|
||||
return dictionary.ContainsKey(typeof(T)) && dictionary[typeof(T)].ContainsKey(key);
|
||||
}
|
||||
|
||||
public void Set<T>(string key, T value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(key))
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
var type = typeof(T).AssemblyQualifiedName;
|
||||
|
||||
SetJson(type, key, ValueWrapper<T>.Serialize(value));
|
||||
}
|
||||
|
||||
internal void SetJson(string type, string key, string value)
|
||||
{
|
||||
var typeValue = Type.GetType(type);
|
||||
|
||||
if (typeValue == null)
|
||||
throw new ArgumentException("\"type\" must be an assembly qualified type name.");
|
||||
|
||||
Dictionary<string, string> entries;
|
||||
|
||||
if (!dictionary.TryGetValue(typeValue, out entries))
|
||||
dictionary.Add(typeValue, entries = new Dictionary<string, string>());
|
||||
|
||||
if (entries.ContainsKey(key))
|
||||
entries[key] = value;
|
||||
else
|
||||
entries.Add(key, value);
|
||||
}
|
||||
|
||||
public T Get<T>(string key, T fallback = default(T))
|
||||
{
|
||||
if (string.IsNullOrEmpty(key))
|
||||
throw new ArgumentNullException("key");
|
||||
|
||||
Dictionary<string, string> entries;
|
||||
|
||||
if (dictionary.TryGetValue(typeof(T), out entries) && entries.ContainsKey(key))
|
||||
{
|
||||
try
|
||||
{
|
||||
return ValueWrapper<T>.Deserialize(entries[key]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
return fallback;
|
||||
}
|
||||
|
||||
public void Remove<T>(string key)
|
||||
{
|
||||
Dictionary<string, string> entries;
|
||||
|
||||
if (!dictionary.TryGetValue(typeof(T), out entries) || !entries.ContainsKey(key))
|
||||
return;
|
||||
|
||||
entries.Remove(key);
|
||||
}
|
||||
|
||||
public void OnBeforeSerialize()
|
||||
{
|
||||
if (m_DictionaryValues == null)
|
||||
return;
|
||||
|
||||
m_DictionaryValues.Clear();
|
||||
|
||||
foreach (var type in dictionary)
|
||||
{
|
||||
foreach (var entry in type.Value)
|
||||
{
|
||||
m_DictionaryValues.Add(new SettingsKeyValuePair()
|
||||
{
|
||||
type = type.Key.AssemblyQualifiedName,
|
||||
key = entry.Key,
|
||||
value = entry.Value
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnAfterDeserialize()
|
||||
{
|
||||
dictionary.Clear();
|
||||
|
||||
foreach (var entry in m_DictionaryValues)
|
||||
{
|
||||
Dictionary<string, string> entries;
|
||||
|
||||
var type = Type.GetType(entry.type);
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
Debug.LogWarning("Could not instantiate type \"" + entry.type + "\". Skipping key: " + entry.key + ".");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dictionary.TryGetValue(type, out entries))
|
||||
entries.Add(entry.key, entry.value);
|
||||
else
|
||||
dictionary.Add(type, new Dictionary<string, string>() { { entry.key, entry.value } });
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new System.Text.StringBuilder();
|
||||
|
||||
foreach (var type in dictionary)
|
||||
{
|
||||
sb.AppendLine("Type: " + type.Key);
|
||||
|
||||
foreach (var entry in type.Value)
|
||||
{
|
||||
sb.AppendLine(string.Format(" {0,-64}{1}", entry.Key, entry.Value));
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67c0fca06520e4f78923163f9541ba6c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 223e1a5330ab8468782152a65e857f94
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "Unity.Settings.Editor",
|
||||
"references": [],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": []
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 49818357e697641afb75d2f8acaf1861
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,397 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.SettingsManagement
|
||||
{
|
||||
[Flags]
|
||||
enum SettingVisibility
|
||||
{
|
||||
None = 0 << 0,
|
||||
|
||||
/// <summary>
|
||||
/// Matches any static field implementing IUserSetting and tagged with [UserSettingAttribute(visibleInSettingsProvider = true)].
|
||||
/// These fields are automatically scraped by the SettingsProvider and displayed.
|
||||
/// </summary>
|
||||
Visible = 1 << 0,
|
||||
|
||||
/// <summary>
|
||||
/// 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].
|
||||
/// </summary>
|
||||
Hidden = 1 << 1,
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
Unlisted = 1 << 2,
|
||||
|
||||
/// <summary>
|
||||
/// A static field implementing IUserSetting that is not marked with any setting attribute.
|
||||
/// Unregistered IUserSetting fields are not affected by the SettingsProvider.
|
||||
/// </summary>
|
||||
Unregistered = 1 << 3,
|
||||
|
||||
All = Visible | Hidden | Unlisted | Unregistered
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An interface that represents a user setting.
|
||||
/// Types implementing IUserSetting are eligible for use with <see cref="UserSettingAttribute"/>, which enables
|
||||
/// fields to automatically populate the <see cref="UserSettingsProvider"/> interface.
|
||||
/// </summary>
|
||||
public interface IUserSetting
|
||||
{
|
||||
/// <summary>
|
||||
/// Implement this property to get the key for this value.
|
||||
/// </summary>
|
||||
/// <value>The key used to identify the settings entry. This is used along with the <see cref="type"/> to uniquely identify the value.</value>
|
||||
string key { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Implement this property to get the type of the stored value.
|
||||
/// </summary>
|
||||
/// <value>The type of value. This is used along with the <see cref="key"/> to uniquely identify the value.</value>
|
||||
Type type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Implement this property to get the location in the UI where this setting will appear.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// Indicates whether this is a <see cref="UnityEditor.SettingsScope.Project"/> setting
|
||||
/// or a <see cref="UnityEditor.SettingsScope.User"/> preference.
|
||||
/// </value>
|
||||
SettingsScope scope { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Implement this property to get the name of the <see cref="ISettingsRepository"/> that this setting should be associated with.
|
||||
/// If null, the first repository matching the <see cref="scope"/> is used.
|
||||
/// </summary>
|
||||
/// <value>The bare filename of this repository.</value>
|
||||
string settingsRepositoryName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Implement this property to get the <see cref="Settings"/> instance to save and load this setting from.
|
||||
/// </summary>
|
||||
/// <value>A reference to <see cref="Settings"/> instance.</value>
|
||||
Settings settings { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Implement this method to return the stored settings value.
|
||||
/// If you are implementing IUserSetting, you should cache this value.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The stored value.
|
||||
/// </returns>
|
||||
object GetValue();
|
||||
|
||||
/// <summary>
|
||||
/// Implement this method to return the the default value for this setting.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The default value for this setting.
|
||||
/// </returns>
|
||||
object GetDefaultValue();
|
||||
|
||||
/// <summary>
|
||||
/// Implement this method to set the value for this setting.
|
||||
/// </summary>
|
||||
/// <param name="value">The new value.</param>
|
||||
/// <param name="saveProjectSettingsImmediately">
|
||||
/// True to immediately serialize the <see cref="ISettingsRepository"/> that is backing this value; or false to postpone.
|
||||
/// If not serializing immediately, be sure to call <see cref="Settings.Save"/>.
|
||||
/// </param>
|
||||
void SetValue(object value, bool saveProjectSettingsImmediately = false);
|
||||
|
||||
/// <summary>
|
||||
/// Implement this method to explicitly update the <see cref="ISettingsRepository"/> 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.
|
||||
/// </summary>
|
||||
void ApplyModifiedProperties();
|
||||
|
||||
/// <summary>
|
||||
/// Implement this method to set the current value back to the default.
|
||||
/// </summary>
|
||||
/// <param name="saveProjectSettingsImmediately">True to immediately re-serialize project settings. By default, no values are updated. </param>
|
||||
void Reset(bool saveProjectSettingsImmediately = false);
|
||||
|
||||
/// <summary>
|
||||
/// Implement this method to delete the saved setting. This does not clear the current value.
|
||||
/// </summary>
|
||||
/// <seealso cref="Reset"/>
|
||||
/// <param name="saveProjectSettingsImmediately">True to immediately re-serialize project settings. By default, no values are updated.</param>
|
||||
void Delete(bool saveProjectSettingsImmediately = false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A generic implementation of <see cref="IUserSetting"/> to use with a <see cref="Settings"/> instance. This default
|
||||
/// implementation assumes that the <see cref="Settings"/> instance contains two <see cref="ISettingsRepository"/> interfaces:
|
||||
/// - Project settings (<see cref="SettingsScope.Project"/>)
|
||||
/// - User preferences (<see cref="SettingsScope.User"/>)
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of value.</typeparam>
|
||||
public class UserSetting<T> : IUserSetting
|
||||
{
|
||||
bool m_Initialized;
|
||||
string m_Key;
|
||||
string m_Repository;
|
||||
T m_Value;
|
||||
T m_DefaultValue;
|
||||
SettingsScope m_Scope;
|
||||
Settings m_Settings;
|
||||
|
||||
UserSetting() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes and returns an instance of the UserSetting<T> type.
|
||||
/// </summary>
|
||||
/// <param name="settings">The <see cref="Settings"/> instance to save and load this setting from.</param>
|
||||
/// <param name="key">The key for this value.</param>
|
||||
/// <param name="value">The default value for this key.</param>
|
||||
/// <param name="scope">The scope for this setting. By default, the scope is the project.</param>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes and returns an instance of the UserSetting<T> type using the specified repository.
|
||||
/// </summary>
|
||||
/// <param name="settings">The <see cref="Settings"/> instance to save and load this setting from.</param>
|
||||
/// <param name="repository">The <see cref="ISettingsRepository"/> name to save and load this setting from. Specify null to save to the first available instance.</param>
|
||||
/// <param name="key">The key for this value.</param>
|
||||
/// <param name="value">The default value for this key.</param>
|
||||
/// <param name="scope">The scope for this setting. By default, the scope is the project.</param>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the key for this value.
|
||||
/// </summary>
|
||||
/// <seealso cref="IUserSetting.key"/>
|
||||
public string key
|
||||
{
|
||||
get { return m_Key; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the repository that this setting is saved in.
|
||||
/// </summary>
|
||||
/// <seealso cref="IUserSetting.settingsRepositoryName" />
|
||||
public string settingsRepositoryName
|
||||
{
|
||||
get { return m_Repository; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type that this setting represents (<T>).
|
||||
/// </summary>
|
||||
/// <seealso cref="IUserSetting.type" />
|
||||
public Type type
|
||||
{
|
||||
get { return typeof(T); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a copy of the default value.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The default value.
|
||||
/// </returns>
|
||||
/// <seealso cref="IUserSetting.GetDefaultValue" />
|
||||
public object GetDefaultValue()
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the currently stored value.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The value that is currently set.
|
||||
/// </returns>
|
||||
/// <seealso cref="IUserSetting.GetValue" />
|
||||
public object GetValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the scope (<see cref="ISettingsRepository"/>) where the <see cref="Settings"/> instance saves
|
||||
/// its data.
|
||||
/// </summary>
|
||||
/// <seealso cref="IUserSetting.scope" />
|
||||
public SettingsScope scope
|
||||
{
|
||||
get { return m_Scope; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Settings"/> instance to read from and save to.
|
||||
/// </summary>
|
||||
/// <seealso cref="IUserSetting.settings" />
|
||||
public Settings settings
|
||||
{
|
||||
get { return m_Settings; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value for this setting from the specified object.
|
||||
/// </summary>
|
||||
/// <param name="value">The new value to set.</param>
|
||||
/// <param name="saveProjectSettingsImmediately">
|
||||
/// Set this value to true if you want to immediately serialize the <see cref="ISettingsRepository"/>
|
||||
/// that is backing this value. By default, this is false.
|
||||
///
|
||||
/// **Note**: If not serializing immediately, you need to call <see cref="Settings.Save"/>.
|
||||
/// </param>
|
||||
/// <seealso cref="IUserSetting.SetValue" />
|
||||
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);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="SetValue" />
|
||||
public void SetValue(T value, bool saveProjectSettingsImmediately = false)
|
||||
{
|
||||
Init();
|
||||
m_Value = value;
|
||||
settings.Set<T>(key, m_Value, m_Scope);
|
||||
|
||||
if (saveProjectSettingsImmediately)
|
||||
settings.Save();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the saved setting but doesn't clear the current value.
|
||||
/// </summary>
|
||||
/// <param name="saveProjectSettingsImmediately">
|
||||
/// Set this value to true if you want to immediately serialize the <see cref="ISettingsRepository"/>
|
||||
/// that is backing this value. By default, this is false.
|
||||
///
|
||||
/// **Note**: If not serializing immediately, you need to call <see cref="Settings.Save"/>.
|
||||
/// </param>
|
||||
/// <seealso cref="Reset" />
|
||||
/// <seealso cref="IUserSetting.Delete"/>
|
||||
public void Delete(bool saveProjectSettingsImmediately = false)
|
||||
{
|
||||
settings.DeleteKey<T>(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<T>.DeepCopy(m_DefaultValue);
|
||||
m_Initialized = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Forces Unity to serialize the changed properties to the <see cref="ISettingsRepository"/> that is backing this value.
|
||||
/// When the inspected type is a reference value, it is possible to change properties without affecting the
|
||||
/// backing setting.
|
||||
/// </summary>
|
||||
/// <seealso cref="IUserSetting.ApplyModifiedProperties"/>
|
||||
public void ApplyModifiedProperties()
|
||||
{
|
||||
settings.Set<T>(key, m_Value, m_Scope);
|
||||
settings.Save();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current value back to the default.
|
||||
/// </summary>
|
||||
/// <param name="saveProjectSettingsImmediately">
|
||||
/// Set this value to true if you want to immediately serialize the <see cref="ISettingsRepository"/>
|
||||
/// that is backing this value. By default, this is false.
|
||||
///
|
||||
/// **Note**: If not serializing immediately, you need to call <see cref="Settings.Save"/>.
|
||||
/// </param>
|
||||
/// <seealso cref="IUserSetting.Reset"/>
|
||||
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<T>.DeepCopy(m_Value);
|
||||
|
||||
if (settings.ContainsKey<T>(m_Key, m_Scope))
|
||||
m_Value = settings.Get<T>(m_Key, m_Scope);
|
||||
else
|
||||
settings.Set<T>(m_Key, m_Value, m_Scope);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default value for this setting.
|
||||
/// </summary>
|
||||
public T defaultValue
|
||||
{
|
||||
get
|
||||
{
|
||||
Init();
|
||||
return ValueWrapper<T>.DeepCopy(m_DefaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the currently stored value.
|
||||
/// </summary>
|
||||
public T value
|
||||
{
|
||||
get
|
||||
{
|
||||
Init();
|
||||
return m_Value;
|
||||
}
|
||||
|
||||
set { SetValue(value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implicit casts this setting to the backing type `T`.
|
||||
/// </summary>
|
||||
/// <param name="pref">The UserSetting<T> to cast to `T`.</param>
|
||||
/// <returns>
|
||||
/// The currently stored <see cref="value"/>.
|
||||
/// </returns>
|
||||
public static implicit operator T(UserSetting<T> pref)
|
||||
{
|
||||
return pref.value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string representation of this setting.
|
||||
/// </summary>
|
||||
/// <returns>A string summary of this setting of format "[scope] setting. Key: [key] Value: [value]".</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0} setting. Key: {1} Value: {2}", scope, key, value);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c3ec6d10638d94feaa03c223b6fee2cc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,141 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.SettingsManagement
|
||||
{
|
||||
/// <summary>
|
||||
/// A collection of utilities for working with settings.
|
||||
/// </summary>
|
||||
static class UserSettings
|
||||
{
|
||||
internal const string packageName = "com.unity.settings-manager";
|
||||
|
||||
internal static string GetSettingsString(IEnumerable<Assembly> assemblies, params SettingsScope[] scopes)
|
||||
{
|
||||
var settings = FindUserSettings(assemblies, SettingVisibility.All);
|
||||
if (scopes != null && scopes.Length > 0)
|
||||
settings = settings.Where(x => scopes.Contains(x.scope));
|
||||
var sb = new System.Text.StringBuilder();
|
||||
Type t = null;
|
||||
|
||||
foreach (var pref in settings.OrderBy(x => x.type.ToString()))
|
||||
{
|
||||
if (pref.type != t)
|
||||
{
|
||||
if (t != null)
|
||||
sb.AppendLine();
|
||||
t = pref.type;
|
||||
sb.AppendLine(pref.type.ToString());
|
||||
}
|
||||
|
||||
var val = pref.GetValue();
|
||||
sb.AppendLine(string.Format("{0,-4}{1,-24}{2,-64}{3}", "", pref.scope, pref.key, val != null ? val.ToString() : "null"));
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Collect all registered UserSetting and HiddenSetting attributes.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<IUserSetting> FindUserSettings(IEnumerable<Assembly> assemblies, SettingVisibility visibility, BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
|
||||
{
|
||||
var loadedTypes = assemblies.SelectMany(x => x.GetTypes());
|
||||
var loadedFields = loadedTypes.SelectMany(x => x.GetFields(flags));
|
||||
var settings = new List<IUserSetting>();
|
||||
|
||||
if ((visibility & (SettingVisibility.Visible | SettingVisibility.Unlisted)) > 0)
|
||||
{
|
||||
var attributes = loadedFields.Where(prop => Attribute.IsDefined(prop, typeof(UserSettingAttribute)));
|
||||
|
||||
foreach (var field in attributes)
|
||||
{
|
||||
var userSetting = (UserSettingAttribute)Attribute.GetCustomAttribute(field, typeof(UserSettingAttribute));
|
||||
|
||||
if (!field.IsStatic || !typeof(IUserSetting).IsAssignableFrom(field.FieldType))
|
||||
{
|
||||
Debug.LogError("[UserSetting] is only valid on static fields of a type implementing `interface IUserSetting`. \"" + field.Name + "\" (" + field.FieldType + ")\n" + field.DeclaringType);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool visible = userSetting.visibleInSettingsProvider;
|
||||
|
||||
if (visible && (visibility & SettingVisibility.Visible) == SettingVisibility.Visible)
|
||||
settings.Add((IUserSetting)field.GetValue(null));
|
||||
else if (!visible && (visibility & SettingVisibility.Hidden) == SettingVisibility.Hidden)
|
||||
settings.Add((IUserSetting)field.GetValue(null));
|
||||
}
|
||||
}
|
||||
|
||||
if ((visibility & SettingVisibility.Unlisted) == SettingVisibility.Unlisted)
|
||||
{
|
||||
var settingsKeys = loadedFields.Where(y => Attribute.IsDefined(y, typeof(SettingsKeyAttribute)));
|
||||
|
||||
foreach (var field in settingsKeys)
|
||||
{
|
||||
if (field.IsStatic)
|
||||
{
|
||||
settings.Add((IUserSetting)field.GetValue(null));
|
||||
}
|
||||
else
|
||||
{
|
||||
var settingAttribute = (SettingsKeyAttribute)Attribute.GetCustomAttribute(field, typeof(SettingsKeyAttribute));
|
||||
var pref = CreateGenericPref(settingAttribute.key, settingAttribute.scope, field);
|
||||
if (pref != null)
|
||||
settings.Add(pref);
|
||||
else
|
||||
Debug.LogWarning("Failed adding [SettingsKey] " + field.FieldType + "\"" + settingAttribute.key + "\" in " + field.DeclaringType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((visibility & SettingVisibility.Unregistered) == SettingVisibility.Unregistered)
|
||||
{
|
||||
var unregisterd = loadedFields.Where(y => typeof(IUserSetting).IsAssignableFrom(y.FieldType)
|
||||
&& !Attribute.IsDefined(y, typeof(SettingsKeyAttribute))
|
||||
&& !Attribute.IsDefined(y, typeof(UserSettingAttribute)));
|
||||
|
||||
foreach (var field in unregisterd)
|
||||
{
|
||||
if (field.IsStatic)
|
||||
{
|
||||
settings.Add((IUserSetting)field.GetValue(null));
|
||||
}
|
||||
else
|
||||
{
|
||||
#if PB_DEBUG
|
||||
Log.Warning("Found unregistered instance field: "
|
||||
+ field.FieldType
|
||||
+ " "
|
||||
+ field.Name
|
||||
+ " in " + field.DeclaringType);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
static IUserSetting CreateGenericPref(string key, SettingsScope scope, FieldInfo field)
|
||||
{
|
||||
try
|
||||
{
|
||||
var type = field.FieldType;
|
||||
if (typeof(IUserSetting).IsAssignableFrom(type) && type.IsGenericType)
|
||||
type = type.GetGenericArguments().FirstOrDefault();
|
||||
var genericPrefClass = typeof(UserSetting<>).MakeGenericType(type);
|
||||
var defaultValue = type.IsValueType ? Activator.CreateInstance(type) : null;
|
||||
return (IUserSetting)Activator.CreateInstance(genericPrefClass, new object[] { key, defaultValue, scope });
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c24f57f3f3c554e51ab791526e33e337
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0dc75b34a006d47f48c004031e6ef14d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,141 @@
|
||||
namespace UnityEditor.SettingsManagement
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a settings repository for user preferences.
|
||||
/// </summary>
|
||||
/// <seealso cref="UnityEditor.EditorPrefs"/>
|
||||
public class UserSettingsRepository : ISettingsRepository
|
||||
{
|
||||
static string GetEditorPrefKey<T>(string key)
|
||||
{
|
||||
return GetEditorPrefKey(typeof(T).FullName, key);
|
||||
}
|
||||
|
||||
static string GetEditorPrefKey(string fullName, string key)
|
||||
{
|
||||
return fullName + "::" + key;
|
||||
}
|
||||
|
||||
static void SetEditorPref<T>(string key, T value)
|
||||
{
|
||||
var k = GetEditorPrefKey<T>(key);
|
||||
|
||||
if (typeof(T) == typeof(string))
|
||||
EditorPrefs.SetString(k, (string)(object)value);
|
||||
else if (typeof(T) == typeof(bool))
|
||||
EditorPrefs.SetBool(k, (bool)(object)value);
|
||||
else if (typeof(T) == typeof(float))
|
||||
EditorPrefs.SetFloat(k, (float)(object)value);
|
||||
else if (typeof(T) == typeof(int))
|
||||
EditorPrefs.SetInt(k, (int)(object)value);
|
||||
else
|
||||
EditorPrefs.SetString(k, ValueWrapper<T>.Serialize(value));
|
||||
}
|
||||
|
||||
static T GetEditorPref<T>(string key, T fallback = default(T))
|
||||
{
|
||||
var k = GetEditorPrefKey<T>(key);
|
||||
|
||||
if (!EditorPrefs.HasKey(k))
|
||||
return fallback;
|
||||
|
||||
var o = (object)fallback;
|
||||
|
||||
if (typeof(T) == typeof(string))
|
||||
o = EditorPrefs.GetString(k, (string)o);
|
||||
else if (typeof(T) == typeof(bool))
|
||||
o = EditorPrefs.GetBool(k, (bool)o);
|
||||
else if (typeof(T) == typeof(float))
|
||||
o = EditorPrefs.GetFloat(k, (float)o);
|
||||
else if (typeof(T) == typeof(int))
|
||||
o = EditorPrefs.GetInt(k, (int)o);
|
||||
else
|
||||
return ValueWrapper<T>.Deserialize(EditorPrefs.GetString(k));
|
||||
|
||||
return (T)o;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="UnityEditor.SettingsScope">scope</see> this repository applies to.
|
||||
/// </summary>
|
||||
/// <value>Indicates that this is a <see cref="UnityEditor.SettingsScope.User"/> preference.</value>
|
||||
/// <seealso cref="ISettingsRepository.scope"/>
|
||||
public SettingsScope scope
|
||||
{
|
||||
get { return SettingsScope.User; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the identifying name for this repository.
|
||||
/// </summary>
|
||||
/// <value>User settings are named "EditorPrefs".</value>
|
||||
public string name
|
||||
{
|
||||
get { return "EditorPrefs"; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full path to the file containing the serialized settings data.
|
||||
/// </summary>
|
||||
/// <remarks>This property returns an empty string.</remarks>
|
||||
/// <value>The location stored for this repository.</value>
|
||||
/// <seealso cref="ISettingsRepository.path"/>
|
||||
public string path
|
||||
{
|
||||
get { return string.Empty; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves all settings to their serialized state.
|
||||
/// </summary>
|
||||
/// <seealso cref="ISettingsRepository.Save"/>
|
||||
public void Save()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a value for a settings entry with a matching key and type `T`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <param name="value">The value to set. This must be serializable.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
public void Set<T>(string key, T value)
|
||||
{
|
||||
SetEditorPref<T>(key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value for a settings entry with a matching key and type `T`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <param name="fallback">Specify the value of type `T` to return if the entry can't be found.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
/// <returns>The value matching both `key` and type `T`. If there was no match, this returns the `fallback` value.</returns>
|
||||
public T Get<T>(string key, T fallback = default(T))
|
||||
{
|
||||
return GetEditorPref<T>(key, fallback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this repository contains a settings entry that matches the specified key and is of type `T`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
/// <returns>True if a settings entry matches both `key` and type `T`; false if no entry is found.</returns>
|
||||
public bool ContainsKey<T>(string key)
|
||||
{
|
||||
return EditorPrefs.HasKey(GetEditorPrefKey<T>(key));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a key-value pair from this settings repository. This method identifies the settings entry to remove
|
||||
/// by matching the specified key for a value of type `T`.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to identify the settings entry.</param>
|
||||
/// <typeparam name="T">The type of value that this key points to.</typeparam>
|
||||
public void Remove<T>(string key)
|
||||
{
|
||||
EditorPrefs.DeleteKey(GetEditorPrefKey<T>(key));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6965211c873de4048aa9043e5e287c73
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.SettingsManagement
|
||||
{
|
||||
[Serializable]
|
||||
sealed class ValueWrapper<T>
|
||||
{
|
||||
#if PRETTY_PRINT_JSON
|
||||
const bool k_PrettyPrintJson = true;
|
||||
#else
|
||||
const bool k_PrettyPrintJson = false;
|
||||
#endif
|
||||
|
||||
[SerializeField]
|
||||
T m_Value;
|
||||
|
||||
public static string Serialize(T value)
|
||||
{
|
||||
var obj = new ValueWrapper<T>() { m_Value = value };
|
||||
return EditorJsonUtility.ToJson(obj, k_PrettyPrintJson);
|
||||
}
|
||||
|
||||
public static T Deserialize(string json)
|
||||
{
|
||||
var value = (object)Activator.CreateInstance<ValueWrapper<T>>();
|
||||
EditorJsonUtility.FromJsonOverwrite(json, value);
|
||||
return ((ValueWrapper<T>)value).m_Value;
|
||||
}
|
||||
|
||||
public static T DeepCopy(T value)
|
||||
{
|
||||
if (typeof(ValueType).IsAssignableFrom(typeof(T)))
|
||||
return value;
|
||||
var str = Serialize(value);
|
||||
return Deserialize(str);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d65bb50aabd144ed9c1a4c2bc6d072e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user