示例#1
0
        public void DrawMethods(Type componentType, object component, string searchTerm, MethodInfo[] methods)
        {
            GUIStyle labelStyle = new GUIStyle(GUI.skin.label)
            {
                alignment = TextAnchor.MiddleRight
            };
            GUIStyle normalButtonStyle = new GUIStyle(GUI.skin.button)
            {
                alignment = TextAnchor.MiddleLeft
            };

            normalButtonStyle.padding = normalButtonStyle.padding.SetLeft(100);

            List <MethodSetup> expandedMethods = SidekickWindow.Current.PersistentData.ExpandedMethods;

            GUIStyle   expandButtonStyle = new GUIStyle(GUI.skin.button);
            RectOffset padding           = expandButtonStyle.padding;

            padding.left              = 0;
            padding.right             = 1;
            expandButtonStyle.padding = padding;

            foreach (MethodInfo method in methods)
            {
                if (!SearchMatches(searchTerm, method.Name))
                {
                    // Does not match search term, skip it
                    continue;
                }

                //				object[] customAttributes = method.GetCustomAttributes(false);
                EditorGUILayout.BeginHorizontal();
                ParameterInfo[] parameters = method.GetParameters();

                if (method.ReturnType == typeof(void))
                {
                    labelStyle.normal.textColor = Color.grey;
                }
                else if (method.ReturnType.IsValueType)
                {
                    labelStyle.normal.textColor = new Color(0, 0, 1);
                }
                else
                {
                    labelStyle.normal.textColor = new Color32(255, 130, 0, 255);
                }

                labelStyle.fontSize = 10;

                var genericArguments = method.GetGenericArguments();

                GUIContent buttonLabel = new GUIContent("", "Click to fire with defaults");
                if (genericArguments.Length != 0)
                {
                    string genericArgumentsDisplay = string.Join(", ", genericArguments.Select(item => item.Name));
                    buttonLabel.text = $"{method.Name} <{genericArgumentsDisplay}> {parameters.Length}";
                }
                else
                {
                    buttonLabel.text = $"{method.Name} {parameters.Length}";
                }

                using (new EditorGUI.DisabledScope(method.IsGenericMethod))
                {
                    bool buttonClicked = GUILayout.Button(buttonLabel, normalButtonStyle);
                    Rect lastRect      = GUILayoutUtility.GetLastRect();
                    lastRect.xMax = normalButtonStyle.padding.left;
                    GUI.Label(lastRect, TypeUtility.NameForType(method.ReturnType), labelStyle);

                    if (buttonClicked)
                    {
                        object[] arguments = null;
                        if (parameters.Length > 0)
                        {
                            arguments = new object[parameters.Length];
                            for (int i = 0; i < parameters.Length; i++)
                            {
                                arguments[i] = TypeUtility.GetDefaultValue(parameters[i].ParameterType);
                            }
                        }
                        var output = FireMethod(method, component, arguments, null);
                        outputObjects.AddRange(output);
                        opacity = 1f;
                    }
                }

                if (parameters.Length > 0 || genericArguments.Length > 0)
                {
                    string methodIdentifier = TypeUtility.GetMethodIdentifier(method);

                    bool   wasExpanded = expandedMethods.Any(item => item.MethodIdentifier == methodIdentifier);
                    string label       = wasExpanded ? "▲" : "▼";
                    bool   expanded    = GUILayout.Toggle(wasExpanded, label, expandButtonStyle, GUILayout.Width(20));
                    if (expanded != wasExpanded)
                    {
                        if (expanded)
                        {
                            MethodSetup methodSetup = new MethodSetup()
                            {
                                MethodIdentifier = methodIdentifier,
                                Values           = new object[parameters.Length],
                                GenericArguments = new Type[genericArguments.Length],
                            };
                            expandedMethods.Add(methodSetup);
                        }
                        else
                        {
                            expandedMethods.RemoveAll(item => item.MethodIdentifier == methodIdentifier);
                        }
                    }

                    EditorGUILayout.EndHorizontal();
                    if (expanded)
                    {
                        MethodSetup methodSetup = expandedMethods.FirstOrDefault(item => item.MethodIdentifier == methodIdentifier);

                        if (methodSetup.Values.Length != parameters.Length)
                        {
                            methodSetup.Values = new object[parameters.Length];
                        }

                        EditorGUI.indentLevel++;

                        for (var i = 0; i < genericArguments.Length; i++)
                        {
                            Type   genericArgument = genericArguments[i];
                            string displayLabel    = genericArgument.Name;

                            Type[] constraints = genericArgument.GetGenericParameterConstraints();
                            if (constraints.Length != 0)
                            {
                                displayLabel += $" ({string.Join(", ", constraints.Select(item => item.Name))})";
                            }

                            EditorGUILayout.BeginHorizontal();
                            EditorGUILayout.LabelField(displayLabel, TypeUtility.NameForType(methodSetup.GenericArguments[i]));
                            var popupRect = GUILayoutUtility.GetLastRect();
                            popupRect.width = EditorGUIUtility.currentViewWidth;

                            var selectTypeButtonLabel = new GUIContent("Select");
                            if (GUILayout.Button(selectTypeButtonLabel, EditorStyles.miniButton))
                            {
                                int index = i;
                                TypeSelectDropdown dropdown = new TypeSelectDropdown(new AdvancedDropdownState(), type => methodSetup.GenericArguments[index] = type, constraints);
                                dropdown.Show(popupRect);
                            }

                            EditorGUILayout.EndHorizontal();
                        }

                        for (int i = 0; i < parameters.Length; i++)
                        {
                            int index = i;
                            VariablePane.DrawVariable(parameters[i].ParameterType, parameters[i].Name, methodSetup.Values[i], "", VariablePane.VariableAttributes.None, null, false, null, newValue =>
                            {
                                methodSetup.Values[index] = newValue;
                            });
                        }

                        EditorGUI.indentLevel--;

                        EditorGUILayout.BeginHorizontal();
                        GUILayout.Space(30);

                        bool anyGenericArgumentsMissing = methodSetup.GenericArguments.Any(item => item == null);

                        using (new EditorGUI.DisabledScope(anyGenericArgumentsMissing))
                        {
                            if (GUILayout.Button("Fire"))
                            {
                                var output = FireMethod(method, component, methodSetup.Values, methodSetup.GenericArguments);
                                outputObjects.AddRange(output);
                                opacity = 1f;
                            }
                        }

                        EditorGUILayout.EndHorizontal();

                        GUILayout.Space(20);
                    }
                }
                else
                {
                    EditorGUILayout.EndHorizontal();
                }
            }
        }
