Editor/Barriers/ArchBarrierSolid.cs
using System;
using Sandbox;

namespace Sunless.Architecture;

// A parapet rather than a railing: one wall through the bay under a coping that oversails both faces. Every
// other style hides the corner between two runs behind a post, and this one has none, so each bay laps half a
// thickness past both of its stations - at a right angle that is exactly the notch, filled.
public static class ArchBarrierSolid {
	public static void Bay( ArchMesh canvas, ArchBarrierBayShape bay, ArchBarrierSpec spec, ArchKit kit, ArchBarrierBrushes brushes ) {
		var half = Half( spec, kit );
		var lap = bay.Along * half;
		var from = bay.From.Flat - lap;
		var to = bay.To.Flat + lap;

		if ( (to - from).Length < 1f ) {
			return;
		}

		var coping = spec.Coping ? MathF.Max( 0f, Cap( spec, kit ) ) : 0f;
		var head = spec.Height - coping;

		if ( head > 0.5f ) {
			canvas.Rake( from, to, -half, half,
				bay.SeatFrom, bay.SeatTo,
				bay.SeatFrom + head, bay.SeatTo + head, brushes.Solid );
		}

		if ( coping < 0.05f ) {
			return;
		}

		var proud = half + MathF.Max( 0f, Proud( spec, kit ) );
		var seat = MathF.Max( 0f, head );

		canvas.Rake( from, to, -proud, proud,
			bay.SeatFrom + seat, bay.SeatTo + seat,
			bay.SeatFrom + spec.Height, bay.SeatTo + spec.Height, brushes.Coping );
	}

	// Thin enough and both faces land on one rung of the grid, which is a prism with no volume at all.
	public static float Half( ArchBarrierSpec spec, ArchKit kit ) {
		var thickness = spec.PanelThickness > 0.5f ? spec.PanelThickness : kit.SolidGuardThickness;

		return MathF.Max( 1f, thickness ) * 0.5f;
	}

	static float Cap( ArchBarrierSpec spec, ArchKit kit ) {
		return spec.CopingHeight > 0.05f ? spec.CopingHeight : kit.SolidGuardCoping;
	}

	static float Proud( ArchBarrierSpec spec, ArchKit kit ) {
		return spec.CopingProud > 0.05f ? spec.CopingProud : kit.SolidGuardProud;
	}
}