91 lines
3.5 KiB
C#
91 lines
3.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using XericLibrary.Runtime.UIGraph;
|
|
|
|
namespace XericUI.XChart.Line
|
|
{
|
|
[AddComponentMenu("Xeric/XChart/Line/Line Chart")]
|
|
[ExecuteAlways]
|
|
public sealed class XLineChart : XChartBase
|
|
{
|
|
[SerializeField] private Color m_LineColor = new Color(0.33f, 0.67f, 1f, 1f);
|
|
[SerializeField] private float m_LineThickness = 2f;
|
|
[SerializeField] private int m_MaximumBuckets = 1024;
|
|
[SerializeField] private float m_WindowDuration = 60f;
|
|
private UILineRendererV2 m_Renderer;
|
|
private long m_LastVersion = -1;
|
|
|
|
protected override void OnEnable()
|
|
{
|
|
base.OnEnable();
|
|
EnsureRenderer();
|
|
}
|
|
|
|
private void EnsureRenderer()
|
|
{
|
|
if (m_Renderer != null) return;
|
|
var layer = new GameObject("LineRenderer", typeof(RectTransform), typeof(UILineRendererV2));
|
|
var rect = layer.GetComponent<RectTransform>();
|
|
rect.SetParent(ToolsRoot, false);
|
|
rect.anchorMin = Vector2.zero;
|
|
rect.anchorMax = Vector2.one;
|
|
rect.offsetMin = Vector2.zero;
|
|
rect.offsetMax = Vector2.zero;
|
|
layer.hideFlags = CurrentFlags;
|
|
m_Renderer = layer.GetComponent<UILineRendererV2>();
|
|
}
|
|
|
|
protected override void LateUpdate()
|
|
{
|
|
base.LateUpdate();
|
|
EnsureRenderer();
|
|
var snapshot = DataModel.Snapshot;
|
|
if (snapshot == null || snapshot.RecordCount < 2 || snapshot.NumericDimensionCount == 0 || snapshot.Version == m_LastVersion) return;
|
|
m_LastVersion = snapshot.Version;
|
|
Draw(snapshot);
|
|
}
|
|
|
|
public bool TryAddSample(double timestamp, float value)
|
|
{
|
|
EnsureDefaultDimension();
|
|
return DataModel.TryAddRecord(timestamp, new[] { value });
|
|
}
|
|
|
|
private void EnsureDefaultDimension()
|
|
{
|
|
if (DataModel.NumericDimensionCount > 0) return;
|
|
DataModel.SetDimensions(new List<XChartDimensionDefinition>
|
|
{
|
|
new XChartDimensionDefinition("value", "Value", XChartDimensionKind.Number),
|
|
});
|
|
}
|
|
|
|
private void Draw(XChartDataSnapshot snapshot)
|
|
{
|
|
m_Renderer.ClearAll();
|
|
float width = Mathf.Max(1f, ((RectTransform)transform).rect.width);
|
|
float height = Mathf.Max(1f, ((RectTransform)transform).rect.height);
|
|
int start = Mathf.Max(0, snapshot.RecordCount - Mathf.Clamp(Mathf.CeilToInt(width), 2, m_MaximumBuckets));
|
|
float min = float.MaxValue;
|
|
float max = float.MinValue;
|
|
for (int i = start; i < snapshot.RecordCount; i++)
|
|
{
|
|
float value = snapshot.Values[i * snapshot.NumericDimensionCount];
|
|
min = Mathf.Min(min, value);
|
|
max = Mathf.Max(max, value);
|
|
}
|
|
if (Mathf.Approximately(min, max)) max = min + 1f;
|
|
var points = new Vector2[snapshot.RecordCount - start];
|
|
for (int i = start; i < snapshot.RecordCount; i++)
|
|
{
|
|
float x = (i - start) * width / Mathf.Max(1, snapshot.RecordCount - start - 1) - width * 0.5f;
|
|
float value = snapshot.Values[i * snapshot.NumericDimensionCount];
|
|
float y = Mathf.InverseLerp(min, max, value) * height - height * 0.5f;
|
|
points[i - start] = new Vector2(x, y);
|
|
}
|
|
m_Renderer.DrawPolyline(points, m_LineColor, m_LineThickness);
|
|
}
|
|
}
|
|
}
|