Editor/Walkway/ArchWalkwayInteractions.cs
namespace Sunless.Architecture;
public sealed class ArchWalkwayHandler : IArchHandler {
public ArchKind Kind => ArchKind.Walkway;
public bool Draw( ArchTool tool, ArchSelection picked ) {
if ( picked.Item is not ArchRoom room ) {
return false;
}
var outline = ArchFloorGen.Footprint( room );
if ( outline.Count < 3 ) {
return false;
}
var gesture = ArchGesture.On( ArchKind.Walkway, room.Id );
var deck = ArchWalkway.Deck( tool.Plan, room );
var top = deck?.BaseHeight ?? MathF.Max( room.BaseHeight + room.WallHeight, room.WalkwayTop );
var reshaped = ArchShapeHandles.Corners( tool, gesture, outline, top );
reshaped |= ArchShapeHandles.Edges( tool, gesture, outline, top );
if ( reshaped ) {
ArchWalkway.Reshape( tool.Plan, room, outline, tool.Kit );
}
var middle = Middle( ArchFloorGen.Footprint( room ) );
var changed = reshaped;
if ( ArchShapeHandles.Move( tool, gesture.At( "body" ), middle, out var moved ) && (moved - middle).Length >= 0.01f ) {
var shifted = ArchFloorGen.Footprint( room );
ArchRemap.Translation( moved - middle ).Loop( shifted );
ArchWalkway.Reshape( tool.Plan, room, shifted, tool.Kit );
changed = true;
}
if ( ArchShapeHandles.Height( tool, gesture.At( "deck" ), middle, top, out var head, Gizmo.Colors.Roll ) ) {
ArchWalkway.Reheight( room, deck, tool.Kit, MathF.Max( 60f, head - room.BaseHeight ) );
changed = true;
}
if ( ArchShapeHandles.Height( tool, gesture.At( "floor" ), middle, room.BaseHeight, out var floor, Gizmo.Colors.Pitch ) ) {
ArchWalkway.Raise( tool.Plan, room, tool.Kit, floor );
changed = true;
}
return changed;
}
static Vector2 Middle( IReadOnlyList<Vector2> outline ) {
if ( outline is not { Count: > 0 } ) {
return Vector2.Zero;
}
ArchFootprint.Bounds( outline, out var min, out var max );
return (min + max) * 0.5f;
}
}
public sealed class ArchWalkwayPreview : IArchPreview {
public ArchKind Kind => ArchKind.Walkway;
public void Draw( ArchPreviewContext context ) {
if ( context.Payload is not ArchRoom link || context.Tool is null ) {
return;
}
var loop = ArchFloorGen.Footprint( link );
if ( loop.Count < 3 ) {
return;
}
ArchFootprint.Bounds( loop, out var min, out var max );
var deck = ArchWalkway.Deck( context.Tool.Plan, link );
var floor = link.BaseHeight + context.Lift;
var head = (deck?.BaseHeight ?? link.BaseHeight + link.WallHeight) + context.Lift;
ArchGhost.Volume( min, max, floor, head );
ArchGhost.Plate( min, max, floor, 8 );
ArchGhost.Brackets( min, max, head );
var alongX = max.x - min.x >= max.y - min.y;
var run = alongX ? max.x - min.x : max.y - min.y;
var across = alongX ? max.y - min.y : max.x - min.x;
Mouth( min, max, alongX, true, floor, head );
Mouth( min, max, alongX, false, floor, head );
ArchGhost.Note( new Vector3( max.x, max.y, head ), $"walkway — {run:0} x {across:0}, {head - floor:0} clear" );
}
static void Mouth( Vector2 min, Vector2 max, bool alongX, bool low, float bottom, float top ) {
var start = alongX
? new Vector2( low ? min.x : max.x, min.y )
: new Vector2( min.x, low ? min.y : max.y );
var end = alongX
? new Vector2( low ? min.x : max.x, max.y )
: new Vector2( max.x, low ? min.y : max.y );
ArchGhost.Footprint( new List<Vector2> { start, end }, bottom, ArchGhost.Accent );
ArchGhost.Footprint( new List<Vector2> { start, end }, top, ArchGhost.Accent );
Gizmo.Draw.Color = ArchGhost.Accent;
Gizmo.Draw.Line( new Vector3( start.x, start.y, bottom ), new Vector3( start.x, start.y, top ) );
Gizmo.Draw.Line( new Vector3( end.x, end.y, bottom ), new Vector3( end.x, end.y, top ) );
}
}