editor/AdvancedMappingTools/Architecture/FountainEditor.cs

Editor stamp tool for Advanced Mapping Tools, generates a fountain mesh from MeshKit primitives. Builds a basin cylinder, optional water surface, a tapering pedestal, up to four tiered bowls and a top finial, with radius, height and tier count exposed as properties.

namespace AdvancedMappingTools;

/// <summary>
/// A fountain: a round basin, water surface, a pedestal and tiered bowls.
/// </summary>
[ToolCategory( "Street" )]
[Title( "Fountain" ), Icon( "water" )]
public sealed class FountainEditor( PrimitiveTool tool ) : StampEditor( tool )
{
	[Property, Group( "Fountain" ), Title( "Radius" ), Range( 8, 1024, slider: false ), WideMode]
	public float Radius { get; set; } = 96.0f;

	[Property, Group( "Fountain" ), Title( "Basin Height" ), Range( 2, 128, slider: false ), WideMode]
	public float BasinHeight { get; set; } = 20.0f;

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

	[Property, Group( "Fountain" ), Title( "Pedestal Radius" ), Range( 1, 128, slider: false ), WideMode]
	public float PedestalRadius { get; set; } = 12.0f;

	[Property, Group( "Fountain" ), Title( "Pedestal Height" ), Range( 4, 512, slider: false ), WideMode]
	public float PedestalHeight { get; set; } = 64.0f;

	[Property, Group( "Fountain" ), Range( 0, 4, slider: false ), WideMode]
	public int Tiers { get; set; } = 2;

	protected override void Stamp( MeshKit kit, Transform frame, Random random )
	{
		var radius = MathF.Max( Radius, 8.0f );
		var basin = MathF.Max( BasinHeight, 2.0f );
		var pedestal = Math.Clamp( PedestalRadius, 1.0f, radius * 0.45f );
		var height = MathF.Max( PedestalHeight, 4.0f );
		var tiers = Math.Clamp( Tiers, 0, 4 );

		kit.Material = TrimMaterial;
		kit.Cylinder( Vector3.Zero, radius, radius, 0.0f, basin, 24 );

		if ( Water )
		{
			kit.Material = SurfaceMaterial;
			kit.Cylinder( Vector3.Zero, radius - 4.0f, radius - 4.0f, basin - 2.0f, basin + 0.5f, 24 );
			kit.Material = TrimMaterial;
		}

		kit.Cylinder( Vector3.Zero, pedestal, pedestal * 0.8f, basin, basin + height, 12 );

		for ( var i = 0; i < tiers; i++ )
		{
			var z = basin + height * (i + 1) / (tiers + 1.0f);
			var r = radius * (0.32f - i * 0.06f);

			kit.Cylinder( Vector3.Zero, r, r * 0.7f, z, z + 6.0f, 16 );
		}

		kit.Cylinder( Vector3.Zero, pedestal * 1.4f, 1.0f, basin + height, basin + height + 12.0f, 12 );
	}
}