editor/AdvancedMappingTools/Architecture/RoofTrussEditor.cs

Editor tool that stamps a roof truss mesh: bottom chord, two rafters, a king post and evenly spaced vertical webs, built with MeshKit boxes and beams. Exposes span, rise, thickness, depth and web count properties.

namespace AdvancedMappingTools;

/// <summary>
/// A single roof truss: bottom chord, two rafters, a king post and vertical webs.
/// Place one per truss position, or use the array options of the editor.
/// </summary>
[ToolCategory( "Roofs" )]
[Title( "Roof Truss" ), Icon( "roofing" )]
public sealed class RoofTrussEditor( PrimitiveTool tool ) : StampEditor( tool )
{
	[Property, Group( "Truss" ), Title( "Span" ), Range( 32, 4096, slider: false ), WideMode]
	public float Span { get; set; } = 384.0f;

	[Property, Group( "Truss" ), Title( "Rise" ), Range( 8, 2048, slider: false ), WideMode]
	public float Rise { get; set; } = 128.0f;

	[Property, Group( "Truss" ), Range( 2, 64, slider: false ), WideMode]
	public float Thickness { get; set; } = 6.0f;

	[Property, Group( "Truss" ), Range( 8, 512, slider: false ), WideMode]
	public float Depth { get; set; } = 8.0f;

	[Property, Group( "Truss" ), Title( "Webs" ), Range( 1, 8, slider: false ), WideMode]
	public int Webs { get; set; } = 2;

	protected override void Stamp( MeshKit kit, Transform frame, Random random )
	{
		var span = MathF.Max( Span, 32.0f );
		var rise = MathF.Max( Rise, 8.0f );
		var t = Math.Clamp( Thickness, 2.0f, 64.0f );
		var depth = Math.Clamp( Depth, 8.0f, 512.0f );
		var half = span * 0.5f;
		var d = depth * 0.5f;

		kit.Box( new Vector3( -half, -d, 0.0f ), new Vector3( half, d, t ) );

		kit.Beam( new Vector3( -half, 0.0f, t ), new Vector3( 0.0f, 0.0f, rise ), t, t );
		kit.Beam( new Vector3( 0.0f, 0.0f, rise ), new Vector3( half, 0.0f, t ), t, t );

		KitPost( kit, 0.0f, t, rise, t, d );

		var webs = Math.Clamp( Webs, 1, 8 );

		for ( var i = 1; i <= webs; i++ )
		{
			var x = -half + span * i / (webs + 1.0f);
			var rafter = rise * (1.0f - MathF.Abs( x ) / half);

			KitPost( kit, x, t, MathF.Max( rafter, t + 2.0f ), t, d );
		}
	}

	static void KitPost( MeshKit kit, float x, float bottom, float top, float thickness, float depth )
	{
		if ( top <= bottom + 1.0f ) return;

		kit.Box( new Vector3( x - thickness * 0.5f, -depth, bottom ), new Vector3( x + thickness * 0.5f, depth, top ) );
	}
}