private void AssignTypeToUsePropertyDrawerDrawer(DrawerProviderData drawersFor, Type attributeOrFieldType) { if (attributeOrFieldType.IsSubclassOf(Types.PropertyAttribute)) { Dictionary <Type, Type> drawerTypesByFieldType; if (drawersFor.propertyDrawersByAttributeType.TryGetValue(attributeOrFieldType, out drawerTypesByFieldType)) { if (drawerTypesByFieldType.ContainsKey(Types.SystemObject)) { return; } } else { drawerTypesByFieldType = new Dictionary <Type, Type>(1); drawersFor.propertyDrawersByAttributeType.Add(attributeOrFieldType, drawerTypesByFieldType); } #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_PROPERTY_DRAWERS Debug.Log(attributeOrFieldType.Name + " (PropertyDrawer) default field type System.Object handled by PropertyDrawerDrawer."); #endif // all PropertyDrawers backed fields default to PropertyDrawerDrawer drawerTypesByFieldType.Add(Types.SystemObject, typeof(PropertyDrawerDrawer)); } else if (!drawersFor.propertyDrawersByFieldType.ContainsKey(attributeOrFieldType)) { // all PropertyDrawers backed fields default to PropertyDrawerDrawer drawersFor.propertyDrawersByFieldType.Add(attributeOrFieldType, typeof(PropertyDrawerDrawer)); } }
public DrawerProviderBase() { drawersFor = new DrawerProviderData(); BuildDictionaries(drawersFor); #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(drawersFor != null); #endif }
// Make PropertyDrawer backed type use to PropertyDrawerDrawer private void BuildDictionariesForPropertyDrawersInUnityNamespaces(DrawerProviderData drawersFor, Dictionary <Type, Type> propertyDrawers) { foreach (var propertyDrawer in propertyDrawers) { var attributeOrFieldType = propertyDrawer.Key; if (IsInUnityNamespace(attributeOrFieldType)) { AssignTypeToUsePropertyDrawerDrawer(drawersFor, attributeOrFieldType); } } }
public void Copy(DrawerProviderData copyOver) { copyOver.fields.Clear(); foreach (var item in fields) { copyOver.fields.Add(item.Key, item.Value); } copyOver.decoratorDrawers.Clear(); foreach (var item in decoratorDrawers) { copyOver.decoratorDrawers.Add(item.Key, item.Value); } copyOver.drawersByAttributeType.Clear(); foreach (var item in drawersByAttributeType) { copyOver.drawersByAttributeType.Add(item.Key, new Dictionary <Type, Type>(item.Value)); } copyOver.propertyDrawerDrawersByFieldType.Clear(); foreach (var item in propertyDrawerDrawersByFieldType) { copyOver.propertyDrawerDrawersByFieldType.Add(item.Key, item.Value); } copyOver.components.Clear(); foreach (var item in components) { copyOver.components.Add(item.Key, item.Value); } copyOver.assets.Clear(); foreach (var item in assets) { copyOver.assets.Add(item.Key, item.Value); } copyOver.assetsByExtension.Clear(); foreach (var item in assetsByExtension) { copyOver.assetsByExtension.Add(item.Key, item.Value); } #if UNITY_EDITOR copyOver.propertyDrawerDrawersRequiringSerializedProperty.Clear(); foreach (var type in propertyDrawerDrawersRequiringSerializedProperty) { copyOver.propertyDrawerDrawersRequiringSerializedProperty.Add(type); } #endif }
private void AssignTypeToUseDecoratorDrawerDrawer(DrawerProviderData drawersFor, Type attributeType) { if (drawersFor.decoratorDrawers.ContainsKey(attributeType)) { return; } #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_DECORATOR_DRAWERS Debug.Log(attributeType.Name + " (DecoratorDrawer) with default field type System.Object handled by DecoratorDrawerDrawer."); #endif drawersFor.decoratorDrawers.Add(attributeType, typeof(DecoratorDrawerDrawer)); }
// Make all Custom Editors existing in Unity namespaces use CustomEditorComponentDrawer or CustomEditorAssetDrawer private void BuildDictionariesForCustomEditorsInUnityNamespaces(DrawerProviderData drawersFor, Dictionary <Type, Type> customEditorsByType) { var componentDrawers = drawersFor.components; var assetDrawers = drawersFor.assets; foreach (var customEditor in customEditorsByType) { var editorType = customEditor.Value; if (IsInUnityNamespace(editorType)) { AssignTypeToUseCustomEditorDrawer(componentDrawers, assetDrawers, customEditor.Key); } } }
// Make PropertyDrawer backed type use to PropertyDrawerDrawer private void BuildDictionariesForDecoratorDrawersInUnityNamespaces(DrawerProviderData drawersFor, Dictionary <Type, Type> decoratorDrawers) { foreach (var decoratorDrawer in decoratorDrawers) { #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(typeof(DecoratorDrawer).IsAssignableFrom(decoratorDrawer.Value)); #endif var attributeOrFieldType = decoratorDrawer.Key; if (IsInUnityNamespace(attributeOrFieldType)) { AssignTypeToUseDecoratorDrawerDrawer(drawersFor, attributeOrFieldType); } } }
protected abstract void BuildDictionaries(DrawerProviderData drawerProviderData);
protected override void BuildDictionaries(DrawerProviderData drawersFor) { var drawerTypes = typeof(IDrawer).GetImplementingNonUnityObjectClassTypes(false); // Priority 1: plugin drawers providers var pluginProviders = DrawerFromPluginProvider.All; for (int n = pluginProviders.Length - 1; n >= 0; n--) { var provider = pluginProviders[n]; if (!provider.IsActive) { #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_PLUGINS Debug.Log("Skipping " + provider.GetType().Name + " because IsActive was " + StringUtils.False); #endif continue; } try { provider.AddFieldDrawer(drawersFor.fields); #if DEV_MODE && PI_ASSERTATIONS AssertAllGUIInstructionTypesImplement(drawersFor.fields.Values, typeof(IFieldDrawer), provider, "AddFieldDrawer"); #endif provider.AddDecoratorDrawerDrawer(drawersFor.decoratorDrawers); #if DEV_MODE && PI_ASSERTATIONS AssertAllGUIInstructionTypesImplement(drawersFor.decoratorDrawers.Values, typeof(IDecoratorDrawerDrawer), provider, "AddDecoratorDrawerDrawer"); #endif provider.AddPropertyDrawerDrawer(drawersFor.propertyDrawersByAttributeType, drawersFor.propertyDrawersByFieldType); #if DEV_MODE && PI_ASSERTATIONS foreach (var dictionary in drawersFor.propertyDrawersByAttributeType.Values) { AssertAllGUIInstructionTypesImplement(dictionary.Values, typeof(IPropertyDrawerDrawer), provider, "AddPropertyDrawerDrawer"); } AssertAllGUIInstructionTypesImplement(drawersFor.propertyDrawersByFieldType.Values, typeof(IPropertyDrawerDrawer), provider, "AddPropertyDrawerDrawer"); #endif provider.AddComponentDrawer(drawersFor.components); #if DEV_MODE && PI_ASSERTATIONS AssertAllGUIInstructionTypesImplementOne(drawersFor.decoratorDrawers.Values, typeof(IEditorlessComponentDrawer), typeof(ICustomEditorComponentDrawer), provider, "AddComponentDrawer"); #endif provider.AddAssetDrawer(drawersFor.assets, drawersFor.assetsByExtension); #if DEV_MODE && PI_ASSERTATIONS AssertAllGUIInstructionTypesImplementOne(drawersFor.assets.Values, typeof(IEditorlessAssetDrawer), typeof(ICustomEditorAssetDrawer), provider, "AddAssetDrawer"); AssertAllGUIInstructionTypesImplementOne(drawersFor.assetsByExtension.Values, typeof(IEditorlessAssetDrawer), typeof(ICustomEditorAssetDrawer), provider, "AddAssetDrawer"); #endif } catch (Exception e) { Debug.LogError(e); } } // Priority 2: non-fallback, non-inherited types BuildDictionariesForExactTypes(drawersFor, drawerTypes, false); // Priority 3: inherited types for non-fallback drawers BuildDictionariesForInheritedTypes(drawersFor, drawerTypes, false); #if UNITY_EDITOR // Priority 4: PropertyDrawers and DecoratorDrawers and Editors outside of Unity namespace var propertyDrawers = CustomEditorUtility.PropertyDrawersByType; var decoratorDrawers = CustomEditorUtility.DecoratorDrawersByType; var customEditors = CustomEditorUtility.CustomEditorsByType; BuildDictionariesForPropertyDrawersInNonUnityNamespaces(drawersFor, propertyDrawers); BuildDictionariesForDecoratorDrawersInNonUnityNamespaces(drawersFor, decoratorDrawers); BuildDictionariesForCustomEditorsInNonUnityNamespaces(drawersFor, customEditors); #endif //Priority 5: fallback, non-inherited types BuildDictionariesForExactTypes(drawersFor, drawerTypes, true); //Priority 6: fallback, inherited types BuildDictionariesForInheritedTypes(drawersFor, drawerTypes, true); // Make sure that GameObjects have some drawer if (drawersFor.gameObject == null) { drawersFor.gameObject = typeof(GameObjectDrawer); } #if UNITY_EDITOR // Priority 4: PropertyDrawer and DecoratorDrawers and Editors inside of Unity namespace BuildDictionariesForPropertyDrawersInUnityNamespaces(drawersFor, propertyDrawers); BuildDictionariesForDecoratorDrawersInUnityNamespaces(drawersFor, decoratorDrawers); BuildDictionariesForCustomEditorsInUnityNamespaces(drawersFor, customEditors); #endif // IUseDrawer overrides. This has highest priority, but it is done as the last step, // because IUseDrawer relies on getting the default drawers for different types. var useDrawerOverrides = UseDrawerAttributeUtility.GetCustomDrawersByClassType(this); foreach (var subjectAndDrawer in useDrawerOverrides) { var subjectType = subjectAndDrawer.Key; var drawerType = subjectAndDrawer.Value; #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(subjectType != null); Debug.Assert(drawerType != null); Debug.Assert(typeof(IDrawer).IsAssignableFrom(drawerType)); #endif if (typeof(IComponentDrawer).IsAssignableFrom(drawerType)) { #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(subjectType.IsComponent()); #endif #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_COMPONENTS Debug.Log(StringUtils.ToStringSansNamespace(subjectType) + " IUseDrawer override: " + StringUtils.ToStringSansNamespace(drawerType)); #endif drawersFor.components[subjectType] = drawerType; } else if (typeof(IAssetDrawer).IsAssignableFrom(drawerType)) // TO DO: support drawer by extension via additional parameters in DrawerForAttribute? { #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(subjectType.IsUnityObject() && !subjectType.IsComponent()); #endif #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_ASSETS Debug.Log(StringUtils.ToStringSansNamespace(subjectType) + " IUseDrawer override: " + StringUtils.ToStringSansNamespace(drawerType)); #endif drawersFor.assets[subjectType] = drawerType; } else if (typeof(IPropertyDrawerDrawer).IsAssignableFrom(drawerType)) { #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_PROPERTY_DRAWERS Debug.Log(StringUtils.ToStringSansNamespace(subjectType) + " IUseDrawer override: " + StringUtils.ToStringSansNamespace(drawerType)); #endif drawersFor.propertyDrawersByFieldType[subjectType] = drawerType; } else if (typeof(IDecoratorDrawerDrawer).IsAssignableFrom(drawerType)) { #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_DECORATOR_DRAWERS Debug.Log(StringUtils.ToStringSansNamespace(subjectType) + " IUseDrawer override: " + StringUtils.ToStringSansNamespace(drawerType)); #endif drawersFor.decoratorDrawers[subjectType] = drawerType; } else if (typeof(IFieldDrawer).IsAssignableFrom(drawerType)) { #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_FIELDS Debug.Log(StringUtils.ToStringSansNamespace(subjectType) + " IUseDrawer override: " + StringUtils.ToStringSansNamespace(drawerType)); #endif drawersFor.fields[subjectType] = drawerType; } #if DEV_MODE else { Debug.LogError("IUseDrawer unrecognized drawerType: " + drawerType.Name + ". The drawer did not implement any of the necessary IDrawer-based interfaces."); } #endif } #if DEV_MODE && PI_ASSERTATIONS && UNITY_EDITOR Debug.Assert(!drawersFor.fields.ContainsValue(null)); Debug.Assert(!drawersFor.fields.ContainsValue(typeof(PropertyDrawerDrawer))); Debug.Assert(!drawersFor.fields.ContainsValue(typeof(DecoratorDrawerDrawer))); Debug.Assert(!drawersFor.decoratorDrawers.ContainsValue(null)); Debug.Assert(!drawersFor.decoratorDrawers.ContainsValue(typeof(PropertyDrawerDrawer))); foreach (var propertyDrawerDrawerBySecondType in drawersFor.propertyDrawersByAttributeType.Values) { Debug.Assert(!propertyDrawerDrawerBySecondType.ContainsValue(null)); Debug.Assert(!propertyDrawerDrawerBySecondType.ContainsValue(typeof(DecoratorDrawerDrawer))); } Debug.Assert(!drawersFor.propertyDrawersByFieldType.ContainsValue(null)); Debug.Assert(!drawersFor.propertyDrawersByFieldType.ContainsValue(typeof(DecoratorDrawerDrawer))); Debug.Assert(!drawersFor.components.ContainsValue(null)); Debug.Assert(!drawersFor.components.ContainsValue(typeof(CustomEditorAssetDrawer))); Debug.Assert(!drawersFor.components.ContainsValue(typeof(AssetDrawer))); Debug.Assert(!drawersFor.assets.ContainsValue(null)); Debug.Assert(!drawersFor.assets.ContainsValue(typeof(CustomEditorComponentDrawer))); Debug.Assert(!drawersFor.assets.ContainsValue(typeof(ComponentDrawer))); Debug.Assert(!drawersFor.assetsByExtension.ContainsValue(typeof(CustomEditorComponentDrawer))); Debug.Assert(!drawersFor.assetsByExtension.ContainsValue(typeof(ComponentDrawer))); #endif }
private void BuildDictionariesForInheritedTypes(DrawerProviderData drawerProviderData, Type[] drawerTypes, bool isFallback) { var fields = drawerProviderData.fields; var assetDrawers = drawerProviderData.assets; var components = drawerProviderData.components; var decoratorDrawers = drawerProviderData.decoratorDrawers; var propertyDrawersByAttributeType = drawerProviderData.propertyDrawersByAttributeType; for (int n = drawerTypes.Length - 1; n >= 0; n--) { var drawerType = drawerTypes[n]; var attributes = (DrawerForBaseAttribute[])drawerType.GetCustomAttributes(typeof(DrawerForBaseAttribute), false); for (int a = attributes.Length - 1; a >= 0; a--) { var attribute = attributes[a]; if (attribute.isFallback != isFallback) { continue; } if (!attribute.TargetExtendingTypes) { continue; } var type = attribute.Target; // if has no target type or target type is a value type // then there are no inhertied types that need to be added // for these drawers if (type == null || type.IsValueType) { continue; } #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_NONFALLBACK_DRAWER if (!isFallback) { Debug.Log(StringUtils.ToStringSansNamespace(type) + " inherited types handled by " + StringUtils.ToStringSansNamespace(drawerType)); } #endif var fieldAttribute = attribute as DrawerForFieldAttribute; if (fieldAttribute != null) { Type[] subjectTypes; if (type == Types.Enum) { subjectTypes = TypeExtensions.EnumTypesIncludingInvisible; } else if (type.IsInterface) { subjectTypes = type.GetImplementingTypes(true); } else { subjectTypes = type.GetExtendingTypes(true); } for (int t = subjectTypes.Length - 1; t >= 0; t--) { var subjectType = subjectTypes[t]; if (!fields.ContainsKey(subjectType)) { #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_ENUM_FIELDS if (drawerType == typeof(EnumDrawer)) { Debug.Log(subjectType.FullName + " handled by " + drawerType.Name + " because it's a base type of " + type.FullName); } #endif #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_DELEGATE_FIELDS if (drawerType == typeof(DelegateDrawer)) { Debug.Log(subjectType.FullName + " handled by " + drawerType.Name + " because it's a base type of " + type.FullName); } #endif #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_UNITY_OBJECT_FIELDS if (drawerType == typeof(ObjectReferenceDrawer)) { Debug.Log(subjectType.FullName + " handled by " + drawerType.Name + " because it's a base type of " + type.FullName); } #endif #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_FIELDS if (drawerType != typeof(EnumDrawer) && drawerType != typeof(DelegateDrawer) && drawerType != typeof(ObjectReferenceDrawer)) { Debug.Log(StringUtils.ToStringSansNamespace(subjectType) + " handled by " + StringUtils.ToStringSansNamespace(drawerType) + " because it's a base type of " + StringUtils.ToStringSansNamespace(type)); } #endif fields.Add(subjectType, drawerType); } } continue; } var decoratorDrawerAttribute = attribute as DrawerForDecoratorAttribute; if (decoratorDrawerAttribute != null) { var attributeTypes = PluginAttributeConverterProvider.GetAttributeTypeAndEachAlias(type); while (attributeTypes.MoveNext()) { var attributeType = attributeTypes.Current; var subjectTypes = attributeType.GetExtendingNonUnityObjectClassTypes(false); for (int t = subjectTypes.Length - 1; t >= 0; t--) { var subjectType = subjectTypes[t]; if (!decoratorDrawers.ContainsKey(subjectType)) { #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_DECORATOR_DRAWERS Debug.Log(subjectType.FullName + " handled by " + drawerType.Name + " because it's a base type of " + attributeType.FullName); #endif decoratorDrawers.Add(subjectType, drawerType); } } } continue; } var propertyDrawerAttribute = attribute as DrawerForAttributeAttribute; if (propertyDrawerAttribute != null) { var attributeTypes = PluginAttributeConverterProvider.GetAttributeTypeAndEachAlias(type); while (attributeTypes.MoveNext()) { var attributeType = attributeTypes.Current; var subjectTypes = attributeType.GetExtendingNonUnityObjectClassTypes(false); for (int t = subjectTypes.Length - 1; t >= 0; t--) { var subjectType = subjectTypes[t]; Dictionary <Type, Type> drawerTypesByFieldType; if (!propertyDrawersByAttributeType.TryGetValue(subjectType, out drawerTypesByFieldType)) { drawerTypesByFieldType = new Dictionary <Type, Type>(1); propertyDrawersByAttributeType.Add(subjectType, drawerTypesByFieldType); } var fieldType = propertyDrawerAttribute.valueType; if (!drawerTypesByFieldType.ContainsKey(fieldType)) { drawerTypesByFieldType.Add(fieldType, drawerType); #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_PROPERTY_DRAWERS Debug.Log(subjectType.Name + " handled by " + drawerType.Name + " with field type " + fieldType.Name + " because it's a base type of " + attributeType.FullName); #endif #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(drawerTypesByFieldType[fieldType] == drawerType); #endif } #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(propertyDrawersByAttributeType.ContainsKey(subjectType)); Debug.Assert(drawerTypesByFieldType.ContainsKey(fieldType)); #endif } } continue; } var componentAttribute = attribute as DrawerForComponentAttribute; if (componentAttribute != null) { var subjectTypes = type.IsInterface ? type.GetImplementingComponentTypes(true) : type.GetExtendingComponentTypes(true); for (int t = subjectTypes.Length - 1; t >= 0; t--) { var subjectType = subjectTypes[t]; if (subjectType.IsAbstract) { #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_COMPONENTS Debug.Log("Skipping component " + subjectType + " because it's abstract..."); #endif continue; } #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(subjectType.IsComponent(), "DrawerForComponent attribute subject has to be Component type: " + StringUtils.ToString(type)); #endif if (!components.ContainsKey(subjectType)) { components.Add(subjectType, drawerType); } } continue; } var assetAttribute = attribute as DrawerForAssetAttribute; if (assetAttribute != null) { var subjectTypes = type.IsInterface ? type.GetImplementingUnityObjectTypes(true) : type.GetExtendingUnityObjectTypes(true); for (int t = subjectTypes.Length - 1; t >= 0; t--) { var subjectType = subjectTypes[t]; if (subjectType.IsAbstract) { #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_ASSETS Debug.Log("Skipping inherited asset type " + subjectType + " because it's abstract..."); #endif continue; } if (subjectType.IsComponent()) { #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(!type.IsInterface, "DrawerForAsset attribute subject can not be Component type: " + StringUtils.ToString(type)); #endif continue; } if (!assetDrawers.ContainsKey(subjectType)) { #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_ASSETS Debug.Log(StringUtils.ToStringSansNamespace(subjectType) + " handled by " + StringUtils.ToStringSansNamespace(drawerType)); #endif assetDrawers.Add(subjectType, drawerType); } } } } } }
private void BuildDictionariesForExactTypes(DrawerProviderData drawersFor, Type[] drawerTypes, bool isFallback) { var fields = drawersFor.fields; var assetDrawers = drawersFor.assets; var components = drawersFor.components; var decoratorDrawers = drawersFor.decoratorDrawers; var propertyDrawersByAttributeType = drawersFor.propertyDrawersByAttributeType; var assetsByExtension = drawersFor.assetsByExtension; for (int n = drawerTypes.Length - 1; n >= 0; n--) { var drawerType = drawerTypes[n]; #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(!drawerType.IsAbstract); #endif var attributes = (DrawerForBaseAttribute[])drawerType.GetCustomAttributes(typeof(DrawerForBaseAttribute), false); for (int a = attributes.Length - 1; a >= 0; a--) { var attribute = attributes[a]; #if DEV_MODE && PI_ASSERTATIONS attribute.AssertDataIsValid(drawerType); #endif if (attribute.isFallback != isFallback) { continue; } var type = attribute.Target; if (type != null) { #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_NONFALLBACK_DRAWER if (!isFallback) { Debug.Log(StringUtils.ToStringSansNamespace(type) + " handled by " + StringUtils.ToStringSansNamespace(drawerType)); } #endif var fieldAttribute = attribute as DrawerForFieldAttribute; if (fieldAttribute != null) { if (!fields.ContainsKey(type)) { #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_FIELDS Debug.Log(StringUtils.ToStringSansNamespace(type) + " handled by " + StringUtils.ToStringSansNamespace(drawerType)); #endif fields.Add(type, drawerType); } continue; } var assetAttribute = attribute as DrawerForAssetAttribute; if (assetAttribute != null) { if (!assetDrawers.ContainsKey(type)) { #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_ASSETS Debug.Log(StringUtils.ToStringSansNamespace(type) + " handled by " + StringUtils.ToStringSansNamespace(drawerType)); #endif assetDrawers.Add(type, drawerType); } continue; } var componentAttribute = attribute as DrawerForComponentAttribute; if (componentAttribute != null) { if (!components.ContainsKey(type)) { #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_COMPONENTS Debug.Log(StringUtils.ToStringSansNamespace(type) + " handled by " + StringUtils.ToStringSansNamespace(drawerType)); #endif components.Add(type, drawerType); } continue; } var decoratorDrawerAttribute = attribute as DrawerForDecoratorAttribute; if (decoratorDrawerAttribute != null) { var attributeTypes = PluginAttributeConverterProvider.GetAttributeTypeAndEachAlias(type); while (attributeTypes.MoveNext()) { var attributeType = attributeTypes.Current; if (!decoratorDrawers.ContainsKey(attributeType)) { #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_DECORATOR_DRAWERS Debug.Log(attributeType.FullName + " handled by " + drawerType.Name); #endif decoratorDrawers.Add(attributeType, drawerType); } } continue; } var propertyDrawerAttribute = attribute as DrawerForAttributeAttribute; if (propertyDrawerAttribute != null) { var attributeTypes = PluginAttributeConverterProvider.GetAttributeTypeAndEachAlias(type); while (attributeTypes.MoveNext()) { var attributeType = attributeTypes.Current; Dictionary <Type, Type> drawerTypesByFieldType; if (!propertyDrawersByAttributeType.TryGetValue(attributeType, out drawerTypesByFieldType)) { drawerTypesByFieldType = new Dictionary <Type, Type>(1); propertyDrawersByAttributeType.Add(attributeType, drawerTypesByFieldType); } var fieldType = propertyDrawerAttribute.valueType; if (!drawerTypesByFieldType.ContainsKey(fieldType)) { drawerTypesByFieldType.Add(fieldType, drawerType); #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_PROPERTY_DRAWERS Debug.Log(attributeType.FullName + " handled by " + drawerType.Name + " with field type " + fieldType.Name); #endif #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(drawerTypesByFieldType[fieldType] == drawerType); #endif } #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(propertyDrawersByAttributeType.ContainsKey(attributeType)); Debug.Assert(drawerTypesByFieldType.ContainsKey(fieldType)); #endif } continue; } var gameObjectDrawerAttribute = attribute as DrawerForGameObjectAttribute; if (gameObjectDrawerAttribute != null) { if (gameObjectDrawerAttribute.requireComponentOnGameObject == null) { if (drawersFor.gameObject == null || !gameObjectDrawerAttribute.isFallback) { drawersFor.gameObject = drawerType; } // Handle choosing between GameObjectDrawer and CategorizedGameObjectDrawer based on user preferences else if (drawerType == typeof(GameObjectDrawer)) { if (!InspectorUtility.Preferences.EnableCategorizedComponents && drawersFor.gameObject == typeof(CategorizedGameObjectDrawer)) { drawersFor.gameObject = drawerType; } } else if (drawerType == typeof(CategorizedGameObjectDrawer)) { if (InspectorUtility.Preferences.EnableCategorizedComponents && drawersFor.gameObject == typeof(GameObjectDrawer)) { drawersFor.gameObject = drawerType; } } } else { drawersFor.gameObjectByComponent[gameObjectDrawerAttribute.requireComponentOnGameObject] = drawerType; } } #if DEV_MODE else { Debug.LogError("Unrecognized DrawerForBaseAttribute type: " + attribute.GetType().Name); } #endif } else { var extensionAttribute = attribute as DrawerByExtensionAttribute; if (extensionAttribute != null) { var extension = extensionAttribute.fileExtension; #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(!string.IsNullOrEmpty(extension), "fileExtension was null or empty on DrawerByExtension attribute of " + StringUtils.TypeToString(drawerType)); #endif if (!assetsByExtension.ContainsKey(extension)) { #if DEV_MODE && DEBUG_BUILD_DICTIONARIES_FOR_ASSETS Debug.Log("Asset extension \"" + extension + "\" handled by " + StringUtils.ToStringSansNamespace(drawerType)); #endif assetsByExtension.Add(extension, drawerType); } #if DEV_MODE && PI_ASSERTATIONS Debug.Assert(assetsByExtension.ContainsKey(extension)); #endif } #if DEV_MODE else { Debug.LogWarning("Ignoring Attribute " + attribute.GetType().Name + " because it had a null Type"); } #endif } } } }