///HELP AREA
        void DoFooter(Rect helpRect, Event e)
        {
            helpRectRequiredHeight = 0;
            var hoveringNode = hoveringIndex >= 0 && currentNode.children.Count > 0? currentNode.children.Values.ToList()[hoveringIndex] : null;

            GUI.color = new Color(0, 0, 0, 0.3f);
            GUI.Box(helpRect, string.Empty, (GUIStyle)"TextField");
            GUI.color = Color.white;
            GUILayout.BeginArea(helpRect);
            GUILayout.BeginVertical();
            var doc = string.Empty;

            if (hoveringNode != null && hoveringNode.item != null)
            {
                doc = hoveringNode.item.content.tooltip;
                var memberInfo = hoveringNode.item.userData as MemberInfo;
                if (memberInfo != null && string.IsNullOrEmpty(doc))
                {
                    if (memberInfo is System.Type)
                    {
                        doc = UserTypePrefs.GetTypeDoc(memberInfo);
                    }
                    else
                    {
                        doc = DocsByReflection.GetMemberSummary(memberInfo);
                    }
                }
            }

            GUILayout.Label(string.Format("<size=9>{0}</size>", doc), helpStyle);
            GUILayout.EndVertical();
            GUILayout.EndArea();
        }
        ///Get a list of ScriptInfos of the baseType excluding: the base type, abstract classes, Obsolete classes and those with the DoNotList attribute, from within the project categorized as a list of ScriptInfo
        public static List <ScriptInfo> GetScriptInfosOfType(Type baseType)
        {
            var infos = new List <ScriptInfo>();

            foreach (var subType in GetAssemblyTypes(baseType))
            {
                if (subType.GetCustomAttributes(typeof(DoNotListAttribute), false).FirstOrDefault() == null && subType.GetCustomAttributes(typeof(ObsoleteAttribute), false).FirstOrDefault() == null)
                {
                    if (subType.IsAbstract)
                    {
                        continue;
                    }

                    var scriptName     = subType.FriendlyName().SplitCamelCase();
                    var scriptCategory = string.Empty;

                    var nameAttribute = subType.GetCustomAttributes(typeof(NameAttribute), false).FirstOrDefault() as NameAttribute;
                    if (nameAttribute != null)
                    {
                        scriptName = nameAttribute.name;
                    }

                    var categoryAttribute = subType.GetCustomAttributes(typeof(CategoryAttribute), true).FirstOrDefault() as CategoryAttribute;
                    if (categoryAttribute != null)
                    {
                        scriptCategory = categoryAttribute.category;
                    }

                    //show the generic types based on constrains and prefered types list
                    if (subType.IsGenericTypeDefinition && subType.GetGenericArguments().Length == 1)
                    {
                        var arg1          = subType.GetGenericArguments()[0];
                        var constrains    = arg1.GetGenericParameterConstraints();
                        var constrainType = constrains.Length == 0? typeof(object) : constrains[0];
                        foreach (var t in UserTypePrefs.GetPreferedTypesList(constrainType, false))
                        {
                            var genericType       = subType.MakeGenericType(new System.Type[] { t });
                            var finalCategoryPath = (string.IsNullOrEmpty(scriptCategory)? "" : (scriptCategory + "/")) + scriptName;
                            finalCategoryPath  = finalCategoryPath.Replace("<T>", " (T)");
                            finalCategoryPath += "/" + (string.IsNullOrEmpty(t.Namespace)? "No Namespace" : t.Namespace.Replace(".", "/"));
                            var finalName = scriptName.Replace("<T>", string.Format(" ({0})", t.FriendlyName()));
                            infos.Add(new ScriptInfo(genericType, finalName, finalCategoryPath));
                        }
                        continue;
                    }
                    //

                    infos.Add(new ScriptInfo(subType, scriptName, scriptCategory));
                }
            }

            infos = infos.OrderBy(script => script.name).ToList();
            infos = infos.OrderBy(script => script.category).ToList();

            return(infos);
        }
        void OnEnable()
        {
                #if UNITY_5
            titleContent = new GUIContent("Preferred Types");
                #else
            title = "Preferred Types";
                #endif

            typeList = UserTypePrefs.GetPreferedTypesList(typeof(object), true);
        }
