A UI Panel that draws an arc-style gauge using an SDF arc shader. It exposes properties for value, sweep, radii, colors, segmentation and writes shader parameters to CommandList before drawing a quad with the UI box material.
using Sandbox.Rendering;
using Sandbox.UI;
using System;
using System.Xml.Linq;
namespace Machines.UI;
/// <summary>
/// A panel that draws an arc gauge using the SDF arc shader. Set Value (0-1) to control fill.
/// </summary>
public class GaugeArc : Panel, IPanelDraw
{
private static Material _material;
/// <summary>
/// Current fill value (0 = empty, 1 = full).
/// </summary>
public float Value { get; set; }
/// <summary>
/// Total arc sweep in degrees (default 90 = 25% of circle).
/// </summary>
public float MaxSweepDegrees { get; set; } = 90f;
/// <summary>
/// Inner radius of the ring (0-1 in UV space).
/// </summary>
public float InnerRadius { get; set; } = 0.75f;
/// <summary>
/// Outer radius of the ring (0-1 in UV space).
/// </summary>
public float OuterRadius { get; set; } = 0.95f;
/// <summary>
/// Color of the filled portion.
/// </summary>
public Color FillColor { get; set; } = Color.Cyan;
/// <summary>
/// Color of the unfilled track background.
/// </summary>
public Color TrackColor { get; set; } = new Color( 0.15f, 0.15f, 0.15f, 0.6f );
/// <summary>
/// Start angle offset in degrees (0 = top).
/// </summary>
public float StartAngleDegrees { get; set; } = 0f;
/// <summary>
/// Rounded cap radius (0 = sharp, 1 = maximum rounding).
/// </summary>
public float CapRadius { get; set; } = 0.3f;
/// <summary>
/// Number of segments (0 or 1 = no gaps).
/// </summary>
public int SegmentCount { get; set; } = 0;
/// <summary>
/// Gap angle between segments in degrees.
/// </summary>
public float GapAngleDegrees { get; set; } = 0f;
/// <summary>
/// Optional fill gradient end color. Null = solid fill (no gradient).
/// </summary>
public Color? FillColorEnd { get; set; } = null;
/// <summary>
/// Optional track gradient end color. Null = solid track (no gradient).
/// </summary>
public Color? TrackColorEnd { get; set; } = null;
public GaugeArc()
{
if ( !_material.IsValid() ) _material = Material.FromShader( "shaders/sdf_arc.shader" );
}
void IPanelDraw.Draw( CommandList cl )
{
if ( !_material.IsValid() ) return;
var sweepRad = MaxSweepDegrees * (MathF.PI / 180f);
var fillRad = MathF.Max( 0f, MathF.Min( Value, 1f ) ) * sweepRad;
var startRad = StartAngleDegrees * (MathF.PI / 180f);
var rect = Box.Rect;
cl.Attributes.Set( "FillAngle", fillRad );
cl.Attributes.Set( "SweepAngle", sweepRad );
cl.Attributes.Set( "InnerRadius", InnerRadius );
cl.Attributes.Set( "OuterRadius", OuterRadius );
cl.Attributes.Set( "FillColor", FillColor );
cl.Attributes.Set( "TrackColor", TrackColor );
cl.Attributes.Set( "StartAngle", startRad );
cl.Attributes.Set( "CapRadius", CapRadius );
cl.Attributes.Set( "SegmentCount", (float)SegmentCount );
cl.Attributes.Set( "GapAngle", GapAngleDegrees * (MathF.PI / 180f) );
var sentinel = new Color( -1f, -1f, -1f, -1f );
cl.Attributes.Set( "FillColorEnd", FillColorEnd ?? sentinel );
cl.Attributes.Set( "TrackColorEnd", TrackColorEnd ?? sentinel );
cl.DrawQuad( rect, Material.UI.Box, Color.White );
}
}