editor/AdvancedMappingTools/Architecture/StormDrainEditor.cs

Editor tool that stamps a storm drain mesh: a square frame with grate bars and an optional cylindrical pipe stub below. Exposes size, frame width, bar count and pipe radius/depth properties.

namespace AdvancedMappingTools;

/// <summary>
/// A storm drain: a square frame with a grate and an optional pipe stub below.
/// </summary>
[ToolCategory( "Street" )]
[Title( "Storm Drain" ), Icon( "water_damage" )]
public sealed class StormDrainEditor( PrimitiveTool tool ) : StampEditor( tool )
{
	[Property, Group( "Drain" ), Range( 8, 256, slider: false ), WideMode]
	public float Size { get; set; } = 48.0f;

	[Property, Group( "Drain" ), Title( "Frame" ), Range( 1, 32, slider: false ), WideMode]
	public float Frame { get; set; } = 4.0f;

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

	[Property, Group( "Drain" ), Title( "Pipe Stub" ), WideMode]
	public bool PipeStub { get; set; } = true;

	[Property, ShowIf( nameof( PipeStub ), true ), Group( "Drain" ), Title( "Pipe Radius" ), Range( 0.5f, 32, slider: false ), WideMode]
	public float PipeRadius { get; set; } = 8.0f;

	[Property, ShowIf( nameof( PipeStub ), true ), Group( "Drain" ), Title( "Pipe Depth" ), Range( 1, 256, slider: false ), WideMode]
	public float PipeDepth { get; set; } = 32.0f;

	protected override void Stamp( MeshKit kit, Transform frame, Random random )
	{
		var half = MathF.Max( Size, 8.0f ) * 0.5f;
		var f = Math.Clamp( Frame, 1.0f, 32.0f );
		var bars = Math.Clamp( Bars, 1, 24 );

		kit.Box( new Vector3( -half, -half, 0.0f ), new Vector3( half, -half + f, 4.0f ) );
		kit.Box( new Vector3( -half, half - f, 0.0f ), new Vector3( half, half, 4.0f ) );
		kit.Box( new Vector3( -half, -half + f, 0.0f ), new Vector3( -half + f, half - f, 4.0f ) );
		kit.Box( new Vector3( half - f, -half + f, 0.0f ), new Vector3( half, half - f, 4.0f ) );

		kit.Material = TrimMaterial;

		for ( var i = 0; i < bars; i++ )
		{
			var y = -half + f + (Size - f * 2.0f) * (i + 0.5f) / bars;

			kit.Box( new Vector3( -half + f, y - 1.0f, 2.0f ), new Vector3( half - f, y + 1.0f, 5.0f ) );
		}

		if ( !PipeStub ) return;

		var radius = Math.Clamp( PipeRadius, 0.5f, 32.0f );

		kit.Cylinder( Vector3.Zero, radius, radius, -MathF.Max( PipeDepth, 1.0f ), 0.0f, 12 );
	}
}