예제 #4
0
파일: EditorUtils.cs 프로젝트: gbyh/XGame
            public ScriptInfo(Type type, string name, string category, int priority = 0)
            {
                this.type     = type;
                this.name     = name;
                this.category = category;
                this.priority = priority;
                if (type != null)
                {
                    var iconAtt = type.RTGetAttribute <IconAttribute>(true);
                    icon = iconAtt != null?UserTypePrefs.GetTypeIcon(iconAtt) : null;

                    var descAtt = type.RTGetAttribute <DescriptionAttribute>(true);
                    description = descAtt != null? descAtt.description : description;
                }
            }
        public static GenericMenu GetPreferedTypesSelectionMenu(Type type, Action <Type> callback, bool showInterfaces = true, GenericMenu menu = null, string subCategory = null)
        {
            if (menu == null)
            {
                menu = new GenericMenu();
            }

            if (subCategory != null)
            {
                subCategory = subCategory + "/";
            }

            GenericMenu.MenuFunction2 Selected = delegate(object t){
                callback((Type)t);
            };

            var listTypes = new Dictionary <Type, string>();

            foreach (var t in UserTypePrefs.GetPreferedTypesList(typeof(object), true))
            {
                if (type.IsAssignableFrom(t) || (t.IsInterface && showInterfaces))
                {
                    var nsString    = string.IsNullOrEmpty(t.Namespace)? "No Namespace/" : (t.Namespace.Replace(".", "/") + "/");
                    var finalString = nsString + t.FriendlyName();
                    menu.AddItem(new GUIContent(subCategory + finalString), false, Selected, t);
                    // listTypes.Add( typeof(List<>).MakeGenericType(new Type[]{t}), finalString );
                    listTypes[typeof(List <>).MakeGenericType(new Type[] { t })] = finalString;
                }
            }

            //menu.AddSeparator(subCategory + "/");
            foreach (var tPair in listTypes)
            {
                menu.AddItem(new GUIContent(subCategory + "List<T>/" + tPair.Value), false, Selected, tPair.Key);
            }

            menu.AddItem(new GUIContent(subCategory + "Add Type..."), false, () => { PreferedTypesEditorWindow.ShowWindow(); });

            return(menu);
        }
        public static void GenerateLinkXML(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                return;
            }

            var spoofTypes = UserTypePrefs.GetPreferedTypesList(typeof(UnityEngine.Object), true);
            var pairs      = new Dictionary <string, List <Type> >();

            foreach (var type in spoofTypes)
            {
                var asmName = type.Assembly.GetName().Name;
                if (!pairs.ContainsKey(asmName))
                {
                    pairs[asmName] = new List <Type>();
                }
                pairs[asmName].Add(type);
            }

            var sb = new StringBuilder();

            sb.AppendLine("<linker>");

            foreach (var pair in pairs)
            {
                sb.AppendLine(string.Format("	<assembly fullname=\"{0}\">", pair.Key));

                foreach (var type in pair.Value)
                {
                    sb.AppendLine("		<type fullname=\""+ type.FullName + "\" preserve=\"all\"/>");
                }

                sb.AppendLine("	</assembly>");
            }

            sb.AppendLine("</linker>");
            File.WriteAllText(path, sb.ToString());
        }
        public static void GenerateAOTClasses(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                return;
            }

            var spoofTypes = defaultSpoofTypes;

            spoofTypes.AddRange(UserTypePrefs.GetPreferedTypesList(typeof(object), true).Where(t => t.IsValueType && !spoofTypes.Contains(t)));
            var types = EditorUtils.GetAssemblyTypes(typeof(object)).Where(t => t.RTGetAttribute <SpoofAOTAttribute>(true) != null).ToList();

            var nClasses = 0;
            var nMethods = 0;

            var sb = new StringBuilder();

            sb.AppendLine("#pragma warning disable 0219, 0168, 0612");
            sb.AppendLine("namespace ParadoxNotion.Internal{");
            sb.AppendLine();
            sb.AppendLine("	//Auto generated classes for AOT support, where using undeclared generic classes with value types is limited. These are not actualy used but rather just declared for the compiler");
            sb.AppendLine("	class AOTDummy{");
            sb.AppendLine();
            sb.AppendLine("		object o = null;");



            foreach (var type in types)
            {
                if (!type.IsAbstract && type.IsGenericTypeDefinition && type.GetGenericArguments().Length == 1)
                {
                    var constrains = type.GetGenericArguments()[0].GetGenericParameterConstraints();
                    if (constrains.Length == 0 || constrains[0].IsValueType)
                    {
                        if (typeof(Delegate).IsAssignableFrom(type))
                        {
                            nClasses++;
                            sb.AppendLine(string.Format("		void {0}()", type.FriendlyName(true).Replace(".", "_").Replace("<T>", "_Delegate")) + "{");
                            foreach (var spoofType in spoofTypes)
                            {
                                var a = type.FriendlyName(true).Replace("<T>", "<" + spoofType.FullName + ">").Replace("+", ".");
                                var b = "_" + type.FriendlyName().Replace("<T>", "_" + spoofType.FullName.Replace(".", "_").Replace("+", "_"));
                                sb.AppendLine(string.Format("			{0} {1} = null;", a, b));
                            }
                            sb.AppendLine("		}");
                        }
                        else
                        {
                            foreach (var spoofType in spoofTypes)
                            {
                                nClasses++;
                                var a = type.FriendlyName(true).Replace(".", "_").Replace("<T>", "_" + spoofType.FullName.Replace(".", "_").Replace("+", "_"));
                                var b = type.FriendlyName(true).Replace("<T>", "<" + spoofType.FullName + ">").Replace("+", ".") + "{}";
                                sb.AppendLine(string.Format("		class {0} : {1}", a, b));
                            }
                        }

                        sb.AppendLine();
                    }
                }
            }

            foreach (var type in types)
            {
                var index = 0;
                foreach (var method in type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly))
                {
                    if (method.IsGenericMethodDefinition && method.GetGenericArguments().Length == 1)
                    {
                        var constrains = method.GetGenericArguments()[0].GetGenericParameterConstraints();
                        if (constrains.Length == 0 || constrains[0].IsValueType)
                        {
                            index++;

                            var decType = method.DeclaringType;
                            var varName = "_" + decType.FullName.Replace(".", "_");
                            sb.AppendLine(string.Format("		void {0}_{1}_{2}()", decType.FullName.Replace(".", "_"), method.Name, index) + " {");
                            if (!method.IsStatic)
                            {
                                sb.AppendLine(string.Format("			{0} {1} = null;", decType.FullName, varName));
                            }

                            foreach (var spoofType in spoofTypes)
                            {
                                nMethods++;
                                var a            = method.IsStatic? decType.FullName : varName;
                                var b            = method.Name;
                                var c            = spoofType.FullName.Replace("+", ".");
                                var paramsString = "";
                                var parameters   = method.GetParameters();
                                for (var i = 0; i < parameters.Length; i++)
                                {
                                    var parameter = parameters[i];
                                    var toString  = parameter.ParameterType.FullName;
                                    if (parameter.ParameterType.IsGenericParameter)
                                    {
                                        toString = spoofType.FullName;
                                    }
                                    if (parameter.ParameterType.IsGenericType)
                                    {
                                        toString = parameter.ParameterType.FriendlyName(true).Replace("<T>", "<" + spoofType.FullName + ">");
                                        toString = toString.Replace("[[T]]", "");
                                    }
                                    toString      = toString.Replace("+", ".");
                                    paramsString += string.Format("({0})o", toString);
                                    if (i < parameters.Length - 1)
                                    {
                                        paramsString += ", ";
                                    }
                                }
                                var d = paramsString;
                                sb.AppendLine(string.Format("			{0}.{1}<{2}>( {3} );", a, b, c, d));
                            }

                            sb.AppendLine("		}");
                            sb.AppendLine();
                        }
                    }
                }
            }

            //custom stuff
            sb.AppendLine("		void CustomSpoof(){");
            foreach (var spoofType in spoofTypes)
            {
                var sName = spoofType.FullName.Replace("+", ".");
                var fName = spoofType.FullName.Replace(".", "_").Replace("+", "_");
                sb.AppendLine(string.Format("			System.Action<{0}> Action_{1};", sName, fName));
                sb.AppendLine(string.Format("			System.Func<{0}> Func_{1};", sName, fName));
                sb.AppendLine(string.Format("			System.Collections.Generic.IList<{0}> List_{1};", sName, fName));
                sb.AppendLine(string.Format("			System.Collections.Generic.IDictionary<System.String, {0}> Dict_{1};", sName, fName));
            }
            sb.AppendLine("		}");

            sb.AppendLine("	}");
            sb.AppendLine("}");
            sb.AppendLine();
            sb.AppendLine(string.Format("//{0} Classes | {1} Methods", nClasses, nMethods));
            sb.AppendLine("#pragma warning restore 0219, 0168, 0612");

            File.WriteAllText(path, sb.ToString());
        }
 //...
 void OnEnable()
 {
     titleContent = new GUIContent("Preferred Types");
     typeList     = UserTypePrefs.GetPreferedTypesList();
     alltypes     = ReflectionTools.GetAllTypes(true).Where(t => !t.IsGenericType && !t.IsGenericTypeDefinition).ToList();
 }
        //THE TREE
        void DoTree(Rect treeRect, Event e)
        {
            GUILayout.BeginArea(treeRect);

            scrollPos = EditorGUILayout.BeginScrollView(scrollPos, false, false);
            GUILayout.BeginVertical();

            if (search != lastSearch)
            {
                hoveringIndex = 0;
                if (!string.IsNullOrEmpty(search))
                {
                    var results = new List <Node>();
                    foreach (var node in leafNodes)
                    {
                        if (filterFavorites && !node.isFavorite)
                        {
                            continue;
                        }
                        if (StringUtils.SearchMatch(search, node.name, node.category))
                        {
                            results.Add(node);
                        }
                    }
                    var searchRootNode = new Node()
                    {
                        name = "Search Root"
                    };
                    //Remaks: scoring is done on category name instead of leaf name
                    searchRootNode.children = results
                                              .OrderBy(r => StringUtils.ScoreSearchMatch(search, r.category, r.category) * (r.isFavorite? 0.5f : 1))
                                              .ToDictionary(r => r.fullPath, r => r);
                    currentNode = searchRootNode;
                }
                else
                {
                    currentNode = rootNode;
                }
                lastSearch = search;
            }

            ///----------------------------------------------------------------------------------------------

            var    i                  = 0;
            var    itemAdded          = false;
            string lastSearchCategory = null;

            foreach (var childPair in currentNode.children)
            {
                var node       = childPair.Value;
                var leafItem   = node.item;
                var memberInfo = leafItem != null? leafItem.userData as MemberInfo : null;
                var isDisabled = leafItem != null && leafItem.func == null && leafItem.func2 == null;
                var icon       = leafItem != null? leafItem.content.image : Icons.folderIcon;
                if (icon == null && memberInfo != null)
                {
                    icon = UserTypePrefs.GetTypeIcon(memberInfo);
                }

                //when within search, show category on top
                if (!string.IsNullOrEmpty(search))
                {
                    var searchCategory = lastSearchCategory;
                    if (memberInfo == null || memberInfo is System.Type)
                    {
                        searchCategory = node.parent.fullPath != null?node.parent.fullPath.Split(new char[] { '/' }, System.StringSplitOptions.RemoveEmptyEntries).FirstOrDefault() : null;
                    }
                    else
                    {
                        searchCategory = memberInfo.ReflectedType.FriendlyName();
                    }

                    if (searchCategory != lastSearchCategory)
                    {
                        lastSearchCategory = searchCategory;
                        GUI.color          = EditorGUIUtility.isProSkin? Color.black : Color.white;
                        GUILayout.BeginHorizontal("box");
                        GUI.color = Color.white;
                        GUILayout.Label(searchCategory, Styles.leftLabel, GUILayout.Height(16));
                        GUILayout.EndHorizontal();
                    }
                }
                //


                if (filterFavorites && !node.isFavorite && !node.HasAnyFavoriteChild())
                {
                    continue;
                }

                if (leafItem != null && leafItem.separator)
                {
                    EditorUtils.Separator();
                    continue;
                }

                itemAdded = true;

                GUI.color = EditorGUIUtility.isProSkin? Color.white : new Color(0.8f, 0.8f, 0.8f, 1);
                GUILayout.BeginHorizontal("box");

                //Prefix icon
                GUI.color = Color.white;
                GUILayout.Label(icon, GUILayout.Width(32), GUILayout.Height(16));
                GUI.enabled = !isDisabled;

                //Favorite
                if (currentKeyType != null)
                {
                    GUI.color = node.isFavorite? Color.white : (node.HasAnyFavoriteChild()? new Color(1, 1, 1, 0.2f) : new Color(0f, 0f, 0f, 0.4f));
                    if (GUILayout.Button(Icons.favoriteIcon, GUIStyle.none, GUILayout.Width(16), GUILayout.Height(16)))
                    {
                        node.ToggleFavorite();
                    }
                    GUI.color = Color.white;
                }

                //Content
                var label = node.name;
                var text  = string.Format("<size=9>{0}</size>", (leafItem == null? string.Format("<b>{0}</b>", label) : label));
                GUILayout.Box(text, (GUIStyle)"label", GUILayout.Width(0), GUILayout.ExpandWidth(true));
                GUILayout.Label(leafItem != null? "●" : "►", GUILayout.Width(20));
                GUILayout.EndHorizontal();

                var elementRect = GUILayoutUtility.GetLastRect();
                if (e.type == EventType.MouseDown && e.button == 0 && elementRect.Contains(e.mousePosition))
                {
                    e.Use();
                    if (leafItem != null)
                    {
                        ExecuteItemFunc(leafItem);
                        break;
                    }
                    else
                    {
                        currentNode   = node;
                        hoveringIndex = 0;
                        break;
                    }
                }

                if (e.type == EventType.MouseMove && elementRect.Contains(e.mousePosition))
                {
                    hoveringIndex = i;
                }

                if (hoveringIndex == i)
                {
                    GUI.color = hoverColor;
                    GUI.DrawTexture(elementRect, EditorGUIUtility.whiteTexture);
                    GUI.color = Color.white;
                }

                i++;
                GUI.enabled = true;
            }

            if (hoveringIndex != lastHoveringIndex)
            {
                base.editorWindow.Repaint();
                lastHoveringIndex = hoveringIndex;
            }

            if (!itemAdded)
            {
                GUILayout.Label("No results to display with current search and filter combination");
            }

            GUILayout.EndVertical();
            EditorGUILayout.EndScrollView();
            GUILayout.EndArea();
        }
 void Save()
 {
     UserTypePrefs.SetPreferedTypesList(typeList);
     ShowNotification(new GUIContent("Configuration Saved!"));
 }
