196 lines
6.3 KiB
C#
196 lines
6.3 KiB
C#
#nullable enable
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using ImGuiNET;
|
|
using T3.Core.DataTypes.Vector;
|
|
using T3.Core.Utils;
|
|
using T3.Editor.Gui.Interaction;
|
|
using T3.Editor.Gui.Styling;
|
|
using T3.Editor.Gui.Windows.TimeLine.Raster;
|
|
|
|
namespace T3.Editor.Gui.UiHelpers;
|
|
|
|
internal sealed class VectorCurvePlotCanvas<T>
|
|
{
|
|
internal VectorCurvePlotCanvas(int resolution = 500)
|
|
{
|
|
_sampleCount = resolution;
|
|
_graphValues = new T[_sampleCount];
|
|
|
|
if (typeof(T) == typeof(float))
|
|
{
|
|
_componentCount = 1;
|
|
}
|
|
else if (typeof(T) == typeof(Vector2))
|
|
{
|
|
_componentCount = 2;
|
|
}
|
|
else if (typeof(T) == typeof(Vector3))
|
|
{
|
|
_componentCount = 3;
|
|
}
|
|
else if (typeof(T) == typeof(Vector4))
|
|
{
|
|
_componentCount = 4;
|
|
}
|
|
else
|
|
{
|
|
_componentCount = 0;
|
|
}
|
|
|
|
_graphPoints = new Vector2[_componentCount, _sampleCount];
|
|
_lastValues = new float[_componentCount];
|
|
}
|
|
|
|
private readonly int _componentCount;
|
|
|
|
public void Draw(T value)
|
|
{
|
|
var dl = ImGui.GetWindowDrawList();
|
|
var min = float.PositiveInfinity;
|
|
var max = float.NegativeInfinity;
|
|
|
|
var newValueComponents = Utilities.GetFloatsFromVector(value);
|
|
|
|
foreach (var vv in _graphValues)
|
|
{
|
|
var components = Utilities.GetFloatsFromVector(vv);
|
|
foreach (var v in components)
|
|
{
|
|
if (v > max)
|
|
max = v;
|
|
|
|
if (v < min)
|
|
min = v;
|
|
}
|
|
}
|
|
|
|
var padding = (max - min) * 0.2f;
|
|
min -= padding;
|
|
max += padding;
|
|
dl.PushClipRect(_canvas.WindowPos, _canvas.WindowPos + _canvas.WindowSize, true);
|
|
if (ImGui.IsWindowHovered() && ImGui.IsMouseClicked(ImGuiMouseButton.Left))
|
|
{
|
|
_paused = !_paused;
|
|
}
|
|
|
|
if (!ImGui.IsWindowFocused())
|
|
{
|
|
_paused = false;
|
|
}
|
|
|
|
if (!_paused)
|
|
{
|
|
_canvas.SetScopeToCanvasArea(new ImRect(0, min, 1, max), flipY: true);
|
|
_lastValues = newValueComponents;
|
|
}
|
|
|
|
_canvas.UpdateCanvas(out _);
|
|
_raster.Draw(_canvas);
|
|
if (!_paused)
|
|
{
|
|
_graphValues[_sampleOffset] = value;
|
|
_sampleOffset = (_sampleOffset + 1) % _sampleCount;
|
|
}
|
|
|
|
var maxLength = Math.Max((int)ImGui.GetWindowSize().X, 10);
|
|
var shownSampleCount = Math.Min(_sampleCount, maxLength);
|
|
var startIndex = Math.Max(0,_sampleCount - shownSampleCount);
|
|
|
|
var x = _canvas.WindowPos.X;
|
|
var dx = (_canvas.WindowSize.X - 20) / shownSampleCount;
|
|
for (var index = startIndex; index < _graphValues.Length; index++)
|
|
{
|
|
var v = _graphValues[(index + _sampleOffset) % _sampleCount];
|
|
var components = Utilities.GetFloatsFromVector(v);
|
|
for (var cIndex = 0; cIndex < components.Length; cIndex++)
|
|
{
|
|
var c = components[cIndex];
|
|
_graphPoints[cIndex,index] = new Vector2((int)x,
|
|
(int)_canvas.TransformY(c));
|
|
}
|
|
x += dx;
|
|
}
|
|
|
|
for(int cIndex= 0; cIndex< _componentCount; cIndex ++)
|
|
{
|
|
var color = _componentCount == 1 ? CurveComponentColors.GrayCurveColor : CurveComponentColors.CurveColors[cIndex];
|
|
dl.AddPolyline(ref _graphPoints[cIndex,startIndex], shownSampleCount, color, ImDrawFlags.None, 1);
|
|
dl.AddCircleFilled(_graphPoints[cIndex, _sampleCount - 1], 3, color);
|
|
}
|
|
|
|
var windowHeight = ImGui.GetWindowSize().Y / T3Ui.UiScaleFactor;
|
|
var font = windowHeight switch
|
|
{
|
|
< 100 => Fonts.FontSmall,
|
|
< 200 => Fonts.FontNormal,
|
|
_ => Fonts.FontLarge,
|
|
};
|
|
|
|
|
|
var y = _canvas.WindowSize.Y * 0.5f - font.FontSize * _componentCount / 2;
|
|
|
|
for (var cIndex = 0; cIndex < _lastValues.Length; cIndex++)
|
|
{
|
|
var color = _componentCount == 1 ? CurveComponentColors.GrayCurveColor : CurveComponentColors.TextColors[cIndex];
|
|
color.Rgba.W= 1;
|
|
|
|
var lastValue = _lastValues[cIndex];
|
|
var valueAsString = $"{lastValue:G4}";
|
|
dl.AddText(font,
|
|
font.FontSize,
|
|
_canvas.WindowPos
|
|
+ new Vector2(_canvas.WindowSize.X - font.FontSize*5,
|
|
y),
|
|
color,
|
|
valueAsString);
|
|
y += font.FontSize;
|
|
}
|
|
|
|
dl.PopClipRect();
|
|
}
|
|
|
|
public void Reset(T clearValue)
|
|
{
|
|
for (var index = 0; index < _sampleCount; index++)
|
|
{
|
|
_graphValues[index] = clearValue;
|
|
}
|
|
}
|
|
|
|
private readonly T[] _graphValues;
|
|
private readonly Vector2[,] _graphPoints;
|
|
private int _sampleOffset;
|
|
private readonly int _sampleCount;
|
|
|
|
private bool _paused;
|
|
private float[] _lastValues;
|
|
|
|
private readonly HorizontalRaster _raster = new();
|
|
private readonly ScalableCanvas _canvas = new CurrentGraphSubCanvas { FillMode = ScalableCanvas.FillModes.FillAvailableContentRegion };
|
|
//private const int MaxComponents = 4;
|
|
}
|
|
|
|
[SuppressMessage("ReSharper", "RedundantArgumentDefaultValue")]
|
|
internal static class CurveComponentColors
|
|
{
|
|
internal static readonly Color GrayCurveColor = new(1f, 1f, 1.0f, 0.3f);
|
|
|
|
internal static readonly Color[] CurveColors =
|
|
[
|
|
new(1f, 0.2f, 0.2f, 0.3f),
|
|
new(0.1f, 1f, 0.2f, 0.3f),
|
|
new(0.1f, 0.4f, 1.0f, 0.5f),
|
|
new(0.5f, 0.5f, 0.5f, 0.5f),
|
|
GrayCurveColor
|
|
];
|
|
|
|
internal static readonly Color[] TextColors =
|
|
[
|
|
new(1f, 0.5f, 0.5f, 1f),
|
|
new(0.4f, 1f, 0.5f, 1f),
|
|
new(0.6f, 0.671f, 1.0f, 1f),
|
|
new(0.6f, 0.6f, 0.6f, 1f),
|
|
GrayCurveColor
|
|
];
|
|
}
|