A data component that represents a balcony part used by the editor. It stores placement, size and visual properties such as anchor, outward direction, width, reach, lift, railing and palette, and exposes computed helpers for determining if it is a Juliet, recessed, its facing and along directions.
using System;
using Sandbox;
namespace Sunless.Architecture;
// A thing standing outside a room hangs off the BUILDING, like a ladder or a downpipe - not off the active
// room, which is whichever one the picker happened to be on. The wall it was placed against is its datum.
//
// Reach is the whole vocabulary: positive projects a slab, zero is a Juliet with nothing to stand on, and
// negative bites a loggia back into the elevation and becomes a cut whose bite re-derives every commit.
public sealed class ArchBalconyPart : IArchPainted, IArchNamed
{
public int Id { get; set; }
public string Name { get; set; } = "Balcony";
public Vector2 Anchor { get; set; }
public Vector2 Outward { get; set; } = new( 1f, 0f );
public float BaseHeight { get; set; }
public float Width { get; set; } = 96f;
public float Reach { get; set; } = 36f;
public float Thickness { get; set; } = 5f;
// The deck's height off the storey floor it hangs on. A datum offset rather than an extent, which is why it
// is a typed number and not a handle - the same bargain the roof's eave drop makes.
public float Lift { get; set; }
public bool Rail { get; set; } = true;
// 0 takes the kit's own balustrade height.
public float RailHeight { get; set; }
public bool Coping { get; set; } = true;
public ArchPalette Palette { get; set; } = new();
public bool IsJuliet => MathF.Abs( Reach ) <= 0.01f;
public bool IsRecessed => Reach < -0.01f;
public Vector2 Facing => Outward.Length < 0.01f ? new Vector2( 1f, 0f ) : Outward.Normal;
public Vector2 Along
{
get
{
var facing = Facing;
return new Vector2( -facing.y, facing.x );
}
}
}