예제 #11
0
        public static List <ScriptInfo> GetScriptInfosOfType(Type baseType, Type extraGenericType = null)
        {
            List <ScriptInfo> infos;

            if (cachedInfos.TryGetValue(baseType, out infos))
            {
                return(infos);
            }

            infos = new List <ScriptInfo>();

            var subTypes = GetAssemblyTypes(baseType);

            if (baseType.IsGenericTypeDefinition)
            {
                subTypes = new List <Type> {
                    baseType
                };
            }

            foreach (var subType in subTypes)
            {
                if (subType.GetCustomAttributes(typeof(DoNotListAttribute), false).FirstOrDefault() == null && subType.GetCustomAttributes(typeof(ObsoleteAttribute), false).FirstOrDefault() == null)
                {
                    if (subType.IsAbstract)
                    {
                        continue;
                    }

                    var scriptName     = subType.FriendlyName().SplitCamelCase();
                    var scriptCategory = string.Empty;

                    var nameAttribute = subType.GetCustomAttributes(typeof(NameAttribute), false).FirstOrDefault() as NameAttribute;
                    if (nameAttribute != null)
                    {
                        scriptName = nameAttribute.name;
                    }

                    var categoryAttribute = subType.GetCustomAttributes(typeof(CategoryAttribute), true).FirstOrDefault() as CategoryAttribute;
                    if (categoryAttribute != null)
                    {
                        scriptCategory = categoryAttribute.category;
                    }


                    //add the generic types based on constrains and prefered types list
                    if (subType.IsGenericTypeDefinition && subType.GetGenericArguments().Length == 1)
                    {
                        //infos.Add(new ScriptInfo(null, scriptName.Replace("<T>", " (T)/" + "Generic Argument"), scriptCategory));

                        var arg1          = subType.GetGenericArguments()[0];
                        var constrains    = arg1.GetGenericParameterConstraints();
                        var constrainType = constrains.Length == 0? typeof(object) : constrains[0];
                        var types         = UserTypePrefs.GetPreferedTypesList(constrainType, true);

                        if (extraGenericType != null)
                        {
                            types.Add(extraGenericType);
                        }

                        foreach (var t in types)
                        {
                            var genericType       = subType.MakeGenericType(new System.Type[] { t });
                            var finalCategoryPath = (string.IsNullOrEmpty(scriptCategory)? "" : (scriptCategory + "/")) + scriptName;
                            finalCategoryPath  = finalCategoryPath.Replace("<T>", " (T)");
                            finalCategoryPath += "/" + (string.IsNullOrEmpty(t.Namespace)? "No Namespace" : t.Namespace.Replace(".", "/"));
                            var finalName = scriptName.Replace("<T>", string.Format(" ({0})", t.FriendlyName()));
                            infos.Add(new ScriptInfo(genericType, finalName, finalCategoryPath));

                            if (constrainType == typeof(object))
                            {
                                var appendListTypesAtt = subType.RTGetAttribute <AppendListTypesAttribute>(true);
                                if (appendListTypesAtt != null)
                                {
                                    var listType  = typeof(List <>).MakeGenericType(new Type[] { t });
                                    var finalType = subType.MakeGenericType(new Type[] { listType });
                                    var cat       = scriptName.Replace("<T>", " (T)");
                                    var nam       = scriptName.Replace("<T>", string.Format(" ({0})", listType.FriendlyName()));
                                    infos.Add(new ScriptInfo(finalType, nam, scriptCategory + "/" + cat + "/List (T)"));
                                }
                            }
                        }
                    }
                    else
                    {
                        infos.Add(new ScriptInfo(subType, scriptName, scriptCategory));
                    }
                }
            }

            infos = infos.OrderBy(script => script.name).ToList();
            infos = infos.OrderBy(script => script.category).ToList();

            return(cachedInfos[baseType] = infos);
        }
예제 #12
0
 void Save()
 {
     UserTypePrefs.SetPreferedTypesList(typeList);
 }
예제 #13
0
        //For generic automatic editors. Passing a MemberInfo will also check for attributes
        public static object GenericField(string name, object value, Type t, MemberInfo member = null, object instance = null)
        {
            if (t == null)
            {
                GUILayout.Label("NO TYPE PROVIDED!");
                return(value);
            }

            //Preliminary Hides
            if (typeof(Delegate).IsAssignableFrom(t))
            {
                return(value);
            }

            name = name.SplitCamelCase();

            //

            IEnumerable <Attribute> attributes = new Attribute[0];

            if (member != null)
            {
                //Hide class?
                if (t.GetCustomAttributes(typeof(HideInInspector), true).FirstOrDefault() != null)
                {
                    return(value);
                }

                attributes = member.GetCustomAttributes(true).Cast <Attribute>();

                //Hide field?
                if (attributes.Any(a => a is HideInInspector))
                {
                    return(value);
                }

                //Is required?
                if (attributes.Any(a => a is RequiredFieldAttribute))
                {
                    if ((value == null || value.Equals(null)) ||
                        (t == typeof(string) && string.IsNullOrEmpty((string)value)) ||
                        (typeof(BBParameter).IsAssignableFrom(t) && (value as BBParameter).isNull))
                    {
                        GUI.backgroundColor = lightRed;
                    }
                }
            }


            if (member != null)
            {
                var nameAtt = attributes.FirstOrDefault(a => a is NameAttribute) as NameAttribute;
                if (nameAtt != null)
                {
                    name = nameAtt.name;
                }

                if (instance != null)
                {
                    var showAtt = attributes.FirstOrDefault(a => a is ShowIfAttribute) as ShowIfAttribute;
                    if (showAtt != null)
                    {
                        var targetField = instance.GetType().GetField(showAtt.fieldName);
                        if (targetField == null || targetField.FieldType != typeof(bool))
                        {
                            GUILayout.Label(string.Format("[ShowIf] Error: bool \"{0}\" does not exist.", showAtt.fieldName));
                        }
                        else
                        {
                            if ((bool)targetField.GetValue(instance) != showAtt.show)
                            {
                                return(value);
                            }
                        }
                    }
                }
            }


            //Before everything check BBParameter
            if (typeof(BBParameter).IsAssignableFrom(t))
            {
                return(BBParameterField(name, (BBParameter)value, false, member));
            }


            //Cutstom object drawers
            var objectDrawer = GetCustomDrawer(t);

            if (objectDrawer != null && !(objectDrawer is NoDrawer))
            {
                return(objectDrawer.DrawGUI(name, value, member as FieldInfo, null, instance));
            }

            //Cutstom attribute drawers
            foreach (CustomDrawerAttribute att in attributes.OfType <CustomDrawerAttribute>())
            {
                var attributeDrawer = GetCustomDrawer(att.GetType());
                if (attributeDrawer != null && !(attributeDrawer is NoDrawer))
                {
                    return(attributeDrawer.DrawGUI(name, value, member as FieldInfo, att, instance));
                }
            }


            //Then check UnityObjects
            if (typeof(UnityObject).IsAssignableFrom(t))
            {
                if (t == typeof(Component) && (Component)value != null)
                {
                    return(ComponentField(name, (Component)value, typeof(Component)));
                }
                return(EditorGUILayout.ObjectField(name, (UnityObject)value, t, true));
            }

            //Force UnityObject field?
            if (member != null && attributes.Any(a => a is ForceObjectFieldAttribute))
            {
                return(EditorGUILayout.ObjectField(name, value as UnityObject, t, true));
            }

            //Restricted popup values?
            if (member != null)
            {
                var popAtt = attributes.FirstOrDefault(a => a is PopupFieldAttribute) as PopupFieldAttribute;
                if (popAtt != null)
                {
                    if (popAtt.staticPath != null)
                    {
                        try
                        {
                            var typeName  = popAtt.staticPath.Substring(0, popAtt.staticPath.LastIndexOf("."));
                            var type      = ReflectionTools.GetType(typeName);
                            var start     = popAtt.staticPath.LastIndexOf(".") + 1;
                            var end       = popAtt.staticPath.Length;
                            var propName  = popAtt.staticPath.Substring(start, end - start);
                            var prop      = type.GetProperty(propName, BindingFlags.Static | BindingFlags.Public);
                            var propValue = prop.GetValue(null, null);
                            var values    = ((IEnumerable)propValue).Cast <object>().ToList();
                            return(Popup <object>(name, value, values));
                        }
                        catch
                        {
                            EditorGUILayout.LabelField(name, "[PopupField] attribute error!");
                            return(value);
                        }
                    }
                    return(Popup <object>(name, value, popAtt.values.ToList()));
                }
            }


            //Check Type of Type
            if (t == typeof(Type))
            {
                return(Popup <Type>(name, (Type)value, UserTypePrefs.GetPreferedTypesList(typeof(object), false)));
            }

            //Check abstract
            if ((value != null && value.GetType().IsAbstract) || (value == null && t.IsAbstract))
            {
                EditorGUILayout.LabelField(name, string.Format("Abstract ({0})", t.FriendlyName()));
                return(value);
            }

            //Create instance for some types
            if (value == null && !t.IsAbstract && !t.IsInterface && (t.IsValueType || t.GetConstructor(Type.EmptyTypes) != null || t.IsArray))
            {
                if (t.IsArray)
                {
                    value = Array.CreateInstance(t.GetElementType(), 0);
                }
                else
                {
                    value = Activator.CreateInstance(t);
                }
            }



            //Check the rest
            //..............
            if (t == typeof(string))
            {
                if (member != null)
                {
                    if (attributes.Any(a => a is TagFieldAttribute))
                    {
                        return(EditorGUILayout.TagField(name, (string)value));
                    }
                    var areaAtt = attributes.FirstOrDefault(a => a is TextAreaFieldAttribute) as TextAreaFieldAttribute;
                    if (areaAtt != null)
                    {
                        GUILayout.Label(name);
                        var areaStyle = new GUIStyle(GUI.skin.GetStyle("TextArea"));
                        areaStyle.wordWrap = true;
                        var s = EditorGUILayout.TextArea((string)value, areaStyle, GUILayout.Height(areaAtt.height));
                        return(s);
                    }
                }

                return(EditorGUILayout.TextField(name, (string)value));
            }

            if (t == typeof(bool))
            {
                return(EditorGUILayout.Toggle(name, (bool)value));
            }

            if (t == typeof(int))
            {
                if (member != null)
                {
                    var sField = attributes.FirstOrDefault(a => a is SliderFieldAttribute) as SliderFieldAttribute;
                    if (sField != null)
                    {
                        return((int)EditorGUILayout.Slider(name, (int)value, (int)sField.left, (int)sField.right));
                    }
                    if (attributes.Any(a => a is LayerFieldAttribute))
                    {
                        return(EditorGUILayout.LayerField(name, (int)value));
                    }
                }

                return(EditorGUILayout.IntField(name, (int)value));
            }

            if (t == typeof(float))
            {
                if (member != null)
                {
                    var sField = attributes.FirstOrDefault(a => a is SliderFieldAttribute) as SliderFieldAttribute;
                    if (sField != null)
                    {
                        return(EditorGUILayout.Slider(name, (float)value, sField.left, sField.right));
                    }
                }
                return(EditorGUILayout.FloatField(name, (float)value));
            }

            if (t == typeof(byte))
            {
                return(Convert.ToByte(Mathf.Clamp(EditorGUILayout.IntField(name, (byte)value), 0, 255)));
            }

            if (t == typeof(Vector2))
            {
                return(EditorGUILayout.Vector2Field(name, (Vector2)value));
            }

            if (t == typeof(Vector3))
            {
                return(EditorGUILayout.Vector3Field(name, (Vector3)value));
            }

            if (t == typeof(Vector4))
            {
                return(EditorGUILayout.Vector4Field(name, (Vector4)value));
            }

            if (t == typeof(Quaternion))
            {
                var quat = (Quaternion)value;
                var vec4 = new Vector4(quat.x, quat.y, quat.z, quat.w);
                vec4 = EditorGUILayout.Vector4Field(name, vec4);
                return(new Quaternion(vec4.x, vec4.y, vec4.z, vec4.w));
            }

            if (t == typeof(Color))
            {
                return(EditorGUILayout.ColorField(name, (Color)value));
            }

            if (t == typeof(Rect))
            {
                return(EditorGUILayout.RectField(name, (Rect)value));
            }

            if (t == typeof(AnimationCurve))
            {
                return(EditorGUILayout.CurveField(name, (AnimationCurve)value));
            }

            if (t == typeof(Bounds))
            {
                return(EditorGUILayout.BoundsField(name, (Bounds)value));
            }

            if (t == typeof(LayerMask))
            {
                return(LayerMaskField(name, (LayerMask)value));
            }

            if (t.IsSubclassOf(typeof(System.Enum)))
            {
#if UNITY_5
                if (t.GetCustomAttributes(typeof(FlagsAttribute), true).FirstOrDefault() != null)
                {
                    return(EditorGUILayout.EnumMaskPopup(new GUIContent(name), (System.Enum)value));
                }
#endif
                return(EditorGUILayout.EnumPopup(name, (System.Enum)value));
            }

            if (typeof(IList).IsAssignableFrom(t))
            {
                return(ListEditor(name, (IList)value, t, instance));
            }

            if (typeof(IDictionary).IsAssignableFrom(t))
            {
                return(DictionaryEditor(name, (IDictionary)value, t, instance));
            }


            //show nested class members recursively
            if (value != null && !t.IsEnum && !t.IsInterface)
            {
                GUILayout.BeginVertical();
                EditorGUILayout.LabelField(name, t.FriendlyName());
                EditorGUI.indentLevel++;
                ShowAutoEditorGUI(value);
                EditorGUI.indentLevel--;
                GUILayout.EndVertical();
            }
            else
            {
                EditorGUILayout.LabelField(name, string.Format("({0})", t.FriendlyName()));
            }

            return(value);
        }
