protected override void OnContentGUI(Rect rect, int row, TreeViewItem itemRaw, string label, bool selected, bool focused, bool useBoldFont, bool isPinging)
            {
                if (Event.current.type != EventType.Repaint)
                {
                    return;
                }

                FrameDebuggerTreeViewItem item = (FrameDebuggerTreeViewItem)itemRaw;
                string     text;
                GUIContent tempContent;
                GUIStyle   style;

                bool      isParent  = (item.hasChildren);
                FontStyle fontStyle = (isParent) ? FontStyle.Bold : FontStyle.Normal;

                childCounter = (isParent) ? 1 : (childCounter + 1);

                // Draw background
                style       = FrameDebuggerStyles.Tree.rowText;
                tempContent = EditorGUIUtility.TempContent("");
                style.Draw(rect, tempContent, false, false, false, false);

                // indent
                float indent = GetContentIndent(item);

                rect.x     += indent;
                rect.width -= indent;

                // child event count
                if (isParent)
                {
                    text        = item.m_ChildEventCount.ToString(CultureInfo.InvariantCulture);
                    tempContent = EditorGUIUtility.TempContent(text);

                    style           = FrameDebuggerStyles.Tree.rowTextRight;
                    style.fontStyle = fontStyle;

                    Rect r = rect;
                    r.width -= kSmallMargin;
                    style.Draw(r, tempContent, false, false, false, false);

                    // reduce width of available space for the name, so that it does not overlap event count
                    rect.width -= style.CalcSize(tempContent).x + kSmallMargin * 2;
                }

                style           = FrameDebuggerStyles.Tree.rowText;
                style.fontStyle = fontStyle;

                // draw event name
                text = item.displayName;

                if (string.IsNullOrEmpty(text))
                {
                    text = FrameDebuggerStyles.Tree.k_UnknownScopeString;
                }

                tempContent = EditorGUIUtility.TempContent(text);
                style.Draw(rect, tempContent, false, false, false, selected && focused);
            }
        public void SelectFrameEventIndex(int eventIndex)
        {
            // Check if we'd end up selecting same "frame event":
            // different tree nodes could result in the same frame debugger event
            // limit, e.g. a hierarchy node sets last child event as the limit.
            // If the limit event is the same, then do not change the currently selected item.
            int[] selection = m_TreeView.GetSelection();
            if (selection.Length > 0)
            {
                FrameDebuggerTreeViewItem item = m_TreeView.FindItem(selection[0]) as FrameDebuggerTreeViewItem;
                if (item != null && eventIndex == item.m_EventIndex)
                {
                    return;
                }
            }

            m_TreeView.SetSelection(new[] { eventIndex }, true);
        }
        void SelectionChanged(int[] selectedIDs)
        {
            if (selectedIDs.Length < 1)
            {
                return;
            }

            int id         = selectedIDs[0];
            int eventIndex = id;
            FrameDebuggerTreeViewItem originalItem = null;

            // For tree hierarchy nodes, their IDs are not the frame event indices;
            // fetch the ID from the node itself in that case.
            // IDs for hierarchy nodes are negative and need to stay consistently ordered so
            // that tree expanded state behaves well when something in the scene changes.
            //
            // When selecting a hierarchy node, we want it's last child event to be set as the limit,
            // so that rendered state corresponds to "everything up to and including this whole sub-tree".
            if (eventIndex <= 0)
            {
                originalItem = m_TreeView.FindItem(id) as FrameDebuggerTreeViewItem;
                FrameDebuggerTreeViewItem item = m_TreeView.FindItem(id) as FrameDebuggerTreeViewItem;
                if (item != null)
                {
                    eventIndex = item.m_EventIndex;
                }

                // If still has no valid ID, do nothing.
                if (eventIndex <= 0)
                {
                    return;
                }
            }

            m_FrameDebugger.ChangeFrameEventLimit(eventIndex, originalItem);
        }
            public override void FetchData()
            {
                FrameDebuggerTreeHierarchyLevel rootLevel = new FrameDebuggerTreeHierarchyLevel(0, 0, string.Empty, null);

                // Hierarchy levels of a tree being built
                List <FrameDebuggerTreeHierarchyLevel> eventStack = new List <FrameDebuggerTreeHierarchyLevel>();

                eventStack.Add(rootLevel);

                int hierarchyIDCounter = -1;

                for (int i = 0; i < m_FrameEvents.Length; ++i)
                {
                    // This will be a slash-delimited string, e.g. Foo/Bar/Baz.
                    // Add "/" in front to account for the single (invisible) root item
                    // that the TreeView always has.
                    string   context = "/" + (FrameDebuggerUtility.GetFrameEventInfoName(i) ?? string.Empty);
                    string[] names   = context.Split('/');

                    // find matching hierarchy level
                    int level = 0;
                    while (level < eventStack.Count && level < names.Length)
                    {
                        if (names[level] != eventStack[level].item.displayName)
                        {
                            break;
                        }

                        ++level;
                    }

                    // close all the further levels from previous events in the stack
                    while (eventStack.Count > 0 && eventStack.Count > level)
                    {
                        CloseLastHierarchyLevel(eventStack, i);
                    }

                    if (FrameDebuggerHelper.IsAHierarchyLevelBreakEvent(m_FrameEvents[i].type))
                    {
                        continue;
                    }

                    // add all further levels for current event
                    for (int j = level; j < names.Length; ++j)
                    {
                        var parent   = eventStack[eventStack.Count - 1];
                        var newLevel = new FrameDebuggerTreeHierarchyLevel(eventStack.Count - 1, --hierarchyIDCounter, names[j], parent.item);
                        parent.children.Add(newLevel.item);
                        eventStack.Add(newLevel);
                    }

                    if (FrameDebuggerHelper.IsAHiddenEvent(m_FrameEvents[i].type))
                    {
                        continue;
                    }

                    // add leaf event to current level
                    var eventObj    = FrameDebuggerUtility.GetFrameEventObject(i);
                    var displayName = string.Empty;

                    if (eventObj)
                    {
                        displayName = " " + eventObj.name;
                    }
                    else
                    {
                        displayName = FrameDebuggerStyles.frameEventTypeNames[(int)m_FrameEvents[i].type];
                    }

                    FrameDebuggerTreeHierarchyLevel parentEvent = eventStack[eventStack.Count - 1];
                    int leafEventID = i + 1;
                    FrameDebuggerTreeViewItem item = new FrameDebuggerTreeViewItem(leafEventID, eventStack.Count - 1, parentEvent.item, displayName);
                    item.m_FrameEvent = m_FrameEvents[i];
                    parentEvent.children.Add(item);
                    ++parentEvent.item.m_ChildEventCount;
                }

                while (eventStack.Count > 0)
                {
                    CloseLastHierarchyLevel(eventStack, m_FrameEvents.Length);
                }

                m_RootItem = rootLevel.item;
            }
 internal FrameDebuggerTreeHierarchyLevel(int depth, int id, string name, FrameDebuggerTreeViewItem parent)
 {
     item     = new FrameDebuggerTreeViewItem(id, depth, parent, name);
     children = new List <TreeViewItem>();
 }
 public FrameDebuggerTreeViewItem(int id, int depth, FrameDebuggerTreeViewItem parent, string displayName)
     : base(id, depth, parent, displayName)
 {
     m_EventIndex = id;
 }