namespace Zinnia.Data.Attribute
{
using System;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
using Zinnia.Utility;
///
/// Displays a custom inspector type picker dropdown.
///
[CustomPropertyDrawer(typeof(TypePickerAttribute))]
public class TypePickerAttributeDrawer : PropertyDrawer
{
///
/// A PickerWindow for a specified type.
///
public class PickerWindow : PickerWindow { }
///
/// The type for the picker inspector.
///
protected Type type;
///
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
label.tooltip = EditorHelper.GetTooltipAttribute(fieldInfo)?.tooltip ?? string.Empty;
using (new EditorGUI.PropertyScope(position, label, property))
{
SerializedProperty assemblyQualifiedTypeNameProperty = property.FindPropertyRelative("assemblyQualifiedTypeName");
int? index = property.TryGetIndex();
label.text = index == null ? label.text : $"Element {index}";
Rect buttonPosition = EditorGUI.PrefixLabel(position, label);
if (type?.AssemblyQualifiedName != assemblyQualifiedTypeNameProperty.stringValue)
{
type = Type.GetType(assemblyQualifiedTypeNameProperty.stringValue);
}
if (!GUI.Button(buttonPosition, new GUIContent(type?.Name, type?.FullName)))
{
return;
}
Rect creatorRect = new Rect
{
min = GUIUtility.GUIToScreenPoint(position.min),
max = GUIUtility.GUIToScreenPoint(position.max)
};
Type baseType = ((TypePickerAttribute)attribute).baseType;
PickerWindow.Show(
creatorRect,
AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(assembly => assembly.GetTypes())
.Where(
possibleComponentType =>
{
AddComponentMenu addComponentMenuAttribute = possibleComponentType
.GetCustomAttributes(true)
.FirstOrDefault();
return baseType.IsAssignableFrom(possibleComponentType)
&& !possibleComponentType.IsAbstract
&& !possibleComponentType.IsNestedPrivate
&& (addComponentMenuAttribute == null
|| !string.IsNullOrWhiteSpace(addComponentMenuAttribute.componentMenu));
})
.OrderBy(componentType => componentType.Name),
selectedType =>
{
assemblyQualifiedTypeNameProperty.stringValue = selectedType.AssemblyQualifiedName;
property.serializedObject.ApplyModifiedProperties();
},
searchedType => searchedType.Name,
drawnType => new GUIContent(
ObjectNames.NicifyVariableName(drawnType.Name),
AssetPreview.GetMiniTypeThumbnail(drawnType),
drawnType.FullName));
}
}
}
}