A data model type for a single stair railing entry in the editor. It stores which edge (left/right/head), whether it is a balustrade or handrail, the fractional span on the step (From/To), height, and provides computed properties Start, End, Stands and a Copy method.
namespace Sunless.Architecture;
// Which edge of a step a railing stands on, in the step's OWN frame - left and right are the walker's, so a
// railing keeps the side it was put on when the flight is turned or the whole stair is swung.
public enum StairEdge
{
Left,
Right,
Head
}
// What stands on that edge. A balustrade is the free-standing run of newels and balusters; a handrail is what a
// side running against plaster gets instead, because balusters inside a wall are balusters nobody can see.
public enum StairRailing
{
Balustrade,
Handrail
}
// One railing, on one edge of one step. A row under the step in the stack, so a stair carries as many as its
// author wants and each is added, restyled and deleted on its own.
//
// A step with NO railing rows falls back to the stair's own Guard setting, which is what every stair authored
// before this had and what the walk still seeds. Putting one row on a step is what takes that step off the
// default - so adding a railing never has to mean re-stating the ones already there.
public sealed class ArchStairGuardPart : IArchNamed
{
public int Id { get; set; }
public string Name { get; set; } = "Railing";
public StairEdge Edge { get; set; }
public StairRailing Railing { get; set; }
// The stretch of that edge it actually covers, as a fraction of the step's own run - so a railing keeps the
// proportion it was dragged to when the step is lengthened, and a step resized under a railing never leaves it
// hanging off the end. The whole edge is 0 to 1, which is what a fresh one takes.
public float From { get; set; }
public float To { get; set; } = 1f;
// Zero takes the kit's handrail height.
public float Height { get; set; }
public float Start => Math.Clamp( MathF.Min( From, To ), 0f, 1f );
public float End => Math.Clamp( MathF.Max( From, To ), 0f, 1f );
public bool Stands => End - Start > 0.01f;
public ArchStairGuardPart Copy() => new()
{
Id = Id,
Name = Name,
Edge = Edge,
Railing = Railing,
From = From,
To = To,
Height = Height
};
}