Editor/Tool/ArchBuildingTool.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Editor;
using Sandbox;

namespace Sunless.Architecture;

[EditorTool( "sunless.architecture" )]
[Title( "Architecture" )]
[Icon( "domain" )]
[Alias( "architecture" )]
public sealed class ArchBuildingTool : ArchTool {
	public override string Shell => ArchShells.Buildings;

	// Navigating the plan is the layer stack's job now. What is left here is the storey: which one
	// you are working on and stacking the next, which belong together and belong to a building.
	public override void BuildTargets( Layout header, Action refresh ) {
		if ( ActiveBuilding() is not { HasContent: true } building ) {
			header.Add( ArchPartUi.Wrapped( "Block out a shell with the Building tool, or pick one in the Plan Layers stack." ) );

			return;
		}

		var storey = header.AddRow();
		storey.Spacing = 4;

		storey.Add( new Label( $"{building.Name} · {ArchStoreyEdit.Name( Level )}" ) );
		storey.Add( Step( "keyboard_arrow_down", "Down a storey", -1, refresh ) );
		storey.Add( Step( "keyboard_arrow_up", "Up a storey", 1, refresh ) );
		storey.Add( new Button( "Add Below", "arrow_downward" ) { Clicked = () => AddStorey( -1, refresh ) } );
		storey.Add( new Button( "Add Above", "arrow_upward" ) { Clicked = () => AddStorey( 1, refresh ) } );
		storey.Add( new Button( "Remove", "remove_circle_outline" ) { Clicked = () => RemoveStorey( refresh ) } );

		if ( Level < 0 ) {
			storey.Add( new Button( "Excavate", "landscape" ) {
				ToolTip = "Reapply the automatic basement terrain openings at Ground stairwells, subtract modifiers, exterior approaches and window wells.",
				Clicked = () => ArchTerrain.Excavate( Scene, Plan, Kit, building )
			} );
		}

		storey.AddStretchCell();
	}

	IconButton Step( string icon, string tooltip, int delta, Action refresh ) {
		var button = new IconButton( icon ) { ToolTip = tooltip, IconSize = 16, FixedSize = 24 };

		button.OnClick = () => {
			Level += delta;

			ApplyVisibility();
			refresh();
		};

		return button;
	}

	void AddStorey( int direction, Action refresh ) {
		var building = ActiveBuilding();
		var result = ArchStoreyEdit.Add( Plan, building, Kit, Level, direction );

		if ( !result.Changed ) {
			Log.Warning( $"Architecture: {result.Error}" );
			return;
		}

		Level = result.Level;
		ActiveRoomId = result.Room.Id;

		Commit( direction < 0 ? "Add Basement" : "Add Floor" );
		refresh();
	}

	void RemoveStorey( Action refresh ) {
		var result = ArchStoreyEdit.Remove( Plan, ActiveBuilding(), Kit, Level );

		if ( !result.Changed ) {
			Log.Warning( $"Architecture: {result.Error}" );
			return;
		}

		Level = result.Level;
		ActiveRoomId = result.Room.Id;

		Commit( "Remove Storey" );
		refresh();
	}
}