Editor/Tool/ArchLayerPieceRows.cs
using Editor;
using Sandbox;
namespace Sunless.Architecture;
sealed class ArchPieceRow : TreeNode {
readonly ArchBuiltPiece piece;
public ArchPieceRow( ArchBuiltPiece piece ) : base( piece.Key ) {
this.piece = piece;
Height = 22;
foreach ( var child in piece.Children ) {
AddItem( new ArchPieceRow( child ) );
}
}
public ArchBuiltPiece Built => piece;
public override void OnPaint( VirtualWidget item ) {
var tool = ArchTool.Active;
var rect = item.Rect;
PaintSelection( item );
var hidden = tool?.PieceHidden( piece.Owner, piece.Piece ) == true;
var alpha = hidden ? 0.28f : 0.85f;
Paint.SetPen( Theme.Text.WithAlpha( alpha ) );
Paint.DrawIcon( rect.Shrink( 4, 0, 0, 0 ), ArchPieces.Glyph( piece.Name ), 14, TextFlag.LeftCenter );
var body = rect.Shrink( 24, 0, ArchLayerStack.ControlWidth * 4f + 4f, 0 );
Paint.DrawText( body, piece.Name, TextFlag.LeftCenter );
Paint.SetPen( Theme.Text.WithAlpha( 0.3f * alpha ) );
Paint.DrawText( body, piece.Renders ? "piece" : "group", TextFlag.RightCenter );
Collision( rect );
Shadow( rect );
Paint.SetPen( Theme.Text.WithAlpha( hidden ? 0.75f : 0.3f ) );
Paint.DrawIcon( Control( rect, 1 ), hidden ? "visibility_off" : "visibility", 14, TextFlag.Center );
}
void Collision( Rect rect ) {
if ( ArchTool.Active is not { } tool ) {
return;
}
var mode = ArchParts.Showing( tool.Plan, tool.Kit, tool.LayerTree, piece.Owner, piece.Piece, out var own );
Paint.SetPen( !own
? Theme.Text.WithAlpha( 0.3f )
: mode == ArchCollisionMode.Complex ? Theme.Yellow : Theme.Blue );
Paint.DrawIcon( Control( rect, 2 ), ArchCollision.Glyph( mode ), 14, TextFlag.Center );
}
void Shadow( Rect rect ) {
if ( ArchTool.Active is not { } tool ) {
return;
}
var casts = ArchParts.ShowingShadows( tool.Plan, tool.Kit, tool.LayerTree, piece.Owner, piece.Piece, out var own );
Paint.SetPen( !own
? Theme.Text.WithAlpha( 0.3f )
: casts ? Theme.Blue : Theme.Yellow );
Paint.DrawIcon( Control( rect, 3 ), ArchShadows.Glyph( casts ), 14, TextFlag.Center );
}
static Rect Control( Rect row, int fromRight ) {
var width = ArchLayerStack.ControlWidth;
return new Rect( row.Right - width * (fromRight + 1), row.Top, width, row.Height );
}
public override string GetTooltip() {
return $"{piece.Piece} · built by layer {piece.Owner}"
+ (piece.Renders ? "" : "\nA group over the pieces under it - it renders nothing itself.");
}
public override void OnActivated() {
if ( ArchTool.Active is { } tool && piece.Object.IsValid() ) {
tool.Frame( piece.Object.GetBounds() );
tool.SelectLayer( tool.LayerTree.Find( piece.Owner ) );
}
}
public void Collisions( ContextMenu menu, ArchTool tool ) {
var showing = ArchParts.Showing( tool.Plan, tool.Kit, tool.LayerTree, piece.Owner, piece.Piece, out _ );
var collisions = menu.AddMenu( "Collisions", ArchCollision.Glyph( showing ) );
collisions.AddOption( ArchParts.Following( tool.Plan, tool.Kit, tool.LayerTree, piece.Owner, piece.Piece ),
"settings", () => Collide( tool, null ) );
collisions.AddSeparator();
foreach ( var mode in new[] { ArchCollisionMode.Solids, ArchCollisionMode.Convex, ArchCollisionMode.Complex, ArchCollisionMode.None } ) {
var captured = mode;
collisions.AddOption( ArchCollision.Describe( captured ), ArchCollision.Glyph( captured ),
() => Collide( tool, captured ) );
}
}
public void Shadows( ContextMenu menu, ArchTool tool ) {
var showing = ArchParts.ShowingShadows( tool.Plan, tool.Kit, tool.LayerTree, piece.Owner, piece.Piece, out _ );
var shadows = menu.AddMenu( "Shadows", ArchShadows.Glyph( showing ) );
shadows.AddOption( ArchParts.FollowingShadows( tool.Plan, tool.Kit, tool.LayerTree, piece.Owner, piece.Piece ),
"settings", () => Cast( tool, null ) );
shadows.AddSeparator();
foreach ( var casts in new[] { true, false } ) {
var captured = casts;
shadows.AddOption( ArchShadows.Describe( captured ), ArchShadows.Glyph( captured ),
() => Cast( tool, captured ) );
}
}
void Cast( ArchTool tool, bool? casts ) {
ArchParts.Record( tool.Plan, piece.Owner, piece.Piece ).Shadows = casts;
tool.Plan.Parts.RemoveAll( record => record is { Collision: null, Shadows: null } );
tool.Affect( ArchLayerGroups.Holding( tool.Plan, piece.Owner )?.Id ?? piece.Owner );
tool.Commit( $"Shadows {piece.Name}" );
}
void Collide( ArchTool tool, ArchCollisionMode? mode ) {
if ( mode is null ) {
tool.Plan.Parts.RemoveAll( record => record.ItemId == piece.Owner && record.Piece == piece.Piece );
} else {
ArchParts.Record( tool.Plan, piece.Owner, piece.Piece ).Collision = mode;
}
tool.Affect( ArchLayerGroups.Holding( tool.Plan, piece.Owner )?.Id ?? piece.Owner );
tool.Commit( $"Collisions {piece.Name}" );
}
public override bool OnContextMenu() {
if ( ArchTool.Active is not { } tool ) {
return false;
}
var menu = new ContextMenu( TreeView );
menu.AddOption( tool.PieceHidden( piece.Owner, piece.Piece ) ? "Show" : "Hide",
tool.PieceHidden( piece.Owner, piece.Piece ) ? "visibility" : "visibility_off",
() => tool.TogglePieceHidden( piece.Owner, piece.Piece ) );
Collisions( menu, tool );
Shadows( menu, tool );
menu.AddSeparator();
menu.AddOption( "Frame", "filter_center_focus", OnActivated );
menu.OpenAtCursor();
return true;
}
}