Editor/Platform/ArchPlatformPart.cs

Editor-side class representing a platform part in the architecture system. Stores geometry (footprint, min/max), heights, ramp and guardrail properties, material palette, stair parts, and provides helpers for outline, footprint detection, dressing (copying visual properties), and reshaping from an outline.

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

namespace Sunless.Architecture;

// Flights are CARVED out of it, so they live here rather than on a room.
public sealed class ArchPlatformPart : IArchCarveHost, IArchCollides, IArchRamped, IArchPainted, IArchNamed
{
	// Overrides the kit for THIS part alone: one wall that needs its exact holes, one tower that needs none.
	public ArchCollisionMode? Collision { get; set; }

	public int Id { get; set; }
	public string Name { get; set; } = "Platform";
	public int Level { get; set; }
	public Vector2 Min { get; set; }
	public Vector2 Max { get; set; }
	public float GradeHeight { get; set; }
	public float TopHeight { get; set; } = 24f;

	// A slab that hangs in the air rather than being poured on the ground: it starts at its own grade
	// instead of an embedment below it, and its underside is a soffit somebody stands under.
	public bool Hung { get; set; }

	// A raked deck. The yaw is the way the top CLIMBS and the fall is how far it drops getting to its foot;
	// zero fall is the whole rise, so a ramp dragged and left alone is a wedge sitting on the ground and
	// pulling its head is the only edit it needs.
	public bool Ramp { get; set; }
	public float RampFall { get; set; }
	public float RampYaw { get; set; }

	// Edge protection round the deck: the same post-and-rail engine a roof edge stands, following the
	// CARVED outline so a notch is guarded down its sides and parting at each carved flight's mouth.
	public bool Guardrail { get; set; }
	public float GuardHeight { get; set; } = 42f;

	public bool Coping { get; set; } = true;
	public float CopingHeight { get; set; } = 4f;
	// The oversail is the shadow line you read a cast coping by.
	public float CopingWidth { get; set; } = 8f;
	public float CopingOversail { get; set; } = 1.5f;
	// The rim of anything carved out of it, finished the same way its own outside edge is.
	public bool CopingInside { get; set; }

	public List<ArchStairPart> Stairs { get; set; } = new();
	public List<Vector2> Footprint { get; set; } = new();
	public ArchPalette Palette { get; set; } = new();

	public float Rise => MathF.Max( 1f, TopHeight - GradeHeight );

	public bool HasFootprint => Footprint.Count >= 4;

	public List<Vector2> Outline() => ArchFootprint.OrRect( Footprint, Min, Max );

	// The DRESSING alone - everything a placement adopts from the seed it was drawn with, and nothing about
	// where it stands. A placement that stamped its gesture on the seed itself carried it into the next one.
	public ArchPlatformPart Dressing()
	{
		return new ArchPlatformPart
		{
			GradeHeight = GradeHeight,
			TopHeight = TopHeight,
			Hung = Hung,
			Ramp = Ramp,
			RampFall = RampFall,
			RampYaw = RampYaw,
			Guardrail = Guardrail,
			GuardHeight = GuardHeight,
			Coping = Coping,
			CopingHeight = CopingHeight,
			CopingWidth = CopingWidth,
			CopingOversail = CopingOversail,
			CopingInside = CopingInside
		};
	}

	public void Reshape( List<Vector2> outline )
	{
		(Footprint, Min, Max) = ArchFootprint.Authored( outline );
	}
}