editor/AdvancedMappingTools/Framework/AnchorToolSettings.cs

Editor settings classes for the Advanced Mapping Tools package. Holds wall mount options (range, size, bolts, connector, tags, material) for the balcony studio and fire escape generators, exposes them as AnchorOptions, and yields the AnchorSite positions where plates get placed. UI is built from Property attributes.

namespace AdvancedMappingTools;
public sealed partial class BalconyStudioSettings : IAnchorAwareSettings
{
	[Property, Group( "Wall Mounts" ), WideMode, Description( "Generate mounts only where a real wall is found behind the platforms. Mount dimensions are world units." )]
	public bool MountsEnabled { get; set; }

	[Property, Group( "Wall Mounts" ), Range( 1, 4096, slider: false ), WideMode]
	public float MountRange { get; set; } = 256;

	[Property, Group( "Wall Mounts" ), Range( 0, 128, slider: false ), WideMode]
	public float MountMinimum { get; set; } = .01f;

	[Property, Group( "Wall Mounts" ), Range( 1, 512, slider: false ), WideMode]
	public float MountWidth { get; set; } = 12;

	[Property, Group( "Wall Mounts" ), Range( 1, 512, slider: false ), WideMode]
	public float MountHeight { get; set; } = 16;

	[Property, Group( "Wall Mounts" ), Range( .1f, 64, slider: false ), WideMode]
	public float MountThickness { get; set; } = 1;

	[Property, Group( "Wall Mounts" ), Range( 0, 128, slider: false ), WideMode]
	public float MountClearance { get; set; }

	[Property, Group( "Wall Mounts" ), Range( -180, 180, slider: false ), WideMode]
	public float MountRotation { get; set; }

	[Property, Group( "Wall Mounts" ), Range( .05f, .45f ), WideMode]
	public float MountInset { get; set; } = .15f;

	[Property, Group( "Wall Mounts" ), WideMode]
	public bool MountBolts { get; set; } = true;

	[Property, Group( "Wall Mounts" ), Range( .1f, 8, slider: false ), WideMode]
	public float MountBoltRadius { get; set; } = .65f;

	[Property, Group( "Wall Mounts" ), WideMode]
	public bool MountConnector { get; set; } = true;

	[Property, Group( "Wall Mounts" ), Range( .1f, 32, slider: false ), WideMode]
	public float MountConnectorWidth { get; set; } = 2;

	[Property, Group( "Wall Mounts" ), WideMode, Description( "Reject plates whose corners are not supported by a continuous surface." )]
	public bool MountCheckEdges { get; set; } = true;

	[Property, Group( "Wall Mounts" ), WideMode]
	public string MountIncludeTags { get; set; } = "";

	[Property, Group( "Wall Mounts" ), WideMode]
	public string MountExcludeTags { get; set; } = "";

	[Property, Group( "Wall Mounts" ), ResourceType( "vmat" ), WideMode]
	public string MountMaterial { get; set; }

	[Property, Group( "Wall Mounts" ), WideMode]
	public bool ShowMountDebug { get; set; }

	[System.Text.Json.Serialization.JsonIgnore, Property, ReadOnly, Group( "Wall Mounts" ), WideMode]
	public string MountStatus => MountsEnabled ? AnchorIntegration.Status( MountOwner ) : "Wall mounts off.";

	public AnchorOptions MountOptions() => new()
	{
		Range = MountRange,
		Minimum = MountMinimum,
		Width = MountWidth,
		Height = MountHeight,
		Thickness = MountThickness,
		Clearance = MountClearance,
		Rotation = MountRotation,
		Bolts = MountBolts,
		BoltRadius = MountBoltRadius,
		Connector = MountConnector,
		ConnectorWidth = MountConnectorWidth,
		CheckEdges = MountCheckEdges,
		IncludeTags = MountIncludeTags,
		ExcludeTags = MountExcludeTags,
		Material = MountMaterial
	};
	[System.Text.Json.Serialization.JsonIgnore]
	public string MountOwner => "Balcony Studio Mounts";

	public IEnumerable<AnchorSite> MountSites()
	{
		var width = MathF.Max( Width, 16 );
		var count = RepeatFloors ? Math.Clamp( FloorCount, 2, 16 ) : 1;
		for ( var i = 0; i < count; i++ )
			foreach ( var side in new[]
			{
				0,
				1
			}

 )
				yield return new( $"floor{i:00}_{side}", new Vector3( width * (side == 0 ? Math.Clamp( MountInset, .05f, .45f ) : 1 - Math.Clamp( MountInset, .05f, .45f )), 0, Elevation + i * Math.Clamp( FloorSpacing, 64, 1024 ) + Math.Clamp( Thickness, 1, 64 ) * .5f ), new Vector3( 0, -1, 0 ) );
	}
}

