This way an inherited drawer will be used if it exists, which might not be too uncommon in the case of SerializeReference fields
		
			
				
	
	
		
			84 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			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 |