C#反射的实践纪录
问题来源:unity profiler 只能看,不能导出数据报表,想实现此功能,怎么办?
由于它是用C#写的,因此,反射大法。
一,使用什么工具,反编译它的代码到C#,经实践,ILSPY即可。
二,想实现一个功能:在CPU usage分析模式下,当在搜索框中输入搜索字符串时,有一个事件:searchChanged,如何将自己的函数注册给这个事件,代码如下:
static PropertyInfo columnStrsInfo; static PropertyInfo searchStrInfo; static EventInfo searchCbEventInfo; static bool hasRegistCallback; //此函数原型要与treeview中的事件原型一致:void SearchChangedCallback(string newSearch) static void OnStrChanged(string str) { Debug.Log("str=====" + str); } static void RegistCallback() { //注意,GetTypeInfo与GetType的用法区别:前者对类型使用,后者对对象使用 var methodInfo = typeof(ProfilerWraper).GetTypeInfo().GetMethod("OnStrChanged", BindingFlags.Static|BindingFlags.NonPublic); var del = Delegate.CreateDelegate(searchCbEventInfo.EventHandlerType, methodInfo); searchCbEventInfo.AddEventHandler(treeView, del); }
其中,treeView是ProfilerFrameDataTreeView类型,类的反编译代码如下:
using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; using UnityEditor; using UnityEditor.IMGUI.Controls; using UnityEditor.Profiling; using UnityEditorInternal.Profiling; using UnityEngine; using UnityEngine.Assertions; namespace UnityEditorInternal { internal class ProfilerFrameDataTreeView : TreeView { private class ExpandedMarkerIdHierarchy { public Dictionary<int, ProfilerFrameDataTreeView.ExpandedMarkerIdHierarchy> expandedMarkers; } public delegate void SelectionChangedCallback(int id); public delegate void SearchChangedCallback(string newSearch); private class FrameDataTreeViewItem : TreeViewItem { private HierarchyFrameDataView m_FrameDataView; private bool m_Initialized; private string[] m_StringProperties; private string m_ResolvedCallstack; public string[] columnStrings { get { return this.m_StringProperties; } } public string resolvedCallstack { get { bool flag = this.m_ResolvedCallstack == null; if (flag) { this.m_ResolvedCallstack = this.m_FrameDataView.ResolveItemCallstack(this.id); } return this.m_ResolvedCallstack; } } public int samplesCount { get { return this.m_FrameDataView.GetItemMergedSamplesCount(this.id); } } public FrameDataTreeViewItem(HierarchyFrameDataView frameDataView, int id, int depth, TreeViewItem parent) : base(id, depth, parent, null) { this.m_FrameDataView = frameDataView; this.m_Initialized = false; } internal void Init(HierarchyFrameDataView frameDataView, int id, int depth, TreeViewItem parent) { this.id = id; this.depth = depth; this.parent = parent; this.displayName = null; this.m_FrameDataView = frameDataView; this.m_Initialized = false; } public void Init(ProfilerFrameDataMultiColumnHeader.Column[] columns, IProfilerSampleNameProvider profilerSampleNameProvider) { bool initialized = this.m_Initialized; if (!initialized) { this.m_StringProperties = new string[columns.Length]; for (int i = 0; i < columns.Length; i++) { int profilerColumn = columns[i].profilerColumn; bool flag = columns[i].profilerColumn == 0; string text; if (flag) { text = profilerSampleNameProvider.GetItemName(this.m_FrameDataView, this.id); this.displayName = text; } else { text = this.m_FrameDataView.GetItemColumnData(this.id, columns[i].profilerColumn); } this.m_StringProperties[i] = text; } this.m_Initialized = true; } } } private struct TreeTraversalState { public ProfilerFrameDataTreeView.FrameDataTreeViewItem item; public ProfilerFrameDataTreeView.ExpandedMarkerIdHierarchy expandedHierarchy; } public static readonly GUIContent kFrameTooltip = EditorGUIUtility.TrTextContent("", "Press 'F' to frame selection", null); private const int kMaxPooledRowsCount = 1000000; private readonly List<TreeViewItem> m_Rows = new List<TreeViewItem>(1000); private ProfilerFrameDataMultiColumnHeader m_MultiColumnHeader; private HierarchyFrameDataView m_FrameDataView; private List<int> m_SelectedItemMarkerIdPath; private string m_LegacySelectedItemMarkerNamePath; [NonSerialized] protected IProfilerSampleNameProvider m_ProfilerSampleNameProvider; [NonSerialized] private ProfilerFrameDataTreeView.ExpandedMarkerIdHierarchy m_ExpandedMarkersHierarchy; [NonSerialized] private List<TreeViewItem> m_RowsPool = new List<TreeViewItem>(); [NonSerialized] private Stack<List<TreeViewItem>> m_ChildrenPool = new Stack<List<TreeViewItem>>(); [NonSerialized] private LinkedList<ProfilerFrameDataTreeView.TreeTraversalState> m_ReusableVisitList = new LinkedList<ProfilerFrameDataTreeView.TreeTraversalState>(); [NonSerialized] private List<int> m_ReusableChildrenIds = new List<int>(1024); [NonSerialized] private Stack<LinkedListNode<ProfilerFrameDataTreeView.TreeTraversalState>> m_TreeTraversalStatePool = new Stack<LinkedListNode<ProfilerFrameDataTreeView.TreeTraversalState>>(); [method: CompilerGenerated] [DebuggerBrowsable(DebuggerBrowsableState.Never), CompilerGenerated] public event ProfilerFrameDataTreeView.SelectionChangedCallback selectionChanged; [method: CompilerGenerated] [DebuggerBrowsable(DebuggerBrowsableState.Never), CompilerGenerated] public event ProfilerFrameDataTreeView.SearchChangedCallback searchChanged; public int sortedProfilerColumn { get { return this.m_MultiColumnHeader.sortedProfilerColumn; } } public bool sortedProfilerColumnAscending { get { return this.m_MultiColumnHeader.sortedProfilerColumnAscending; } } public ProfilerFrameDataTreeView(TreeViewState state, ProfilerFrameDataMultiColumnHeader multicolumnHeader, IProfilerSampleNameProvider profilerSampleNameProvider) : base(state, multicolumnHeader) { Assert.IsNotNull<ProfilerFrameDataMultiColumnHeader>(multicolumnHeader); base.deselectOnUnhandledMouseDown = true; this.m_ProfilerSampleNameProvider = profilerSampleNameProvider; this.m_MultiColumnHeader = multicolumnHeader; this.m_MultiColumnHeader.sortingChanged += new MultiColumnHeader.HeaderCallback(this.OnSortingChanged); } public void SetFrameDataView(HierarchyFrameDataView frameDataView) { bool flag = !object.Equals(this.m_FrameDataView, frameDataView); bool flag2 = frameDataView != null && frameDataView.valid && (frameDataView.sortColumn != this.m_MultiColumnHeader.sortedProfilerColumn || frameDataView.sortColumnAscending != this.m_MultiColumnHeader.sortedProfilerColumnAscending); bool flag3 = flag; if (flag3) { this.StoreExpandedState(); this.StoreSelectedState(); } this.m_FrameDataView = frameDataView; bool flag4 = flag2; if (flag4) { this.m_FrameDataView.Sort(this.m_MultiColumnHeader.sortedProfilerColumn, this.m_MultiColumnHeader.sortedProfilerColumnAscending); } bool flag5 = flag | flag2; if (flag5) { base.Reload(); } } private void AddExpandedChildrenRecursively(TreeViewItem item, ProfilerFrameDataTreeView.ExpandedMarkerIdHierarchy expandedHierarchy) { bool flag = item.children == null; if (!flag) { for (int i = 0; i < item.children.Count; i++) { TreeViewItem treeViewItem = item.children[i]; bool flag2 = treeViewItem.children != null && treeViewItem.children[0] != null; if (flag2) { ProfilerFrameDataTreeView.ExpandedMarkerIdHierarchy expandedMarkerIdHierarchy = new ProfilerFrameDataTreeView.ExpandedMarkerIdHierarchy(); bool flag3 = expandedHierarchy.expandedMarkers == null; if (flag3) { expandedHierarchy.expandedMarkers = new Dictionary<int, ProfilerFrameDataTreeView.ExpandedMarkerIdHierarchy>(); } try { expandedHierarchy.expandedMarkers.Add(this.m_FrameDataView.GetItemMarkerID(treeViewItem.id), expandedMarkerIdHierarchy); } catch (ArgumentException) { } this.AddExpandedChildrenRecursively(treeViewItem, expandedMarkerIdHierarchy); } } } } private void StoreExpandedState() { bool flag = this.m_ExpandedMarkersHierarchy != null; if (!flag) { bool flag2 = this.m_FrameDataView == null || !this.m_FrameDataView.valid; if (!flag2) { this.m_ExpandedMarkersHierarchy = new ProfilerFrameDataTreeView.ExpandedMarkerIdHierarchy(); this.AddExpandedChildrenRecursively(base.rootItem, this.m_ExpandedMarkersHierarchy); } } } public void SetSelectionFromLegacyPropertyPath(string selectedPropertyPath) { bool flag = this.m_SelectedItemMarkerIdPath != null && this.PropertyPathMatchesSelectedIDs(selectedPropertyPath, base.state.selectedIDs); if (!flag) { this.m_LegacySelectedItemMarkerNamePath = selectedPropertyPath; this.m_SelectedItemMarkerIdPath = null; } } private bool PropertyPathMatchesSelectedIDs(string legacyPropertyPath, List<int> selectedIDs) { bool flag = this.m_FrameDataView == null || !this.m_FrameDataView.valid; bool result; if (flag) { result = false; } else { bool flag2 = string.IsNullOrEmpty(legacyPropertyPath) || selectedIDs == null || selectedIDs.Count == 0; if (flag2) { result = (string.IsNullOrEmpty(legacyPropertyPath) && (selectedIDs == null || selectedIDs.Count == 0)); } else { result = (this.m_FrameDataView.GetItemPath(selectedIDs[0]) == legacyPropertyPath); } } return result; } private void StoreSelectedState() { bool flag = this.m_SelectedItemMarkerIdPath != null || this.m_LegacySelectedItemMarkerNamePath != null; if (!flag) { bool flag2 = this.m_FrameDataView == null || !this.m_FrameDataView.valid; if (!flag2) { IList<int> selection = base.GetSelection(); bool flag3 = selection.Count == 0; if (!flag3) { this.m_FrameDataView.GetItemMarkerIDPath(selection[0], this.m_SelectedItemMarkerIdPath); } } } } private void MigrateExpandedState(List<int> newExpandedIds) { bool flag = newExpandedIds == null; if (!flag) { base.state.expandedIDs = newExpandedIds; } } private void MigrateSelectedState(bool expandIfNecessary) { bool flag = this.m_SelectedItemMarkerIdPath == null && this.m_LegacySelectedItemMarkerNamePath == null; if (!flag) { int num = this.m_FrameDataView.GetRootItemID(); bool flag2 = true; bool flag3 = this.m_SelectedItemMarkerIdPath != null; if (flag3) { foreach (int current in this.m_SelectedItemMarkerIdPath) { bool flag4 = this.m_FrameDataView.HasItemChildren(num); if (flag4) { this.m_FrameDataView.GetItemChildren(num, this.m_ReusableChildrenIds); foreach (int current2 in this.m_ReusableChildrenIds) { bool flag5 = current == this.m_FrameDataView.GetItemMarkerID(current2); if (flag5) { bool flag6 = !base.IsExpanded(num); if (flag6) { flag2 = false; } num = current2; break; } } } bool flag7 = num == 0; if (flag7) { break; } } } else { bool flag8 = this.m_LegacySelectedItemMarkerNamePath != null; if (flag8) { List<int> list = new List<int>(); string[] array = this.m_LegacySelectedItemMarkerNamePath.Split(new char[] { '/' }); string[] array2 = array; for (int i = 0; i < array2.Length; i++) { string a = array2[i]; bool flag9 = this.m_FrameDataView.HasItemChildren(num); if (flag9) { this.m_FrameDataView.GetItemChildren(num, this.m_ReusableChildrenIds); foreach (int current3 in this.m_ReusableChildrenIds) { bool flag10 = a == this.m_FrameDataView.GetItemName(current3); if (flag10) { bool flag11 = !base.IsExpanded(num); if (flag11) { flag2 = false; } num = current3; list.Add(this.m_FrameDataView.GetItemMarkerID(current3)); break; } } } bool flag12 = num == 0; if (flag12) { break; } } this.m_SelectedItemMarkerIdPath = list; this.m_LegacySelectedItemMarkerNamePath = null; } } List<int> arg_24B_0; if (num != 0) { (arg_24B_0 = new List<int>()).Add(num); } else { arg_24B_0 = new List<int>(); } List<int> selectedIDs = arg_24B_0; base.state.selectedIDs = selectedIDs; bool flag13 = ProfilerDriver.enabled && (ProfilerDriver.profileEditor || EditorApplication.isPlaying); bool flag14 = !flag13; bool flag15 = ((num != 0 && base.isInitialized) & flag14) && (flag2 | expandIfNecessary); if (flag15) { base.FrameItem(num); } } } public IList<int> GetSelectedInstanceIds() { bool flag = this.m_FrameDataView == null || !this.m_FrameDataView.valid; IList<int> result; if (flag) { result = null; } else { IList<int> selection = base.GetSelection(); bool flag2 = selection == null || selection.Count == 0; if (flag2) { result = null; } else { List<int> list = new List<int>(); List<int> list2 = new List<int>(); foreach (int current in selection) { this.m_FrameDataView.GetItemMergedSamplesInstanceID(current, list2); list.AddRange(list2); } result = list; } } return result; } public void Clear() { bool flag = this.m_FrameDataView == null; if (!flag) { this.m_FrameDataView.Dispose(); this.m_FrameDataView = null; this.m_RowsPool.Clear(); this.m_ChildrenPool.Clear(); this.m_ReusableVisitList.Clear(); this.m_ReusableChildrenIds.Clear(); this.m_TreeTraversalStatePool.Clear(); base.Reload(); } } protected override TreeViewItem BuildRoot() { int id = (this.m_FrameDataView != null) ? this.m_FrameDataView.GetRootItemID() : 0; return new ProfilerFrameDataTreeView.FrameDataTreeViewItem(this.m_FrameDataView, id, -1, null); } protected override IList<TreeViewItem> BuildRows(TreeViewItem root) { bool flag = this.m_RowsPool.Count < 1000000; if (flag) { this.m_RowsPool.AddRange(this.m_Rows); } this.m_Rows.Clear(); bool flag2 = this.m_FrameDataView == null || !this.m_FrameDataView.valid; IList<TreeViewItem> rows; if (flag2) { rows = this.m_Rows; } else { List<int> newExpandedIds = (this.m_ExpandedMarkersHierarchy == null) ? null : new List<int>(base.state.expandedIDs.Count); bool flag3 = !string.IsNullOrEmpty(base.searchString); if (flag3) { this.Search(root, base.searchString, this.m_Rows); } else { this.AddAllChildren((ProfilerFrameDataTreeView.FrameDataTreeViewItem)root, this.m_ExpandedMarkersHierarchy, this.m_Rows, newExpandedIds); } this.MigrateExpandedState(newExpandedIds); this.MigrateSelectedState(false); rows = this.m_Rows; } return rows; } private void Search(TreeViewItem searchFromThis, string search, List<TreeViewItem> result) { bool flag = searchFromThis == null; if (flag) { throw new ArgumentException("Invalid searchFromThis: cannot be null", "searchFromThis"); } bool flag2 = string.IsNullOrEmpty(search); if (flag2) { throw new ArgumentException("Invalid search: cannot be null or empty", "search"); } Stack<int> stack = new Stack<int>(); this.m_FrameDataView.GetItemChildren(searchFromThis.id, this.m_ReusableChildrenIds); foreach (int current in this.m_ReusableChildrenIds) { stack.Push(current); } while (stack.Count > 0) { int num = stack.Pop(); string itemName = this.m_ProfilerSampleNameProvider.GetItemName(this.m_FrameDataView, num); bool flag3 = itemName.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0; if (flag3) { ProfilerFrameDataTreeView.FrameDataTreeViewItem frameDataTreeViewItem = this.AcquireFrameDataTreeViewItem(this.m_FrameDataView, num, 0, searchFromThis); searchFromThis.AddChild(frameDataTreeViewItem); result.Add(frameDataTreeViewItem); } this.m_FrameDataView.GetItemChildren(num, this.m_ReusableChildrenIds); foreach (int current2 in this.m_ReusableChildrenIds) { stack.Push(current2); } } } private LinkedListNode<ProfilerFrameDataTreeView.TreeTraversalState> AcquireTreeTraversalStateNode(ProfilerFrameDataTreeView.FrameDataTreeViewItem item, ProfilerFrameDataTreeView.ExpandedMarkerIdHierarchy expandedHierarchy) { bool flag = this.m_TreeTraversalStatePool.Count == 0; LinkedListNode<ProfilerFrameDataTreeView.TreeTraversalState> result; if (flag) { result = new LinkedListNode<ProfilerFrameDataTreeView.TreeTraversalState>(new ProfilerFrameDataTreeView.TreeTraversalState { item = item, expandedHierarchy = expandedHierarchy }); } else { LinkedListNode<ProfilerFrameDataTreeView.TreeTraversalState> linkedListNode = this.m_TreeTraversalStatePool.Pop(); linkedListNode.Value = new ProfilerFrameDataTreeView.TreeTraversalState { item = item, expandedHierarchy = expandedHierarchy }; result = linkedListNode; } return result; } private ProfilerFrameDataTreeView.FrameDataTreeViewItem AcquireFrameDataTreeViewItem(HierarchyFrameDataView frameDataView, int id, int depth, TreeViewItem parent) { bool flag = this.m_RowsPool.Count > 0; ProfilerFrameDataTreeView.FrameDataTreeViewItem result; if (flag) { ProfilerFrameDataTreeView.FrameDataTreeViewItem frameDataTreeViewItem = (ProfilerFrameDataTreeView.FrameDataTreeViewItem)this.m_RowsPool[this.m_RowsPool.Count - 1]; this.m_RowsPool.RemoveAt(this.m_RowsPool.Count - 1); frameDataTreeViewItem.Init(this.m_FrameDataView, id, depth, parent); bool flag2 = frameDataTreeViewItem.children != null; if (flag2) { this.m_ChildrenPool.Push(frameDataTreeViewItem.children); frameDataTreeViewItem.children = null; } result = frameDataTreeViewItem; } else { result = new ProfilerFrameDataTreeView.FrameDataTreeViewItem(this.m_FrameDataView, id, depth, parent); } return result; } private void AddAllChildren(ProfilerFrameDataTreeView.FrameDataTreeViewItem parent, ProfilerFrameDataTreeView.ExpandedMarkerIdHierarchy parentExpandedHierararchy, IList<TreeViewItem> newRows, List<int> newExpandedIds) { this.m_ReusableVisitList.AddFirst(this.AcquireTreeTraversalStateNode(parent, parentExpandedHierararchy)); while (this.m_ReusableVisitList.First != null) { ProfilerFrameDataTreeView.TreeTraversalState value = this.m_ReusableVisitList.First.Value; this.m_TreeTraversalStatePool.Push(this.m_ReusableVisitList.First); this.m_ReusableVisitList.RemoveFirst(); bool flag = value.item.depth != -1; if (flag) { newRows.Add(value.item); } this.m_FrameDataView.GetItemChildren(value.item.id, this.m_ReusableChildrenIds); int count = this.m_ReusableChildrenIds.Count; bool flag2 = count == 0; if (!flag2) { bool flag3 = value.item.depth != -1; if (flag3) { bool flag4 = this.m_ExpandedMarkersHierarchy == null; bool flag5; if (flag4) { flag5 = base.IsExpanded(value.item.id); } else { flag5 = (value.expandedHierarchy != null); } bool flag6 = !flag5; if (flag6) { bool flag7 = value.item.children == null; if (flag7) { value.item.children = TreeView.CreateChildListForCollapsedParent(); } continue; } bool flag8 = newExpandedIds != null; if (flag8) { newExpandedIds.Add(value.item.id); } } bool flag9 = value.item.children == null; if (flag9) { bool flag10 = this.m_ChildrenPool.Count > 0; if (flag10) { value.item.children = this.m_ChildrenPool.Pop(); } else { value.item.children = new List<TreeViewItem>(); } } value.item.children.Clear(); value.item.children.Capacity = count; for (int i = 0; i < count; i++) { ProfilerFrameDataTreeView.FrameDataTreeViewItem item = this.AcquireFrameDataTreeViewItem(this.m_FrameDataView, this.m_ReusableChildrenIds[i], value.item.depth + 1, value.item); value.item.children.Add(item); } LinkedListNode<ProfilerFrameDataTreeView.TreeTraversalState> linkedListNode = null; foreach (TreeViewItem current in value.item.children) { int itemMarkerID = this.m_FrameDataView.GetItemMarkerID(current.id); ProfilerFrameDataTreeView.ExpandedMarkerIdHierarchy expandedHierarchy = null; bool flag11 = value.expandedHierarchy != null && value.expandedHierarchy.expandedMarkers != null; if (flag11) { value.expandedHierarchy.expandedMarkers.TryGetValue(itemMarkerID, out expandedHierarchy); } LinkedListNode<ProfilerFrameDataTreeView.TreeTraversalState> linkedListNode2 = this.AcquireTreeTraversalStateNode((ProfilerFrameDataTreeView.FrameDataTreeViewItem)current, expandedHierarchy); bool flag12 = linkedListNode == null; if (flag12) { this.m_ReusableVisitList.AddFirst(linkedListNode2); } else { this.m_ReusableVisitList.AddAfter(linkedListNode, linkedListNode2); } linkedListNode = linkedListNode2; } } } bool flag13 = newExpandedIds != null; if (flag13) { newExpandedIds.Sort(); } } protected override bool CanMultiSelect(TreeViewItem item) { return false; } protected override void SelectionChanged(IList<int> selectedIds) { bool flag = selectedIds.Count > 0; if (flag) { this.m_SelectedItemMarkerIdPath = null; this.m_LegacySelectedItemMarkerNamePath = null; } int id = (selectedIds.Count > 0) ? selectedIds[0] : -1; bool flag2 = this.selectionChanged != null; if (flag2) { this.selectionChanged(id); } } protected override void ExpandedStateChanged() { this.m_ExpandedMarkersHierarchy = null; } protected override void DoubleClickedItem(int id) { } protected override void ContextClickedItem(int id) { } protected override void ContextClicked() { } protected override void SearchChanged(string newSearch) { bool flag = this.searchChanged != null; if (flag) { this.searchChanged(newSearch); } } protected override IList<int> GetAncestors(int id) { bool flag = this.m_FrameDataView == null || !this.m_FrameDataView.valid; IList<int> result; if (flag) { result = new List<int>(); } else { List<int> list = new List<int>(); this.m_FrameDataView.GetItemAncestors(id, list); result = list; } return result; } protected override IList<int> GetDescendantsThatHaveChildren(int id) { bool flag = this.m_FrameDataView == null || !this.m_FrameDataView.valid; IList<int> result; if (flag) { result = new List<int>(); } else { List<int> list = new List<int>(); this.m_FrameDataView.GetItemDescendantsThatHaveChildren(id, list); result = list; } return result; } private void OnSortingChanged(MultiColumnHeader header) { bool flag = this.m_FrameDataView == null || base.multiColumnHeader.sortedColumnIndex == -1; if (!flag) { this.m_FrameDataView.Sort(this.m_MultiColumnHeader.sortedProfilerColumn, this.m_MultiColumnHeader.sortedProfilerColumnAscending); base.Reload(); } } public override void OnGUI(Rect rect) { bool flag = this.m_LegacySelectedItemMarkerNamePath != null; if (flag) { this.MigrateSelectedState(true); } base.OnGUI(rect); } protected override void RowGUI(TreeView.RowGUIArgs args) { bool flag = Event.get_current().get_rawType() != 7; if (!flag) { ProfilerFrameDataTreeView.FrameDataTreeViewItem frameDataTreeViewItem = (ProfilerFrameDataTreeView.FrameDataTreeViewItem)args.item; frameDataTreeViewItem.Init(this.m_MultiColumnHeader.columns, this.m_ProfilerSampleNameProvider); for (int i = 0; i < args.GetNumVisibleColumns(); i++) { Rect cellRect = args.GetCellRect(i); this.CellGUI(cellRect, frameDataTreeViewItem, i == 0, args.GetColumn(i), ref args); } bool flag2 = !args.selected; if (!flag2) { bool flag3 = args.rowRect.Contains(Event.get_current().get_mousePosition()); bool flag4 = !flag3; if (!flag4) { bool hasSearch = base.hasSearch; if (hasSearch) { GUIStyle.SetMouseTooltip(ProfilerFrameDataTreeView.kFrameTooltip.get_tooltip(), args.rowRect); } } } } } private void CellGUI(Rect cellRect, ProfilerFrameDataTreeView.FrameDataTreeViewItem item, bool needsIndent, int column, ref TreeView.RowGUIArgs args) { if (needsIndent) { float num = base.GetContentIndent(item) + base.extraSpaceBeforeIconAndLabel; cellRect.set_xMin(cellRect.get_xMin() + num); } base.CenterRectUsingSingleLineHeight(ref cellRect); GUIContent gUIContent = GUIContent.Temp(item.columnStrings[column], string.Empty); TreeView.DefaultStyles.label.Draw(cellRect, gUIContent, false, false, args.selected, args.focused); } } }