예제 #14
0
파일: EditorUtils.cs 프로젝트: gbyh/XGame
        public static List <ScriptInfo> GetScriptInfosOfType(Type baseType)
        {
            if (cachedInfos == null)
            {
                cachedInfos = new Dictionary <Type, List <ScriptInfo> >();
            }

            List <ScriptInfo> infosResult;

            if (cachedInfos.TryGetValue(baseType, out infosResult))
            {
                return(infosResult.ToList());
            }

            infosResult = new List <ScriptInfo>();

            var subTypes = GetAssemblyTypes(baseType);

            if (baseType.IsGenericTypeDefinition)
            {
                subTypes = new List <Type> {
                    baseType
                };
            }

            foreach (var subType in subTypes)
            {
                if (subType.IsDefined(typeof(DoNotListAttribute), true) || subType.IsDefined(typeof(ObsoleteAttribute), true))
                {
                    continue;
                }

                if (subType.IsAbstract)
                {
                    continue;
                }

                var isGeneric      = subType.IsGenericTypeDefinition && subType.GetGenericArguments().Length == 1;
                var scriptName     = subType.FriendlyName().SplitCamelCase();
                var scriptCategory = string.Empty;
                var scriptPriority = 0;

                var nameAttribute = subType.RTGetAttribute <NameAttribute>(true);
                if (nameAttribute != null)
                {
                    scriptPriority = nameAttribute.priority;
                    scriptName     = nameAttribute.name;
                    if (isGeneric && !scriptName.EndsWith("<T>"))
                    {
                        scriptName += " (T)";
                    }
                }

                var categoryAttribute = subType.RTGetAttribute <CategoryAttribute>(true);
                if (categoryAttribute != null)
                {
                    scriptCategory = categoryAttribute.category;
                }

                var info = new ScriptInfo(subType, scriptName, scriptCategory, scriptPriority);
                info.originalType     = subType;
                info.originalName     = scriptName;
                info.originalCategory = scriptCategory;

                //add the generic types based on constrains and prefered types list
                if (isGeneric)
                {
                    var exposeAsBaseDefinition = subType.RTIsDefined <ExposeAsDefinition>(true);
                    if (!exposeAsBaseDefinition)
                    {
                        var typesToWrap = UserTypePrefs.GetPreferedTypesList(true);
                        foreach (var t in typesToWrap)
                        {
                            infosResult.Add(info.MakeGenericInfo(t, string.Format("/{0}/{1}", info.name, t.NamespaceToPath())));
                            infosResult.Add(info.MakeGenericInfo(typeof(List <>).MakeGenericType(t), string.Format("/{0}/{1}{2}", info.name, UserTypePrefs.LIST_MENU_STRING, t.NamespaceToPath()), -1));
                            infosResult.Add(info.MakeGenericInfo(typeof(Dictionary <,>).MakeGenericType(typeof(string), t), string.Format("/{0}/{1}{2}", info.name, UserTypePrefs.DICT_MENU_STRING, t.NamespaceToPath()), -2));
                        }
                        continue;
                    }
                }

                infosResult.Add(info);
            }

            infosResult = infosResult
                          .Where(s => s != null)
                          .OrderBy(s => s.GetBaseInfo().name)
                          .OrderBy(s => s.GetBaseInfo().priority * -1)
                          .OrderBy(s => s.GetBaseInfo().category)
                          .ToList();
            cachedInfos[baseType] = infosResult;
            return(infosResult);
        }
		///Draws an Editor field for object of type directly
		public static object DrawEditorFieldDirect(GUIContent content, object value, Type t, FieldInfo field = null, object context = null, object[] attributes = null){
			
			if ( typeof(UnityObject).IsAssignableFrom(t) == false && t != typeof(Type) ) {
				//Check abstract
				if ( (value != null && value.GetType().IsAbstract) || (value == null && t.IsAbstract) ){
					EditorGUILayout.LabelField(content, new GUIContent(string.Format("Abstract ({0})", t.FriendlyName()) ) );
					return value;
				}

				//Auto create instance for some types
				if (value == null && t != typeof(object) && !t.IsAbstract && !t.IsInterface){
					if (t.GetConstructor(Type.EmptyTypes) != null || t.IsArray){
						if (t.IsArray){ value = Array.CreateInstance(t.GetElementType(), 0); }
						else { value = Activator.CreateInstance(t); }
					}
				}
			}

			//Check the type
            if ( typeof(UnityObject).IsAssignableFrom(t) ) {
                if (t == typeof(Component) && (value is Component)){
                    return ComponentField(content, (Component)value, typeof(Component));
                }
                return EditorGUILayout.ObjectField(content, (UnityObject)value, t, true);
		    }

			if (t == typeof(Type)){
				return Popup<Type>(content, (Type)value, UserTypePrefs.GetPreferedTypesList(true) );
			}

            if (t == typeof(string)){
				return EditorGUILayout.TextField(content, (string)value);
			}

			if (t == typeof(char)){
				var c = (char)value;
				var s = c.ToString();
				s = EditorGUILayout.TextField(content, s);
				return string.IsNullOrEmpty(s)? (char)c : (char)s[0];
			}

			if (t == typeof(bool)){
				return EditorGUILayout.Toggle(content, (bool)value);
			}

			if (t == typeof(int)){
				return EditorGUILayout.IntField(content, (int)value);
			}

			if (t == typeof(float)){
				return EditorGUILayout.FloatField(content, (float)value);
			}

			if (t == typeof(byte)){
				return Convert.ToByte( Mathf.Clamp(EditorGUILayout.IntField(content, (byte)value), 0, 255) );
			}

			if (t == typeof(Vector2)){
				return EditorGUILayout.Vector2Field(content, (Vector2)value);
			}

			if (t == typeof(Vector3)){
				return EditorGUILayout.Vector3Field(content, (Vector3)value);
			}

			if (t == typeof(Vector4)){
				return EditorGUILayout.Vector4Field(content, (Vector4)value);
			}

			if (t == typeof(Quaternion)){
				var quat = (Quaternion)value;
				var vec4 = new Vector4(quat.x, quat.y, quat.z, quat.w);
				vec4 = EditorGUILayout.Vector4Field(content, vec4);
				return new Quaternion(vec4.x, vec4.y, vec4.z, vec4.w);
			}

			if (t == typeof(Color)){
				return EditorGUILayout.ColorField(content, (Color)value);
			}

			if (t == typeof(Rect)){
				return EditorGUILayout.RectField(content, (Rect)value);
			}

			if (t == typeof(AnimationCurve)){
				return EditorGUILayout.CurveField(content, (AnimationCurve)value);
			}

			if (t == typeof(Bounds)){
				return EditorGUILayout.BoundsField(content, (Bounds)value);
			}

			if (t == typeof(LayerMask)){
				return LayerMaskField(content, (LayerMask)value);
			}
            
			if (t.IsSubclassOf(typeof(System.Enum))){
				if (t.IsDefined(typeof(FlagsAttribute), true)){
					return EditorGUILayout.EnumFlagsField(content, (System.Enum)value);
				}
				return EditorGUILayout.EnumPopup(content, (System.Enum)value);
			}

			if (typeof(IList).IsAssignableFrom(t)){
				return ListEditor(content, (IList)value, t, field, context, attributes);
			}

			if (typeof(IDictionary).IsAssignableFrom(t)){
				return DictionaryEditor(content, (IDictionary)value, t, field, context, attributes);
			}

			//show nested class members recursively
			if (value != null && (t.IsClass || t.IsValueType)){
				
				if (EditorGUI.indentLevel <= 8){
					GUILayout.BeginVertical();
					EditorGUILayout.LabelField(content, new GUIContent( string.Format("({0})", t.FriendlyName()) ) );
					EditorGUI.indentLevel ++;
					ReflectedObjectInspector(value);
					EditorGUI.indentLevel --;
					GUILayout.EndVertical();
				}
		
			} else {

				EditorGUILayout.LabelField(content, new GUIContent(string.Format("NonInspectable ({0})", t.FriendlyName()) ) );
			}
			
			return value;
		}
