Code/Demos/BeatPad/OscilloscopeBlob.cs
using System;
using Goo;
using Sandbox.UI;
using static Sandbox.BeatPadTokens;
namespace Sandbox;
// pure presenter for the retro-LCD oscilloscope: scrolling synthetic trace on an Ink LCD. trace state (sample ring) lives in BeatPadUI; zero per-frame allocation.
internal static class OscilloscopeBlob
{
public readonly record struct Props(
float[] Samples, // -1..1, newest at the end (scrolls right -> left)
float Glow); // 0..1 overall brightness hint (the decaying hit envelope)
public static Container Build(Props p)
{
int n = p.Samples.Length;
float colPct = 100f / n;
float traceAlpha = 0.55f + 0.45f * Math.Clamp(p.Glow, 0f, 1f);
var lcd = new Container
{
Key = "lcd",
Width = Length.Percent(100),
Height = Length.Percent(100),
Position = PositionMode.Relative,
BackgroundColor = Ink,
BorderColor = Ink,
BorderWidth = OutlineWidth,
BorderRadius = ScopeRadius,
Children =
{
// dimmed center axis
new Container
{
Key = "axis",
Position = PositionMode.Absolute,
Left = 0, Top = Length.Percent(50),
Width = Length.Percent(100), Height = 1f,
BackgroundColor = Hot.WithAlpha(0.22f),
PointerEvents = PointerEvents.None,
},
},
};
// Each sample -> a thin vertical bar from the midline to the sample's amplitude.
const float halfSpan = 0.46f; // fraction of height available each side of center
for (int i = 0; i < n; i++)
{
float s = Math.Clamp(p.Samples[i], -1f, 1f);
float h = MathF.Abs(s) * halfSpan; // fraction of full height
float top = s >= 0f ? (0.5f - h) : 0.5f; // grow up for +, down for -
lcd.Children.Add(new Container
{
Key = $"c{i}",
Position = PositionMode.Absolute,
Left = Length.Percent(i * colPct),
Top = Length.Percent(top * 100f),
Width = Length.Percent(colPct * 0.7f),
Height = Length.Percent(MathF.Max(h * 100f, 0.6f)),
BackgroundColor = Hot.WithAlpha(traceAlpha),
PointerEvents = PointerEvents.None,
});
}
return lcd;
}
}