Editor/Services/ArchClearance.cs
using System;
using Sandbox;
namespace Sunless.Architecture;
// Clears and Blocked are explicit - the three cases build different geometry.
public readonly struct ArchSplit {
public bool Clears { get; init; }
public bool Blocked { get; init; }
public float At { get; init; }
public bool Splits => !Clears && !Blocked;
}
// One question that used to carry seven names - a SPLIT, not a truncation: stopping short leaves bare wall.
public static class ArchClearance {
// Order-agnostic - a rake read from its high end answers the same as from its low.
public static ArchSplit Cross( float from, float to, float ceiling ) {
if ( from <= ceiling && to <= ceiling ) {
return new ArchSplit { Clears = true, At = 1f };
}
if ( from >= ceiling && to >= ceiling ) {
return new ArchSplit { Blocked = true, At = 0f };
}
return new ArchSplit { At = Math.Clamp( (ceiling - from) / (to - from), 0f, 1f ) };
}
// It says so when it bites - a silent clamp reads as the setting not working.
public static float Fits( float requested, float limit, float floor, string what, string why ) {
var fitted = MathF.Min( MathF.Max( 0f, requested ), MathF.Max( floor, limit ) );
if ( requested - fitted > 1f ) {
Log.Info( $"Architecture: {what} cut from {requested:0} to {fitted:0} - {why}." );
}
return fitted;
}
}