public sealed partial class FireEscapeSettings : IAnchorAwareSettings
{
	[Property, Group( "Wall Mounts" ), WideMode, Description( "Generate mounts only where a real wall is found behind the platforms. Mount dimensions are world units." )]
	public bool MountsEnabled { get; set; }

	[Property, Group( "Wall Mounts" ), Range( 1, 4096, slider: false ), WideMode]
	public float MountRange { get; set; } = 256;

	[Property, Group( "Wall Mounts" ), Range( 0, 128, slider: false ), WideMode]
	public float MountMinimum { get; set; } = .01f;

	[Property, Group( "Wall Mounts" ), Range( 1, 512, slider: false ), WideMode]
	public float MountWidth { get; set; } = 12;

	[Property, Group( "Wall Mounts" ), Range( 1, 512, slider: false ), WideMode]
	public float MountHeight { get; set; } = 16;

	[Property, Group( "Wall Mounts" ), Range( .1f, 64, slider: false ), WideMode]
	public float MountThickness { get; set; } = 1;

	[Property, Group( "Wall Mounts" ), Range( 0, 128, slider: false ), WideMode]
	public float MountClearance { get; set; }

	[Property, Group( "Wall Mounts" ), Range( -180, 180, slider: false ), WideMode]
	public float MountRotation { get; set; }

	[Property, Group( "Wall Mounts" ), Range( .05f, .45f ), WideMode]
	public float MountInset { get; set; } = .15f;

	[Property, Group( "Wall Mounts" ), WideMode]
	public bool MountBolts { get; set; } = true;

	[Property, Group( "Wall Mounts" ), Range( .1f, 8, slider: false ), WideMode]
	public float MountBoltRadius { get; set; } = .65f;

	[Property, Group( "Wall Mounts" ), WideMode]
	public bool MountConnector { get; set; } = true;

	[Property, Group( "Wall Mounts" ), Range( .1f, 32, slider: false ), WideMode]
	public float MountConnectorWidth { get; set; } = 2;

	[Property, Group( "Wall Mounts" ), WideMode, Description( "Reject plates whose corners are not supported by a continuous surface." )]
	public bool MountCheckEdges { get; set; } = true;

	[Property, Group( "Wall Mounts" ), WideMode]
	public string MountIncludeTags { get; set; } = "";

	[Property, Group( "Wall Mounts" ), WideMode]
	public string MountExcludeTags { get; set; } = "";

	[Property, Group( "Wall Mounts" ), ResourceType( "vmat" ), WideMode]
	public string MountMaterial { get; set; }

	[Property, Group( "Wall Mounts" ), WideMode]
	public bool ShowMountDebug { get; set; }

	[System.Text.Json.Serialization.JsonIgnore, Property, ReadOnly, Group( "Wall Mounts" ), WideMode]
	public string MountStatus => MountsEnabled ? AnchorIntegration.Status( MountOwner ) : "Wall mounts off.";

	public AnchorOptions MountOptions() => new()
	{
		Range = MountRange,
		Minimum = MountMinimum,
		Width = MountWidth,
		Height = MountHeight,
		Thickness = MountThickness,
		Clearance = MountClearance,
		Rotation = MountRotation,
		Bolts = MountBolts,
		BoltRadius = MountBoltRadius,
		Connector = MountConnector,
		ConnectorWidth = MountConnectorWidth,
		CheckEdges = MountCheckEdges,
		IncludeTags = MountIncludeTags,
		ExcludeTags = MountExcludeTags,
		Material = MountMaterial
	};
	[System.Text.Json.Serialization.JsonIgnore]
	public string MountOwner => "Fire Escape Mounts";

	public IEnumerable<AnchorSite> MountSites()
	{
		var width = MathF.Max( PlatformWidth, 32 );
		var scale = MathF.Max( Scale, .01f );
		for ( var i = 0; i < Math.Clamp( Storeys, 1, 8 ); i++ )
			foreach ( var side in new[]
			{
				0,
				1
			}

 )
				yield return new( $"floor{i:00}_{side}", new Vector3( (side == 0 ? -1 : 1) * width * (.5f - Math.Clamp( MountInset, .05f, .45f )), 0, (i + 1) * MathF.Max( StoreyHeight, 32 ) - FireEscapeGenerator.Deck * .5f ) * scale, new Vector3( 0, -1, 0 ) );
	}

	public override IReadOnlySet<string> UnusedOptions => AnchorIntegration.Hidden( this );
}