using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using UnityEngine; namespace UnityEditor.SettingsManagement { /// /// A collection of utilities for working with settings. /// static class UserSettings { internal const string packageName = "com.unity.settings-manager"; internal static string GetSettingsString(IEnumerable 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(); } /// /// Collect all registered UserSetting and HiddenSetting attributes. /// /// public static IEnumerable FindUserSettings(IEnumerable 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(); 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; } } } }