using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using UnityEditor; using UnityEngine; namespace Funique { [CustomPropertyDrawer(typeof(TypeDropdownAttribute))] public class TypeDropdownDrawer : PropertyDrawer { internal class TypeStorage { internal List types = new List(); } internal static Dictionary dict = new Dictionary(); internal static Dictionary naming_dict = new Dictionary(); object GetValue(SerializedProperty property) { object obj = property.serializedObject.targetObject; FieldInfo field = null; foreach (var path in property.propertyPath.Split('.')) { var type = obj.GetType(); field = type.GetField(path); obj = field.GetValue(obj); } return obj; } void Fill(Type type) { TypeStorage buffer = new TypeStorage(); buffer.types.Add(null); dict[type] = buffer; Assembly[] asss = System.AppDomain.CurrentDomain.GetAssemblies(); foreach (var i in asss) { foreach (var t in i.GetTypes()) { if (t.IsSubclassOf(type) || (t == type && !t.IsAbstract)) { buffer.types.Add(t); } } } naming_dict[type] = buffer.types.Select(x => x == null ? "NULL" : x.FullName).ToArray(); } Type GetType(string type) { Assembly[] asss = System.AppDomain.CurrentDomain.GetAssemblies(); Type[] r = asss.SelectMany(x => x.GetTypes()).Where(x => x.Name == type || x.FullName == type).ToArray(); if (r.Length > 0) return r[0]; return null; } int GetIndex(object target, Type type) { if (target == null) return 0; TypeStorage buffer = dict[type]; return buffer.types.FindIndex(x => target.GetType() == x); } public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { //base.OnGUI(position, property, label); TypeDropdownAttribute a = (TypeDropdownAttribute)attribute; string typename = property.managedReferenceFieldTypename.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[1]; Type type = GetType(typename); object obj = GetValue(property); if (!dict.ContainsKey(type)) Fill(type); int index = GetIndex(obj, type); string[] fs = naming_dict[type]; int result = EditorGUI.Popup(position, label, index, fs.Select(x => new GUIContent(x)).ToArray()); if (result != index) { if (result == 0) property.managedReferenceValue = null; else property.managedReferenceValue = Activator.CreateInstance(dict[type].types[result]); property.serializedObject.ApplyModifiedProperties(); } } } }