示例#2
0
        private static void DrawIndividualVariable(GUIContent label, Type fieldType, object fieldValue, IEnumerable <Attribute> customAttributes, out bool handled, Action <object> changeCallback)
        {
            EditorGUI.BeginChangeCheck();
            handled = true;
            object newValue;

            RangeAttribute rangeAttribute = null;

            if (customAttributes != null)
            {
                foreach (var customAttribute in customAttributes)
                {
                    if (customAttribute is RangeAttribute attribute)
                    {
                        rangeAttribute = attribute;
                    }
                }
            }

            if (fieldType == typeof(int))
            {
                if (SidekickSettings.PreferUnityAttributes && rangeAttribute != null)
                {
                    newValue = EditorGUILayout.IntSlider(label, (int)fieldValue, (int)rangeAttribute.min, (int)rangeAttribute.max);
                }
                else
                {
                    newValue = EditorGUILayout.IntField(label, (int)fieldValue);
                }
            }
            else if (fieldType == typeof(uint))
            {
                long newLong = EditorGUILayout.LongField(label, (uint)fieldValue);
                // Replicate Unity's built in behaviour
                newValue = (uint)Mathf.Clamp(newLong, uint.MinValue, uint.MaxValue);
            }
            else if (fieldType == typeof(long))
            {
                newValue = EditorGUILayout.LongField(label, (long)fieldValue);
            }
            else if (fieldType == typeof(ulong))
            {
                // Note that Unity doesn't have a built in way to handle larger values than long.MaxValue (its inspector
                // doesn't work correctly with ulong in fact), so display it as a validated text field
                string newString = EditorGUILayout.TextField(label, ((ulong)fieldValue).ToString());
                if (ulong.TryParse(newString, out ulong newULong))
                {
                    newValue = newULong;
                }
                else
                {
                    newValue = fieldValue;
                }
            }
            else if (fieldType == typeof(byte))
            {
                int newInt = EditorGUILayout.IntField(label, (byte)fieldValue);
                // Replicate Unity's built in behaviour
                newValue = (byte)Mathf.Clamp(newInt, byte.MinValue, byte.MaxValue);
            }
            else if (fieldType == typeof(sbyte))
            {
                int newInt = EditorGUILayout.IntField(label, (sbyte)fieldValue);
                // Replicate Unity's built in behaviour
                newValue = (sbyte)Mathf.Clamp(newInt, sbyte.MinValue, sbyte.MaxValue);
            }
            else if (fieldType == typeof(ushort))
            {
                int newInt = EditorGUILayout.IntField(label, (ushort)fieldValue);
                // Replicate Unity's built in behaviour
                newValue = (ushort)Mathf.Clamp(newInt, ushort.MinValue, ushort.MaxValue);
            }
            else if (fieldType == typeof(short))
            {
                int newInt = EditorGUILayout.IntField(label, (short)fieldValue);
                // Replicate Unity's built in behaviour
                newValue = (short)Mathf.Clamp(newInt, short.MinValue, short.MaxValue);
            }
            else if (fieldType == typeof(string))
            {
                newValue = EditorGUILayout.TextField(label, (string)fieldValue);
            }
            else if (fieldType == typeof(char))
            {
                string newString = EditorGUILayout.TextField(label, new string((char)fieldValue, 1));
                // Replicate Unity's built in behaviour
                if (newString.Length == 1)
                {
                    newValue = newString[0];
                }
                else
                {
                    newValue = fieldValue;
                }
            }
            else if (fieldType == typeof(float))
            {
                if (SidekickSettings.PreferUnityAttributes && rangeAttribute != null)
                {
                    newValue = EditorGUILayout.Slider(label, (float)fieldValue, rangeAttribute.min, rangeAttribute.max);
                }
                else
                {
                    newValue = EditorGUILayout.FloatField(label, (float)fieldValue);
                }
            }
            else if (fieldType == typeof(double))
            {
                newValue = EditorGUILayout.DoubleField(label, (double)fieldValue);
            }
            else if (fieldType == typeof(bool))
            {
                newValue = EditorGUILayout.Toggle(label, (bool)fieldValue);
            }
            else if (fieldType == typeof(Vector2))
            {
                newValue = EditorGUILayout.Vector2Field(label, (Vector2)fieldValue);
            }
            else if (fieldType == typeof(Vector3))
            {
                newValue = EditorGUILayout.Vector3Field(label, (Vector3)fieldValue);
            }
            else if (fieldType == typeof(Vector4))
            {
                newValue = EditorGUILayout.Vector4Field(label, (Vector4)fieldValue);
            }
            else if (fieldType == typeof(Vector2Int))
            {
                newValue = EditorGUILayout.Vector2IntField(label, (Vector2Int)fieldValue);
            }
            else if (fieldType == typeof(Vector3Int))
            {
                newValue = EditorGUILayout.Vector3IntField(label, (Vector3Int)fieldValue);
            }
            else if (fieldType == typeof(Quaternion))
            {
                Quaternion quaternion = (Quaternion)fieldValue;
                Vector4    vector     = new Vector4(quaternion.x, quaternion.y, quaternion.z, quaternion.w);
                vector   = EditorGUILayout.Vector4Field(label, vector);
                newValue = new Quaternion(vector.x, vector.y, vector.z, vector.z);
            }
#if UNITY_MATH_EXISTS
            else if (fieldType == typeof(float2))
            {
                newValue = (float2)EditorGUILayout.Vector2Field(label, (float2)fieldValue);
            }
            else if (fieldType == typeof(float3))
            {
                newValue = (float3)EditorGUILayout.Vector3Field(label, (float3)fieldValue);
            }
            else if (fieldType == typeof(float4))
            {
                newValue = (float4)EditorGUILayout.Vector4Field(label, (float4)fieldValue);
            }
#endif
            else if (fieldType == typeof(Bounds))
            {
                newValue = EditorGUILayout.BoundsField(label, (Bounds)fieldValue);
            }
            else if (fieldType == typeof(BoundsInt))
            {
                newValue = EditorGUILayout.BoundsIntField(label, (BoundsInt)fieldValue);
            }
            else if (fieldType == typeof(Color))
            {
                newValue = EditorGUILayout.ColorField(label, (Color)fieldValue);
            }
            else if (fieldType == typeof(Color32))
            {
                newValue = (Color32)EditorGUILayout.ColorField(label, (Color32)fieldValue);
            }
            else if (fieldType == typeof(Gradient))
            {
                newValue = EditorGUILayout.GradientField(new GUIContent(label), (Gradient)fieldValue);
            }
            else if (fieldType == typeof(AnimationCurve))
            {
                newValue = EditorGUILayout.CurveField(label, (AnimationCurve)fieldValue);
            }
            else if (fieldType.IsSubclassOf(typeof(Enum)))
            {
                newValue = EditorGUILayout.EnumPopup(label, (Enum)fieldValue);
                Type underlyingType = Enum.GetUnderlyingType(fieldValue.GetType());
                // Cast from the enum to the underlying type (e.g. byte) then to int
                object cast = Convert.ChangeType(newValue, underlyingType);
                cast = Convert.ChangeType(cast, typeof(int));
                // Allow them to edit as an int then cast back
                newValue = Convert.ChangeType(EditorGUILayout.IntField((int)cast), underlyingType);
            }
            else if (fieldType == typeof(Rect))
            {
                newValue = EditorGUILayout.RectField(label, (Rect)fieldValue);
            }
            else if (fieldType == typeof(RectInt))
            {
                newValue = EditorGUILayout.RectIntField(label, (RectInt)fieldValue);
            }
            else if (fieldType.IsSubclassOf(typeof(UnityEngine.Object)))
            {
                newValue = EditorGUILayout.ObjectField(label, (UnityEngine.Object)fieldValue, fieldType, true);
            }
            else if (fieldType == typeof(Type))
            {
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.LabelField(label, new GUIContent(TypeUtility.NameForType((Type)fieldValue)));
                var popupRect = GUILayoutUtility.GetLastRect();
                popupRect.width = EditorGUIUtility.currentViewWidth;

                var selectTypeButtonLabel = new GUIContent("Select");
                if (GUILayout.Button(selectTypeButtonLabel, EditorStyles.miniButton))
                {
                    TypeSelectDropdown dropdown = new TypeSelectDropdown(new AdvancedDropdownState(), type =>
                    {
                        // Async apply
                        changeCallback?.Invoke(type);
                    });
                    dropdown.Show(popupRect);
                }

                EditorGUILayout.EndHorizontal();
                newValue = fieldValue;
            }
            else
            {
                handled  = false;
                newValue = fieldValue;
            }

            if (EditorGUI.EndChangeCheck())
            {
                changeCallback?.Invoke(newValue);
            }
        }