예제 #16
0
        //THE TREE
        void DoTree(Rect treeRect, Event e)
        {
            GUILayout.BeginArea(treeRect);

            scrollPos = EditorGUILayout.BeginScrollView(scrollPos, false, false);
            GUILayout.BeginVertical();

            if (search != lastSearch)
            {
                hoveringIndex = 0;
                if (!string.IsNullOrEmpty(search))
                {
                    var searchRootNode = new Node()
                    {
                        name = "Search Root"
                    };
                    foreach (var node in leafNodes)
                    {
                        if (filterFavorites && !node.isFavorite)
                        {
                            continue;
                        }
                        if (StringUtils.SearchMatch(search, node.fullPath))
                        {
                            searchRootNode.children[node.fullPath] = node;
                        }
                    }
                    currentNode = searchRootNode;
                }
                else
                {
                    currentNode = rootNode;
                }
                lastSearch = search;
            }

            ///----------------------------------------------------------------------------------------------

            var  i          = 0;
            var  itemAdded  = false;
            Node lastParent = null;

            foreach (var childPair in currentNode.children)
            {
                var node       = childPair.Value;
                var leafItem   = node.item;
                var icon       = leafItem != null? leafItem.content.image : Icons.folderIcon;
                var isDisabled = leafItem != null && leafItem.func == null && leafItem.func2 == null;

                //when with search, show category on top
                if (!string.IsNullOrEmpty(search))
                {
                    var currentParent = node.parent;
                    if (currentParent != lastParent)
                    {
                        lastParent = currentParent;
                        GUI.color  = Color.black;
                        GUILayout.BeginHorizontal("box");
                        GUI.color = Color.white;
                        var headerLabel = string.Format("<size=10><b>{0}{1}</b></size>", currentParent.unfolded? "▼" : "▶", currentParent.fullPath);
                        if (GUILayout.Button(headerLabel, Styles.leftLabel, GUILayout.Height(16)))
                        {
                            currentParent.unfolded = !currentParent.unfolded;
                        }
                        GUILayout.EndHorizontal();
                    }

                    if (!node.parent.unfolded)
                    {
                        continue;
                    }
                }

                if (filterFavorites && !node.isFavorite && !node.HasAnyFavoriteChild())
                {
                    continue;
                }

                if (leafItem != null && leafItem.separator)
                {
                    EditorUtils.Separator();
                    continue;
                }

                itemAdded = true;

                GUI.color = Color.white;
                GUILayout.BeginHorizontal("box");
                GUI.color = Color.white;

                //Prefix icon
                if (icon != null)
                {
                    var memberInfo = leafItem != null? leafItem.userData as MemberInfo : null;
                    var typeInfo   = memberInfo is System.Type? (System.Type)memberInfo : (memberInfo != null? memberInfo.DeclaringType : null);
                    if (typeInfo != null && icon.name == UserTypePrefs.DEFAULT_TYPE_ICON_NAME)
                    {
                        GUI.color = UserTypePrefs.GetTypeColor(typeInfo);
                    }
                }
                GUILayout.Label(icon, GUILayout.Width(32), GUILayout.Height(16));
                GUI.color   = Color.white;
                GUI.enabled = !isDisabled;

                //Favorite
                if (currentKeyType != null)
                {
                    GUI.color = node.isFavorite? Color.white : (node.HasAnyFavoriteChild()? new Color(1, 1, 1, 0.2f) : new Color(0f, 0f, 0f, 0.4f));
                    if (GUILayout.Button(Icons.favoriteIcon, GUIStyle.none, GUILayout.Width(16), GUILayout.Height(16)))
                    {
                        node.ToggleFavorite();
                    }
                    GUI.color = Color.white;
                }

                //Content
                var label = node.name;
                var text  = string.Format("<size=9>{0}</size>", (leafItem == null? string.Format("<b>{0}</b>", label) : label));
                GUILayout.Box(text, (GUIStyle)"label", GUILayout.Width(0), GUILayout.ExpandWidth(true));
                GUILayout.Label(leafItem != null? "●" : "►", GUILayout.Width(20));
                GUILayout.EndHorizontal();

                var elementRect = GUILayoutUtility.GetLastRect();
                if (e.type == EventType.MouseDown && e.button == 0 && elementRect.Contains(e.mousePosition))
                {
                    e.Use();
                    if (leafItem != null)
                    {
                        ExecuteItemFunc(leafItem);
                        break;
                    }
                    else
                    {
                        currentNode   = node;
                        hoveringIndex = 0;
                        break;
                    }
                }

                if (e.type == EventType.MouseMove && elementRect.Contains(e.mousePosition))
                {
                    hoveringIndex = i;
                }

                if (hoveringIndex == i)
                {
                    GUI.color = hoverColor;
                    GUI.DrawTexture(elementRect, EditorGUIUtility.whiteTexture);
                    GUI.color = Color.white;
                    base.editorWindow.Repaint();
                }

                i++;
                GUI.enabled = true;
            }

            if (!itemAdded)
            {
                GUILayout.Label("No results to display with current search and filter combination");
            }

            GUILayout.EndVertical();
            EditorGUILayout.EndScrollView();
            GUILayout.EndArea();
        }
        /// !* Providing an open GenericTypeDefinition for 'baseType', wraps the Preferred Types wihin the 1st Generic Argument of that Definition *!
        public static GenericMenu GetPreferedTypesSelectionMenu(Type baseType, Action <Type> callback, GenericMenu menu = null, string subCategory = null, bool showAddTypeOption = false)
        {
            if (menu == null)
            {
                menu = new GenericMenu();
            }

            if (subCategory != null)
            {
                subCategory = subCategory + "/";
            }

            var constrainType     = baseType;
            var isGeneric         = baseType.IsGenericTypeDefinition && baseType.GetGenericArguments().Length == 1;
            var genericDefinition = isGeneric? baseType : null;

            if (isGeneric)
            {
                var arg1       = genericDefinition.GetGenericArguments().First();
                var constrains = arg1.GetGenericParameterConstraints();
                constrainType = constrains.Length == 0? typeof(object) : constrains.First();
            }

            GenericMenu.MenuFunction2 Selected = delegate(object t){
                callback((Type)t);
            };

            var listTypes = new Dictionary <Type, string>();
            var dictTypes = new Dictionary <Type, string>();

            foreach (var t in UserTypePrefs.GetPreferedTypesList(constrainType, true))
            {
                var nsString    = t.NamespaceToPath() + "/";
                var finalType   = isGeneric? genericDefinition.MakeGenericType(t) : t;
                var finalString = nsString + finalType.FriendlyName();
                menu.AddItem(new GUIContent(subCategory + finalString), false, Selected, finalType);

                var listType      = typeof(List <>).MakeGenericType(t);
                var finalListType = isGeneric? genericDefinition.MakeGenericType(listType) : listType;
                if (constrainType.IsAssignableFrom(finalListType))
                {
                    listTypes[finalListType] = nsString;
                }

                var dictType      = typeof(Dictionary <,>).MakeGenericType(typeof(string), t);
                var finalDictType = isGeneric? genericDefinition.MakeGenericType(dictType) : dictType;
                if (constrainType.IsAssignableFrom(finalDictType))
                {
                    dictTypes[finalDictType] = nsString;
                }
            }

            foreach (var tPair in listTypes)
            {
                menu.AddItem(new GUIContent(subCategory + UserTypePrefs.LIST_MENU_STRING + tPair.Value + tPair.Key.FriendlyName()), false, Selected, tPair.Key);
            }

            foreach (var tPair in dictTypes)
            {
                menu.AddItem(new GUIContent(subCategory + UserTypePrefs.DICT_MENU_STRING + tPair.Value + tPair.Key.FriendlyName()), false, Selected, tPair.Key);
            }

            if (showAddTypeOption)
            {
                menu.AddItem(new GUIContent(subCategory + "Add Type..."), false, () => { PreferedTypesEditorWindow.ShowWindow(); });
            }

            return(menu);
        }
