接上篇博客
前一篇有一個侷限性:數據是死的,也就是說必須先獲取到數據,再生成圖表。可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);
}
}