Utility class for determining which side of an ArchWall faces outward relative to a room and building. It probes points on either side of the wall to see which side is occupied by a room and returns an outward-facing normal, with a fallback using the room footprint when probing is ambiguous.
using System;
using System.Collections.Generic;
using Sandbox;
namespace Sunless.Architecture;
// Which way a wall faces out of its building, decided by probing both sides for a room rather than by the winding
// the wall was authored in. Fixtures, approaches and anything else seated on an exterior face reads this.
public static class ArchWallFaces
{
public static bool TryOutward( ArchWall wall, ArchRoom room, ArchBuilding building, out Vector2 outward )
{
var normal = wall.Normal;
var midpoint = wall.PointAt( wall.Length * 0.5f );
var probe = MathF.Max( 4f, wall.Thickness );
var positiveOccupied = Occupied( building, room.Floor, midpoint + normal * probe );
var negativeOccupied = Occupied( building, room.Floor, midpoint - normal * probe );
if ( positiveOccupied == negativeOccupied )
{
outward = default;
return false;
}
outward = positiveOccupied ? -normal : normal;
return true;
}
public static Vector2 Outward( ArchWall wall, ArchRoom room, ArchBuilding building )
{
if ( TryOutward( wall, room, building, out var outward ) )
{
return outward;
}
var normal = wall.Normal;
var midpoint = wall.PointAt( wall.Length * 0.5f );
return ArchFloorGen.Contains( ArchFloorGen.Footprint( room ), midpoint + normal * 4f ) ? -normal : normal;
}
static bool Occupied( ArchBuilding building, int level, Vector2 point )
{
if ( building is null )
{
return false;
}
foreach ( var room in building.Rooms )
{
if ( room.Floor == level && ArchFloorGen.Contains( ArchFloorGen.Footprint( room ), point ) )
{
return true;
}
}
return false;
}
}