Editor/Floor/ArchBasementWell.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Sandbox;
namespace Sunless.Architecture;
public sealed class ArchBasementWellShape
{
public List<Vector2> Outline { get; init; }
public Vector2 WallLeft { get; init; }
public Vector2 WallRight { get; init; }
public Vector2 OuterLeft { get; init; }
public Vector2 OuterRight { get; init; }
public float Bottom { get; init; }
public float Top { get; init; }
public float Thickness { get; init; }
}
public static class ArchBasementWell
{
public static ArchBasementWellShape Resolve( ArchRoom room, ArchWall wall, ArchOpening opening, ArchBuilding building, ArchKit kit )
{
if ( room is null || wall is null || opening is null || building is null || kit is null ||
room.Floor >= 0 || !opening.BasementWell || opening.Kind != OpeningKind.Window )
{
return null;
}
var outward = ArchWallFaces.Outward( wall, room, building );
var along = wall.Direction;
var centre = wall.PointAt( opening.Offset );
var halfWidth = opening.Width * 0.5f + MathF.Max( 4f, kit.WallThickness * 0.5f );
var wallFace = (wall.Thickness > 0f ? wall.Thickness : kit.WallThickness) * 0.5f;
var depth = MathF.Max( 18f, opening.BasementWellDepth );
var thickness = MathF.Max( 3f, MathF.Min( 6f, kit.WallThickness * 0.5f ) );
var wallLeft = centre - along * halfWidth + outward * wallFace;
var wallRight = centre + along * halfWidth + outward * wallFace;
var outerLeft = wallLeft + outward * depth;
var outerRight = wallRight + outward * depth;
var sill = room.BaseHeight + opening.SillHeight;
return new ArchBasementWellShape
{
Outline = new List<Vector2> { wallLeft, outerLeft, outerRight, wallRight },
WallLeft = wallLeft,
WallRight = wallRight,
OuterLeft = outerLeft,
OuterRight = outerRight,
Bottom = sill - MathF.Max( 6f, kit.FloorThickness ),
Top = ArchBuild.FloorOf( building, kit, 0 ) + MathF.Max( 4f, thickness ),
Thickness = thickness
};
}
public static void Build( ArchMesh canvas, ArchBasementWellShape shape, ArchBrush brush )
{
if ( canvas is null || shape is null || shape.Top - shape.Bottom < 1f )
{
return;
}
var floorBottom = shape.Bottom - MathF.Max( 3f, shape.Thickness );
Solid( canvas, shape.Outline, floorBottom, shape.Bottom, brush );
Wall( canvas, shape.OuterLeft, shape.OuterRight, shape.Thickness, shape.Bottom, shape.Top, brush );
Wall( canvas, shape.WallLeft, shape.OuterLeft, shape.Thickness, shape.Bottom, shape.Top, brush );
Wall( canvas, shape.OuterRight, shape.WallRight, shape.Thickness, shape.Bottom, shape.Top, brush );
}
static void Wall( ArchMesh canvas, Vector2 from, Vector2 to, float thickness, float bottom, float top, ArchBrush brush )
{
var span = to - from;
if ( span.IsNearZeroLength )
{
return;
}
var half = new Vector2( -span.Normal.y, span.Normal.x ) * thickness * 0.5f;
Solid( canvas, new List<Vector2> { from - half, to - half, to + half, from + half }, bottom, top, brush );
}
static void Solid( ArchMesh canvas, IReadOnlyList<Vector2> outline, float bottom, float top, ArchBrush brush )
{
var lower = outline.Select( point => new Vector3( point.x, point.y, bottom ) ).ToList();
var upper = outline.Select( point => new Vector3( point.x, point.y, top ) ).ToList();
canvas.Prism( lower, upper, brush );
}
}