Editor/Walkway/ArchWalkwayManifest.cs

Manifest class describing the Walkway arch kind for the editor. It defines metadata (kind, slot, label, glyph, subtool), host types, children kinds, naming/rename behavior, filing/unfiling into ArchBuilding, how to enumerate Walkway payloads (rooms that span), loop footprint retrieval, and height lookup.

using System;
using System.Collections.Generic;
using System.Linq;
using Sandbox;

namespace Sunless.Architecture;

public sealed class ArchWalkwayManifest : ArchKindManifest
{
	public override ArchKind Kind => ArchKind.Walkway;

	// A walkway is an ArchRoom that Spans, and the room manifest already claims that type, so this one claims none.
	public override Type Payload => null;

	public override string Slot => "Rooms";

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

	public override string Label => "Walkway";

	public override string Glyph => ArchIcons.Get( "subtool_walkway", "link" );

	public override string Subtool => ArchSubtools.Walkway;

	public override string HostOutput => "Walkway deck and endpoints";

	public override IEnumerable<ArchKind> Children => new[]
	{
		ArchKind.Stair, ArchKind.Roof, ArchKind.Trim, ArchKind.Pillar
	};

	public override int DirectRank => 0;

	public override string NameOf( object payload, int id )
	{
		return payload is ArchRoom room ? room.Name : base.NameOf( payload, id );
	}

	public override bool TryRename( object payload, string name )
	{
		if ( string.IsNullOrWhiteSpace( name ) || payload is not ArchRoom room )
		{
			return false;
		}

		room.Name = name;

		return true;
	}

	public override IEnumerable<object> Filed( ArchPlan plan, object host )
	{
		if ( host is not ArchBuilding building )
		{
			return Array.Empty<object>();
		}

		return building.Rooms.Where( room => room.Spans );
	}

	public override bool File( object host, object payload )
	{
		if ( host is not ArchBuilding building || payload is not ArchRoom room )
		{
			return false;
		}

		building.Rooms.Add( room );

		return true;
	}

	public override bool Unfile( ArchPlan plan, object payload )
	{
		if ( plan is null || payload is not ArchRoom room )
		{
			return false;
		}

		return plan.OwnerOf( room ) is { } holder && holder.Rooms.Remove( room );
	}

	public override IReadOnlyList<List<Vector2>> Loops( object payload )
	{
		if ( payload is not ArchRoom room )
		{
			return Array.Empty<List<Vector2>>();
		}

		var footprint = ArchFloorGen.Footprint( room );

		if ( footprint.Count < 3 )
		{
			return Array.Empty<List<Vector2>>();
		}

		return new List<List<Vector2>> { footprint };
	}

	public override float Height( object payload, float fallback )
	{
		return payload is ArchRoom room ? room.BaseHeight : fallback;
	}
}