Editor/Stair/ArchStairContextAction.cs

Editor context action for stairs in the architecture editor. It finds a stair part under the cursor and populates a context menu with options to change balustrade (StairGuard), wall handrail, top landing railing, and underside (StairUnder), applying changes via context.Tool.Commit.

Reflection
namespace Sunless.Architecture;

public sealed class ArchStairContextAction : IArchContextAction
{
	public ArchKind Kind => ArchKind.Stair;

	public bool Build( ArchContextActionContext context )
	{
		var hit = ArchPick.HitsAt( context.Tool.LayerTree, context.Tool.Kit, context.Level, context.Point )
			.FirstOrDefault( candidate => candidate.Layer.Kind == ArchKind.Stair );
		var node = context.Tool.LayerTree.Find( hit?.Layer.ItemId ?? 0 );

		if ( node?.Payload is not ArchStairPart stair || node.Room?.Stairs.Contains( stair ) != true )
		{
			return false;
		}

		var sides = context.Menu.AddMenu( $"{stair.Name} balustrade", "fence" );

		foreach ( var value in Enum.GetValues<StairGuard>() )
		{
			var captured = value;
			var option = sides.AddOption( captured.ToString(), null,
				() => { stair.Guard = captured; context.Tool.Commit( "Stair Balustrade" ); } );

			option.Checkable = true;
			option.Checked = stair.Guard == captured;
		}

		var wallRail = sides.AddOption( "Handrail on walled sides", null,
			() => { stair.WallRail = !stair.WallRail; context.Tool.Commit( "Stair Wall Rail" ); } );

		wallRail.Checkable = true;
		wallRail.Checked = stair.WallRail;

		var guard = context.Menu.AddOption( "Top landing railing", "vertical_align_top",
			() => { stair.WellGuard = !stair.WellGuard; context.Tool.Commit( "Stair Well Guard" ); } );

		guard.Checkable = true;
		guard.Checked = stair.WellGuard;

		var under = context.Menu.AddMenu( $"{stair.Name} underside", "door_front" );

		foreach ( var value in Enum.GetValues<StairUnder>() )
		{
			var captured = value;
			var option = under.AddOption( captured.ToString(), null,
				() => { stair.Under = captured; context.Tool.Commit( "Stair Underside" ); } );

			option.Checkable = true;
			option.Checked = stair.Under == captured;
		}

		context.Menu.AddSeparator();

		return true;
	}
}