An editor-side data model for wall openings (doors, windows, etc.). Defines enums for kinds, glass state and furniture, a shape struct, and a sealed ArchOpening class that stores layout, appearance and behavior properties with a palette.
using System;
using System.Collections.Generic;
using System.Linq;
using Sandbox;
namespace Sunless.Architecture;
public enum OpeningKind
{
Archway,
Door,
DoubleDoor,
Garage,
Window,
Hatch
}
public enum GlassState
{
Intact,
Broken
}
// What is fixed over the hole. The burglar bar leads because it is on every window of every house in these
// suburbs; a boarded panel, a roller shutter and a security gate are the same welded grid at another pitch,
// running the other way, at another depth.
public enum OpeningFurniture
{
None,
Bars,
Boarded,
Shutter,
Gate
}
// WHERE a hole goes in a wall, in the wall's own along-and-up terms, so a module that wants an entrance can ask
// for one without resolving the unit that fills it.
public readonly struct ArchOpeningShape
{
public float Offset { get; init; }
public float Width { get; init; }
public float Height { get; init; }
public float SillHeight { get; init; }
}
public sealed class ArchOpening : IArchPainted
{
public int Id { get; set; }
// Deleting the part that punched it takes the hole - a stair walking through a wall owns its archway.
public int OwnerId { get; set; }
// The cut standing where this unit is. Re-derived every commit like any other effect, so dragging the
// shaft off the window - or unticking Windows on it - hands the window straight back.
public int SwallowedBy { get; set; }
public string Preset { get; set; } = "door";
public float Offset { get; set; }
public float Width { get; set; }
public float Height { get; set; }
public float SillHeight { get; set; }
public OpeningKind Kind { get; set; } = OpeningKind.Door;
public bool Cased { get; set; } = true;
public bool HasSill { get; set; } = true;
public float CasingWidth { get; set; }
public bool Leaf { get; set; } = true;
public bool FlipHinge { get; set; }
// Rides the engine's StartOpen - a leaf built open would slide twice as far when used.
public bool StartOpen { get; set; }
public bool Glazed { get; set; }
public bool AutoLayout { get; set; } = true;
// Units side by side in one opening, each with its own sashes.
public int Lights { get; set; } = 1;
public int Sashes { get; set; } = 2;
// Per sash, not per unit - so 6-over-6 is three across by two down.
public int PanesAcross { get; set; } = 2;
public int PanesDown { get; set; } = 3;
public GlassState Glass { get; set; } = GlassState.Intact;
// Panes on their own object so fragmenting glass can find them - intent only for now.
public bool Breakable { get; set; }
public OpeningFurniture Furniture { get; set; }
public ArchPalette Palette { get; set; } = new();
public float Left => Offset - Width * 0.5f;
public float Right => Offset + Width * 0.5f;
public float Top => SillHeight + Height;
// The kind has the last word - a retyped preset keeps numbers that mean nothing.
public bool IsGlazed => Glazed && Kind.Glazes();
public bool IsSilled => HasSill && Kind.Sills();
public bool IsHung => Leaf && Kind.Hangs();
public OpeningFurniture Fitted => Kind.Carries( Furniture ) ? Furniture : OpeningFurniture.None;
}