Editor/Services/ArchStoreyEdges.cs
using System.Collections.Generic;
using System.Linq;
using Sandbox;
namespace Sunless.Architecture;
public readonly record struct ArchSnapLoop( IReadOnlyList<Vector2> Loop, bool Above );
// Every non-wall edge on this storey a plan point can snap to.
public static class ArchStoreyEdges {
public static List<ArchSnapLoop> On( ArchPlan plan, ArchKit kit, int level ) {
var edges = new List<ArchSnapLoop>();
foreach ( var building in plan?.Buildings ?? Enumerable.Empty<ArchBuilding>() ) {
// Plinth first — on a raised foundation it is the visible edge, not the shell behind it.
Take( edges, ArchFloorGen.FoundationOutline( plan, building, kit, level ), false );
Take( edges, ArchRegion.Shell( ArchRegion.Storey( building, level ), kit.WallThickness ), false );
foreach ( var room in building.Rooms.Where( standing => standing.Floor > level && ArchLayerGate.On( standing ) ) ) {
Take( edges, ArchRegion.Shell( ArchRegion.Footprints( new[] { room }, false ), kit.WallThickness ), true );
Take( edges, ArchOverhangGen.Unsupported( room, building, kit ), true );
}
foreach ( var platform in building.Platforms.Where( ArchLayerGate.On ) ) {
Take( edges, new List<List<Vector2>> { platform.Outline() }, platform.Hung );
}
}
return edges;
}
static void Take( List<ArchSnapLoop> edges, IEnumerable<List<Vector2>> loops, bool above ) {
foreach ( var loop in loops.Where( standing => standing.Count >= 3 ) ) {
edges.Add( new ArchSnapLoop( loop, above ) );
}
}
}