Johannes Deml 70f2cdaf16 Add logic to check for inherited PropertyDrawers from base classes and interfaces
This way an inherited drawer will be used if it exists, which might not be too uncommon in the case of SerializeReference fields
2024-01-17 13:27:49 +01:00

84 lines
2.4 KiB
C#

#if UNITY_2019_3_OR_NEWER
using System;
using System.Collections.Generic;
using UnityEditor;
using System.Reflection;
namespace MackySoft.SerializeReferenceExtensions.Editor
{
public static class PropertyDrawerCache
{
static readonly Dictionary<Type, PropertyDrawer> s_Caches = new Dictionary<Type, PropertyDrawer>();
public static bool TryGetPropertyDrawer (Type type,out PropertyDrawer drawer)
{
if (!s_Caches.TryGetValue(type,out drawer))
{
Type drawerType = GetCustomPropertyDrawerType(type);
drawer = (drawerType != null) ? (PropertyDrawer)Activator.CreateInstance(drawerType) : null;
s_Caches.Add(type, drawer);
}
return (drawer != null);
}
static Type GetCustomPropertyDrawerType (Type type)
{
Type[] interfaceTypes = type.GetInterfaces();
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (Type drawerType in assembly.GetTypes())
{
var customPropertyDrawerAttributes = drawerType.GetCustomAttributes(typeof(CustomPropertyDrawer), true);
foreach (CustomPropertyDrawer customPropertyDrawer in customPropertyDrawerAttributes)
{
var field = customPropertyDrawer.GetType().GetField("m_Type", BindingFlags.NonPublic | BindingFlags.Instance);
if (field != null)
{
var fieldType = field.GetValue(customPropertyDrawer) as Type;
if (fieldType != null)
{
if (fieldType == type)
{
return drawerType;
}
// If the property drawer also allows for being applied to child classes, check if they match
var useForChildrenField = customPropertyDrawer.GetType().GetField("m_UseForChildren", BindingFlags.NonPublic | BindingFlags.Instance);
if (useForChildrenField != null)
{
object useForChildrenValue = useForChildrenField.GetValue(customPropertyDrawer);
if (useForChildrenValue is bool && (bool)useForChildrenValue)
{
// Check interfaces
if (Array.Exists(interfaceTypes, interfaceType => interfaceType == fieldType))
{
return drawerType;
}
// Check derived types
Type baseType = type.BaseType;
while (baseType != null)
{
if (baseType == fieldType)
{
return drawerType;
}
baseType = baseType.BaseType;
}
}
}
}
}
}
}
}
return null;
}
}
}
#endif