Editor/Geometry/ArchWallFaces.cs

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.

NetworkingFile AccessProcess ExecutionReflectionNative InteropObfuscated CodeEncoded DataExternal DownloadSelf Modifying CodeCredential AccessHttp Calls
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;
	}
}