editor/AdvancedMappingTools/Architecture/ConstructionSiteEditor.cs

Editor tool that stamps a construction site layout into a mesh: perimeter fence, site container, material piles and barriers. Extends StampEditor and builds geometry with MeshKit boxes and cylinders.

namespace AdvancedMappingTools;

/// <summary>
/// A small construction site: perimeter fence, material piles, barriers and a site container.
/// </summary>
[ToolCategory( "Buildings" )]
[Title( "Construction Site" ), Icon( "construction" )]
public sealed class ConstructionSiteEditor( PrimitiveTool tool ) : StampEditor( tool )
{
	[Property, Group( "Site" ), Range( 64, 4096, slider: false ), WideMode]
	public float Length { get; set; } = 512.0f;

	[Property, Group( "Site" ), Range( 64, 4096, slider: false ), WideMode]
	public float Depth { get; set; } = 384.0f;

	[Property, Group( "Site" ), Title( "Fence" ), WideMode]
	public bool Fence { get; set; } = true;

	[Property, Group( "Site" ), Title( "Barriers" ), Range( 0, 16, slider: false ), WideMode]
	public int Barriers { get; set; } = 4;

	[Property, Group( "Site" ), Title( "Material Piles" ), WideMode]
	public bool Piles { get; set; } = true;

	[Property, Group( "Site" ), Title( "Container" ), WideMode]
	public bool Container { get; set; } = true;

	protected override void Stamp( MeshKit kit, Transform frame, Random random )
	{
		var length = MathF.Max( Length, 64.0f );
		var depth = MathF.Max( Depth, 64.0f );
		var half = length * 0.5f;
		var d = depth * 0.5f;
		var random2 = new Random( Seed );

		if ( Fence )
		{
			kit.Material = TrimMaterial;

			for ( var x = -half; x <= half; x += 64.0f )
			{
				kit.Box( new Vector3( x - 2, -d - 2, 0 ), new Vector3( x + 2, -d + 2, 64 ) );
				kit.Box( new Vector3( x - 2, d - 2, 0 ), new Vector3( x + 2, d + 2, 64 ) );
			}

			for ( var y = -d; y <= d; y += 64.0f )
			{
				kit.Box( new Vector3( -half - 2, y - 2, 0 ), new Vector3( -half + 2, y + 2, 64 ) );
				kit.Box( new Vector3( half - 2, y - 2, 0 ), new Vector3( half + 2, y + 2, 64 ) );
			}

			kit.Box( new Vector3( -half, -d - 1, 56 ), new Vector3( half, -d + 1, 62 ) );
			kit.Box( new Vector3( -half, d - 1, 56 ), new Vector3( half, d + 1, 62 ) );
			kit.Box( new Vector3( -half - 1, -d, 56 ), new Vector3( -half + 1, d, 62 ) );
			kit.Box( new Vector3( half - 1, -d, 56 ), new Vector3( half + 1, d, 62 ) );
		}

		kit.Material = SurfaceMaterial;

		if ( Container )
		{
			var cx = half * 0.45f;
			var cy = d * 0.35f;

			kit.Box( new Vector3( cx - 96, cy - 24, 0 ), new Vector3( cx + 96, cy + 24, 48 ) );
		}

		if ( Piles )
		{
			for ( var i = 0; i < 2; i++ )
			{
				var x = -half * 0.4f + i * 96.0f;
				var y = -d * 0.3f + (float)random2.NextDouble() * 32.0f;
				var radius = 40.0f + (float)random2.NextDouble() * 16.0f;

				kit.Cylinder( new Vector3( x, y, 0 ), radius, 6.0f, 0.0f, 32.0f + (float)random2.NextDouble() * 16.0f, 12 );
			}
		}

		kit.Material = TrimMaterial;

		for ( var i = 0; i < Math.Clamp( Barriers, 0, 16 ); i++ )
		{
			var x = -half * 0.6f + i * 56.0f;

			if ( x > half * 0.9f ) break;

			kit.Box( new Vector3( x - 24, d * 0.5f, 0 ), new Vector3( x + 24, d * 0.5f + 12, 24 ) );
			kit.Box( new Vector3( x - 18, d * 0.5f, 24 ), new Vector3( x + 18, d * 0.5f + 10, 32 ) );
		}
	}
}