示例#3
0
        void OnGUI()
        {
            // Flexible width for the label based on overall width
            EditorGUIUtility.labelWidth = Mathf.Round(EditorGUIUtility.currentViewWidth * 0.4f);
            // Use inline controls if there is enough horizontal room
            EditorGUIUtility.wideMode = EditorGUIUtility.currentViewWidth > 400;

            // Frame rate tracking
            if (Event.current.type == EventType.Repaint)
            {
                AnimationHelper.UpdateTime();
            }

            current = this;

            CleanStacks();

            DrawToolbar();

            Type[]       inspectedTypes       = null;
            object[]     inspectedContexts    = null;
            ECSContext[] inspectedECSContexts = null;

            GUILayout.Space(9);

            string buttonPrefix = "";

#if ECS_EXISTS
            int selectionWrapWidth = 465;
#else
            int selectionWrapWidth = 400;
#endif
            if (EditorGUIUtility.currentViewWidth > selectionWrapWidth)
            {
                EditorGUILayout.BeginHorizontal();
                GUILayout.Label("Selection Helpers");
            }
            else
            {
                buttonPrefix = "Select ";
            }

            var popupRect = GUILayoutUtility.GetLastRect();
            popupRect.width = EditorGUIUtility.currentViewWidth;

            if (GUILayout.Button(new GUIContent(buttonPrefix + "Type From Assembly"), EditorStyles.miniButton))
            {
                TypeSelectDropdown dropdown = new TypeSelectDropdown(new AdvancedDropdownState(), SetSelection);
                dropdown.Show(popupRect);
            }

            if (GUILayout.Button(new GUIContent(buttonPrefix + "Loaded Unity Object"), EditorStyles.miniButton))
            {
                UnityObjectSelectDropdown dropdown = new UnityObjectSelectDropdown(new AdvancedDropdownState(), SetSelection);
                dropdown.Show(popupRect);
            }

#if ECS_EXISTS
            if (GUILayout.Button(new GUIContent(buttonPrefix + "ECS System"), EditorStyles.miniButton))
            {
                ECSSystemSelectDropdown dropdown = new ECSSystemSelectDropdown(new AdvancedDropdownState(), SetSelection);
                dropdown.Show(popupRect);
            }
#endif

            if (EditorGUIUtility.currentViewWidth > selectionWrapWidth)
            {
                EditorGUILayout.EndHorizontal();
            }

            if (activeSelection.IsEmpty)
            {
                GUILayout.FlexibleSpace();
                GUIStyle style = new GUIStyle(EditorStyles.wordWrappedLabel)
                {
                    alignment = TextAnchor.MiddleCenter
                };
                GUILayout.Label("No object selected.\n\nSelect something in Unity or use one of the selection helper buttons.", style);
                GUILayout.FlexibleSpace();
                return;
            }

            if (activeSelection.Object != null)
            {
                if (activeSelection.Object is GameObject selectedGameObject)
                {
                    List <object> components = selectedGameObject.GetComponents <Component>().Cast <object>().ToList();
                    components.RemoveAll(item => item == null);
                    components.Insert(0, selectedGameObject);
                    inspectedContexts = components.ToArray();
                }
#if ECS_EXISTS
                else if (activeSelection.Object is EntitySelectionProxy entitySelectionProxy)
                {
                    EntityManager currentEntityManager = entitySelectionProxy.World.EntityManager;
                    string        name = currentEntityManager.GetName(entitySelectionProxy.Entity);

                    if (string.IsNullOrEmpty(name))
                    {
                        name = "Entity " + entitySelectionProxy.Entity.Index;
                    }

                    inspectedContexts       = new object [1 + currentEntityManager.GetComponentCount(entitySelectionProxy.Entity)];
                    inspectedContexts[0]    = activeSelection.Object;
                    inspectedECSContexts    = new ECSContext[1 + currentEntityManager.GetComponentCount(entitySelectionProxy.Entity)];
                    inspectedECSContexts[0] = new ECSContext {
                        EntityManager = currentEntityManager, Entity = entitySelectionProxy.Entity
                    };

                    NativeArray <ComponentType> types = currentEntityManager.GetComponentTypes(entitySelectionProxy.Entity);
                    for (var index = 0; index < types.Length; index++)
                    {
                        object componentData = ECSAccess.GetComponentData(currentEntityManager, entitySelectionProxy.Entity, types[index]);

                        inspectedContexts[1 + index]    = componentData;
                        inspectedECSContexts[1 + index] = new ECSContext {
                            EntityManager = currentEntityManager, Entity = entitySelectionProxy.Entity, ComponentType = types[index]
                        };
                    }

                    types.Dispose();
                }
#endif
                else
                {
                    inspectedContexts = new[] { activeSelection.Object };
                }

                inspectedTypes = inspectedContexts.Select(x => x.GetType()).ToArray();
            }
            else
            {
                inspectedTypes = new[] { activeSelection.Type };

                inspectedContexts = new Type[] { null };
            }

            if (inspectedECSContexts == null)
            {
                inspectedECSContexts = new ECSContext[inspectedContexts.Length];
            }

            GUILayout.Space(5);
            searchTerm = searchField.OnToolbarGUI(searchTerm);

            SidekickEditorGUI.BeginLabelHighlight(searchTerm);

            mode = SidekickUtility.EnumToolbar(mode);

            GUILayout.Space(5);
            scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);

            for (int i = 0; i < inspectedTypes.Length; i++)
            {
                Type type = inspectedTypes[i];

                var inspectedContext    = inspectedContexts[i];
                var inspectedECSContext = inspectedECSContexts[i];

                bool?activeOrEnabled = inspectedContext switch
                {
                    GameObject gameObject => gameObject.activeSelf,
                    Behaviour behaviour => behaviour.enabled,
                    _ => null
                };

                if (typesHidden.All(row => row.Key != type))
                {
                    typesHidden.Add(new KeyValuePair <Type, bool>(type, false));
                }

                int index = typesHidden.FindIndex(row => row.Key == type);

                string name;
                if (inspectedContexts[0] != null)
                {
                    if (activeOrEnabled.HasValue)
                    {
                        name = "              " + type.Name;
                    }
                    else
                    {
                        name = "       " + type.Name;
                    }

                    if (i == 0 && inspectedContexts[i] is Object unityObject)
                    {
                        name += $" ({unityObject.name})";
                    }
                }
                else
                {
                    name = type.Name + " (Class)";
                }

                GUIContent content = new GUIContent(name, $"{type.FullName}, {type.Assembly.FullName}");

                Rect foldoutRect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.foldoutHeader);

                Rect toggleRect = foldoutRect;
                toggleRect.xMin += 36;
                toggleRect.width = 20;

                Rect iconRect = foldoutRect;
                iconRect.xMin  += 16;
                iconRect.yMin  += 1;
                iconRect.height = iconRect.width = 16;

                // Have to do this before BeginFoldoutHeaderGroup otherwise it'll consume the mouse down event
                if (activeOrEnabled.HasValue && SidekickEditorGUI.DetectClickInRect(toggleRect))
                {
                    switch (inspectedContexts[i])
                    {
                    case GameObject gameObject:
                        gameObject.SetActive(!gameObject.activeSelf);
                        break;

                    case Behaviour behaviour:
                        behaviour.enabled = !behaviour.enabled;
                        break;
                    }
                }

                bool foldout = EditorGUI.BeginFoldoutHeaderGroup(foldoutRect, !typesHidden[index].Value, content, EditorStyles.foldoutHeader, rect => ClassUtilities.GetMenu(inspectedContext, inspectedECSContext).DropDown(rect));

                Texture icon = SidekickEditorGUI.GetIcon(inspectedContexts[i], type);
                if (icon != null)
                {
                    GUI.DrawTexture(iconRect, icon);
                }

                // Right click context menu
                if (SidekickEditorGUI.DetectClickInRect(foldoutRect, 1))
                {
                    ClassUtilities.GetMenu(inspectedContext, inspectedECSContext).DropDown(new Rect(Event.current.mousePosition, Vector2.zero));
                }

                if (activeOrEnabled.HasValue)
                {
                    EditorGUI.Toggle(toggleRect, activeOrEnabled.Value);
                }

                EditorGUILayout.EndFoldoutHeaderGroup();

                typesHidden[index] = new KeyValuePair <Type, bool>(type, !foldout);

                if (!typesHidden[index].Value)
                {
                    SidekickEditorGUI.DrawSplitter(0.5f);

                    EditorGUI.indentLevel++;

                    BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.DeclaredOnly;

                    if (inspectedContext != null) // Is this an object instance?
                    {
                        bindingFlags |= BindingFlags.Instance;
                    }

                    var typeScope = type;

                    while (typeScope != null)
                    {
                        if (InspectionExclusions.GetExcludedTypes().Contains(typeScope))
                        {
                            break;
                        }

                        if (typeScope != type)
                        {
                            SidekickEditorGUI.DrawTypeChainHeader(new GUIContent(": " + typeScope.Name));
                        }

                        FieldInfo[]    fields     = typeScope.GetFields(bindingFlags);
                        PropertyInfo[] properties = typeScope.GetProperties(bindingFlags);
                        MethodInfo[]   methods    = typeScope.GetMethods(bindingFlags);

                        // Hide methods and backing fields that have been generated for properties
                        if (SidekickSettings.HideAutoGenerated)
                        {
                            List <MethodInfo> methodList = new List <MethodInfo>(methods.Length);

                            foreach (MethodInfo method in methods)
                            {
                                if (!TypeUtility.IsPropertyMethod(method, typeScope))
                                {
                                    methodList.Add(method);
                                }
                            }

                            methods = methodList.ToArray();

                            List <FieldInfo> fieldList = new List <FieldInfo>(fields.Length);

                            for (int j = 0; j < fields.Length; j++)
                            {
                                if (!TypeUtility.IsBackingField(fields[j], typeScope))
                                {
                                    fieldList.Add(fields[j]);
                                }
                            }

                            fields = fieldList.ToArray();
                        }


                        FieldInfo[] events = typeScope.GetFields(bindingFlags);

                        if (mode == InspectorMode.Fields)
                        {
                            fieldPane.DrawFields(inspectedTypes[i], inspectedContexts[i], inspectedECSContext, searchTerm, fields);
                        }
                        else if (mode == InspectorMode.Properties)
                        {
                            propertyPane.DrawProperties(inspectedTypes[i], inspectedContexts[i], searchTerm, properties);
                        }
                        else if (mode == InspectorMode.Methods)
                        {
                            methodPane.DrawMethods(inspectedTypes[i], inspectedContexts[i], searchTerm, methods);
                        }
                        else if (mode == InspectorMode.Events)
                        {
                            eventPane.DrawEvents(inspectedTypes[i], inspectedContexts[i], searchTerm, events);
                        }

                        typeScope = typeScope.BaseType;
                    }


                    EditorGUI.indentLevel--;
                }

                SidekickEditorGUI.DrawSplitter();
            }

            EditorGUILayout.Space();
            EditorGUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();

            if (inspectedTypes[0] == typeof(GameObject)
#if ECS_EXISTS
                || inspectedTypes[0] == typeof(EntitySelectionProxy)
#endif
                )
            {
                bool pressed    = GUILayout.Button("Add Component", GUILayout.Width(230), GUILayout.Height(24));
                var  popupRect2 = GUILayoutUtility.GetLastRect();
                popupRect2.width = EditorGUIUtility.currentViewWidth;
                if (pressed)
                {
                    if (inspectedTypes[0] == typeof(GameObject))
                    {
                        TypeSelectDropdown dropdown = new TypeSelectDropdown(new AdvancedDropdownState(), type =>
                        {
                            ((GameObject)inspectedContexts[0]).AddComponent(type);
                        }, new[] { typeof(Component) });
                        dropdown.Show(popupRect2);
                    }
#if ECS_EXISTS
                    else if (inspectedTypes[0] == typeof(EntitySelectionProxy))
                    {
                        TypeSelectDropdown dropdown = new TypeSelectDropdown(new AdvancedDropdownState(), type =>
                        {
                            inspectedECSContexts[0].EntityManager.AddComponent(inspectedECSContexts[0].Entity, ComponentType.ReadWrite(type));
                        }, null, new [] { typeof(IComponentData) });
                        dropdown.Show(popupRect2);
                    }
#endif
                }
            }

            GUILayout.FlexibleSpace();
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.EndScrollView();

            if (mode == InspectorMode.Methods)
            {
                methodPane.PostDraw();
            }


            //if(AnimationHelper.AnimationActive)
            {
                // Cause repaint on next frame
                Repaint();
                if (Event.current.type == EventType.Repaint)
                {
                    //AnimationHelper.ClearAnimationActive();
                }
            }

            SidekickEditorGUI.EndLabelHighlight();
        }