using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Bootstrap; using UnityEditor; using UnityEditor.UIElements; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.UIElements; namespace Editor.Bootstrap { /// /// Settings provider for the custom boot behaviour /// public class CustomBootSettingsProvider : SettingsProvider { /// /// Internal reference to the serialized boot settings object /// private SerializedObject customBootSettings; private CustomBootSettingsProvider(string path, SettingsScope scopes = SettingsScope.Project, IEnumerable keywords = null) : base(path, scopes, keywords) { } /// /// Initialise the UI for the settings provider /// /// /// public override void OnActivate(string searchContext, VisualElement rootElement) { customBootSettings = CustomBootSettingsUtil.GetSerializedSettings(); var styleSheet = AssetDatabase.LoadAssetAtPath("Assets/Editor/StyleSheets/CustomBootStyles.uss"); rootElement.styleSheets.Add(styleSheet); rootElement.AddToClassList("settings"); var title = new Label() { text = "Custom Boot" }; title.AddToClassList("title"); rootElement.Add(title); var properties = new VisualElement() { style = { flexDirection = FlexDirection.Column } }; properties.AddToClassList("property-list"); var runtimeProp = customBootSettings.FindProperty(nameof(CustomBootProjectSettings.RuntimeSettings)); var editorProp = customBootSettings.FindProperty(nameof(CustomBootProjectSettings.EditorSettings)); properties.Add(CreateBootSettingsEditor(runtimeProp)); properties.Add(CreateBootSettingsEditor(editorProp)); rootElement.Add(properties); rootElement.Bind(customBootSettings); } /// /// Draw an editor for the CustomBootSettings object associated with the given property /// /// /// private static VisualElement CreateBootSettingsEditor(SerializedProperty property) { var bootSettingsObject = new SerializedObject(AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath((property.boxedValue as AssetReference).AssetGUID))); var propertyEditorContainer = new VisualElement(); DrawObject(propertyEditorContainer, bootSettingsObject); return propertyEditorContainer; } /// /// Generic SerializedObject property editor /// /// /// private static void DrawObject(VisualElement container, SerializedObject o) { var l = new Label(o.targetObject.name); container.Add(l); var f = GetVisibleSerializedFields(o.targetObject.GetType()); foreach (var field in f) { var prop = o.FindProperty(field.Name); var pField = new PropertyField(prop); container.Add(pField); } container.Bind(o); } /// /// Retrieve all accessible serialised fields for the given type /// /// /// private static FieldInfo[] GetVisibleSerializedFields(Type T) { var publicFields = T.GetFields(BindingFlags.Instance | BindingFlags.Public); var infoFields = publicFields.Where(t => t.GetCustomAttribute() == null).ToList(); var privateFields = T.GetFields(BindingFlags.Instance | BindingFlags.NonPublic); infoFields.AddRange(privateFields.Where(t => t.GetCustomAttribute() != null)); return infoFields.ToArray(); } /// /// Create the Settings Provider. Internally, this will ensure the settings object is created. /// /// [SettingsProvider] public static SettingsProvider CreateCustomBootSettingsProvider() { if (!CustomBootSettingsUtil.IsSettingsAvailable()) { CustomBootSettingsUtil.GetOrCreateSettings(); } var provider = new CustomBootSettingsProvider("Project/Custom Boot", SettingsScope.Project); return provider; } } }