Editor stamp tool that builds a drawbridge from two piers, two bascule leaves, and optional chains using MeshKit primitives. Leaves pivot at the piers and lift as RaiseAngle increases.
namespace AdvancedMappingTools;
/// <summary>
/// A drawbridge: two piers, two bascule leaves, chains and counterweights. The leaves are
/// closed at Raise 0 and lift up as the angle grows.
/// </summary>
[ToolCategory( "Tunnels & Bridges" )]
[Title( "Drawbridge" ), Icon( "door_sliding" )]
public sealed class DrawbridgeEditor( PrimitiveTool tool ) : StampEditor( tool )
{
[Property, Group( "Drawbridge" ), Range( 32, 2048, slider: false ), WideMode]
public float Span { get; set; } = 256.0f;
[Property, Group( "Drawbridge" ), Range( 16, 512, slider: false ), WideMode]
public float Width { get; set; } = 96.0f;
[Property, Group( "Drawbridge" ), Title( "Deck" ), Range( 1, 64, slider: false ), WideMode]
public float Deck { get; set; } = 8.0f;
[Property, Group( "Drawbridge" ), Title( "Pier Height" ), Range( 8, 512, slider: false ), WideMode]
public float PierHeight { get; set; } = 64.0f;
[Property, Group( "Drawbridge" ), Title( "Raise Angle" ), Range( 0, 80 ), WideMode]
public float RaiseAngle { get; set; } = 0.0f;
[Property, Group( "Drawbridge" ), Title( "Chains" ), WideMode]
public bool Chains { get; set; } = true;
protected override void Stamp( MeshKit kit, Transform frame, Random random )
{
var span = MathF.Max( Span, 32.0f );
var width = MathF.Max( Width, 16.0f );
var deck = Math.Clamp( Deck, 1.0f, 64.0f );
var pier = MathF.Max( PierHeight, 8.0f );
var half = span * 0.5f;
var w = width * 0.5f;
var raise = Math.Clamp( RaiseAngle, 0.0f, 80.0f );
var leaf = half;
foreach ( var side in new[] { -1.0f, 1.0f } )
{
var x = half * side;
kit.Box( new Vector3( x - 12, -w - 8, -pier ), new Vector3( x + 12, w + 8, deck ) );
kit.Box( new Vector3( x - 8, -w, deck ), new Vector3( x + 8, w, deck + 8 ) );
kit.Frame = frame.ToWorld( new Transform( new Vector3( x, 0, deck ), Rotation.From( raise * side, 0, 0 ) * Rotation.FromYaw( side < 0 ? 0 : 180 ) ) );
kit.Box( new Vector3( 0, -w, 0 ), new Vector3( leaf, w, deck * 0.5f ) );
var tipWorld = kit.Frame.PointToWorld( new Vector3( leaf, 0, 0 ) );
kit.Frame = frame;
if ( !Chains ) continue;
kit.Beam( new Vector3( x, 0, deck + 8 ), frame.PointToLocal( tipWorld ), 2.0f, 2.0f );
}
}
}