Editor/Span/ArchSpanUi.cs

Editor UI builder for an arch span part. It adds form buttons for PillarSpan enum values and numeric fields for properties like thickness, drop, springing, rise, ring, segments, and beam depth, wiring change callbacks.

Reflection
using System;
using System.Linq;
using Editor;
using Sandbox;

namespace Sunless.Architecture;

public static class ArchSpanUi
{
	public static void Build( ToolSidebarWidget panel, ArchSpanPart span, Action refresh, Action changed )
	{
		using ( var forms = ArchIconGrid.In( panel.AddGroup( "Form" ) ) )
		{
			foreach ( var value in Enum.GetValues<PillarSpan>().Where( value => value != PillarSpan.None ) )
			{
				var captured = value;

				forms.Pick( $"Span: {Hint( captured )}", $"span_{captured}".ToLowerInvariant(), Glyph( captured ),
					span.Form == captured, () => { span.Form = captured; refresh?.Invoke(); changed?.Invoke(); } );
			}
		}

		var group = panel.AddGroup( "Section" );

		group.Add( ArchPartUi.Number( "Thickness (0 takes the piers')", span.Thickness, 0f, value => span.Thickness = value, changed ) );
		group.Add( ArchPartUi.Number( "Drop below the head", span.Drop, 0f, value => span.Drop = value, changed ) );
		group.Add( ArchPartUi.Number( "Springs from floor (0 takes the rise)", span.Springing, 0f, value => span.Springing = value, changed ) );

		if ( span.Form == PillarSpan.Beam )
		{
			group.Add( ArchPartUi.Number( "Depth", span.BeamDepth, 18f, value => span.BeamDepth = value, changed ) );

			return;
		}

		group.Add( ArchPartUi.Number( "Rise", span.Rise, 48f, value => span.Rise = value, changed ) );

		if ( span.Form == PillarSpan.Arch )
		{
			group.Add( ArchPartUi.Number( "Ring", span.Ring, 10f, value => span.Ring = value, changed ) );
		}

		group.Add( ArchPartUi.Integer( "Segments", span.Segments, 10, value => span.Segments = value, changed ) );
	}

	public static string Hint( PillarSpan form ) => form switch
	{
		PillarSpan.Beam => "a straight block from pier to pier",
		PillarSpan.Arch => "a ring turned between them",
		PillarSpan.Haunch => "a cove filling the corner at each end, with nothing between",
		_ => "nothing between them"
	};

	public static string Glyph( PillarSpan form ) => form switch
	{
		PillarSpan.Beam => "horizontal_rule",
		PillarSpan.Arch => "bridge",
		PillarSpan.Haunch => "rounded_corner",
		_ => "block"
	};
}