Static helper for staging and describing an architectural opening preset. It builds a simple mock building/room/wall with a centered opening for preview, computes an interest bounding box, generates a cache identity string from preset properties, and returns a short textual description.
using System;
using System.Collections.Generic;
using Sandbox;
namespace Sunless.Architecture;
// One staging of an opening preset, shared by the designer's turntable and the browser's card art - two
// stagings of the same preset are free to disagree about what the drag will actually build.
public static class ArchOpeningStage
{
public static ArchStaged Of( ArchOpeningPreset unit, ArchKit kit )
{
var span = MathF.Max( 192f, unit.Width + 96f );
var wallHeight = MathF.Max( 128f, unit.SillHeight + unit.Height + 32f );
var wall = new ArchWall
{
Id = 2,
Start = Vector2.Zero,
End = new Vector2( span, 0f ),
Height = wallHeight,
Thickness = kit.WallThickness,
Baseboard = false,
Cap = true,
Openings = new List<ArchOpening> { unit.Spawn( 3, span * 0.5f ) }
};
var room = new ArchRoom
{
Id = 1,
WallHeight = wallHeight,
HasFloor = false,
RaisedFoundation = false,
Walls = new List<ArchWall> { wall }
};
var building = new ArchBuilding
{
Id = 1,
Rooms = new List<ArchRoom> { room },
StoreyHeight = wallHeight
};
return new ArchStaged(
new ArchPlan { Units = new List<ArchUnit> { building } },
new Vector3( span * 0.5f, 0f, wallHeight * 0.5f ),
MathF.Max( 260f, MathF.Max( span, wallHeight ) * 1.65f ) );
}
// Where the unit stands in the staging, generously enough to hold its casing and sill but nowhere near
// the ends of the run, whose cut faces wear the Reveal role too.
public static BBox Interest( ArchOpeningPreset unit, ArchKit kit )
{
var span = MathF.Max( 192f, unit.Width + 96f );
var casing = MathF.Max( unit.CasingWidth > 0f ? unit.CasingWidth : kit.CasingWidth, 8f );
var margin = casing + 12f;
var thickness = MathF.Max( kit.WallThickness, 16f );
return new BBox(
new Vector3( span * 0.5f - unit.Width * 0.5f - margin, -thickness, unit.SillHeight - margin ),
new Vector3( span * 0.5f + unit.Width * 0.5f + margin, thickness, unit.SillHeight + unit.Height + margin ) );
}
// The preview cache key: everything the geometry is derived from, so an edited preset re-stages and
// an untouched one never does.
public static string Identity( ArchOpeningPreset unit )
{
return string.Join( ".",
"opening",
unit.Name,
unit.Kind,
$"{unit.Width:0.##}x{unit.Height:0.##}",
$"{unit.SillHeight:0.##}",
$"{unit.CasingWidth:0.##}",
unit.Cased,
unit.HasSill,
unit.Leaf,
unit.Glazed,
unit.AutoLayout,
unit.Lights,
unit.Sashes,
$"{unit.PanesAcross}x{unit.PanesDown}",
unit.Glass,
unit.Breakable,
unit.Furniture );
}
public static string Describe( ArchOpeningPreset unit )
{
return unit.IsGlazed
? $"{unit.Width:0}x{unit.Height:0} · {unit.PanesAcross * unit.PanesDown} panes"
: $"{unit.Width:0}x{unit.Height:0}";
}
}