接上篇博客
前一篇有一个局限性:数据是死的,也就是说必须先获取到数据,再生成图表。可unity proflier基本上是实时获取数据并呈现的,那么之前的方案就行不通了。
先上效果图
这里是实时获取monoUsed数
原理就是先生成N个为0的数据,然后每点击一次button添加一个新的数据,删除一个末尾的数据,这样就可以动态的显示了。
代码和上一篇大同小异,无非多了一个增加数据和删除数据的方法。
代码:
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.Profiling;
public class DataClass
{
public int[] data = new int[1];
}
public class Paint : EditorWindow
{
List<DataClass> list = new List<DataClass>();
DataClass data = null;
private Material _graphMaterial;
[MenuItem("#############Paint##############/Paint")]
public static void ShowWindow()
{
Rect wr = new Rect(0, 0, 1000, 500);
Paint window = (Paint)GetWindowWithRect(typeof(Paint), wr, true, "Paint");
window.wantsMouseMove = false;
window.Show();
window.Focus();
}
const int LAYERS = 1;
private GUIStyle _headStyle;
private Rect _axisRect = new Rect(170, 250 - 250, 800, 300);
private Rect _graphRect = new Rect(170, 270 - 250, 760, 280);
public int _index = 10;
private Rect _graphContentRect = new Rect(170, 270 - 250, 760, 280);
private Color[] _layerColor = new Color[LAYERS]
{
new Color(220f / 255f, 20f / 255f, 60f / 255f),
//new Color(255f / 255f, 165f / 255f, 0f / 255f),
//new Color(255f / 255f, 255f / 255f, 0f / 255f),
//new Color(124f / 255f, 252f / 255f, 0f / 255f),
//new Color(0f / 255f, 255f / 255f, 255f / 255f),
//new Color(0f / 255f, 0f / 255f, 255f / 255f),
//new Color(128f / 255f, 0f / 255f, 128f / 255f),
};
private Vector3[][] _points = new Vector3[LAYERS][];
//当前鼠标指向的x轴坐标
private int _current;
private bool _clickGraph;
//采样数据
private int _sampleCount;
private List<DataClass> _samples = new List<DataClass>();
private void OnEnable()
{
//捕获数据
_samples = GenFackeData();
//数据横坐标大小
_sampleCount = _samples.Count;
}
private void OnGUI()
{
if (_headStyle == null)
{
_headStyle = new GUIStyle();
_headStyle.fontSize = 15;
_headStyle.alignment = TextAnchor.MiddleCenter;
_headStyle.normal.textColor = new Color(0.8f, 0.8f, 0.8f);
}
if (_graphMaterial == null)
{
_graphMaterial = new Material(Shader.Find("Hidden/Internal-Colored"));
_graphMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
_graphMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
_graphMaterial.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off);
_graphMaterial.SetInt("_ZWrite", 0);
}
if (EditorApplication.isPlaying)
{
DrawGraph();
//鼠标交互
HandleEvent();
}
if (GUI.Button(new Rect(50, 320, 120, 20), "获取新数据"))
{
AddData();
DelectData();
_samples = list;
_sampleCount = _samples.Count + 1;
}
}
//划线算法核心
public void DrawGraph()
{
if (_points[0] == null || _points[0].Length != _sampleCount)
{
for (int layer = 0; layer < LAYERS; ++layer)
_points[layer] = new Vector3[_sampleCount];
}
float maxValue = GetListMaxValue(_samples);
float avgValue = GetListAverageValue(_samples);
//划线算法核心
for (int i = 0; i < _samples.Count; ++i)
{
for (int layer = 0; layer < LAYERS; layer++)
{
_points[layer][i].x = (float)i / _sampleCount * _graphContentRect.width + _graphContentRect.xMin;
_points[layer][i].y = _graphContentRect.yMax - _samples[i].data[layer] / maxValue * _graphContentRect.height;
}
}
//填充颜色
//画点连线
//_graphMaterial.SetPass(0);
//for (int layer = 0; layer < LAYERS; ++layer)
//{
// GL.Begin(GL.TRIANGLE_STRIP);
// GL.Color(_layerColor[layer]);
// for (int i = 0; i < _samples.Count; ++i)
// {
// if (_graphRect.Contains(_points[layer][i]))
// {
// //提交顶点
// GL.Vertex(_points[layer][i]);
// if (layer == LAYERS - 1)
// GL.Vertex3(_points[layer][i].x, _graphContentRect.yMax, 0);
// else
// GL.Vertex(_points[layer + 1][i]);
// }
// }
// GL.End();
//}
//连点成线
Handles.BeginGUI();
for (int layer = 0; layer < LAYERS; ++layer)
{
Handles.color = _layerColor[layer];
Handles.DrawAAPolyLine(_points[layer].Where(p => _graphRect.Contains(p)).ToArray());
}
Handles.EndGUI();
//鼠标定位线
if (_graphRect.Contains(_points[0][_current]))
{
Handles.BeginGUI();
Handles.color = Color.white;
//纵向线
Handles.DrawAAPolyLine(5, new Vector2(_points[0][_current].x, _points[0][_current].y), new Vector2(_points[0][_current].x, _axisRect.yMax));
Handles.EndGUI();
//横向坐标数据
//EditorGUI.LabelField(new Rect(_points[0][_current].x, _axisRect.yMin + 310, 50, 50), _current.ToString() + "/" + (_sampleCount - 1));
//纵向坐标数据
for (int i = 0; i < LAYERS; i++)
{
EditorGUI.LabelField(new Rect(_points[i][_current].x, _points[i][_current].y, 20, 20), _samples[_current].data[i].ToString());
}
}
string detail = string.Format(
"<color={0}>monoUsed:{1:N0}</color>",
Color2String(_layerColor[0]), _samples[_current].data[0]);
EditorGUI.LabelField(new Rect(_axisRect.center.x - 400, _axisRect.yMax + 20, 800, 50), detail, _headStyle);
//坐标轴
DrawArrow(new Vector2(_axisRect.xMin, _axisRect.yMax), new Vector2(_axisRect.xMin, _axisRect.yMin), Color.white);
DrawArrow(new Vector2(_axisRect.xMin, _axisRect.yMax), new Vector2(_axisRect.xMax, _axisRect.yMax), Color.white);
}
//鼠标交互
public void HandleEvent()
{
var point = Event.current.mousePosition;
switch (Event.current.type)
{
//滑动鼠标
case EventType.MouseDrag:
if (Event.current.button == 0 && _clickGraph)
{
UpdateCurrentSample();
Repaint();
}
if (Event.current.button == 2 && _clickGraph)
{
_graphContentRect.x += Event.current.delta.x;
if (_graphContentRect.x > _graphRect.x)
_graphContentRect.x = _graphRect.x;
if (_graphContentRect.xMax < _graphRect.xMax)
_graphContentRect.x = _graphRect.xMax - _graphContentRect.width;
Repaint();
}
break;
//单击鼠标左键
case EventType.MouseDown:
//如果集合内获取过点 就肯定按下了鼠标
_clickGraph = _graphRect.Contains(point);
if (_clickGraph)
//EditorGUI.FocusTextInControl(null);
if (Event.current.button == 0 && _clickGraph)
{
UpdateCurrentSample();
Repaint();
}
if (Event.current.button == 1)
{
//DrawFloatMenu();
Repaint();
}
break;
//键盘左右键
case EventType.KeyDown:
if (Event.current.keyCode == KeyCode.LeftArrow)
SetCurrentIndex(_current - 1);
if (Event.current.keyCode == KeyCode.RightArrow)
SetCurrentIndex(_current + 1);
Repaint();
break;
}
}
private void UpdateCurrentSample()
{
float x = Event.current.mousePosition.x;
float distance = float.MaxValue;
int index = 0;
for (int i = 0; i < _points[0].Length; ++i)
{
//找最近距离的点
if (_graphRect.Contains(_points[0][i]) && Mathf.Abs(x - _points[0][i].x) < distance)
{
distance = Mathf.Abs(x - _points[0][i].x);
index = i;
}
}
//设置当前点
SetCurrentIndex(index);
}
private void SetCurrentIndex(int i)
{
_current = Mathf.Clamp(i, 0, _samples.Count - 1);
}
//Color转string
private string Color2String(Color color)
{
string c = "#";
//ToString("X2")转换为大写16进制
c += ((int)(color.r * 255)).ToString("X2");
c += ((int)(color.g * 255)).ToString("X2");
c += ((int)(color.b * 255)).ToString("X2");
return c;
}
//画坐标轴
private void DrawArrow(Vector2 from, Vector2 to, Color color)
{
Handles.BeginGUI();
Handles.color = color;
Handles.DrawAAPolyLine(3, from, to);
Vector2 v0 = from - to;
v0 *= 10 / v0.magnitude;
Vector2 v1 = new Vector2(v0.x * 0.866f - v0.y * 0.5f, v0.x * 0.5f + v0.y * 0.866f);
Vector2 v2 = new Vector2(v0.x * 0.866f + v0.y * 0.5f, v0.x * -0.5f + v0.y * 0.866f); ;
Handles.DrawAAPolyLine(3, to + v1, to, to + v2);
Handles.EndGUI();
}
private int GetListMaxValue(List<DataClass> list)
{
List<int> newList = new List<int>();
for (int i = 0; i < list.Count; i++)
{
for (int j = 0; j < LAYERS; j++)
{
newList.Add(list[i].data[j]);
}
}
return newList.Max();
}
private float GetListAverageValue(List<DataClass> list)
{
List<int> newList = new List<int>();
for (int i = 0; i < list.Count; i++)
{
for (int j = 0; j < LAYERS; j++)
{
newList.Add(list[i].data[j]);
}
}
return (float)newList.Average();
}
//捕获数据
private List<DataClass> GenFackeData()
{
for (int i = 0; i < 100; i++)
{
data = new DataClass();
data.data[0] = 0;
list.Add(data);
}
return list;
}
//新加数据
private void AddData()
{
data = new DataClass();
var monoUsed = (Profiler.GetMonoUsedSizeLong() >> 10) / 1024f;
data.data[0] = (int)monoUsed;
list.Add(data);
}
//摒弃末尾数据
private void DelectData()
{
list.RemoveAt(0);
}
}