using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Jovian.Utilities; using UnityEngine; namespace InspectorToolkit { /// /// Finds all objects in the project of 'objectType' then creates a dropdown showing all values matching 'memberName' /// E.g. Find all 'ScriptableObject' and list their 'name' values in a list. /// public class ObjectsPropertyAttribute : PropertyAttribute { public readonly Type objectType; public readonly string memberName; public ObjectsPropertyAttribute(Type objectType, string memberName) { this.objectType = objectType; this.memberName = memberName; } } } #if UNITY_EDITOR namespace InspectorToolkit.Internal { using UnityEditor; using System.Reflection; [CustomPropertyDrawer(typeof(ObjectsPropertyAttribute))] public class ObjectsPropertyAttributeDrawer : PropertyDrawer { private bool isInitialized; private bool hasValidTarget; private string[] values; private int selectedIndex = -1; public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { if (property.propertyType != SerializedPropertyType.String) { label.text = $"(!) {label.text}"; label.tooltip = $"ObjectPropertiesAttribute only works on strings.\n\n{label.tooltip}"; EditorGUI.PropertyField(position, property, label); return; } if (!isInitialized) { Initialize(property.stringValue); } EditorGUI.BeginChangeCheck(); selectedIndex = Array.IndexOf(values, property.stringValue); selectedIndex = EditorGUI.Popup(position, label.text, selectedIndex, values); if (EditorGUI.EndChangeCheck()) { property.stringValue = values[selectedIndex]; property.serializedObject.ApplyModifiedProperties(); } } private void Initialize(string currentValue) { ObjectsPropertyAttribute objectsPropertyAttribute = (ObjectsPropertyAttribute)attribute; List objectsOfType = AssetUtility.FindAllAssetsInProject(objectsPropertyAttribute.objectType); const BindingFlags searchFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance; FieldInfo field = objectsPropertyAttribute.objectType.GetFields(searchFlags) .FirstOrDefault(memberInfo => memberInfo.Name == objectsPropertyAttribute.memberName); PropertyInfo property = objectsPropertyAttribute.objectType.GetProperties(searchFlags) .FirstOrDefault(memberInfo => memberInfo.Name == objectsPropertyAttribute.memberName); if (field != null) { values = objectsOfType.Select(obj => field.GetValue(obj).ToString()).ToArray(); } else if (property != null) { values = objectsOfType.Select(obj => property.GetValue(obj).ToString()).ToArray(); } else { values = new string[] { }; Debug.LogError($"Cannot find member '{objectsPropertyAttribute.memberName}' for type '{objectsPropertyAttribute.objectType.Name}'"); } isInitialized = true; selectedIndex = Array.IndexOf(values, currentValue); } } } #endif