void DrawChildren(float yMin)
        {
            int listKeyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard);

            var backgroundRect = new Rect(0, yMin, m_WindowWidth, k_SearchHeight);

            GUI.Label(backgroundRect, GUIContent.none, Styles.searchBackground);

            EditorGUI.BeginChangeCheck();
            var searchRect = new Rect(k_OffsetX + k_Padding, backgroundRect.y + k_Padding, m_WindowWidth - 2 * k_OffsetX - k_Padding, Styles.searchFieldStyle.fixedHeight);

            m_SearchFilterString = EditorGUI.ToolbarSearchField(searchRect, m_SearchFilterString, false);
            if (EditorGUI.EndChangeCheck())
            {
                m_Debounce.Execute();
            }

            if (m_Enumerator != null)
            {
                Search();
            }

            yMin = searchRect.height + (m_ListArea.gridSize < k_MinIconSize ? 11f : 0f);
            var listRect = new Rect(k_Padding, searchRect.y + yMin, m_WindowWidth - 2 * k_Padding, k_SearchHeight - yMin - k_Padding);

            m_ListArea.OnGUI(listRect, listKeyboardControlID);

            if (m_Enumerator == null && m_Results.Length == 0)
            {
                var labelRect = new Rect(m_NoResultsX, backgroundRect.y + 69f, m_WindowWidth, EditorGUI.kSingleLineHeight);
                EditorGUI.LabelField(backgroundRect, m_SearchFilter.nameFilter.Length == 0 ? Styles.noChildrenLabel : Styles.noResultsLabel, Styles.centered);
            }
        }
        void SearchArea(Rect toolbarRect)
        {
            GUI.Label(toolbarRect, GUIContent.none, s_Styles.searchBg);

            // ESC clears search field and removes it's focus. But if we get an esc event we only want to clear search field.
            // So we need special handling afterwards.
            bool wasEscape = Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape;

            GUI.SetNextControlName(kSearchFieldTag);
            string newSearchFilter = EditorGUI.SearchField(new Rect(5, 5, toolbarRect.width - 10, 15), m_SearchString);

            if (wasEscape && Event.current.type == EventType.Used)
            {
                // If we hit esc and the string WAS empty, it's an actual cancel event.
                if (m_SearchString != string.Empty)
                {
                    // Otherwise the string has been cleared and focus has been lost. We don't have anything else to recieve focus, so we want to refocus the search field.
                    m_FocusSearchFilter = true;
                }
            }

            if (newSearchFilter != m_SearchString || m_FocusSearchFilter)
            {
                m_SearchString = newSearchFilter;
                m_Debounce.Execute();
            }

            if (m_FocusSearchFilter)
            {
                EditorGUI.FocusTextInControl(kSearchFieldTag);
                if (Event.current.type == EventType.Repaint)
                {
                    m_FocusSearchFilter = false;
                }
            }
        }
        // This is our search field
        void SearchArea()
        {
            GUI.Label(new Rect(0, 0, position.width, kToolbarHeight), GUIContent.none, EditorStyles.toolbar);

            // ESC clears search field and removes it's focus. But if we get an esc event we only want to clear search field.
            // So we need special handling afterwards.
            bool wasEscape = Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape;

            GUI.SetNextControlName("SearchFilter");
            string searchFilter = EditorGUI.ToolbarSearchField(new Rect(2, 2, position.width - 2, 16), m_SearchFilter, false);

            if (wasEscape && Event.current.type == EventType.Used)
            {
                // If we hit esc and the string WAS empty, it's an actual cancel event.
                if (m_SearchFilter == "")
                {
                    Cancel();
                }

                // Otherwise the string has been cleared and focus has been lost. We don't have anything else to recieve focus, so we want to refocus the search field.
                m_FocusSearchFilter = true;
            }

            if (searchFilter != m_SearchFilter || m_FocusSearchFilter)
            {
                m_SearchFilter = searchFilter;
                m_Debounce.Execute();
            }

            if (m_FocusSearchFilter)
            {
                EditorGUI.FocusTextInControl("SearchFilter");
                m_FocusSearchFilter = false;
            }

            GUI.changed = false;

            GUI.Label(new Rect(0, kToolbarHeight, position.width, kToolbarHeight), GUIContent.none, EditorStyles.toolbar);

            // TAB BAR
            GUILayout.BeginArea(new Rect(4, kToolbarHeight, position.width - 4, kToolbarHeight));
            GUILayout.BeginHorizontal();

            // Asset Tab
            bool showAssets = GUILayout.Toggle(m_IsShowingAssets, Styles.assetsTabLabel, Styles.tab);

            if (!m_IsShowingAssets && showAssets)
            {
                m_IsShowingAssets = true;
            }


            // The Scene Tab
            if (!m_AllowSceneObjects)
            {
                GUI.enabled = false;
                GUI.color   = new Color(1, 1, 1, 0);
            }

            bool showingSceneTab = !m_IsShowingAssets;

            showingSceneTab = GUILayout.Toggle(showingSceneTab, Styles.sceneTabLabel, Styles.tab);
            if (m_IsShowingAssets && showingSceneTab)
            {
                m_IsShowingAssets = false;
            }


            if (!m_AllowSceneObjects)
            {
                GUI.color   = new Color(1, 1, 1, 1);
                GUI.enabled = true;
            }

            GUILayout.EndHorizontal();
            GUILayout.EndArea();

            if (GUI.changed)
            {
                m_Debounce.Execute();
            }

            var size = new Vector2(0, 0);

            if (m_IsShowingAssets)
            {
                Styles.packagesVisibilityContent.text = PackageManagerUtilityInternal.HiddenPackagesCount.ToString();
                size = EditorStyles.toolbarButton.CalcSize(Styles.packagesVisibilityContent);
            }

            if (m_ListArea.CanShowThumbnails())
            {
                EditorGUI.BeginChangeCheck();
                var newGridSize = (int)GUI.HorizontalSlider(new Rect(position.width - (60 + size.x), kToolbarHeight + GUI.skin.horizontalSlider.margin.top, 55, EditorGUI.kSingleLineHeight), m_ListArea.gridSize, m_ListArea.minGridSize, m_ListArea.maxGridSize);
                if (EditorGUI.EndChangeCheck())
                {
                    m_ListArea.gridSize = newGridSize;
                }
            }

            if (m_IsShowingAssets)
            {
                EditorGUI.BeginChangeCheck();
                var skipHiddenPackages = GUI.Toggle(new Rect(position.width - size.x, kToolbarHeight, size.x, EditorStyles.toolbarButton.fixedHeight), m_SkipHiddenPackages, Styles.packagesVisibilityContent, EditorStyles.toolbarButtonRight);
                if (EditorGUI.EndChangeCheck())
                {
                    m_SkipHiddenPackages = skipHiddenPackages;
                    FilterSettingsChanged();
                }
            }
        }
        public override void OnGUI(Rect rect)
        {
            if (editorWindow.position.y != targetPositionY)
            {
                editorWindow.position = new Rect(editorWindow.position)
                {
                    y = targetPositionY
                }
            }
            ;

            // Escape closes the window
            if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape)
            {
                editorWindow.Close();
                GUIUtility.ExitGUI();
            }

            if (!DrawHeader())
            {
                return;
            }

            float height = k_HeaderHeight;

            if (target.isVariant)
            {
                height += DrawVariantHierarchy();
            }

            height += DrawChildrenLabel(height);

            if (displayChildren)
            {
                DrawChildren(height);
            }

            if (materialEditor.convertState == ConvertAction.Flatten)
            {
                materialEditor.convertState = ConvertAction.None;
                Undo.RecordObject(target, "Flatten Material Variant");
                target.parent = null;
                Init();
            }
        }

        bool DrawHeader()
        {
            Rect headerRect = GUILayoutUtility.GetRect(20, windowWidth, k_HeaderHeight, k_HeaderHeight);

            EditorGUI.DrawRect(headerRect, Colors.headerBackground);

            var   headerLabel = target.isVariant ? Styles.variantLabel : Styles.instanceLabel;
            float labelSize   = Styles.boldRightAligned.CalcSize(headerLabel).x;

            Rect labelRect   = new Rect(k_OffsetX, headerRect.y + k_Padding, labelSize, EditorGUIUtility.singleLineHeight);
            Rect contentRect = new Rect(labelRect.x + labelRect.width + k_Padding, labelRect.y, windowWidth, labelRect.height);

            GUI.Label(labelRect, headerLabel, Styles.boldRightAligned);
            DoObjectLabel(contentRect, target, EditorStyles.boldLabel);

            labelRect.y = labelRect.height + 2 * k_Padding;
            if (materialEditor.convertState == ConvertAction.None)
            {
                int result;
                labelRect.width = k_ConvertLabelWidth;
                using (new EditorGUI.DisabledScope(!enabled))
                    result = EditorGUI.Popup(labelRect, target.isVariant ? 1 : 0, Styles.headerPopupOptions);
                if (result == 0 && target.isVariant)
                {
                    materialEditor.convertState = ConvertAction.Flatten;
                    targetPositionY             = singleLinePositionY;
                }
                if (result == 1 && !target.isVariant)
                {
                    materialEditor.convertState = ConvertAction.Convert;
                    targetPositionY             = singleLinePositionY + k_PositionShiftY;
                }
            }
            else if (materialEditor.convertState == ConvertAction.Convert)
            {
                GUI.enabled     = false;
                labelRect.width = 200f;
                EditorGUI.Button(labelRect, Styles.convertingLabel);
                GUI.enabled = true;

                // Conversion helper
                labelRect.y     = k_HeaderHeight;
                labelRect.width = windowWidth;
                EditorGUI.LabelField(labelRect, Styles.conversionHelpLabel);

                labelRect.x = windowWidth - 14;
                if (GUI.Button(labelRect, GUIContent.none, EditorStyles.toolbarSearchFieldCancelButton))
                {
                    materialEditor.convertState = ConvertAction.None;
                    targetPositionY             = singleLinePositionY;
                    materialEditor.Repaint();
                }

                labelRect.x = k_OffsetX;
                var oldLabelWidth = EditorGUIUtility.labelWidth;
                EditorGUIUtility.labelWidth = 70;
                EditorGUI.BeginChangeCheck();
                var parent = target.parent;
                materialEditor.ParentField(new Rect(k_OffsetX, labelRect.yMax + k_Padding, windowWidth - 2 * k_OffsetX, k_EntryHeight));
                if (EditorGUI.EndChangeCheck() && parent != target.parent)
                {
                    materialEditor.convertState = ConvertAction.None;
                    Init();
                }
                EditorGUIUtility.labelWidth = oldLabelWidth;
                return(false);
            }

            return(true);
        }

        float DrawVariantHierarchy()
        {
            // Draw table header
            Rect entryRect = new Rect(0, k_HeaderHeight, windowWidth, k_EntryHeight);

            EditorGUI.DrawRect(entryRect, Colors.rowBackground(0));

            var labelRect = entryRect;

            labelRect.x = k_TitleWidth;
            GUI.Label(labelRect, Styles.ancestorLabel, EditorStyles.miniLabel);

            labelRect.x = overridesX + k_Padding;
            GUI.Label(labelRect, Styles.overridesLabel, EditorStyles.miniLabel);

            labelRect.x = locksX + k_Padding;
            GUI.Label(labelRect, Styles.locksLabel, EditorStyles.miniLabel);

            float tableHeight = Mathf.Min(numRows, k_MaxTableRows) * k_EntryHeight + (namesWidth > maxNameWidth ? k_ScrollbarHeight : 0);
            float realHeight  = numRows * k_EntryHeight + (namesWidth > maxNameWidth ? k_ScrollbarHeight : 0);
            var   tableRect   = new Rect(0, k_HeaderHeight + k_EntryHeight, windowWidth - 1, tableHeight);

            scroll.y = GUI.BeginScrollView(tableRect, scroll, new Rect(tableRect)
            {
                width = tableRect.width - k_ScrollbarWidth, height = realHeight
            }).y;

            // Draw overrides and locks table
            int      i       = numRows;
            Material current = target;

            while (current != null)
            {
                entryRect.y = k_HeaderHeight + i * k_EntryHeight;
                EditorGUI.DrawRect(entryRect, Colors.rowBackground(i--));

                DisplayOverridesAndLocks(entryRect, current);
                current = current.parent;
            }

            var scrollRect = new Rect(k_TitleWidth, k_HeaderHeight + k_EntryHeight, Mathf.Min(namesWidth, maxNameWidth), numRows * k_EntryHeight);

            scroll.x = GUI.BeginScrollView(new Rect(scrollRect)
            {
                height = scrollRect.height + k_ScrollbarHeight
            }, scroll, new Rect(scrollRect)
            {
                width = namesWidth
            }).x;

            // Draw scrollable table
            i           = numRows;
            current     = target;
            entryRect.x = k_TitleWidth;
            while (i != 0)
            {
                entryRect.y = k_HeaderHeight + i-- *k_EntryHeight;

                if (current == null)
                {
                    GUI.Label(entryRect, EditorGUIUtility.TempContent("Missing (Material)"));
                    break;
                }
                DoObjectLabel(entryRect, current);
                current = current.parent;
            }

            GUI.EndScrollView();

            float height = tableHeight + k_EntryHeight;

            // Draw selected label
            labelRect.x     = k_OffsetX;
            labelRect.y     = k_HeaderHeight + numRows * k_EntryHeight;
            labelRect.width = k_TitleWidth - labelRect.x;
            GUI.Label(labelRect, Styles.selectedLabel);

            // Draw parent label
            labelRect.y = k_HeaderHeight + (numRows - 1) * k_EntryHeight;
            GUI.Label(labelRect, Styles.parentLabel);

            // Draw root label
            if (labelRect.y != k_HeaderHeight + k_EntryHeight)
            {
                labelRect.y = k_HeaderHeight + k_EntryHeight;
                GUI.Label(labelRect, Styles.rootLabel);
            }

            // Draw vertical splits
            Rect splitBar = new Rect(overridesX - k_SplitWidth, k_HeaderHeight, k_SplitWidth, (numRows + 1) * k_EntryHeight);

            EditorGUI.DrawRect(splitBar, Colors.headerBackground);
            splitBar.x = locksX - k_SplitWidth;
            EditorGUI.DrawRect(splitBar, Colors.headerBackground);

            GUI.EndScrollView();

            return(height);
        }

        float DrawChildrenLabel(float yMin)
        {
            var labelRect = new Rect(k_OffsetX, yMin, 100, k_EntryHeight);

            if (target.isVariant)
            {
                displayChildren = EditorGUI.Foldout(labelRect, displayChildren, Styles.childrenLabel, true);
            }
            else
            {
                EditorGUI.LabelField(labelRect, Styles.childrenLabel);
            }

            if (displayChildren)
            {
                if (listArea == null)
                {
                    InitListArea();
                }

                labelRect = new Rect(labelRect.x + 58 + (target.isVariant ? 12 : 0), labelRect.y + 2, k_SliderWidth, EditorGUI.kSingleLineHeight);
                if (results.Length != 0)
                {
                    EditorGUI.LabelField(labelRect, results.Length.ToString(), Styles.boldNumber);
                }

                EditorGUI.BeginChangeCheck();
                labelRect.x = windowWidth - k_OffsetX - k_SliderWidth;
                var newGridSize = (int)GUI.HorizontalSlider(labelRect, listArea.gridSize, listArea.minGridSize, listArea.maxGridSize);
                if (EditorGUI.EndChangeCheck())
                {
                    listArea.gridSize = newGridSize;
                }
            }

            return(k_EntryHeight);
        }

        void DrawChildren(float yMin)
        {
            var backgroundRect = new Rect(0, yMin, windowWidth, k_SearchHeight);

            GUI.Label(backgroundRect, GUIContent.none, Styles.searchBackground);

            EditorGUI.BeginChangeCheck();
            var searchRect = new Rect(k_OffsetX + k_Padding, backgroundRect.y + k_Padding, windowWidth - 2 * k_OffsetX - k_Padding, Styles.searchFieldStyle.fixedHeight);

            searchFilterString = EditorGUI.ToolbarSearchField(searchRect, searchFilterString, false);
            if (EditorGUI.EndChangeCheck())
            {
                debounce.Execute();
            }

            if (enumerator != null)
            {
                Search();
            }

            yMin = searchRect.height + (listArea.gridSize < k_MinIconSize ? 11f : 0f);
            var listRect = new Rect(k_Padding, searchRect.y + yMin, windowWidth - 2 * k_Padding, k_SearchHeight - yMin - k_Padding);

            int listKeyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard);

            listArea.OnGUI(listRect, listKeyboardControlID);

            if (enumerator == null && results.Length == 0)
            {
                var labelRect = new Rect(noResultsX, backgroundRect.y + 69f, windowWidth, EditorGUI.kSingleLineHeight);
                EditorGUI.LabelField(backgroundRect, searchFilter.nameFilter.Length == 0 ? Styles.noChildrenLabel : Styles.noResultsLabel, Styles.centered);
            }
        }

        void InitListArea()
        {
            listArea = new ObjectListArea(s_ListAreaState, editorWindow, false)
            {
                allowDeselection      = true,
                allowMultiSelect      = false,
                allowRenaming         = false,
                allowBuiltinResources = true,
            };

            listArea.itemSelectedCallback += (bool doubleClicked) =>
            {
                if (listArea.GetSelection().Length == 0)
                {
                    return;
                }
                var selection = listArea.GetSelection()[0];
                GUIUtility.keyboardControl = GUIUtility.GetControlID(FocusType.Keyboard);
                if (doubleClicked)
                {
                    Selection.SetActiveObjectWithContext(EditorUtility.InstanceIDToObject(selection), null);
                    Event.current.Use();
                    editorWindow.Close();
                    GUIUtility.ExitGUI();
                }
                else
                {
                    EditorGUIUtility.PingObject(selection);
                    Event.current.Use();
                }
            };

            SearchFilterChanged();
        }