源战役客户端
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

369 行
12 KiB

  1. using System;
  2. using NUnit.Framework.Constraints;
  3. using UnityEngine;
  4. using System.Collections.Generic;
  5. using Treemap;
  6. using UnityEditor;
  7. using Assets.Editor.Treemap;
  8. using System.Linq;
  9. using UnityEngine.UI;
  10. namespace MemoryProfilerWindow
  11. {
  12. public class TreeMapView
  13. {
  14. CrawledMemorySnapshot _unpackedCrawl;
  15. private ZoomArea _ZoomArea;
  16. private Dictionary<string, Group> _groups = new Dictionary<string, Group>();
  17. private List<Item> _items = new List<Item>();
  18. private List<Mesh> _cachedMeshes = new List<Mesh>();
  19. private Item _selectedItem;
  20. private Group _selectedGroup;
  21. private Item _mouseDownItem;
  22. MemoryProfilerWindow _hostWindow;
  23. private Vector2 mouseTreemapPosition { get { return _ZoomArea.ViewToDrawingTransformPoint(Event.current.mousePosition); } }
  24. public void Setup(MemoryProfilerWindow hostWindow, CrawledMemorySnapshot _unpackedCrawl)
  25. {
  26. this._unpackedCrawl = _unpackedCrawl;
  27. this._hostWindow = hostWindow;
  28. _ZoomArea = new ZoomArea(true)
  29. {
  30. vRangeMin = -110f,
  31. vRangeMax = 110f,
  32. hRangeMin = -110f,
  33. hRangeMax = 110f,
  34. hBaseRangeMin = -110f,
  35. vBaseRangeMin = -110f,
  36. hBaseRangeMax = 110f,
  37. vBaseRangeMax = 110f,
  38. shownArea = new Rect(-110f, -110f, 220f, 220f)
  39. };
  40. RefreshCaches();
  41. RefreshMesh();
  42. }
  43. public void Draw()
  44. {
  45. if (_hostWindow == null)
  46. return;
  47. Rect r = new Rect(0f, 25f, _hostWindow.position.width - _hostWindow._inspector.width, _hostWindow.position.height - 25f);
  48. _ZoomArea.rect = r;
  49. _ZoomArea.BeginViewGUI();
  50. GUI.BeginGroup(r);
  51. Handles.matrix = _ZoomArea.drawingToViewMatrix;
  52. HandleMouseClick();
  53. RenderTreemap();
  54. GUI.EndGroup();
  55. _ZoomArea.EndViewGUI();
  56. }
  57. private void OnHoveredGroupChanged()
  58. {
  59. RefreshCachedRects(false);
  60. }
  61. private void HandleMouseClick()
  62. {
  63. if ((Event.current.type == EventType.MouseDown || Event.current.type == EventType.MouseUp) && Event.current.button == 0)
  64. {
  65. if (_ZoomArea.drawRect.Contains(Event.current.mousePosition))
  66. {
  67. Group group = _groups.Values.FirstOrDefault(i => i._position.Contains(mouseTreemapPosition));
  68. Item item = _items.FirstOrDefault(i => i._position.Contains(mouseTreemapPosition));
  69. if (item != null && _selectedGroup == item._group)
  70. {
  71. switch (Event.current.type)
  72. {
  73. case EventType.MouseDown:
  74. _mouseDownItem = item;
  75. break;
  76. case EventType.MouseUp:
  77. if (_mouseDownItem == item)
  78. {
  79. _hostWindow.SelectThing(item._thingInMemory);
  80. Event.current.Use();
  81. }
  82. break;
  83. }
  84. }
  85. else if (group != null)
  86. {
  87. switch (Event.current.type)
  88. {
  89. case EventType.MouseUp:
  90. _hostWindow.SelectGroup(group);
  91. Event.current.Use();
  92. break;
  93. }
  94. }
  95. }
  96. }
  97. }
  98. public void SelectThing(ThingInMemory thing)
  99. {
  100. _selectedItem = _items.First(i => i._thingInMemory == thing);
  101. _selectedGroup = _selectedItem._group;
  102. RefreshCachedRects(false);
  103. }
  104. public void SelectGroup(Group group)
  105. {
  106. _selectedItem = null;
  107. _selectedGroup = group;
  108. RefreshCachedRects(false);
  109. }
  110. void RefreshCaches()
  111. {
  112. _items.Clear();
  113. _groups.Clear();
  114. foreach (ThingInMemory thingInMemory in _unpackedCrawl.allObjects)
  115. {
  116. string groupName = GetGroupName(thingInMemory);
  117. if (groupName.Length == 0)
  118. continue;
  119. if (!_groups.ContainsKey(groupName))
  120. {
  121. Group newGroup = new Group();
  122. newGroup._name = groupName;
  123. newGroup._items = new List<Item>();
  124. _groups.Add(groupName, newGroup);
  125. }
  126. Item item = new Item(thingInMemory, _groups[groupName]);
  127. _items.Add(item);
  128. _groups[groupName]._items.Add(item);
  129. }
  130. foreach (Group group in _groups.Values)
  131. {
  132. group._items.Sort();
  133. }
  134. _items.Sort();
  135. RefreshCachedRects(true);
  136. }
  137. private void RefreshCachedRects(bool fullRefresh)
  138. {
  139. Rect space = new Rect(-100f, -100f, 200f, 200f);
  140. if (fullRefresh)
  141. {
  142. List<Group> groups = _groups.Values.ToList();
  143. groups.Sort();
  144. float[] groupTotalValues = new float[groups.Count];
  145. for (int i = 0; i < groups.Count; i++)
  146. {
  147. groupTotalValues[i] = groups.ElementAt(i).totalMemorySize;
  148. }
  149. Rect[] groupRects = Utility.GetTreemapRects(groupTotalValues, space);
  150. for (int groupIndex = 0; groupIndex < groupRects.Length; groupIndex++)
  151. {
  152. Group group = groups[groupIndex];
  153. group._position = groupRects[groupIndex];
  154. }
  155. }
  156. if (_selectedGroup != null)
  157. {
  158. Rect[] rects = Utility.GetTreemapRects(_selectedGroup.memorySizes, _selectedGroup._position);
  159. for (int i = 0; i < rects.Length; i++)
  160. {
  161. _selectedGroup._items[i]._position = rects[i];
  162. }
  163. }
  164. RefreshMesh();
  165. }
  166. public void CleanupMeshes ()
  167. {
  168. if (_cachedMeshes == null) {
  169. _cachedMeshes = new List<Mesh> ();
  170. }
  171. else {
  172. for (int i = 0; i < _cachedMeshes.Count; i++) {
  173. UnityEngine.Object.DestroyImmediate (_cachedMeshes [i]);
  174. }
  175. _cachedMeshes.Clear ();
  176. }
  177. }
  178. private void RefreshMesh()
  179. {
  180. CleanupMeshes ();
  181. const int maxVerts = 32000;
  182. Vector3[] vertices = new Vector3[maxVerts];
  183. Color[] colors = new Color[maxVerts];
  184. int[] triangles = new int[maxVerts * 6 / 4];
  185. int meshItemIndex = 0;
  186. int totalItemIndex = 0;
  187. List<ITreemapRenderable> visible = new List<ITreemapRenderable>();
  188. foreach (Group group in _groups.Values)
  189. {
  190. if (group != _selectedGroup)
  191. {
  192. visible.Add(group);
  193. }
  194. else
  195. {
  196. foreach (Item item in group._items)
  197. {
  198. visible.Add(item);
  199. }
  200. }
  201. }
  202. foreach (ITreemapRenderable item in visible)
  203. {
  204. int index = meshItemIndex * 4;
  205. vertices[index++] = new Vector3(item.GetPosition().xMin, item.GetPosition().yMin, 0f);
  206. vertices[index++] = new Vector3(item.GetPosition().xMax, item.GetPosition().yMin, 0f);
  207. vertices[index++] = new Vector3(item.GetPosition().xMax, item.GetPosition().yMax, 0f);
  208. vertices[index++] = new Vector3(item.GetPosition().xMin, item.GetPosition().yMax, 0f);
  209. index = meshItemIndex * 4;
  210. var color = item.GetColor();
  211. if (item == _selectedItem)
  212. color *= 1.5f;
  213. colors[index++] = color;
  214. colors[index++] = color * 0.75f;
  215. colors[index++] = color * 0.5f;
  216. colors[index++] = color * 0.75f;
  217. index = meshItemIndex * 6;
  218. triangles[index++] = meshItemIndex * 4 + 0;
  219. triangles[index++] = meshItemIndex * 4 + 1;
  220. triangles[index++] = meshItemIndex * 4 + 3;
  221. triangles[index++] = meshItemIndex * 4 + 1;
  222. triangles[index++] = meshItemIndex * 4 + 2;
  223. triangles[index++] = meshItemIndex * 4 + 3;
  224. meshItemIndex++;
  225. totalItemIndex++;
  226. if (meshItemIndex >= maxVerts / 4 || totalItemIndex == visible.Count)
  227. {
  228. Mesh mesh = new Mesh();
  229. mesh.hideFlags = HideFlags.DontSaveInEditor | HideFlags.HideInHierarchy | HideFlags.NotEditable;
  230. mesh.vertices = vertices;
  231. mesh.triangles = triangles;
  232. mesh.colors = colors;
  233. _cachedMeshes.Add(mesh);
  234. vertices = new Vector3[maxVerts];
  235. colors = new Color[maxVerts];
  236. triangles = new int[maxVerts * 6 / 4];
  237. meshItemIndex = 0;
  238. }
  239. }
  240. }
  241. public void RenderTreemap()
  242. {
  243. if (_cachedMeshes == null)
  244. return;
  245. Material mat = (Material)EditorGUIUtility.LoadRequired("SceneView/2DHandleLines.mat");
  246. mat.SetPass(0);
  247. for (int i = 0; i < _cachedMeshes.Count; i++)
  248. {
  249. Graphics.DrawMeshNow(_cachedMeshes[i], Handles.matrix);
  250. }
  251. RenderLabels();
  252. }
  253. private void RenderLabels()
  254. {
  255. if (_groups == null)
  256. return;
  257. GUI.color = Color.black;
  258. Matrix4x4 mat = _ZoomArea.drawingToViewMatrix;
  259. foreach (Group group in _groups.Values)
  260. {
  261. if (Utility.IsInside(group._position, _ZoomArea.shownArea))
  262. {
  263. if (_selectedItem != null && _selectedItem._group == group)
  264. {
  265. RenderGroupItems(group);
  266. }
  267. else
  268. {
  269. RenderGroupLabel(group);
  270. }
  271. }
  272. }
  273. GUI.color = Color.white;
  274. }
  275. private void RenderGroupLabel(Group group)
  276. {
  277. Matrix4x4 mat = _ZoomArea.drawingToViewMatrix;
  278. Vector3 p1 = mat.MultiplyPoint(new Vector3(group._position.xMin, group._position.yMin));
  279. Vector3 p2 = mat.MultiplyPoint(new Vector3(group._position.xMax, group._position.yMax));
  280. if (p2.x - p1.x > 30f)
  281. {
  282. Rect rect = new Rect(p1.x, p2.y, p2.x - p1.x, p1.y - p2.y);
  283. GUI.Label(rect, group.GetLabel());
  284. }
  285. }
  286. private void RenderGroupItems(Group group)
  287. {
  288. Matrix4x4 mat = _ZoomArea.drawingToViewMatrix;
  289. foreach (Item item in group._items)
  290. {
  291. if (Utility.IsInside(item._position, _ZoomArea.shownArea))
  292. {
  293. Vector3 p1 = mat.MultiplyPoint(new Vector3(item._position.xMin, item._position.yMin));
  294. Vector3 p2 = mat.MultiplyPoint(new Vector3(item._position.xMax, item._position.yMax));
  295. if (p2.x - p1.x > 30f)
  296. {
  297. Rect rect = new Rect(p1.x, p2.y, p2.x - p1.x, p1.y - p2.y);
  298. string row1 = item._group._name;
  299. string row2 = EditorUtility.FormatBytes(item.memorySize);
  300. GUI.Label(rect, row1 + "\n" + row2);
  301. }
  302. }
  303. }
  304. }
  305. public string GetGroupName(ThingInMemory thing)
  306. {
  307. if (thing is NativeUnityEngineObject)
  308. return (thing as NativeUnityEngineObject).className ?? "MissingName";
  309. if (thing is ManagedObject)
  310. return (thing as ManagedObject).typeDescription.name;
  311. return thing.GetType().Name;
  312. }
  313. }
  314. }