editor/AdvancedMappingTools/Procedural/DoorGenerator.cs

Editor-side procedural generator for a door assembly in the Advanced Mapping Tools package. Builds a frame (left, right, top bars), a door leaf and a two-sided handle as separate parts, with the hinge side chosen from the seeded stream.

namespace AdvancedMappingTools;

public sealed record DoorRequest(
	string Id, string Name, float Width, float Height, float Depth, float BarWidth,
	Material FrameMaterial, Material LeafMaterial );

/// <summary>
/// A door with separate frame pieces, leaf and handle. The origin is the middle of the threshold.
/// </summary>
public static class DoorGenerator
{
	public const string Category = "door";

	public static PartPlan Generate( DoorRequest request, GenContext context )
	{
		var group = context.Group( request.Id, request.Name, "DoorAssembly", Category );
		var stream = context.Stream( Category, request.Id );
		var x = request.Width * 0.5f;
		var z = request.Height;
		var bar = request.BarWidth;
		var depth = request.Depth * 0.5f;

		// The seed picks the hinge side, the handle goes on the other one.
		var handleSide = stream.Chance( 0.5f ) ? 1.0f : -1.0f;

		void Part( string name, string label, string kind, Material material, Action<MeshKit> build ) =>
			group.Add( context.Solid( $"{request.Id}/{name}", label, kind, Category, material, build ) );

		Part( "frame_left", "Left Frame", "FrameBar", request.FrameMaterial, kit => kit.Box( new Vector3( -x, -depth, 0.0f ), new Vector3( -x + bar, depth, z ) ) );
		Part( "frame_right", "Right Frame", "FrameBar", request.FrameMaterial, kit => kit.Box( new Vector3( x - bar, -depth, 0.0f ), new Vector3( x, depth, z ) ) );
		Part( "frame_top", "Top Frame", "FrameBar", request.FrameMaterial, kit => kit.Box( new Vector3( -x + bar, -depth, z - bar ), new Vector3( x - bar, depth, z ) ) );
		Part( "leaf", "Door Leaf", "DoorLeaf", request.LeafMaterial, kit => kit.Box( new Vector3( -x + bar, -1.0f, 0.5f ), new Vector3( x - bar, 1.0f, z - bar ) ) );

		var handleX = (x - bar - 4.0f) * handleSide;

		Part( "handle", "Handle", "Handle", request.FrameMaterial, kit =>
		{
			kit.Box( new Vector3( handleX - 2.0f, -2.5f, 40.0f ), new Vector3( handleX + 2.0f, -1.0f, 41.0f ) );
			kit.Box( new Vector3( handleX - 2.0f, 1.0f, 40.0f ), new Vector3( handleX + 2.0f, 2.5f, 41.0f ) );
		} );

		return group;
	}
}