內容非原創 是參考一個大佬的源碼改的。
大佬地址:https://blog.51cto.com/13638120/2103991
先上效果圖:
這裏數據是完全隨機的,當然如果有需要可以捕獲一些真數據。
先貼源碼,思路其實很簡單,想必大家看了都能懂。
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
public class DataClass
{
public int[] data = new int[7];
}
public class Paint : EditorWindow
{
[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 = 7;
private GUIStyle _headStyle;
private Rect _axisRect = new Rect(170, 250 - 250, 800, 300);
private Rect _graphRect = new Rect(170, 270 - 250, 760, 280);
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 (EditorApplication.isPlaying)
{
DrawGraph();
//鼠標交互
HandleEvent();
}
if (GUI.Button(new Rect(50, 320, 120, 20), "生成隨機數據"))
{
//捕獲數據
_samples = GenFackeData();
//數據橫座標大小
_sampleCount = _samples.Count;
}
}
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;
}
}
//填充顏色
//畫點連線
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();
}
//鼠標定位線
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());
}
//EditorGUI.LabelField(new Rect(_points[0][_current].x, _points[0][_current].y, 20, 20), _samples[_current].data[0].ToString());
//EditorGUI.LabelField(new Rect(_points[1][_current].x, _points[1][_current].y, 20, 20), _samples[_current].data[1].ToString());
//EditorGUI.LabelField(new Rect(_points[2][_current].x, _points[2][_current].y, 20, 20), _samples[_current].data[2].ToString());
//EditorGUI.LabelField(new Rect(_points[3][_current].x, _points[3][_current].y, 20, 20), _samples[_current].data[3].ToString());
}
//座標軸
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()
{
List<DataClass> list = new List<DataClass>();
DataClass data = null;
for (int i = 0; i < 100; i++)
{
data = new DataClass();
data.data[0] = Random.Range(90, 100);
data.data[1] = Random.Range(80, 90);
data.data[2] = Random.Range(70, 80);
data.data[3] = Random.Range(55, 70);
data.data[4] = Random.Range(40, 45);
data.data[5] = Random.Range(20, 30);
data.data[6] = Random.Range(0, 15);
list.Add(data);
}
return list;
}
}