Editor/Stair/ArchStairStepManifest.cs

Editor manifest describing one step (a lane) of an architectural stair. It maps the step to its slot name, host types, children kinds, UI label/glyph/subtool, display name logic, and other metadata used by the editor.

Reflection
using System;
using System.Collections.Generic;

namespace Sunless.Architecture;

// One step of a climb, as a row of its own under the stair that holds it. The stair's Lanes list IS the stack, in
// order, so filing, unfiling, reordering and deleting all come off the slot with nothing written for them - moving
// a row up the stack moves that step down the climb, because list order has always been climb order.
public sealed class ArchStairStepManifest : ArchKindManifest<ArchStairLane>
{
	public override ArchKind Kind => ArchKind.StairStep;

	public override string Slot => "Lanes";

	public override IEnumerable<Type> Hosts => new[] { typeof( ArchStairPart ) };

	public override string Label => "Step";

	public override string Glyph => ArchIcons.Get( "subtool_stair", "stairs" );

	public override string Subtool => ArchSubtools.Stair;

	public override string HostOutput => "The step's own rectangle in the shaft";

	// The railings standing on this step's edges, each its own row.
	public override IEnumerable<ArchKind> Children => new[] { ArchKind.StairGuard };

	public override int DirectRank => 5;

	// A flight opens the slab over it exactly as the stair does; a platform standing in the well is the same hole.
	public override ArchLayerStage Stage( object payload ) => ArchLayerStage.Void;

	// Read off the step rather than off a stored name, because a step has none: what it IS and how far it runs are
	// the two things that tell one row from the next when a stair has six of them.
	public override string DisplayName( object payload )
	{
		if ( payload is not ArchStairLane lane )
		{
			return null;
		}

		return lane.Climbs
			? $"Flight · {lane.Length:0} run"
			: $"Platform · {lane.Length:0} deep";
	}

	public override IReadOnlyList<List<Vector2>> Loops( object payload ) => Array.Empty<List<Vector2>>();
}