UI

Painter

Painter is the 2D drawing API. You use it to draw shapes, lines, text and images from code, without panels or stylesheets. Everything is batched and rendered on the GPU, so it's cheap enough to redraw every frame.

A HUD drawn entirely with Painter

You can paint onto:

  • A panel, by overriding OnDraw( Painter painter ).
  • A camera, on the HUD or as an overlay above the UI.
  • A texture, to bake a drawing you can reuse.
  • A command list, to draw at any stage of rendering.

See Destinations for each of these.

Here's a panel that draws a health bar. OnDraw is called every frame, and the painter's coordinates start at the panel's top-left corner.

public class HealthBar : Panel
{
	public float Health { get; set; } = 0.75f;

	public override void OnDraw( Painter painter )
	{
		var bounds = painter.Bounds;

		// Background
		painter.Fill = Color.Black.WithAlpha( 0.5f );
		painter.Stroke = Stroke.Solid( Color.White, 2 );
		painter.Rect( bounds, 8 );

		// Bar
		var bar = bounds.Shrink( 4 );
		bar.Width *= Health;
		painter.Fill = Fill.LinearGradient( Color.Red, Color.Orange );
		painter.Stroke = Stroke.None;
		painter.Rect( bar, 4 );

		// Label
		painter.TextStyle = new TextStyle { FontSize = 16, Color = Color.White, Alignment = TextFlag.Center };
		painter.Text( $"{Health * 100:0}%", bounds );
	}
}

The same code works on the camera HUD, where the coordinates are screen pixels instead:

protected override void OnUpdate()
{
	using var painter = Scene.Camera.BeginHud();

	painter.Fill = Color.White;
	painter.Circle( painter.Bounds.Center, 4 );
}

Painter keeps a small amount of drawing state. Set it, then draw. Every shape you draw uses whatever the state is at the time.

PropertyWhat it doesDefault
FillPaints the inside of closed shapes. A color, gradient or image.Fill.None
StrokePaints the edge of shapes and the body of lines.Stroke.None
TextStyleFont, size, color and alignment for Text.White 16px Roboto
OpacityAlpha multiplier for everything drawn.1
BlendModeHow drawing blends with what's behind it.Normal
TransformMoves, rotates and scales the drawing axes.Identity

Clip restricts drawing to a rectangle, and Scope() saves the state so you can change it temporarily:

using ( painter.Scope() )
{
	painter.Opacity = 0.5f;
	painter.Rotate( 45 );
	painter.Rect( rect );
}

// Opacity and transform are back to what they were

Nothing is drawn unless there's a fill or a stroke. If you draw a shape and nothing appears, that's usually why.

  • Shapes - rectangles, circles, arcs, polygons, lines, curves and symbols.
  • Fill & Stroke - solid colors, gradients, images, dashes, caps and joins.
  • Text - drawing and measuring text.
  • Transforms & Clipping - transforms, clipping, opacity, blend modes and scopes.
  • Layers & Filters - group drawing for opacity, blur, masks and backdrop effects.
  • Destinations - panels, cameras, textures, command lists and 3D lines.

Source: Facepunch/sbox-docs (CC-BY-4.0) · updated 2026-09-16. Read it rendered on the official docs.

More in UI

Community wiki — not affiliated with Facepunch Studios. For the latest and most authoritative information, see the official developer wiki.