Editor/Pillar/ArchSpanUi.cs
using System;
using System.Linq;
using Editor;
using Sandbox;
namespace Sunless.Architecture;
public static class ArchSpanUi {
// The sheet lays both halves in one go; the Pillars sequence asks them as two steps, because picking a form
// is an answer and typing a section is not.
public static void Build( ToolSidebarWidget panel, ArchSpanPart span, Action refresh, Action changed ) {
Form( panel.AddGroup( "Form" ), span, refresh, changed );
Section( panel.AddGroup( "Section" ), span, changed );
}
// Handed step.Chose as its refresh by the sequence and a plain refresh by the sheet - it advances by doing
// what it already did.
public static void Form( Layout group, ArchSpanPart span, Action refresh, Action changed ) {
using var forms = ArchIconGrid.In( group );
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; changed?.Invoke(); refresh?.Invoke(); } );
}
}
public static void Section( Layout group, ArchSpanPart span, Action changed ) {
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 ) );
}
// What the section step reads back closed: the one dimension the form is judged on, kit stock and all.
public static string Measured( ArchSpanPart span ) {
return span.Form == PillarSpan.Beam
? $"{Stocked( span.BeamDepth, 18f ):0} deep"
: $"{Stocked( span.Rise, 48f ):0} rise";
}
static float Stocked( float value, float stock ) => value > 0f ? value : stock;
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"
};
}