예제 #18
0
        void OnGUI()
        {
            EditorGUILayout.HelpBox("Here you can specify frequently used types for your game for easier access wherever you need to select a type, like for example when you create a new blackboard variable or using any refelection based actions. Furthermore, it is essential when working with AOT platforms like iOS or WebGL, that you generate an AOT Classes and link.xml files with the relevant button bellow.\nTo add types in the list quicker, you can also Drag&Drop an object, or a Script file in this editor window, or seach it bellow.", MessageType.Info);



            GUILayout.BeginHorizontal();
            search = EditorGUILayout.TextField(search, (GUIStyle)"ToolbarSeachTextField");
            if (GUILayout.Button("", (GUIStyle)"ToolbarSeachCancelButton"))
            {
                search = null;
                GUIUtility.keyboardControl = 0;
            }
            GUILayout.EndHorizontal();

            if (search != null && search.Length > 2)
            {
                GUILayout.Label(string.Format("<b>{0}</b>", "Showing Search Results. Click the plus button to add the type."));
                GUILayout.Space(5);
                scrollPos = GUILayout.BeginScrollView(scrollPos);
                foreach (var type in EditorUtils.GetAssemblyTypes(typeof(object)))
                {
                    if (type.Name.ToUpper().Contains(search.ToUpper()))
                    {
                        GUILayout.BeginHorizontal("box");
                        if (GUILayout.Button("+", GUILayout.Width(20)))
                        {
                            AddType(type);
                        }
                        EditorGUILayout.LabelField(type.Name, type.Namespace);
                        GUILayout.EndHorizontal();
                    }
                }
                GUILayout.EndScrollView();

                return;
            }



            if (GUILayout.Button("Add New Type"))
            {
                GenericMenu.MenuFunction2 Selected = delegate(object o){
                    if (o is System.Type)
                    {
                        AddType((System.Type)o);
                    }
                    if (o is string)                      //namespace
                    {
                        foreach (var type in EditorUtils.GetAssemblyTypes(typeof(object)))
                        {
                            if (type.Namespace == (string)o)
                            {
                                AddType(type);
                            }
                        }
                    }
                };

                var menu = new UnityEditor.GenericMenu();
                menu.AddItem(new GUIContent("Classes/System/Object"), false, Selected, typeof(object));
                foreach (var t in EditorUtils.GetAssemblyTypes(typeof(object)))
                {
                    var friendlyName = (string.IsNullOrEmpty(t.Namespace)? "No Namespace/" : t.Namespace.Replace(".", "/") + "/") + t.FriendlyName();
                    var category     = "Classes/";
                    if (t.IsInterface)
                    {
                        category = "Interfaces/";
                    }
                    if (t.IsEnum)
                    {
                        category = "Enumerations/";
                    }
                    menu.AddItem(new GUIContent(category + friendlyName), false, Selected, t);

                    if (t.Namespace != null)
                    {
                        var ns = t.Namespace.Replace(".", "/");
                        menu.AddItem(new GUIContent("Namespaces/" + ns), false, Selected, t.Namespace);
                    }
                }
                menu.ShowAsContext();
                Event.current.Use();
            }

#if !UNITY_WEBPLAYER
            if (GUILayout.Button("Generate AOTClasses.cs and link.xml Files"))
            {
                if (EditorUtility.DisplayDialog("Generate AOT Classes", "A script relevant to AOT compatibility for certain platforms will now be generated.", "OK"))
                {
                    var path = EditorUtility.SaveFilePanelInProject("AOT Classes File", "AOTClasses", "cs", "");
                    if (!string.IsNullOrEmpty(path))
                    {
                        AOTClassesGenerator.GenerateAOTClasses(path);
                    }
                }

                if (EditorUtility.DisplayDialog("Generate link.xml File", "A file relevant to 'code stripping' for platforms that have code stripping enabled will now be generated.", "OK"))
                {
                    var path = EditorUtility.SaveFilePanelInProject("AOT link.xml", "link", "xml", "");
                    if (!string.IsNullOrEmpty(path))
                    {
                        AOTClassesGenerator.GenerateLinkXML(path);
                    }
                }

                AssetDatabase.Refresh();
            }

            GUILayout.BeginHorizontal();

            if (GUILayout.Button("RESET DEFAULTS"))
            {
                if (EditorUtility.DisplayDialog("Reset Preferred Types", "Are you sure?", "Yes", "NO!"))
                {
                    UserTypePrefs.ResetTypeConfiguration();
                    typeList = UserTypePrefs.GetPreferedTypesList(typeof(object));
                    Save();
                }
            }

            if (GUILayout.Button("Save Preset"))
            {
                var path = EditorUtility.SaveFilePanelInProject("Save Types Preset", "", "typePrefs", "");
                if (!string.IsNullOrEmpty(path))
                {
                    System.IO.File.WriteAllText(path, JSONSerializer.Serialize(typeof(List <System.Type>), typeList, true));
                    AssetDatabase.Refresh();
                }
            }

            if (GUILayout.Button("Load Preset"))
            {
                var path = EditorUtility.OpenFilePanel("Load Types Preset", "Assets", "typePrefs");
                if (!string.IsNullOrEmpty(path))
                {
                    var json = System.IO.File.ReadAllText(path);
                    typeList = JSONSerializer.Deserialize <List <System.Type> >(json);
                    Save();
                }
            }

            GUILayout.EndHorizontal();
#endif

            GUILayout.Space(5);

            scrollPos = GUILayout.BeginScrollView(scrollPos);

            for (int i = 0; i < typeList.Count; i++)
            {
                GUILayout.BeginHorizontal("box");
                EditorGUILayout.LabelField(typeList[i].Name, typeList[i].Namespace);
                if (GUILayout.Button("X", GUILayout.Width(18)))
                {
                    RemoveType(typeList[i]);
                }
                GUILayout.EndHorizontal();
            }

            GUILayout.EndScrollView();

            AcceptDrops();

            Repaint();
        }
        ///----------------------------------------------------------------------------------------------

        ///Returns a type icon
        public static Texture GetTypeIcon(System.Type type)
        {
            return(UserTypePrefs.GetTypeIcon(type));
        }
