private static Type GetUnityTypeWithName(string name) { if (UnityTypes == null) { UnityTypes = new Dictionary <string, Type>(); foreach (var type in AssemblyUtilities.GetTypes(AssemblyTypeFlags.UnityTypes | AssemblyTypeFlags.UnityEditorTypes) .Where(n => typeof(UnityEngine.Object).IsAssignableFrom(n))) { if (UnityTypes.ContainsKey(type.Name)) { UnityTypes[type.Name] = null; } else { UnityTypes[type.Name] = type; } } } Type result; UnityTypes.TryGetValue(name, out result); return(result); }
private static HashSet <Type> GetScriptableObjectTypes() { var customTypes = AssemblyUtilities.GetTypes(AssemblyTypeFlags.CustomTypes); var scrobTypes = customTypes.Where(type => type.IsClass && typeof(ScriptableObject).IsAssignableFrom(type) && !typeof(EditorWindow).IsAssignableFrom(type) && !typeof(Editor).IsAssignableFrom(type)); return(new HashSet <Type>(scrobTypes)); }
protected override void BuildSelectionTree(OdinMenuTree tree) { var scriptableObjectTypes = AssemblyUtilities.GetTypes(AssemblyTypeFlags.CustomTypes) .Where(x => x.IsClass && !x.IsAbstract && x.InheritsFrom(typeof(T))); tree.Selection.SupportsMultiSelect = false; tree.Config.DrawSearchToolbar = true; tree.AddRange(scriptableObjectTypes, x => x.GetNiceName()) .AddThumbnailIcons(); }
/// <summary> /// Builds the selection tree. /// </summary> protected override void BuildSelectionTree(OdinMenuTree tree) { tree.Config.UseCachedExpandedStates = false; tree.DefaultMenuStyle.NotSelectedIconAlpha = 1f; if (types == null) { List <OdinMenuItem> items; if (cachedAllTypesMenuItems.TryGetValue(this.assemblyTypeFlags, out items)) { AddRecursive(tree, items, tree.MenuItems); } else { var assemblyTypes = OrderTypes(AssemblyUtilities.GetTypes(this.assemblyTypeFlags).Where(x => char.IsLetter(x.Name.Trim()[0]))); foreach (var t in assemblyTypes) { var niceName = t.GetNiceName(); string path = this.GetTypeNamePath(t, niceName); var last = tree.AddObjectAtPath(path, t).AddThumbnailIcons().Last(); last.SearchString = niceName == path ? path : niceName + "|" + path; } cachedAllTypesMenuItems[this.assemblyTypeFlags] = tree.MenuItems; } } else { foreach (var t in this.types) { var niceName = t.GetNiceName(); string path = this.GetTypeNamePath(t, niceName); var last = tree.AddObjectAtPath(path, t).Last(); last.SearchString = niceName == path ? path : niceName + "|" + path; if (this.FlattenTree && t.Namespace != null) { last.OnDrawItem += x => GUI.Label(x.Rect.Padding(10, 0).AlignCenterY(16), t.Namespace, SirenixGUIStyles.RightAlignedGreyMiniLabel); } } tree.EnumerateTree(x => x.Value != null, false).AddThumbnailIcons(); } //tree.EnumerateTree().ForEach(i => //{ // var t = i.Value as Type; // if (t != null) { i.SearchString = t.GetNiceFullName(); } //}); tree.Selection.SupportsMultiSelect = this.supportsMultiSelect; tree.Selection.SelectionChanged += (t) => { lastType = this.SelectionTree.Selection.Select(x => x.Value).OfType <Type>().LastOrDefault() ?? lastType; }; }
private void DrawTopBar() { Rect rect = SirenixEditorGUI.BeginHorizontalToolbar(); { var iconRect = rect.AlignLeft(SerializationInfoMenuItem.IconSize).AlignMiddle(SerializationInfoMenuItem.IconSize); iconRect.x += SerializationInfoMenuItem.IconSpacing * 2; GUI.color = (this.backendFlags & SerializationBackendFlags.Odin) != 0 ? Color.white : new Color(1f, 1f, 1f, 0.2f); GUI.DrawTexture(iconRect.Padding(2), EditorIcons.OdinInspectorLogo, ScaleMode.ScaleToFit); iconRect.x += SerializationInfoMenuItem.IconSize + SerializationInfoMenuItem.IconSpacing * 2; GUI.color = (this.backendFlags & SerializationBackendFlags.Unity) != 0 ? Color.white : new Color(1f, 1f, 1f, 0.2f); GUI.DrawTexture(iconRect.Padding(2), EditorIcons.UnityLogo, ScaleMode.ScaleToFit); GUI.color = Color.white; var typeName = " " + (this.targetType == null ? "Select Type" : this.targetType.GetNiceName().SplitPascalCase()) + " "; GUILayout.Space(iconRect.xMax + 3); bool selectB = SirenixEditorGUI.ToolbarButton(new GUIContent(typeName)); GUILayout.FlexibleSpace(); bool selectA = SirenixEditorGUI.ToolbarButton(EditorIcons.TriangleDown); if (selectA || selectB) { var btnRect = GUIHelper.GetCurrentLayoutRect().HorizontalPadding(20).AlignTop(20); btnRect = btnRect.AlignRight(400); var source = AssemblyUtilities.GetTypes(AssemblyTypeFlags.CustomTypes) .Where(x => !x.IsAbstract && x.IsClass && x.InheritsFrom <UnityEngine.Object>()) .Where(x => !x.Assembly.FullName.StartsWith("Sirenix")) .OrderBy(x => x.Assembly.GetAssemblyTypeFlag()) .OrderBy(x => x.Assembly.GetAssemblyTypeFlag()) .ThenBy(x => x.Namespace) .ThenByDescending(x => x.Name); var p = new TypeSelector(source, false); p.SelectionChanged += (types) => { var t = types.FirstOrDefault(); if (t != null) { this.targetType = t; this.odinContext = this.targetType.IsDefined <ShowOdinSerializedPropertiesInInspectorAttribute>(true); this.CreateMenuTree(true); } }; p.SetSelection(this.targetType); p.ShowInPopup(300); } } SirenixEditorGUI.EndHorizontalToolbar(); }
private void Reset() { var types = AssemblyUtilities.GetTypes(AssemblyTypeFlags.UserTypes | AssemblyTypeFlags.PluginTypes); var filteredTypes = types.Where(type => type.IsSubclassOf(typeof(Packet)) && !packetMappingPreset.ContainsValue(type) && !packetMapping.ContainsValue(type)).ToList(); var codeOffset = packetMapping.Count == 0 ? 100 : packetMapping.Keys.Max() + 1; for (var i = 0; i < filteredTypes.Count; ++i) { packetMapping.Add((ushort)(codeOffset + i), filteredTypes[i]); } }
static OdinDatabaseInitializer() { foreach (var type in AssemblyUtilities.GetTypes(AssemblyTypeFlags.All)) { if (!typeof(IOdinDatabase).IsAssignableFrom(type) || type.IsAbstract) { continue; } var info = typeof(GlobalConfig <>).MakeGenericType(type).GetProperty("Instance", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); if (info?.GetValue(null, null) == null) { return; } } }
/// <summary> /// Builds the selection tree. /// </summary> protected override void BuildSelectionTree(OdinMenuTree tree) { tree.DefaultMenuStyle.NotSelectedIconAlpha = 1f; if (types == null) { List <OdinMenuItem> items; if (cachedAllTypesMenuItems.TryGetValue(this.assemblyTypeFlags, out items)) { AddRecursive(tree, items, tree.MenuItems); } else { var assemblyTypes = OrderTypes(AssemblyUtilities.GetTypes(this.assemblyTypeFlags).Where(x => char.IsLetter(x.Name.Trim()[0]))); foreach (var t in assemblyTypes) { string path = string.IsNullOrEmpty(t.Namespace) ? t.GetNiceName() : t.Namespace + "/" + t.GetNiceName(); tree.AddObjectAtPath(path, t).AddThumbnailIcons(); } cachedAllTypesMenuItems[this.assemblyTypeFlags] = tree.MenuItems; } } else { foreach (var t in this.types) { string path = string.IsNullOrEmpty(t.Namespace) ? t.GetNiceName() : t.Namespace + "/" + t.GetNiceName(); tree.AddObjectAtPath(path, t); } tree.EnumerateTree(x => x.ObjectInstance != null, false).AddThumbnailIcons(); } tree.EnumerateTree().ForEach(i => { var t = i.ObjectInstance as Type; if (t != null) { i.SearchString = t.GetNiceFullName(); } }); tree.Selection.SupportsMultiSelect = this.supportsMultiSelect; tree.Selection.SelectionChanged += (t) => { lastType = this.SelectionTree.Selection.Select(x => x.ObjectInstance).OfType <Type>().LastOrDefault() ?? lastType; }; }
private IEnumerable GetAvailableHooks() { var notTheseHooks = new HashSet <Type>(); if (this.Hooks != null) { notTheseHooks.AddRange(this.Hooks.Where(n => n.Hook != null).Select(n => n.Hook.GetType())); } var availableHookTypes = AssemblyUtilities.GetTypes(AssemblyTypeFlags.CustomTypes) .Where(type => !type.IsAbstract && !type.IsInterface && !notTheseHooks.Contains(type) && typeof(IValidationHook).IsAssignableFrom(type) && type.GetConstructor(Type.EmptyTypes) != null).ToList(); return(availableHookTypes .Select(type => new AutomatedValidationHook((IValidationHook)Activator.CreateInstance(type))) .Select(x => new ValueDropdownItem(x.Hook.Name, x))); }
protected override OdinMenuTree BuildMenuTree() { var tree = new OdinMenuTree(); var branches = AssemblyUtilities.GetTypes(AssemblyTypeFlags.CustomTypes) .Where(x => x.InheritsFrom <IBranch>() && !x.IsAbstract); foreach (var item in branches) { var obj = Activator.CreateInstance(item); var branch = obj as IBranch; branch.Setup(tree); tree.Add(branch.Path, obj); } return(tree); }
static DatabaseInitializer() { if (UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode) { return; } foreach (var type in AssemblyUtilities.GetTypes(AssemblyTypeFlags.All)) { if (!typeof(IDatabase).IsAssignableFrom(type) || type.IsAbstract) { continue; } //Debug.Log($"Database Initialization of type: {type.Name}"); var info = typeof(GlobalConfig <>).MakeGenericType(type).GetProperty("Instance", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); if (info?.GetValue(null, null) == null) { return; } } }
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); }) ); }
private TypeTreeNode GetTypeTree(Type type) { TypeTreeNode rootNode; if (typeTrees.TryGetValue(type, out rootNode) == false) { var typeFlag = AssemblyUtilities.GetAssemblyTypeFlag(type.Assembly); var additionalTypes = new List <Type>() { typeof(NullType), type, typeof(string), typeof(List <>).MakeGenericType(type), type.MakeArrayType(), type.MakeArrayType(2), type.MakeArrayType(3) }; var additions = additionalTypes .Select(x => new { type = x, flag = (x == typeof(NullType) || x.IsArray) ? typeFlag : AssemblyUtilities.GetAssemblyTypeFlag(x.Assembly) }) .ToArray(); rootNode = typeTrees[type] = new TypeTreeNode() { ChildNodes = AssemblyUtilities .GetAllAssemblies() .Select(x => new { assembly = x, flag = AssemblyUtilities.GetAssemblyTypeFlag(x) }) .GroupBy(a => a.flag) .Select(a => new TypeTreeNode() { AssemblyTypeFlag = a.Key, IsVisible = (a.Key & AssemblyTypeFlags.UserTypes) != 0, ChildNodes = AssemblyUtilities .GetTypes(a.Key) .Where(x => ((a.Key & AssemblyTypeFlags.UserTypes) != 0 || x.IsPublic) && x != type) // Only include public types or types from User assembly. .Prepend(additions.Where(x => x.flag == a.Key).Select(x => x.type)) .Select(t => CanCreateInstance(type, ref t) ? t : null) .Where(t => t != null) .Distinct() .GroupBy(t => ((t == typeof(NullType) || t.IsArray) ? type : t).Namespace ?? "ALSO!GROUP!ME") .Select(g => new TypeTreeNode() { Namespace = (g.Key == "ALSO!GROUP!ME") ? null : g.Key, ChildNodes = g .Select(t => new TypeTreeNode() { Type = t }) .Where(x => x.Type == null || x.Type.GetNiceName().Contains('$') == false) .OrderBy(t => t.Type == typeof(NullType)) .ThenBy(t => t.Type == null ? "" : t.Type.Name) .ToList() }) .Where(x => x.Type == null || x.Type.GetNiceName().Contains('$') == false) .OrderBy(x => x.Namespace) .ThenBy(x => x.Type) .ToList() }) .OrderBy(x => x.AssemblyTypeFlag) .ToList() }; rootNode.IsVisible = true; rootNode.Initialize(this, null); } else { rootNode.Initialize(this, null); } this.hideFoldoutLabels = rootNode.EnumerateTree().Count(x => x.Type != null) < 20; if (this.hideFoldoutLabels) { foreach (var item in rootNode.EnumerateTree()) { item.IsVisible = true; } } else { var firstCollection = rootNode.EnumerateTree().FirstOrDefault(x => x.ChildNodes != null && x.ChildNodes.Count > 0); if (firstCollection != null) { firstCollection.IsVisible = true; } } var firstTypeNode = rootNode.EnumerateTree().FirstOrDefault(x => x.Type != null); if (firstTypeNode != null) { firstTypeNode.ForceSetSelected = true; } if (this.autoSelectFirst && firstTypeNode != null) { this.chosenType = firstTypeNode.Type; } return(rootNode); }
static DrawerLocator() { // 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 allTypes = AssemblyUtilities.GetTypes(AssemblyTypeFlags.CustomTypes | AssemblyTypeFlags.UnityEditorTypes) .Where(type => type.IsAbstract == false && type.IsClass && (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 (DrawerLocator.CustomPropertyDrawerTypeField != null && DrawerLocator.CustomPropertyDrawerUseForChildrenField != null) { unityPropertyDrawers = allTypes.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) && UnitySerializationUtility.GuessIfUnityWillSerialize(drawnType)) { return(true); } } return(false); }) .Select(n => { var drawnType = (Type)CustomPropertyDrawerTypeField.GetValue(n.Attribute); if (drawnType.IsAbstract || (bool)DrawerLocator.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 = allTypes.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)DrawerLocator.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 = allTypes.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)DrawerLocator.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; Unity PropertyDrawers and DecoratorDrawers have been disabled in the inspector."); unityPropertyDrawers = Enumerable.Empty <Type>(); unityPropertyAttributeDrawers = Enumerable.Empty <Type>(); unityDecoratorDrawers = Enumerable.Empty <Type>(); } // // Find, group and sort all defined property drawer types // DrawerLocator.PropertyDrawerInfos = allTypes.Where(type => type.ImplementsOpenGenericClass(typeof(OdinValueDrawer <>)) && type.GetConstructor(Type.EmptyTypes) != null && type.IsDefined <OdinDrawerAttribute>(false)) .Append(unityPropertyDrawers) .Select(drawerType => { Type drawnType; if (!DrawerIsValid(drawerType, out drawnType) || drawnType == null) { return(null); } return(new DrawerInfo(drawerType, drawnType, null, drawerType.GetAttribute <OdinDrawerAttribute>(false))); }) .Where(info => info != null) .Distinct() .OrderByDescending(info => info.Priority) .ToList(); DrawerLocator.AttributeDrawerInfos = allTypes.Where(type => type.ImplementsOpenGenericClass(typeof(OdinAttributeDrawer <>)) && type.GetConstructor(Type.EmptyTypes) != null && type.IsDefined <OdinDrawerAttribute>(false)) .Append(unityDecoratorDrawers) .Append(unityPropertyAttributeDrawers) .Select(type => { if (type.ImplementsOpenGenericClass(typeof(OdinAttributeDrawer <,>))) { Type drawnType; if (!DrawerIsValid(type, out drawnType)) { return(null); } Type[] args = type.GetArgumentsOfInheritedOpenGenericClass(typeof(OdinAttributeDrawer <,>)); return(new DrawerInfo(type, drawnType, args[0], type.GetAttribute <OdinDrawerAttribute>(false))); } else { return(new DrawerInfo(type, null, type.GetArgumentsOfInheritedOpenGenericClass(typeof(OdinAttributeDrawer <>))[0], type.GetAttribute <OdinDrawerAttribute>(false))); } }) .Where(info => info != null) .Distinct() .OrderByDescending(info => info.Priority) .ToList(); DrawerLocator.GroupDrawerInfos = allTypes.Where(type => type.IsGenericTypeDefinition == false && type.IsGenericType == false && type.ImplementsOpenGenericClass(typeof(OdinGroupDrawer <>)) && type.GetConstructor(Type.EmptyTypes) != null) .Select(type => new DrawerInfo(type, null, type.GetArgumentsOfInheritedOpenGenericClass(typeof(OdinGroupDrawer <>))[0], type.GetAttribute <OdinDrawerAttribute>(false))) .Where(info => info.OdinDrawerAttribute != null) .Distinct() .OrderByDescending(info => info.Priority) .ToList(); // // Register found drawers in various dictionaries // for (int i = 0; i < DrawerLocator.PropertyDrawerInfos.Count; i++) { var info = DrawerLocator.PropertyDrawerInfos[i]; DrawerLocator.DrawerTypePriorityLookup[info.DrawerType] = info.Priority; //Debug.Log("Found value drawer: " + info); } for (int i = 0; i < DrawerLocator.AttributeDrawerInfos.Count; i++) { var info = DrawerLocator.AttributeDrawerInfos[i]; DrawerLocator.DrawerTypePriorityLookup[info.DrawerType] = info.Priority; //Debug.Log("Found attribute drawer: " + info); // Also register in attribute value drawer maps if (info.DrawnValueType != null) { List <DrawerInfo> list; if (!DrawerLocator.AttributeDrawerMap.TryGetValue(info.DrawnAttributeType, out list)) { list = new List <DrawerInfo>(); DrawerLocator.AttributeDrawerMap.Add(info.DrawnAttributeType, list); } list.Add(info); } } }
/// <summary> /// Not yet documented. /// </summary> public static Type GuessContainedType(this SerializedProperty property) { switch (property.propertyType) { case SerializedPropertyType.Generic: return(null); case SerializedPropertyType.Integer: return(typeof(int)); case SerializedPropertyType.Boolean: return(typeof(bool)); case SerializedPropertyType.Float: return(typeof(float)); case SerializedPropertyType.String: return(typeof(string)); case SerializedPropertyType.Color: return(typeof(Color)); case SerializedPropertyType.ObjectReference: { if (!object.ReferenceEquals(property.objectReferenceValue, null)) { return(property.objectReferenceValue.GetType()); } string typeName = property.GetProperTypeName(); var possibles = AssemblyUtilities.GetTypes(AssemblyTypeFlags.UnityTypes | AssemblyTypeFlags.UnityEditorTypes) .Where(n => n.Name == typeName && typeof(UnityEngine.Object).IsAssignableFrom(n)) .ToList(); if (possibles.Count == 1) { return(possibles[0]); } return(null); } case SerializedPropertyType.LayerMask: return(typeof(LayerMask)); case SerializedPropertyType.Enum: return(null); case SerializedPropertyType.Vector2: return(typeof(Vector2)); case SerializedPropertyType.Vector3: return(typeof(Vector3)); case SerializedPropertyType.Vector4: return(typeof(Vector4)); case SerializedPropertyType.Rect: return(typeof(Rect)); case SerializedPropertyType.ArraySize: return(null); case SerializedPropertyType.Character: return(typeof(char)); case SerializedPropertyType.AnimationCurve: return(typeof(AnimationCurve)); case SerializedPropertyType.Bounds: return(typeof(Bounds)); case SerializedPropertyType.Gradient: return(typeof(Gradient)); case SerializedPropertyType.Quaternion: return(typeof(Quaternion)); default: return(null); } }
static InspectorTypeDrawingConfigDrawer() { NeverDrawTypes = new HashSet <Type>(); { var networkView = AssemblyUtilities.GetTypeByCachedFullName("UnityEngine.NetworkView"); if (networkView != null) { NeverDrawTypes.Add(networkView); } var gUIText = AssemblyUtilities.GetTypeByCachedFullName("UnityEngine.GUIText"); if (gUIText != null) { NeverDrawTypes.Add(gUIText); } } var unityObjectTypes = AssemblyUtilities.GetTypes(AssemblyTypeFlags.All) // @Tor: Consider switching to AssemblyTypeFlags.CustomTypes? .Where(type => !type.Assembly.IsDynamic() && typeof(UnityEngine.Object).IsAssignableFrom(type) && //TypeExtensions.IsValidIdentifier(type.FullName) && !type.IsDefined <CompilerGeneratedAttribute>() && !type.IsDefined <ObsoleteAttribute>() && !typeof(Joint).IsAssignableFrom(type) && !NeverDrawTypes.Contains(type)) .ToArray(); Dictionary <Type, Type> haveDrawersAlready = new Dictionary <Type, Type>(); Dictionary <Type, Type> derivedClassDrawnTypes = new Dictionary <Type, Type>(); unityObjectTypes.ForEach(type => { if (typeof(Editor).IsAssignableFrom(type)) { try { bool editorForChildClasses; var drawnType = InspectorTypeDrawingConfig.GetEditorDrawnType(type, out editorForChildClasses); if (drawnType != null) { if (!haveDrawersAlready.ContainsKey(drawnType)) { haveDrawersAlready.Add(drawnType, type); } if (editorForChildClasses && !derivedClassDrawnTypes.ContainsKey(drawnType)) { derivedClassDrawnTypes.Add(drawnType, type); } } if (/*type.IsVisible && */ InspectorTypeDrawingConfig.UnityInspectorEditorIsValidBase(type, null)) { PossibleEditorTypes.Add(type); } } catch (TypeLoadException) { } catch (ReflectionTypeLoadException) { } } }); HashSet <Type> stopBaseTypeLookUpTypes = new HashSet <Type>() { typeof(object), typeof(Component), typeof(Behaviour), typeof(MonoBehaviour), typeof(UnityEngine.Object), typeof(ScriptableObject), typeof(StateMachineBehaviour), //typeof(Networking.NetworkBehaviour) }; if (UnityNetworkingUtility.NetworkBehaviourType != null) { // UnityEngine.Networking has been removed in Unity 2019+. stopBaseTypeLookUpTypes.Add(UnityNetworkingUtility.NetworkBehaviourType); } //Debug.Log("Searching the following " + unityObjectTypes.Length + " types for Odin-drawable types:\n\n" + string.Join("\n", unityObjectTypes.Select(n => n.GetNiceFullName()).ToArray())); unityObjectTypes.Where(type => /*type.IsVisible && */ !type.IsAbstract && !type.IsGenericTypeDefinition && !type.IsGenericType && !typeof(Editor).IsAssignableFrom(type) && !typeof(EditorWindow).IsAssignableFrom(type)) .ForEach(type => { Type preExistingEditorType; bool haveDrawerAlready = haveDrawersAlready.TryGetValue(type, out preExistingEditorType); if (!haveDrawerAlready) { Type baseType = type.BaseType; while (baseType != null && !stopBaseTypeLookUpTypes.Contains(baseType)) { Type editor; if (derivedClassDrawnTypes.TryGetValue(baseType, out editor)) { haveDrawerAlready = true; preExistingEditorType = editor; break; } baseType = baseType.BaseType; } } if (!haveDrawerAlready) { PossibleDrawnTypes.Add(type); } AddTypeToGroups(type, preExistingEditorType); }); //Debug.Log("Found the following " + PossibleDrawnTypes.Count + " types that Odin can draw:\n\n" + string.Join("\n", PossibleDrawnTypes.Select(n => n.GetNiceFullName()).ToArray())); // Remove editor entries for any types that are not eligible to be drawn { bool fixedAny = false; foreach (var type in InspectorConfig.Instance.DrawingConfig.GetAllDrawnTypesWithEntries()) { if (!PossibleDrawnTypes.Contains(type)) { InspectorConfig.Instance.DrawingConfig.ClearEditorEntryForDrawnType(type); fixedAny = true; } } if (fixedAny) { AssetDatabase.SaveAssets(); } } UpdateRootGroupHasEligibletypes(); UpdateRootGroupConflicts(); SortRootGroups(); UpdateRootGroupsSearch("", DisplayType.AllUnityObjects); }
private IEnumerable <Type> GetAssetTypes() => AssemblyUtilities.GetTypes(AssemblyTypeFlags.UserTypes) .Where(x => x.InheritsFrom <ScriptableObject>() && !x.IsAbstract);