Editor/Barriers/ArchRetainingGen.cs
using System.Collections.Generic;
using Sandbox;

namespace Sunless.Architecture;

// The wall the resolve described, plus the ArchWing returns that bury its ends in the bank.
public static class ArchRetainingGen {
	public static void Build( ArchMesh canvas, ArchRetainingShape shape, ArchKit kit, ArchBarrierBrushes brushes ) {
		if ( shape is null || !shape.IsUsable ) {
			return;
		}

		using ( canvas.Part( ArchPieces.Retaining ) ) {
			foreach ( var bay in shape.Bays ) {
				Bay( canvas, bay, shape, kit, brushes.Plinth );
			}

			ArchWing.Build( canvas, shape.Returns, shape.Stem, kit, brushes.Plinth );
		}
	}

	// Leans back into the fill: the open face is battered, the buried face stands plumb, and the foot follows
	// the grade on the open side rather than one level line under the whole run.
	static void Bay( ArchMesh canvas, ArchRetainingBay bay, ArchRetainingShape shape, ArchKit kit, ArchBrush brush ) {
		var span = bay.To.At - bay.From.At;

		if ( span.Length < 0.05f ) {
			return;
		}

		var embedment = ArchGround.Embedment( kit );
		var half = shape.Stem * 0.5f;

		var lower = new List<Vector3>
		{
			Corner( bay.From, -half, bay.From.Grade - embedment ),
			Corner( bay.To, -half, bay.To.Grade - embedment ),
			Corner( bay.To, half, bay.To.Grade - embedment ),
			Corner( bay.From, half, bay.From.Grade - embedment )
		};

		var upper = new List<Vector3>
		{
			Corner( bay.From, shape.Lean - half, bay.From.Head ),
			Corner( bay.To, shape.Lean - half, bay.To.Head ),
			Corner( bay.To, half, bay.To.Head ),
			Corner( bay.From, half, bay.From.Head )
		};

		canvas.Prism( lower, upper, brush, tangent: new Vector3( span.x, span.y, 0f ).Normal );
	}

	// Offset along the STATION's own fill direction, so two bays quote a shared joint identically and a corner mitres.
	static Vector3 Corner( ArchRetainingStation station, float offset, float height ) {
		var point = station.At + station.Fill * offset;

		return new Vector3( point.x, point.y, height );
	}
}