예제 #20
0
        ///----------------------------------------------------------------------------------------------

        ///Return a color for a type.
        public static Color GetTypeColor(System.Type type)
        {
            return(UserTypePrefs.GetTypeColor(type));
        }
        //For generic automatic editors. Passing a MemberInfo will also check for attributes
        public static object GenericField(string name, object value, Type t, MemberInfo member = null, object instance = null)
        {
            if (t == null)
            {
                GUILayout.Label("NO TYPE PROVIDED!");
                return(value);
            }

            if (member != null)
            {
                //Hide class?
                if (t.GetCustomAttributes(typeof(HideInInspector), true).FirstOrDefault() != null)
                {
                    return(value);
                }

                //Hide field?
                if (member.GetCustomAttributes(typeof(HideInInspector), true).FirstOrDefault() != null)
                {
                    return(value);
                }

                //Is required?
                if (member.GetCustomAttributes(typeof(RequiredFieldAttribute), true).FirstOrDefault() != null)
                {
                    if ((value == null || value.Equals(null)) ||
                        (t == typeof(string) && string.IsNullOrEmpty((string)value)) ||
                        (typeof(BBParameter).IsAssignableFrom(t) && (value as BBParameter).isNull))
                    {
                        GUI.backgroundColor = lightRed;
                    }
                }
            }


            name = name.SplitCamelCase();


            if (member != null)
            {
                var nameAtt = member.GetCustomAttributes(typeof(NameAttribute), true).FirstOrDefault() as NameAttribute;
                if (nameAtt != null)
                {
                    name = nameAtt.name;
                }

                if (instance != null)
                {
                    var showAtt = member.GetCustomAttributes(typeof(ShowIfAttribute), true).FirstOrDefault() as ShowIfAttribute;
                    if (showAtt != null)
                    {
                        var targetField = instance.GetType().GetField(showAtt.fieldName);
                        if (targetField == null || targetField.FieldType != typeof(bool))
                        {
                            GUILayout.Label(string.Format("[ShowIf] Error: bool \"{0}\" does not exist.", showAtt.fieldName));
                        }
                        else
                        {
                            if ((bool)targetField.GetValue(instance) != showAtt.show)
                            {
                                return(value);
                            }
                        }
                    }
                }
            }



            //Before everything check BBParameter
            if (typeof(BBParameter).IsAssignableFrom(t))
            {
                return(BBParameterField(name, (BBParameter)value, false, member));
            }

            //Then check UnityObjects
            if (typeof(UnityObject).IsAssignableFrom(t))
            {
                if (t == typeof(Component) && (Component)value != null)
                {
                    return(ComponentField(name, (Component)value, typeof(Component)));
                }
                return(EditorGUILayout.ObjectField(name, (UnityObject)value, t, (typeof(Component).IsAssignableFrom(t) || t == typeof(GameObject) || t == typeof(UnityObject))));
            }

            //Force UnityObject field?
            if (member != null && member.GetCustomAttributes(typeof(ForceObjectFieldAttribute), true).FirstOrDefault() != null)
            {
                return(EditorGUILayout.ObjectField(name, value as UnityObject, t, true));
            }

            //Restricted popup values?
            if (member != null)
            {
                var popAtt = member.GetCustomAttributes(typeof(PopupFieldAttribute), true).FirstOrDefault() as PopupFieldAttribute;
                if (popAtt != null)
                {
                    return(Popup <object>(name, value, popAtt.values.ToList(), false));
                }
            }


            //Check Type of Type
            if (t == typeof(Type))
            {
                return(Popup <Type>(name, (Type)value, UserTypePrefs.GetPreferedTypesList(typeof(object), false)));
            }

            //Check abstract
            if ((value != null && value.GetType().IsAbstract) || (value == null && t.IsAbstract))
            {
                EditorGUILayout.LabelField(name, string.Format("Abstract ({0})", t.FriendlyName()));
                return(value);
            }

            //Create instance for some types
            if (value == null && !t.IsAbstract && !t.IsInterface && (t.IsValueType || t.GetConstructor(Type.EmptyTypes) != null || t.IsArray))
            {
                if (t.IsArray)
                {
                    value = Array.CreateInstance(t.GetElementType(), 0);
                }
                else
                {
                    value = Activator.CreateInstance(t);
                }
            }



            //Check the rest
            //..............
            if (t == typeof(string))
            {
                if (member != null)
                {
                    if (member.GetCustomAttributes(typeof(TagFieldAttribute), true).FirstOrDefault() != null)
                    {
                        return(EditorGUILayout.TagField(name, (string)value));
                    }
                    var areaAtt = member.GetCustomAttributes(typeof(TextAreaFieldAttribute), true).FirstOrDefault() as TextAreaFieldAttribute;
                    if (areaAtt != null)
                    {
                        GUILayout.Label(name);
                        var areaStyle = new GUIStyle(GUI.skin.GetStyle("TextArea"));
                        areaStyle.wordWrap = true;
                        var s = EditorGUILayout.TextArea((string)value, areaStyle, GUILayout.Height(areaAtt.height));
                        return(s);
                    }
                }

                return(EditorGUILayout.TextField(name, (string)value));
            }

            if (t == typeof(bool))
            {
                return(EditorGUILayout.Toggle(name, (bool)value));
            }

            if (t == typeof(int))
            {
                if (member != null)
                {
                    var sField = member.GetCustomAttributes(typeof(SliderFieldAttribute), true).FirstOrDefault() as SliderFieldAttribute;
                    if (sField != null)
                    {
                        return((int)EditorGUILayout.Slider(name, (int)value, (int)sField.left, (int)sField.right));
                    }
                    if (member.GetCustomAttributes(typeof(LayerFieldAttribute), true).FirstOrDefault() != null)
                    {
                        return(EditorGUILayout.LayerField(name, (int)value));
                    }
                }

                return(EditorGUILayout.IntField(name, (int)value));
            }

            if (t == typeof(float))
            {
                if (member != null)
                {
                    var sField = member.GetCustomAttributes(typeof(SliderFieldAttribute), true).FirstOrDefault() as SliderFieldAttribute;
                    if (sField != null)
                    {
                        return(EditorGUILayout.Slider(name, (float)value, sField.left, sField.right));
                    }
                }
                return(EditorGUILayout.FloatField(name, (float)value));
            }

            if (t == typeof(Vector2))
            {
                return(EditorGUILayout.Vector2Field(name, (Vector2)value));
            }

            if (t == typeof(Vector3))
            {
                return(EditorGUILayout.Vector3Field(name, (Vector3)value));
            }

            if (t == typeof(Vector4))
            {
                return(EditorGUILayout.Vector4Field(name, (Vector4)value));
            }

            if (t == typeof(Quaternion))
            {
                var quat = (Quaternion)value;
                var vec4 = new Vector4(quat.x, quat.y, quat.z, quat.w);
                vec4 = EditorGUILayout.Vector4Field(name, vec4);
                return(new Quaternion(vec4.x, vec4.y, vec4.z, vec4.w));
            }

            if (t == typeof(Color))
            {
                return(EditorGUILayout.ColorField(name, (Color)value));
            }

            if (t == typeof(Rect))
            {
                return(EditorGUILayout.RectField(name, (Rect)value));
            }

            if (t == typeof(AnimationCurve))
            {
                return(EditorGUILayout.CurveField(name, (AnimationCurve)value));
            }

            if (t == typeof(Bounds))
            {
                return(EditorGUILayout.BoundsField(name, (Bounds)value));
            }

            if (t == typeof(LayerMask))
            {
                return(LayerMaskField(name, (LayerMask)value));
            }

            if (t.IsSubclassOf(typeof(System.Enum)))
            {
                return(EditorGUILayout.EnumPopup(name, (System.Enum)value));
            }

            if (typeof(IList).IsAssignableFrom(t))
            {
                return(ListEditor(name, (IList)value, t));
            }

            if (typeof(IDictionary).IsAssignableFrom(t))
            {
                return(DictionaryEditor(name, (IDictionary)value, t));
            }


            //show nested class members recursively
            if (value != null && !t.IsEnum && !t.IsInterface)
            {
                GUILayout.BeginVertical();
                EditorGUILayout.LabelField(name, t.FriendlyName());
                EditorGUI.indentLevel++;
                foreach (var field in value.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public))
                {
                    field.SetValue(value, GenericField(field.Name, field.GetValue(value), field.FieldType, field));
                }
                EditorGUI.indentLevel--;
                GUILayout.EndVertical();
            }
            else
            {
                EditorGUILayout.LabelField(name, string.Format("({0})", t.FriendlyName()));
            }

            return(value);
        }
예제 #22
0
 void OnEnable()
 {
     titleContent = new GUIContent("Preferred Types");
     typeList     = UserTypePrefs.GetPreferedTypesList();
     alltypes     = EditorUtils.GetAssemblyTypes(typeof(object)).Where(t => !t.IsGenericType && !t.IsGenericTypeDefinition).ToList();
 }
예제 #23
0
 ///Return a string hex color for a type.
 public static string GetTypeHexColor(System.Type type)
 {
     return(UserTypePrefs.GetTypeHexColor(type));
 }
