Editor stamp tool that generates skylight geometry from a MeshKit: a curb ring, frame and optional glass, in rectangular, round or strip shapes. Exposes width, length, curb height and frame width properties.
namespace AdvancedMappingTools;
public enum SkylightShape
{
Rectangular,
Round,
Strip
}
/// <summary>
/// A roof skylight: a curb, a frame and glass. Rectangular, round or a long strip.
/// </summary>
[ToolCategory( "Roofs" )]
[Title( "Skylight" ), Icon( "window" )]
public sealed class SkylightEditor( PrimitiveTool tool ) : StampEditor( tool )
{
[Property, Group( "Skylight" ), WideMode]
public SkylightShape Shape { get; set; } = SkylightShape.Rectangular;
[Property, Group( "Skylight" ), Range( 8, 1024, slider: false ), WideMode]
public float Width { get; set; } = 64.0f;
[Property, Group( "Skylight" ), Range( 8, 2048, slider: false ), WideMode]
public float Length { get; set; } = 96.0f;
[Property, Group( "Skylight" ), Title( "Curb Height" ), Range( 1, 96, slider: false ), WideMode]
public float CurbHeight { get; set; } = 12.0f;
[Property, Group( "Skylight" ), Title( "Frame Width" ), Range( 1, 32, slider: false ), WideMode]
public float FrameWidth { get; set; } = 4.0f;
[Property, Group( "Skylight" ), Title( "Glass" ), WideMode]
public bool Glass { get; set; } = true;
protected override void Stamp( MeshKit kit, Transform frame, Random random )
{
var w = Width * 0.5f;
var l = Length * 0.5f;
var h = MathF.Max( CurbHeight, 1.0f );
var f = Math.Clamp( FrameWidth, 0.5f, MathF.Min( w, l ) * 0.45f );
if ( Shape == SkylightShape.Round )
{
var r = MathF.Min( w, l );
kit.Cylinder( Vector3.Zero, r, r, 0.0f, h, 16 );
kit.Cylinder( Vector3.Zero, r - f, r - f, h, h + 1.5f, 16 );
if ( Glass )
{
kit.Material = TrimMaterial;
kit.Cylinder( Vector3.Zero, r - f * 0.5f, r - f * 0.5f, h + 0.2f, h + 1.0f, 16 );
}
return;
}
// A strip runs the whole length: two long rails, cross bars, one glass band.
if ( Shape == SkylightShape.Strip )
{
// Long rails on the two long sides at x = ±w, cross bars between them.
kit.Box( new Vector3( -w, -l, 0.0f ), new Vector3( -w + f, l, h ) );
kit.Box( new Vector3( w - f, -l, 0.0f ), new Vector3( w, l, h ) );
for ( var y = -l + f; y < l - f; y += 32.0f )
kit.Box( new Vector3( -w + f, y, 0.0f ), new Vector3( w - f, MathF.Min( y + f * 0.6f, l - f ), h ) );
if ( Glass )
{
kit.Material = TrimMaterial;
kit.Box( new Vector3( -w + f, -l + f, h * 0.55f ), new Vector3( w - f, l - f, h * 0.55f + 0.6f ) );
}
return;
}
// Curb ring: four bars around the opening.
kit.Box( new Vector3( -w, -l, 0.0f ), new Vector3( w, -l + f, h ) );
kit.Box( new Vector3( -w, l - f, 0.0f ), new Vector3( w, l, h ) );
kit.Box( new Vector3( -w, -l + f, 0.0f ), new Vector3( -w + f, l - f, h ) );
kit.Box( new Vector3( w - f, -l + f, 0.0f ), new Vector3( w, l - f, h ) );
if ( !Glass ) return;
kit.Material = TrimMaterial;
kit.Box( new Vector3( -w + f, -l + f, h * 0.55f ), new Vector3( w - f, l - f, h * 0.55f + 0.6f ) );
}
}