public bool Process(ref TypeSearchInfo info, ref string errorMessage) { return(this.rule(ref info, ref errorMessage)); }
static DrawerUtilities() { // This method is *very* expensive performance-wise and generates lots of garbage due to liberal use of LINQ for readability. // This is acceptable, as it only runs once per AppDomain reload, and only ever in the editor. // // First, get all relevant types // var typesToSearch = AssemblyUtilities.GetTypes(AssemblyTypeFlags.CustomTypes | AssemblyTypeFlags.UnityEditorTypes) .Where(type => !type.IsAbstract && type.IsClass && !type.IsDefined(typeof(OdinDontRegisterAttribute), false) && (typeof(OdinDrawer).IsAssignableFrom(type) || (typeof(GUIDrawer).IsAssignableFrom(type) && (!(type.Namespace ?? "").StartsWith("Unity", StringComparison.InvariantCulture) || !ExcludeUnityDrawers.Contains(type.Name))))) .ToArray(); // // Find all regular Unity property and decorator drawers and create alias drawers for them // IEnumerable <Type> unityPropertyDrawers; IEnumerable <Type> unityPropertyAttributeDrawers; IEnumerable <Type> unityDecoratorDrawers; if (DrawerUtilities.CustomPropertyDrawerTypeField != null && DrawerUtilities.CustomPropertyDrawerUseForChildrenField != null) { unityPropertyDrawers = typesToSearch.Where(type => type.IsGenericTypeDefinition == false && typeof(PropertyDrawer).IsAssignableFrom(type) && type.GetConstructor(Type.EmptyTypes) != null) .SelectMany(type => type.GetCustomAttributes <CustomPropertyDrawer>(true).Select(attr => new { Type = type, Attribute = attr })) .Where(n => { if (n.Attribute != null) { var drawnType = CustomPropertyDrawerTypeField.GetValue(n.Attribute) as Type; if (drawnType != null && !typeof(PropertyAttribute).IsAssignableFrom(drawnType)) { return(true); } } return(false); }) .Select(n => { var drawnType = (Type)CustomPropertyDrawerTypeField.GetValue(n.Attribute); if (drawnType.IsAbstract || (bool)DrawerUtilities.CustomPropertyDrawerUseForChildrenField.GetValue(n.Attribute)) { var tArg = typeof(AbstractTypeUnityPropertyDrawer <, ,>).GetGenericArguments()[2]; return(typeof(AbstractTypeUnityPropertyDrawer <, ,>).MakeGenericType(n.Type, drawnType, tArg)); } else { return(typeof(UnityPropertyDrawer <,>).MakeGenericType(n.Type, drawnType)); } }); unityPropertyAttributeDrawers = typesToSearch.Where(type => type.IsGenericTypeDefinition == false && typeof(PropertyDrawer).IsAssignableFrom(type) && type.GetConstructor(Type.EmptyTypes) != null) .SelectMany(type => type.GetCustomAttributes <CustomPropertyDrawer>(true).Select(attr => new { Type = type, Attribute = attr })) .Where(n => { if (n.Attribute != null) { var drawnType = CustomPropertyDrawerTypeField.GetValue(n.Attribute) as Type; if (drawnType != null && typeof(PropertyAttribute).IsAssignableFrom(drawnType)) { return(true); } } return(false); }) .Select(n => { Type drawnType = (Type)CustomPropertyDrawerTypeField.GetValue(n.Attribute); if ((bool)DrawerUtilities.CustomPropertyDrawerUseForChildrenField.GetValue(n.Attribute)) { var tAttributeArgParam = typeof(UnityPropertyAttributeDrawer <, ,>).GetGenericArguments()[1]; return(typeof(UnityPropertyAttributeDrawer <, ,>).MakeGenericType(n.Type, tAttributeArgParam, drawnType)); } else { return(typeof(UnityPropertyAttributeDrawer <, ,>).MakeGenericType(n.Type, drawnType, typeof(PropertyAttribute))); } }); unityDecoratorDrawers = typesToSearch.Where(type => type.IsGenericTypeDefinition == false && typeof(DecoratorDrawer).IsAssignableFrom(type) && type.GetConstructor(Type.EmptyTypes) != null) .Select(type => new { Type = type, Attribute = type.GetCustomAttribute <CustomPropertyDrawer>(true) }) .Where(n => n.Attribute != null) .Select(n => new { Type = n.Type, Attribute = n.Attribute, DrawnType = CustomPropertyDrawerTypeField.GetValue(n.Attribute) as Type }) .Where(n => n.DrawnType != null && typeof(PropertyAttribute).IsAssignableFrom(n.DrawnType)) .Select(n => { if ((bool)DrawerUtilities.CustomPropertyDrawerUseForChildrenField.GetValue(n.Attribute)) { var tAttributeArgParam = typeof(UnityDecoratorAttributeDrawer <, ,>).GetGenericArguments()[1]; return(typeof(UnityDecoratorAttributeDrawer <, ,>).MakeGenericType(n.Type, tAttributeArgParam, n.DrawnType)); } else { return(typeof(UnityDecoratorAttributeDrawer <, ,>).MakeGenericType(n.Type, n.DrawnType, typeof(PropertyAttribute))); } }); } else { Debug.LogWarning("Could not find internal fields 'm_Type' and/or 'm_UseForChildren' in type CustomPropertyDrawer in this version of Unity; support for legacy Unity PropertyDrawers and DecoratorDrawers have been disabled in Odin's inspector. Please report this on Odin's issue tracker."); unityPropertyDrawers = Enumerable.Empty <Type>(); unityPropertyAttributeDrawers = Enumerable.Empty <Type>(); unityDecoratorDrawers = Enumerable.Empty <Type>(); } DrawerUtilities.AllDrawerTypes = typesToSearch .Where(type => typeof(OdinDrawer).IsAssignableFrom(type)) .AppendWith(unityPropertyDrawers) .AppendWith(unityPropertyAttributeDrawers) .AppendWith(unityDecoratorDrawers) .OrderByDescending(type => GetDrawerPriority(type)) .ToList(); //DrawerUtilities.SearchIndex.IndexingRules.Add(new TypeMatchIndexingRule( // "DEBUG", // (ref TypeSearchInfo info, ref string error) => // { // Debug.Log("Indexed drawer: " + info.MatchType.GetNiceFullName()); // return true; // })); // Unity drawers have a peculiar method of generic target selection, // where you pass in the generic type definition that you wish to draw. // // We need to support this, for Unity's own legacy drawers. DrawerUtilities.SearchIndex.MatchRules.Add(new TypeSearch.TypeMatchRule( "Unity Drawer Generic Target Matcher", (info, targets) => { if (targets.Length != 1) { return(null); } if (!info.Targets[0].IsGenericTypeDefinition) { return(null); } var baseDef = info.MatchType.GetGenericTypeDefinition(); bool abstractUnityValueDrawer = baseDef == typeof(AbstractTypeUnityPropertyDrawer <, ,>); bool plainUnityValueDrawer = baseDef == typeof(UnityPropertyDrawer <,>); if (!(abstractUnityValueDrawer || plainUnityValueDrawer)) { return(null); } if (abstractUnityValueDrawer) { if (targets[0].ImplementsOpenGenericType(info.Targets[0])) { var args = info.MatchType.GetGenericArguments(); return(info.MatchType.GetGenericTypeDefinition().MakeGenericType(args[0], targets[0], targets[0])); } } else { if (!targets[0].IsGenericType) { return(null); } if (targets[0].GetGenericTypeDefinition() == info.Targets[0]) { var args = info.MatchType.GetGenericArguments(); return(info.MatchType.GetGenericTypeDefinition().MakeGenericType(args[0], targets[0])); } } return(null); }) ); DrawerUtilities.SearchIndex.AddIndexedTypes( DrawerUtilities.AllDrawerTypes .Select((type, i) => { var info = new TypeSearchInfo() { MatchType = type, Priority = DrawerUtilities.AllDrawerTypes.Count - i, Targets = null }; if (type.ImplementsOpenGenericClass(typeof(OdinValueDrawer <>))) { info.Targets = type.GetArgumentsOfInheritedOpenGenericClass(typeof(OdinValueDrawer <>)); } else if (type.ImplementsOpenGenericClass(typeof(OdinAttributeDrawer <>))) { if (type.ImplementsOpenGenericClass(typeof(OdinAttributeDrawer <,>))) { info.Targets = type.GetArgumentsOfInheritedOpenGenericClass(typeof(OdinAttributeDrawer <,>)); InvalidAttributeTargetUtility.RegisterValidAttributeTarget(info.Targets[0], info.Targets[1]); } else { info.Targets = type.GetArgumentsOfInheritedOpenGenericClass(typeof(OdinAttributeDrawer <>)); } } else if (type.ImplementsOpenGenericClass(typeof(OdinGroupDrawer <>))) { info.Targets = type.GetArgumentsOfInheritedOpenGenericClass(typeof(OdinGroupDrawer <>)); } else if (!type.IsFullyConstructedGenericType()) { info.Targets = type.GetGenericArguments(); } info.Targets = info.Targets ?? Type.EmptyTypes; return(info); }) ); }