예제 #24
0
        void OnGUI()
        {
            GUI.skin.label.richText = true;
            EditorGUILayout.HelpBox("Here you can specify frequently used types for your project and for easier access wherever you need to select a type, like for example when you create a new blackboard variable or using any refelection based actions.\nFurthermore, it is essential when working with AOT platforms like iOS or WebGL, that you generate an AOT Classes and link.xml files with the relevant button bellow.\nTo add types in the list quicker, you can also Drag&Drop an object, or a Script file in this editor window.", MessageType.Info);

            if (GUILayout.Button("Add New Type"))
            {
                GenericMenu.MenuFunction2 Selected = delegate(object o){
                    if (o is System.Type)
                    {
                        AddType((System.Type)o);
                    }
                    if (o is string)                      //namespace
                    {
                        foreach (var type in alltypes)
                        {
                            if (type.Namespace == (string)o)
                            {
                                AddType(type);
                            }
                        }
                    }
                };

                var menu       = new GenericMenu();
                var Namespaces = new List <string>();
                menu.AddItem(new GUIContent("Classes/System/Object"), false, Selected, typeof(object));
                foreach (var t in alltypes)
                {
                    var friendlyName = (string.IsNullOrEmpty(t.Namespace)? "No namespace/" : t.Namespace.Replace(".", "/") + "/") + t.FriendlyName();
                    var category     = "Classes/";
                    if (t.IsValueType)
                    {
                        category = "Structs/";
                    }
                    if (t.IsInterface)
                    {
                        category = "Interfaces/";
                    }
                    if (t.IsEnum)
                    {
                        category = "Enumerations/";
                    }
                    var icon = UserTypePrefs.GetTypeIcon(t);
                    menu.AddItem(new GUIContent(category + friendlyName, icon), typeList.Contains(t), Selected, t);
                    if (t.Namespace != null && !Namespaces.Contains(t.Namespace))
                    {
                        Namespaces.Add(t.Namespace);
                    }
                }

                menu.AddSeparator("/");
                foreach (var ns in Namespaces)
                {
                    var path = "Whole Namespaces/" + ns.Replace(".", "/") + "/Add " + ns;
                    menu.AddItem(new GUIContent(path), false, Selected, ns);
                }

                menu.ShowAsBrowser("Add Preferred Type");
            }


            if (GUILayout.Button("Generate AOTClasses.cs and link.xml Files"))
            {
                if (EditorUtility.DisplayDialog("Generate AOT Classes", "A script relevant to AOT compatibility for certain platforms will now be generated.", "OK"))
                {
                    var path = EditorUtility.SaveFilePanelInProject("AOT Classes File", "AOTClasses", "cs", "");
                    if (!string.IsNullOrEmpty(path))
                    {
                        AOTClassesGenerator.GenerateAOTClasses(path, UserTypePrefs.GetPreferedTypesList(typeof(object), true).ToArray());
                    }
                }

                if (EditorUtility.DisplayDialog("Generate link.xml File", "A file relevant to 'code stripping' for platforms that have code stripping enabled will now be generated.", "OK"))
                {
                    var path = EditorUtility.SaveFilePanelInProject("AOT link.xml", "link", "xml", "");
                    if (!string.IsNullOrEmpty(path))
                    {
                        AOTClassesGenerator.GenerateLinkXML(path, UserTypePrefs.GetPreferedTypesList(typeof(object)).ToArray());
                    }
                }

                AssetDatabase.Refresh();
            }

            GUILayout.BeginHorizontal();

            if (GUILayout.Button("RESET DEFAULTS"))
            {
                if (EditorUtility.DisplayDialog("Reset Preferred Types", "Are you sure?", "Yes", "NO!"))
                {
                    UserTypePrefs.ResetTypeConfiguration();
                    typeList = UserTypePrefs.GetPreferedTypesList(typeof(object));
                    Save();
                }
            }

            if (GUILayout.Button("Save Preset"))
            {
                var path = EditorUtility.SaveFilePanelInProject("Save Types Preset", "", "typePrefs", "");
                if (!string.IsNullOrEmpty(path))
                {
                    System.IO.File.WriteAllText(path, JSONSerializer.Serialize(typeof(List <System.Type>), typeList, true));
                    AssetDatabase.Refresh();
                }
            }

            if (GUILayout.Button("Load Preset"))
            {
                var path = EditorUtility.OpenFilePanel("Load Types Preset", "Assets", "typePrefs");
                if (!string.IsNullOrEmpty(path))
                {
                    var json = System.IO.File.ReadAllText(path);
                    typeList = JSONSerializer.Deserialize <List <System.Type> >(json);
                    Save();
                }
            }

            GUILayout.EndHorizontal();
            GUILayout.Space(5);

            scrollPos = GUILayout.BeginScrollView(scrollPos);
            for (int i = 0; i < typeList.Count; i++)
            {
                GUILayout.BeginHorizontal("box");
                var type = typeList[i];
                if (type == null)
                {
                    GUILayout.Label("MISSING TYPE", GUILayout.Width(300));
                    GUILayout.Label("---");
                }
                else
                {
                    var name  = type.FriendlyName();
                    var icon  = UserTypePrefs.GetTypeIcon(type);
                    var color = icon != null && icon.name == UserTypePrefs.DEFAULT_TYPE_ICON_NAME? UserTypePrefs.GetTypeColor(type) : Color.white;
                    GUI.color = color;
                    GUILayout.Label(icon, GUILayout.Width(16), GUILayout.Height(16));
                    GUI.color = Color.white;
                    GUILayout.Label(name, GUILayout.Width(300));
                    GUILayout.Label(type.Namespace);
                }
                if (GUILayout.Button("X", GUILayout.Width(18)))
                {
                    RemoveType(type);
                }
                GUILayout.EndHorizontal();
            }
            GUILayout.EndScrollView();

            AcceptDrops();
            Repaint();
        }
예제 #25
0
        //THE TREE
        void DoTree(Rect treeRect, Event e)
        {
            GUILayout.BeginArea(treeRect);

            ///TREE
            scrollPos = EditorGUILayout.BeginScrollView(scrollPos, false, false);
            GUILayout.BeginVertical();

            if (search != lastSearch)
            {
                hoveringIndex = 0;
                if (!string.IsNullOrEmpty(search) && search.Length >= 2)
                {
                    var searchRootNode = new Node()
                    {
                        name = "Search Root"
                    };
                    var a = search.ToUpper();
                    foreach (var node in leafNodes)
                    {
                        var b     = node.name.ToUpper();
                        var match = false;
                        if (searchMode == SearchMode.Contains)
                        {
                            match = true;
                            var words = a.Split(' ');
                            foreach (var word in words)
                            {
                                if (!b.Contains(word))
                                {
                                    match = false;
                                    break;
                                }
                            }
                        }
                        if (searchMode == SearchMode.StartsWith && b.StartsWith(a))
                        {
                            match = true;
                        }
                        if (match)
                        {
                            searchRootNode.children[node.name] = node;
                        }
                    }
                    currentNode = searchRootNode;
                }
                else
                {
                    currentNode = rootNode;
                }
                lastSearch = search;
            }

            var  i          = 0;
            var  itemAdded  = false;
            Node lastParent = null;

            foreach (var childPair in currentNode.children)
            {
                var node       = childPair.Value;
                var leafItem   = node.item;
                var icon       = leafItem != null? leafItem.content.image : EditorUtils.folderIcon;
                var isDisabled = leafItem != null && leafItem.func == null && leafItem.func2 == null;

                if (leafItem != null && leafItem.separator)
                {
                    EditorUtils.Separator();
                    continue;
                }

                if (search != null && search.Length >= 2)
                {
                    var currentParent = node.parent;
                    if (currentParent != lastParent)
                    {
                        lastParent = currentParent;
                        GUI.color  = EditorGUIUtility.isProSkin? Color.black : Color.white;
                        GUILayout.BeginHorizontal("box");
                        GUI.color = Color.white;
                        if (GUILayout.Button(currentParent.unfolded? "▼" : "▶", (GUIStyle)"label", GUILayout.Width(16)))
                        {
                            currentParent.unfolded = !currentParent.unfolded;
                        }
                        GUILayout.Label(string.Format("<size=12><b>{0}</b></size>", currentParent.fullPath));
                        GUILayout.EndHorizontal();
                    }

                    if (!node.parent.unfolded)
                    {
                        continue;
                    }
                }

                if (filterFavorites && !node.isFavorite && !node.HasAnyFavoriteChild())
                {
                    continue;
                }

                itemAdded = true;

                GUI.color = EditorGUIUtility.isProSkin? Color.white : new Color(0.8f, 0.8f, 0.8f, 1);
                GUILayout.BeginHorizontal("box");
                GUI.color = Color.white;

                //Prefix icon
                if (icon != null)
                {
                    var memberInfo = leafItem != null? leafItem.userData as MemberInfo : null;
                    var typeInfo   = memberInfo is System.Type? (System.Type)memberInfo : (memberInfo != null? memberInfo.DeclaringType : null);
                    if (typeInfo != null && icon.name == UserTypePrefs.DEFAULT_TYPE_ICON_NAME)
                    {
                        GUI.color = UserTypePrefs.GetTypeColor(typeInfo);
                    }
                }
                GUILayout.Label(icon, GUILayout.Width(32), GUILayout.Height(16));
                GUI.color   = Color.white;
                GUI.enabled = !isDisabled;

                //Favorite
                if (currentKeyType != null)
                {
                    GUI.color = node.isFavorite? Color.white : (node.HasAnyFavoriteChild()? new Color(1, 1, 1, 0.2f) : new Color(0f, 0f, 0f, 0.4f));
                    if (GUILayout.Button(EditorUtils.favoriteIcon, GUIStyle.none, GUILayout.Width(16), GUILayout.Height(16)))
                    {
                        node.ToggleFavorite();
                    }
                    GUI.color = Color.white;
                }

                //Content
                var label = node.name;
                if (search != null && search.Length >= 2)                  //simple highlight
                {
                    label = Regex.Replace(label, search, "<b>$&</b>", RegexOptions.IgnoreCase);
                }

                var text = string.Format("<size=9>{0}</size>", (leafItem == null? string.Format("<b>{0}</b>", label) : label));
                GUILayout.Box(text, (GUIStyle)"label", GUILayout.Width(0), GUILayout.ExpandWidth(true));
                var buttonRect = GUILayoutUtility.GetLastRect();
                if (e.type == EventType.MouseDown && e.button == 0 && buttonRect.Contains(e.mousePosition))
                {
                    e.Use();
                    if (leafItem != null)
                    {
                        ExecuteItemFunc(leafItem);
                        break;
                    }
                    else
                    {
                        currentNode   = node;
                        hoveringIndex = 0;
                        break;
                    }
                }

                //Suffix icon
                GUILayout.Label(leafItem != null? "<b>+</b>" : "►", GUILayout.Width(20));

                GUILayout.EndHorizontal();
                var lastRect = GUILayoutUtility.GetLastRect();

                if (lastRect.Contains(e.mousePosition) && e.type == EventType.MouseMove)
                {
                    hoveringIndex = i;
                }

                if (hoveringIndex == i)
                {
                    GUI.color = hoverColor;
                    GUI.DrawTexture(lastRect, EditorGUIUtility.whiteTexture);
                    GUI.color = Color.white;
                    base.editorWindow.Repaint();
                }

                i++;

                GUI.enabled = true;
            }

            if (!itemAdded)
            {
                GUILayout.Label("No results to display with current search and filter combination");
            }

            GUILayout.EndVertical();
            EditorGUILayout.EndScrollView();
            GUILayout.EndArea();
        }