protected override void SelectionChanged(IList <int> selectedIds) { ProfilerTimeSampleSelection selection; // When we navigate through frames and there is no path exists, // we still want to be able to frame and select proper sample once it is present again. // Thus we invalidate selection only if user selected new item. // Same applies to expanded state. if (selectedIds.Count > 0) { ClearSelection(setClearedSelection: false); } if (selectedIds.Count > 0 && m_FrameDataView.valid) { List <int> rawIds = new List <int>(); if (selectedIds.Count > 1) { List <int> ids = new List <int>(); for (int i = 0; i < selectedIds.Count; i++) { m_FrameDataView.GetItemRawFrameDataViewIndices(selectedIds[i], ids); } } else { m_FrameDataView.GetItemRawFrameDataViewIndices(selectedIds[0], rawIds); } selection = new ProfilerTimeSampleSelection(m_FrameDataView.frameIndex, m_FrameDataView.threadGroupName, m_FrameDataView.threadName, m_FrameDataView.threadId, rawIds, m_ProfilerSampleNameProvider.GetItemName(m_FrameDataView, selectedIds[0])); var selectedId = selectedIds[0]; var rawSampleIndices = new List <int>(m_FrameDataView.GetItemMergedSamplesCount(selectedId)); m_FrameDataView.GetItemRawFrameDataViewIndices(selectedId, rawSampleIndices); var markerIDs = new List <int>(m_FrameDataView.GetItemDepth(selectedId)); using (var iterator = new RawFrameDataView(m_FrameDataView.frameIndex, m_FrameDataView.threadIndex)) { string name = null; ProfilerTimelineGUI.GetItemMarkerIdPath(iterator, m_ProfilerSampleNameProvider, rawSampleIndices[0], ref name, ref markerIDs); } selection.GenerateMarkerNamePath(m_FrameDataView, markerIDs); } else { selection = null; } var id = selectedIds.Count > 0 ? selectedIds[0] : RawFrameDataView.invalidSampleIndex; if (selectionChanged != null) { selectionChanged.Invoke(selection); } }
public void DoGUI(HierarchyFrameDataView frameDataView, bool fetchData, ref bool updateViewLive, ProfilerViewType viewType) { using (m_DoGUIMarker.Auto()) { if (Event.current.type != EventType.Layout && m_ThreadIndexDuringLastNonLayoutEvent != threadIndexInThreadNames) { m_ThreadIndexDuringLastNonLayoutEvent = threadIndexInThreadNames; EditorGUIUtility.ExitGUI(); } InitIfNeeded(); var isSearchAllowed = string.IsNullOrEmpty(treeView.searchString) || !(m_ProfilerWindow.ProfilerWindowOverheadIsAffectingProfilingRecordingData() && ProfilerDriver.deepProfiling); var isDataAvailable = frameDataView != null && frameDataView.valid; var showDetailedView = isDataAvailable && m_DetailedViewType != DetailedViewType.None; if (showDetailedView) { SplitterGUILayout.BeginHorizontalSplit(m_DetailedViewSpliterState); } // Hierarchy view area GUILayout.BeginVertical(); if (isDataAvailable && (threadIndex != frameDataView.threadIndex || threadName != frameDataView.threadName)) { SetFrameDataView(frameDataView); } DrawToolbar(frameDataView, showDetailedView, ref updateViewLive, viewType); if (!string.IsNullOrEmpty(dataAvailabilityMessage)) { GUILayout.Label(dataAvailabilityMessage, BaseStyles.label); } else if (!isDataAvailable) { if (!fetchData && !updateViewLive) { GUILayout.Label(BaseStyles.liveUpdateMessage, BaseStyles.label); } else { GUILayout.Label(BaseStyles.noData, BaseStyles.label); } } else if (!isSearchAllowed) { GUILayout.Label(BaseStyles.disabledSearchText, BaseStyles.label); } else { var rect = GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none, GUILayout.ExpandHeight(true), GUILayout.ExpandHeight(true)); m_TreeView.SetFrameDataView(frameDataView); m_TreeView.OnGUI(rect, updateViewLive); if (m_TreeView.HasSelection() && m_TreeView.proxySelectionInfo.hasProxySelection) { if (m_TreeView.proxySelectionInfo.cachedDisplayContent == null) { var diff = Math.Abs(m_TreeView.proxySelectionInfo.pathLengthDifferenceForProxy); m_TreeView.proxySelectionInfo.cachedDisplayContent = new GUIContent( BaseStyles.selectionExtraInfoHierarhcyView + string.Format( BaseStyles.proxySampleMessage, m_TreeView.proxySelectionInfo.nonProxyName, diff, diff == 1 ? BaseStyles.proxySampleMessageScopeSingular : BaseStyles.proxySampleMessageScopePlural), BaseStyles.warningTriangle.image); } GUILayout.BeginHorizontal(); GUILayout.Box(m_TreeView.proxySelectionInfo.cachedDisplayContent, BaseStyles.selectionExtraInfoArea); var rectForSampleStackButton = GUILayoutUtility.GetRect(BaseStyles.showDetailsDropdownContent, BaseStyles.tooltipDropdown, GUILayout.ExpandHeight(false), GUILayout.ExpandHeight(false)); if (GUI.Button(rectForSampleStackButton, BaseStyles.showDetailsDropdownContent, BaseStyles.tooltipDropdown)) { var selection = m_TreeView.GetSelection(); var selectedId = (selection != null && selection.Count > 0) ? selection[0] : ProfilerFrameDataHierarchyView.invalidTreeViewId; if (selectedId >= 0) { var menu = new GenericMenu(); // Show Sample Selection: var rawSampleIndices = new List <int>(frameDataView.GetItemMergedSamplesCount(selectedId)); frameDataView.GetItemRawFrameDataViewIndices(selectedId, rawSampleIndices); var actualMarkerIdPath = new List <int>(frameDataView.GetItemDepth(selectedId)); using (var iterator = new RawFrameDataView(frameDataView.frameIndex, frameDataView.threadIndex)) { string name = null; var rawIndex = ProfilerTimelineGUI.GetItemMarkerIdPath(iterator, cpuModule, rawSampleIndices[0], ref name, ref actualMarkerIdPath); } var actualMarkerPath = new List <string>(actualMarkerIdPath.Count); foreach (var id in actualMarkerIdPath) { if ((frameDataView.GetMarkerFlags(id) & Unity.Profiling.LowLevel.MarkerFlags.AvailabilityEditor) != 0) { actualMarkerPath.Add(string.Format("EditorOnly [{0}]", frameDataView.GetMarkerName(id))); } else { actualMarkerPath.Add(frameDataView.GetMarkerName(id)); } } // admittedly, it'd be nice to only generate the text if sample selection option was chosen... // however, that would need to happen in an OnGui call and not within the callback of the generic menu, // to be able to calculate the needed window size and avoid glitches on first displaying it. // at least the user already clicked on the dropdown for this... string selectedSampleStackText = null; var sampleStackSb = new System.Text.StringBuilder(); if (m_TreeView.proxySelectionInfo.nonProxySampleStack != null && m_TreeView.proxySelectionInfo.nonProxySampleStack.Count > 0) { for (int i = m_TreeView.proxySelectionInfo.nonProxySampleStack.Count - 1; i >= 0; i--) { sampleStackSb.AppendLine(m_TreeView.proxySelectionInfo.nonProxySampleStack[i]); } selectedSampleStackText = sampleStackSb.ToString(); } string actualSampleStackText = null; if (actualMarkerPath != null && actualMarkerPath.Count > 0) { sampleStackSb.Clear(); for (int i = actualMarkerPath.Count - 1; i >= 0; i--) { sampleStackSb.AppendLine(actualMarkerPath[i]); } actualSampleStackText = sampleStackSb.ToString(); } var selectionSampleStackContent = selectedSampleStackText != null ? new GUIContent(selectedSampleStackText) : null; var actualSampleStackContent = actualSampleStackText != null ? new GUIContent(actualSampleStackText) : null; var sampleStackWindowSize = SelectedSampleStackWindow.CalculateSize(selectionSampleStackContent, actualSampleStackContent); menu.AddItem(BaseStyles.showSelectedSampleStacks, false, () => { SelectedSampleStackWindow.ShowSampleStackWindow(GUIUtility.GUIToScreenRect(rectForSampleStackButton).position, sampleStackWindowSize, selectionSampleStackContent, actualSampleStackContent); }); menu.DropDown(rectForSampleStackButton); } } GUILayout.EndHorizontal(); } } GUILayout.EndVertical(); if (showDetailedView) { GUILayout.BeginVertical(); // Detailed view area EditorGUILayout.BeginHorizontal(BaseStyles.toolbar); DrawDetailedViewPopup(); GUILayout.FlexibleSpace(); cpuModule.DrawOptionsMenuPopup(); EditorGUILayout.EndHorizontal(); switch (m_DetailedViewType) { case DetailedViewType.Objects: detailedObjectsView.DoGUI(BaseStyles.header, frameDataView, m_TreeView.GetSelection()); break; case DetailedViewType.CallersAndCallees: detailedCallsView.DoGUI(BaseStyles.header, frameDataView, m_TreeView.GetSelection()); break; } GUILayout.EndVertical(); SplitterGUILayout.EndHorizontalSplit(); } HandleKeyboardEvents(); } }