Editor/Tool/ArchFixtureRoles.cs
using System.Collections.Generic;
namespace Sunless.Architecture;
// What the fixture tool authors that it does not own. Each role previews its own draft and places it, because the
// shape a preview draws belongs to the role and the fixture tool has no business resolving one. An unanswered role
// is a fixture that simply cannot be stood, rather than an error.
public interface IArchLadders {
bool Preview( ArchPlan plan, ArchKit kit, ArchFixtureStation? at, ArchLadderPart draft );
ArchLadderPart Place( ArchPlan plan, ArchKit kit, ArchFixtureStation? at, ArchLadderPart draft, out ArchBuilding host );
// Handed the buildings, because a recipe hangs a ladder on a building not yet filed in the plan.
ArchLadderPart Place( IEnumerable<ArchBuilding> buildings, ArchPlan plan, ArchKit kit, Vector2 point, ArchLadderPart draft, out ArchBuilding host );
}
public interface IArchBalconies {
bool Preview( ArchPlan plan, ArchKit kit, ArchFixtureStation? at, ArchBalconyPart draft );
ArchBalconyPart Place( ArchPlan plan, ArchKit kit, ArchFixtureStation? at, ArchBalconyPart draft, out ArchBuilding host );
void Remove( ArchPlan plan, ArchBuilding building, ArchBalconyPart balcony );
}
// What a recess or a proud pier takes out of a wall, drawn by the module that cuts it - a block is a stack of slabs
// on either face, not a box, so the role draws its own ghost rather than handing back an envelope.
public interface IArchWallMods {
bool Preview( ArchWallModPart part, ArchWall wall, ArchKit kit, float wallHeight, float floor );
}
public static class ArchLadders {
static IArchLadders Load() => ArchRoles.One<IArchLadders>();
public static bool Preview( ArchPlan plan, ArchKit kit, ArchFixtureStation? at, ArchLadderPart draft ) {
return Load()?.Preview( plan, kit, at, draft ) == true;
}
public static ArchLadderPart Place( ArchPlan plan, ArchKit kit, ArchFixtureStation? at, ArchLadderPart draft, out ArchBuilding host ) {
if ( Load() is not { } ladders ) {
host = null;
return null;
}
return ladders.Place( plan, kit, at, draft, out host );
}
public static ArchLadderPart Place( IEnumerable<ArchBuilding> buildings, ArchPlan plan, ArchKit kit, Vector2 point, ArchLadderPart draft, out ArchBuilding host ) {
if ( Load() is not { } ladders ) {
host = null;
return null;
}
return ladders.Place( buildings, plan, kit, point, draft, out host );
}
}
public static class ArchBalconies {
static IArchBalconies Load() => ArchRoles.One<IArchBalconies>();
public static bool Preview( ArchPlan plan, ArchKit kit, ArchFixtureStation? at, ArchBalconyPart draft ) {
return Load()?.Preview( plan, kit, at, draft ) == true;
}
public static ArchBalconyPart Place( ArchPlan plan, ArchKit kit, ArchFixtureStation? at, ArchBalconyPart draft, out ArchBuilding host ) {
if ( Load() is not { } balconies ) {
host = null;
return null;
}
return balconies.Place( plan, kit, at, draft, out host );
}
public static void Remove( ArchPlan plan, ArchBuilding building, ArchBalconyPart balcony ) {
Load()?.Remove( plan, building, balcony );
}
}
public static class ArchWallModBlocks {
public static bool Preview( ArchWallModPart part, ArchWall wall, ArchKit kit, float wallHeight, float floor ) {
return ArchRoles.One<IArchWallMods>() is { } mods && mods.Preview( part, wall, kit, wallHeight, floor );
}
}
// The single-implementation half of ArchAnswers, for roles a caller reaches with no table of its own. A role
// nothing answers hands back null, which every caller falls back from rather than erroring.
public static class ArchRoles {
public static T One<T>() where T : class => Answering( typeof( T ) ) as T;
static object Answering( Type role ) {
if ( role == typeof( IArchWallForms ) ) return new ArchWallFormsRole();
if ( role == typeof( IArchWallMods ) ) return new ArchWallModRole();
if ( role == typeof( IArchBalconies ) ) return new ArchBalconyRole();
if ( role == typeof( IArchLadders ) ) return new ArchLadderRole();
if ( role == typeof( IArchFlightBuilder ) ) return new ArchFlightBuilder();
if ( role == typeof( IArchWellEdges ) ) return new ArchStairWellEdges();
if ( role == typeof( IArchPiercer ) ) return new ArchStairPiercer();
if ( role == typeof( IArchHostCarving ) ) return new ArchStairHostCarving();
if ( role == typeof( IArchExteriorStairs ) ) return new ArchExteriorStairAuthoring();
return null;
}
}