源战役客户端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

369 regels
12 KiB

using System;
using NUnit.Framework.Constraints;
using UnityEngine;
using System.Collections.Generic;
using Treemap;
using UnityEditor;
using Assets.Editor.Treemap;
using System.Linq;
using UnityEngine.UI;
namespace MemoryProfilerWindow
{
public class TreeMapView
{
CrawledMemorySnapshot _unpackedCrawl;
private ZoomArea _ZoomArea;
private Dictionary<string, Group> _groups = new Dictionary<string, Group>();
private List<Item> _items = new List<Item>();
private List<Mesh> _cachedMeshes = new List<Mesh>();
private Item _selectedItem;
private Group _selectedGroup;
private Item _mouseDownItem;
MemoryProfilerWindow _hostWindow;
private Vector2 mouseTreemapPosition { get { return _ZoomArea.ViewToDrawingTransformPoint(Event.current.mousePosition); } }
public void Setup(MemoryProfilerWindow hostWindow, CrawledMemorySnapshot _unpackedCrawl)
{
this._unpackedCrawl = _unpackedCrawl;
this._hostWindow = hostWindow;
_ZoomArea = new ZoomArea(true)
{
vRangeMin = -110f,
vRangeMax = 110f,
hRangeMin = -110f,
hRangeMax = 110f,
hBaseRangeMin = -110f,
vBaseRangeMin = -110f,
hBaseRangeMax = 110f,
vBaseRangeMax = 110f,
shownArea = new Rect(-110f, -110f, 220f, 220f)
};
RefreshCaches();
RefreshMesh();
}
public void Draw()
{
if (_hostWindow == null)
return;
Rect r = new Rect(0f, 25f, _hostWindow.position.width - _hostWindow._inspector.width, _hostWindow.position.height - 25f);
_ZoomArea.rect = r;
_ZoomArea.BeginViewGUI();
GUI.BeginGroup(r);
Handles.matrix = _ZoomArea.drawingToViewMatrix;
HandleMouseClick();
RenderTreemap();
GUI.EndGroup();
_ZoomArea.EndViewGUI();
}
private void OnHoveredGroupChanged()
{
RefreshCachedRects(false);
}
private void HandleMouseClick()
{
if ((Event.current.type == EventType.MouseDown || Event.current.type == EventType.MouseUp) && Event.current.button == 0)
{
if (_ZoomArea.drawRect.Contains(Event.current.mousePosition))
{
Group group = _groups.Values.FirstOrDefault(i => i._position.Contains(mouseTreemapPosition));
Item item = _items.FirstOrDefault(i => i._position.Contains(mouseTreemapPosition));
if (item != null && _selectedGroup == item._group)
{
switch (Event.current.type)
{
case EventType.MouseDown:
_mouseDownItem = item;
break;
case EventType.MouseUp:
if (_mouseDownItem == item)
{
_hostWindow.SelectThing(item._thingInMemory);
Event.current.Use();
}
break;
}
}
else if (group != null)
{
switch (Event.current.type)
{
case EventType.MouseUp:
_hostWindow.SelectGroup(group);
Event.current.Use();
break;
}
}
}
}
}
public void SelectThing(ThingInMemory thing)
{
_selectedItem = _items.First(i => i._thingInMemory == thing);
_selectedGroup = _selectedItem._group;
RefreshCachedRects(false);
}
public void SelectGroup(Group group)
{
_selectedItem = null;
_selectedGroup = group;
RefreshCachedRects(false);
}
void RefreshCaches()
{
_items.Clear();
_groups.Clear();
foreach (ThingInMemory thingInMemory in _unpackedCrawl.allObjects)
{
string groupName = GetGroupName(thingInMemory);
if (groupName.Length == 0)
continue;
if (!_groups.ContainsKey(groupName))
{
Group newGroup = new Group();
newGroup._name = groupName;
newGroup._items = new List<Item>();
_groups.Add(groupName, newGroup);
}
Item item = new Item(thingInMemory, _groups[groupName]);
_items.Add(item);
_groups[groupName]._items.Add(item);
}
foreach (Group group in _groups.Values)
{
group._items.Sort();
}
_items.Sort();
RefreshCachedRects(true);
}
private void RefreshCachedRects(bool fullRefresh)
{
Rect space = new Rect(-100f, -100f, 200f, 200f);
if (fullRefresh)
{
List<Group> groups = _groups.Values.ToList();
groups.Sort();
float[] groupTotalValues = new float[groups.Count];
for (int i = 0; i < groups.Count; i++)
{
groupTotalValues[i] = groups.ElementAt(i).totalMemorySize;
}
Rect[] groupRects = Utility.GetTreemapRects(groupTotalValues, space);
for (int groupIndex = 0; groupIndex < groupRects.Length; groupIndex++)
{
Group group = groups[groupIndex];
group._position = groupRects[groupIndex];
}
}
if (_selectedGroup != null)
{
Rect[] rects = Utility.GetTreemapRects(_selectedGroup.memorySizes, _selectedGroup._position);
for (int i = 0; i < rects.Length; i++)
{
_selectedGroup._items[i]._position = rects[i];
}
}
RefreshMesh();
}
public void CleanupMeshes ()
{
if (_cachedMeshes == null) {
_cachedMeshes = new List<Mesh> ();
}
else {
for (int i = 0; i < _cachedMeshes.Count; i++) {
UnityEngine.Object.DestroyImmediate (_cachedMeshes [i]);
}
_cachedMeshes.Clear ();
}
}
private void RefreshMesh()
{
CleanupMeshes ();
const int maxVerts = 32000;
Vector3[] vertices = new Vector3[maxVerts];
Color[] colors = new Color[maxVerts];
int[] triangles = new int[maxVerts * 6 / 4];
int meshItemIndex = 0;
int totalItemIndex = 0;
List<ITreemapRenderable> visible = new List<ITreemapRenderable>();
foreach (Group group in _groups.Values)
{
if (group != _selectedGroup)
{
visible.Add(group);
}
else
{
foreach (Item item in group._items)
{
visible.Add(item);
}
}
}
foreach (ITreemapRenderable item in visible)
{
int index = meshItemIndex * 4;
vertices[index++] = new Vector3(item.GetPosition().xMin, item.GetPosition().yMin, 0f);
vertices[index++] = new Vector3(item.GetPosition().xMax, item.GetPosition().yMin, 0f);
vertices[index++] = new Vector3(item.GetPosition().xMax, item.GetPosition().yMax, 0f);
vertices[index++] = new Vector3(item.GetPosition().xMin, item.GetPosition().yMax, 0f);
index = meshItemIndex * 4;
var color = item.GetColor();
if (item == _selectedItem)
color *= 1.5f;
colors[index++] = color;
colors[index++] = color * 0.75f;
colors[index++] = color * 0.5f;
colors[index++] = color * 0.75f;
index = meshItemIndex * 6;
triangles[index++] = meshItemIndex * 4 + 0;
triangles[index++] = meshItemIndex * 4 + 1;
triangles[index++] = meshItemIndex * 4 + 3;
triangles[index++] = meshItemIndex * 4 + 1;
triangles[index++] = meshItemIndex * 4 + 2;
triangles[index++] = meshItemIndex * 4 + 3;
meshItemIndex++;
totalItemIndex++;
if (meshItemIndex >= maxVerts / 4 || totalItemIndex == visible.Count)
{
Mesh mesh = new Mesh();
mesh.hideFlags = HideFlags.DontSaveInEditor | HideFlags.HideInHierarchy | HideFlags.NotEditable;
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.colors = colors;
_cachedMeshes.Add(mesh);
vertices = new Vector3[maxVerts];
colors = new Color[maxVerts];
triangles = new int[maxVerts * 6 / 4];
meshItemIndex = 0;
}
}
}
public void RenderTreemap()
{
if (_cachedMeshes == null)
return;
Material mat = (Material)EditorGUIUtility.LoadRequired("SceneView/2DHandleLines.mat");
mat.SetPass(0);
for (int i = 0; i < _cachedMeshes.Count; i++)
{
Graphics.DrawMeshNow(_cachedMeshes[i], Handles.matrix);
}
RenderLabels();
}
private void RenderLabels()
{
if (_groups == null)
return;
GUI.color = Color.black;
Matrix4x4 mat = _ZoomArea.drawingToViewMatrix;
foreach (Group group in _groups.Values)
{
if (Utility.IsInside(group._position, _ZoomArea.shownArea))
{
if (_selectedItem != null && _selectedItem._group == group)
{
RenderGroupItems(group);
}
else
{
RenderGroupLabel(group);
}
}
}
GUI.color = Color.white;
}
private void RenderGroupLabel(Group group)
{
Matrix4x4 mat = _ZoomArea.drawingToViewMatrix;
Vector3 p1 = mat.MultiplyPoint(new Vector3(group._position.xMin, group._position.yMin));
Vector3 p2 = mat.MultiplyPoint(new Vector3(group._position.xMax, group._position.yMax));
if (p2.x - p1.x > 30f)
{
Rect rect = new Rect(p1.x, p2.y, p2.x - p1.x, p1.y - p2.y);
GUI.Label(rect, group.GetLabel());
}
}
private void RenderGroupItems(Group group)
{
Matrix4x4 mat = _ZoomArea.drawingToViewMatrix;
foreach (Item item in group._items)
{
if (Utility.IsInside(item._position, _ZoomArea.shownArea))
{
Vector3 p1 = mat.MultiplyPoint(new Vector3(item._position.xMin, item._position.yMin));
Vector3 p2 = mat.MultiplyPoint(new Vector3(item._position.xMax, item._position.yMax));
if (p2.x - p1.x > 30f)
{
Rect rect = new Rect(p1.x, p2.y, p2.x - p1.x, p1.y - p2.y);
string row1 = item._group._name;
string row2 = EditorUtility.FormatBytes(item.memorySize);
GUI.Label(rect, row1 + "\n" + row2);
}
}
}
}
public string GetGroupName(ThingInMemory thing)
{
if (thing is NativeUnityEngineObject)
return (thing as NativeUnityEngineObject).className ?? "MissingName";
if (thing is ManagedObject)
return (thing as ManagedObject).typeDescription.name;
return thing.GetType().Name;
}
}
}