Editor tool for the Advanced Mapping Tools package. Places a rectangular foundation slab with an optional wider footing, fitting the footing bottom to the ground surface when FitToGround is on, and tags the built object with amt.foundation.
namespace AdvancedMappingTools;
/// <summary>
/// A rectangular foundation pad with a projecting footing. One click per pad.
/// </summary>
[ToolCategory( "Buildings" )]
[Title( "Foundation" ), Icon( "foundation" )]
public sealed class FoundationEditor( PrimitiveTool tool ) : GroundAwareStampEditor( tool )
{
[Property, Group( "Foundation" ), Range( 8, 4096, slider: false ), WideMode]
public float Width { get; set; } = 256.0f;
[Property, Group( "Foundation" ), Range( 8, 4096, slider: false ), WideMode]
public float Depth { get; set; } = 192.0f;
[Property, Group( "Foundation" ), Range( 1, 128, slider: false ), WideMode]
public float Thickness { get; set; } = 8.0f;
[Property, Group( "Foundation" ), Title( "Footing Depth" ), Range( 0, 128, slider: false ), WideMode]
public float FootingDepth { get; set; } = 16.0f;
[Property, Group( "Foundation" ), Title( "Footing Width" ), Range( 0, 128, slider: false ), WideMode]
public float FootingWidth { get; set; } = 10.0f;
protected override void OnBuilt( MeshComponent component )
{
base.OnBuilt( component );
component.GameObject.Tags.Add( "amt.foundation" );
}
protected override void Stamp( MeshKit kit, Transform frame, Random random )
{
var w = Width * 0.5f;
var d = Depth * 0.5f;
var footing = MathF.Max( FootingDepth, 0.0f );
if ( footing > 0 && FootingWidth > 0 )
{
var corners = new[]
{
new Vector3( -w - FootingWidth, -d - FootingWidth, 0 ),
new Vector3( w + FootingWidth, -d - FootingWidth, 0 ),
new Vector3( w + FootingWidth, d + FootingWidth, 0 ),
new Vector3( -w - FootingWidth, d + FootingWidth, 0 )
};
if ( FitToGround )
{
var read = GroundRead ?? SurfaceSolver.Begin( SceneEditorSession.Active?.Scene ?? Game.ActiveScene );
var samples = read.ProbePath( corners.Select( c => frame.PointToWorld( c ) ), Vector3.Down, Options() );
var bottom = corners.Select( ( c, i ) => read.AcceptBelow( samples[i], frame.PointToLocal( samples[i].Position ).z, 0 ) ? c.WithZ( frame.PointToLocal( samples[i].Position ).z ) : c - Vector3.Up * footing ).ToArray();
kit.BeginPart();
kit.Face( bottom[2], bottom[1], bottom[0] );
kit.Face( bottom[3], bottom[2], bottom[0] );
kit.Face( corners );
for ( var i = 0; i < 4; i++ )
{
var j = (i + 1) % 4;
kit.Face( bottom[i], bottom[j], corners[j], corners[i] );
}
SurfaceDebug.Record( Title, read );
}
else
kit.Box( new( -w - FootingWidth, -d - FootingWidth, -footing ), new( w + FootingWidth, d + FootingWidth, 0 ) );
}
kit.Box( new Vector3( -w, -d, 0.0f ), new Vector3( w, d, MathF.Max( Thickness, 1.0f ) ) );
}
}