Editor tool that stamps a scaffolding frame into the map: posts, ledgers, optional planks and diagonal bracing, with posts optionally fitted to the ground surface. Exposes length, depth, height, bay width and level count as properties.
namespace AdvancedMappingTools;
/// <summary>
/// A scaffolding frame: posts, ledgers, planks and optional diagonal bracing.
/// </summary>
[ToolCategory( "Buildings" )]
[Title( "Scaffolding" ), Icon( "grid_view" )]
public sealed partial class ScaffoldingEditor( PrimitiveTool tool ) : GroundAwareStampEditor( tool )
{
[Property, Group( "Scaffolding" ), Range( 32, 2048, slider: false ), WideMode]
public float Length { get; set; } = 384.0f;
[Property, Group( "Scaffolding" ), Range( 8, 1024, slider: false ), WideMode]
public float Depth { get; set; } = 48.0f;
[Property, Group( "Scaffolding" ), Range( 16, 1024, slider: false ), WideMode]
public float Height { get; set; } = 192.0f;
[Property, Group( "Scaffolding" ), Title( "Bay Width" ), Range( 16, 256, slider: false ), WideMode]
public float BayWidth { get; set; } = 96.0f;
[Property, Group( "Scaffolding" ), Range( 1, 16, slider: false ), WideMode]
public int Levels { get; set; } = 3;
[Property, Group( "Scaffolding" ), Title( "Planks" ), WideMode]
public bool Planks { get; set; } = true;
[Property, Group( "Scaffolding" ), Title( "Bracing" ), WideMode]
public bool Bracing { get; set; } = true;
protected override void Stamp( MeshKit kit, Transform frame, Random random )
{
var length = MathF.Max( Length, 32.0f );
var depth = MathF.Max( Depth, 8.0f );
var height = MathF.Max( Height, 16.0f );
var bay = Math.Clamp( BayWidth, 16.0f, 256.0f );
var levels = Math.Clamp( Levels, 1, 16 );
var step = height / levels;
var posts = MathF.Max( MathF.Round( length / bay ), 1.0f );
var read = FitToGround ? (GroundRead ?? SurfaceSolver.Begin( SceneEditorSession.Active?.Scene ?? Game.ActiveScene )) : null;
void Post( float x, float y )
{
var bottom = 0f;
if ( read != null )
{
var sample = read.Probe( frame.PointToWorld( new Vector3( x, y + 2, height ) ), Vector3.Down, Options() );
if ( read.AcceptBelow( sample, frame.PointToLocal( sample.Position ).z, height ) )
bottom = frame.PointToLocal( sample.Position ).z;
}
kit.Box( new( x - 2, y, bottom ), new( x + 2, y + 4, height ) );
}
for ( var i = 0; i <= posts; i++ )
{
var x = -length * 0.5f + length * i / posts;
Post( x, -depth * .5f );
Post( x, depth * .5f - 4 );
}
for ( var level = 1; level <= levels; level++ )
{
var z = step * level;
kit.Box( new Vector3( -length * 0.5f, -depth * 0.5f, z - 2 ), new Vector3( length * 0.5f, -depth * 0.5f + 4, z + 2 ) );
kit.Box( new Vector3( -length * 0.5f, depth * 0.5f - 4, z - 2 ), new Vector3( length * 0.5f, depth * 0.5f, z + 2 ) );
if ( Planks )
kit.Box( new Vector3( -length * 0.5f, -depth * 0.5f + 4, z - 1 ), new Vector3( length * 0.5f, depth * 0.5f - 4, z + 2 ) );
}
BuildSurfaceMounts( kit, frame );
if ( !Bracing )
return;
for ( var level = 0; level < levels; level++ )
{
var z0 = step * level + 4;
var z1 = step * (level + 1) - 4;
if ( z1 <= z0 )
continue;
kit.Beam( new Vector3( -length * 0.5f, -depth * 0.5f + 2, z0 ), new Vector3( -length * 0.5f + bay, -depth * 0.5f + 2, z1 ), 2.0f, 4.0f );
kit.Beam( new Vector3( length * 0.5f, depth * 0.5f - 2, z0 ), new Vector3( length * 0.5f - bay, depth * 0.5f - 2, z1 ), 2.0f, 4.0f );
}
}
}