Editor utility that updates ArchTrimPart instances which follow other layer shapes. It re-derives a trim part's 3D path from the followed layer's loop and height and assigns the path if it changed, returning counts/booleans for updates.
using System.Collections.Generic;
using System.Linq;
using Sandbox;
namespace Sunless.Architecture;
// A run that follows another layer's shape is an affector on nothing, but it is a CONSUMER of one - so
// it obeys the same rule: its path is re-derived from where its host stands NOW, on every commit,
// through the one shape answer the host's own generator reads. Drag the cut and the run goes round it.
// A host that stops resolving lets the run keep the path it last had, because a run vanishing because a
// neighbour was deleted is worse than one left standing where it was.
public static class ArchTrimAffector
{
public static int Resolve( ArchPlan plan, ArchKit kit )
{
var kinds = ArchKinds.Load();
var followed = 0;
foreach ( var room in plan.AllRooms() )
{
foreach ( var trim in plan.Filed<ArchTrimPart>( room, kinds ).Where( trim => trim.Follows ) )
{
if ( Refollow( plan, trim ) )
{
followed++;
}
}
}
return followed;
}
public static bool Refollow( ArchPlan plan, ArchTrimPart trim )
{
var loops = ArchLayerShape.Loops( plan, trim.FollowsId );
if ( loops.Count == 0 )
{
return false;
}
var loop = loops[System.Math.Clamp( trim.FollowsLoop, 0, loops.Count - 1 )];
var height = ArchLayerShape.HeightOf( plan, trim.FollowsId, 0f ) + trim.Lift;
var path = loop.Select( corner => new Vector3( corner.x, corner.y, height ) ).ToList();
if ( Same( trim.Path, path ) )
{
return false;
}
trim.Path = path;
trim.Closed = true;
return true;
}
// Rewriting an unchanged path every commit would make every rebuild look like an edit to undo.
static bool Same( IReadOnlyList<Vector3> standing, IReadOnlyList<Vector3> wanted )
{
if ( standing.Count != wanted.Count )
{
return false;
}
for ( var index = 0; index < wanted.Count; index++ )
{
if ( (standing[index] - wanted[index]).Length > 0.05f )
{
return false;
}
}
return true;
}
}