Editor/Wall/ArchBalconyPart.cs
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;
public BarrierStyle GuardStyle { get; set; } = BarrierStyle.Picket;
// 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 );
}
}
}