Editor/Wall/ArchOpening.cs
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,
// A pair hinged either side of the hole rather than a grid across it - the same bordered field of members,
// resolved twice against the wall beside the reveal.
Leaves
}
// What is built over the head, standing on the wall rather than in the hole. A hood is a shelf on corbels and a
// pediment is that shelf under a gable; neither is a kind of opening, because the hole under it is unchanged.
public enum OpeningHood {
None,
Cornice,
Pediment
}
// 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 Dictionary<string, string> Extensions { get; set; } = new();
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 OpeningHood Hood { get; set; }
public bool BasementWell { get; set; }
public float BasementWellDepth { get; set; } = 36f;
// Art the author drew, standing where the extruded leaf would have. Aimed in the prefab's own space, so the
// pivot Blender left behind never decides where it lands.
public string LeafPrefab { get; set; } = "";
public Vector3 LeafAnchor { get; set; }
public Vector3 LeafAnchorAlong { get; set; }
public Angles LeafAnchorTurn { get; set; }
public bool LeafFits { get; set; }
public string LeafMaterialGroup { 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;
public OpeningHood Hooded => Kind.Wears( Hood ) ? Hood : OpeningHood.None;
public ArchAimedPrefab LeafArt => new( LeafPrefab, LeafAnchor, LeafAnchorAlong, LeafAnchorTurn, LeafFits );
}