editor/AdvancedMappingTools/Placement/WallOpeningGrid.cs

Placement

namespace AdvancedMappingTools;
public sealed partial class WallOpeningEditor
{
	[Property, Group( "Grid" ), WideMode]
	public bool RepeatGrid { get; set; }

	[Property, Group( "Grid" ), Range( 1, 16, slider: false ), WideMode]
	public int Columns { get; set; } = 3;

	[Property, Group( "Grid" ), Range( 1, 16, slider: false ), WideMode]
	public int Rows { get; set; } = 2;

	[Property, Group( "Grid" ), Range( 8, 2048, slider: false ), WideMode]
	public float ColumnSpacing { get; set; } = 96;

	[Property, Group( "Grid" ), Range( 8, 2048, slider: false ), WideMode]
	public float RowSpacing { get; set; } = 128;

	public List<WallOpeningSpec> Candidates( ConnectedWallSettings settings, float along )
	{
		var result = new List<WallOpeningSpec>();
		var line = ConnectedWallGenerator.Line( settings );
		var length = line.Length;
		for ( var y = 0; y < (RepeatGrid ? Math.Clamp( Rows, 1, 16 ) : 1); y++ )
			for ( var x = 0; x < (RepeatGrid ? Math.Clamp( Columns, 1, 16 ) : 1); x++ )
			{
				var a = along + x * Math.Clamp( ColumnSpacing, 8, 2048 );
				// The clicked opening moves in from the wall's end, as it always did; the
				// repeated ones that do not fit are left out.
				if ( x == 0 && length > Width + CornerClearance * 2.0f )
					a = Math.Clamp( a, Width * .5f + CornerClearance, length - Width * .5f - CornerClearance );
				var low = Low + y * Math.Clamp( RowSpacing, 8, 2048 );
				var height = High - Low;
				if ( a - Width * .5f < CornerClearance || a + Width * .5f > length - CornerClearance || low + height > settings.Height )
					continue;
				if ( MathF.Abs( ClearOfCorners( line, a, settings.Thickness ) - a ) > .01f )
					continue;
				var item = new WallOpeningSpec
				{
					Along = a,
					Width = Width,
					Sill = low,
					Height = height,
					Window = IsWindow,
					Door = Kind == WallOpeningKind.Door,
					Enabled = Enabled,
					Frame = Frame,
					Glass = Glass,
					Leaf = DoorLeaf,
					FrameMaterial = OpeningFrameSurface?.ResourcePath,
					GlassMaterial = OpeningGlassSurface?.ResourcePath,
					LeafMaterial = OpeningLeafSurface?.ResourcePath
				};
				if ( settings.PlacedOpenings.Concat( result ).Any( o => o.Enabled && MathF.Abs( o.Along - a ) < (o.Width + Width) * .5f && o.Sill < low + height && o.Sill + o.Height > low ) )
					continue;
				result.Add( item );
			}

		return result;
	}
}