项目文件夹

文件
2026-07-13 13:13:17 +08:00

126 行
4.1 KiB
C#

using ImGuiNET;
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 CurvePlotCanvas
{
internal CurvePlotCanvas(int resolution = 500)
{
_sampleCount = resolution;
_graphValues = new float[_sampleCount];
_graphPoints = new Vector2[_sampleCount];
}
internal void Draw(float value)
{
var dl = ImGui.GetWindowDrawList();
var min = float.PositiveInfinity;
var max = float.NegativeInfinity;
foreach (var v in _graphValues)
{
if (v > max)
max = v;
if (v < min)
min = v;
}
var padding = (max - min) * 0.2f;
if (padding < 0.001f)
padding = 0.05f;
min -= padding;
max += padding;
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);
_lastValue = value;
}
_canvas.UpdateCanvas(out _);
dl.PushClipRect(_canvas.WindowPos, _canvas.WindowPos + _canvas.WindowSize, true);
_raster.Draw(_canvas);
if (!_paused && float.IsFinite(value) && !float.IsInfinity(value) && !float.IsNaN(value))
{
_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];
_graphPoints[index] = new Vector2(
(int)x,
(int)_canvas.TransformY(v));
x += dx;
}
dl.AddPolyline(ref _graphPoints[startIndex],
shownSampleCount ,
UiColors.Text.Fade(0.3f),
ImDrawFlags.None,
1);
dl.AddCircleFilled(_graphPoints[_sampleCount - 1], 3, UiColors.Gray);
var windowHeight = ImGui.GetWindowSize().Y / T3Ui.UiScaleFactor;
var font = windowHeight switch
{
< 100 => Fonts.FontSmall,
< 200 => Fonts.FontNormal,
_ => Fonts.FontLarge,
};
var valueAsString = $"{_lastValue:G5}";
dl.AddText(font,
font.FontSize,
_canvas.WindowPos
+ new Vector2(_canvas.WindowSize.X - font.FontSize*5,
_canvas.WindowSize.Y * 0.5f - font.FontSize / 2),
UiColors.Text,
valueAsString);
dl.PopClipRect();
}
public void Reset(float clearValue = 0)
{
for (var index = 0; index < _sampleCount; index++)
{
_graphValues[index] = clearValue;
}
}
private readonly float[] _graphValues;
private readonly Vector2[] _graphPoints;
private int _sampleOffset;
private readonly int _sampleCount;
private bool _paused;
private float _lastValue;
private readonly HorizontalRaster _raster = new();
private readonly ScalableCanvas _canvas = new CurrentGraphSubCanvas { FillMode = ScalableCanvas.FillModes.FillAvailableContentRegion };
}