Editor/Pipe/ArchPipeHandlers.cs

Editor handlers for pipe and bracket architectural parts. ArchPipeHandler lets the user move pipe nodes by rendering control handles and propagating moved positions to all pipes that share the same node id. ArchBracketHandler provides a volume handle to reshape a bracket part and applies the pulled bounds to the bracket.

Reflection
namespace Sunless.Architecture;

public sealed class ArchPipeHandler : IArchHandler
{
	public ArchKind Kind => ArchKind.Pipe;

	public bool Draw( ArchTool tool, ArchSelection picked )
	{
		if ( picked.Item is not ArchPipePart run )
		{
			return false;
		}

		var gesture = ArchGesture.On( ArchKind.Pipe, run.Id );
		var changed = false;

		foreach ( var node in run.Nodes )
		{
			if ( !ArchShapeHandles.Control( tool, gesture.At( "node", node.Id ), node.Position, out var position ) )
			{
				continue;
			}

			foreach ( var shared in ArchPipe.All( tool.Plan ).SelectMany( candidate => candidate.Nodes ).Where( candidate => candidate.Id == node.Id ) )
			{
				shared.Position = position;
			}

			changed = true;
		}

		return changed;
	}
}

public sealed class ArchBracketHandler : IArchHandler
{
	public ArchKind Kind => ArchKind.Bracket;

	public bool Draw( ArchTool tool, ArchSelection picked )
	{
		if ( picked.Item is not ArchPipeBracketPart bracket )
		{
			return false;
		}

		if ( !ArchShapeHandles.Volume( tool, ArchGesture.On( ArchKind.Bracket, bracket.Id ).At( "volume" ), bracket.Min, bracket.Max, bracket.BaseHeight, bracket.TopHeight, out var pulled ) )
		{
			return false;
		}

		bracket.Reshape( pulled );

		return true;
	}
}