A Blazor-style UI panel (SpectatorPanel) for the game's spectator HUD. It displays the currently selected player's display name, left/right navigation hints when multiple players exist, and adjusts layout when paused. It also handles input to cycle the spectated player and contributes a UI hash for redraw optimization.
@namespace Sandbox
@using Sandbox;
@using Sandbox.UI;
@using System;
@inherits Panel
@{
var player = Manager.Instance.SelectedPlayer;
var displayName = player.IsValid()
? player.Network?.Owner?.DisplayName ?? ""
: "";
var multiPlayer = Manager.Instance.Players.Count > 1;
}
<root>
<div class="top bar" style="padding-top: @(Manager.Instance.IsPaused ? 232 : 32)px;">
<div class="header">
@if ( multiPlayer )
{
<div class="nav-hint">
<label class="arrow-label">←</label>
<InputHint class="cycle-hint" Button="SpectateLeft" />
</div>
}
<label class="spectating-label">Spectating</label>
<label class="player-name">@displayName</label>
@if ( multiPlayer )
{
<div class="nav-hint">
<InputHint class="cycle-hint" Button="SpectateRight" />
<label class="arrow-label">→</label>
</div>
}
</div>
@* <label class="subheader">You will join the next game if there are enough slots</label> *@
</div>
<div class="filler">
</div>
</root>
@code
{
void CyclePlayer( int direction )
{
var players = Manager.Instance.Players;
if ( players.Count <= 1 ) return;
var current = Manager.Instance.SelectedPlayer;
var index = current.IsValid() ? players.IndexOf( current ) : 0;
index = (index + direction + players.Count) % players.Count;
Manager.Instance.SelectedPlayer = players[index];
}
public override void Tick()
{
base.Tick();
if ( !Manager.Instance.IsSpectator ) return;
if ( Manager.Instance.Players.Count <= 1 ) return;
var pressedLeft = Input.Pressed( "SpectateLeft" ) || Input.Keyboard.Pressed( "left" );
var pressedRight = Input.Pressed( "SpectateRight" ) || Input.Keyboard.Pressed( "right" );
if ( pressedLeft ) CyclePlayer( -1 );
else if ( pressedRight ) CyclePlayer( 1 );
}
protected override int BuildHash()
{
return System.HashCode.Combine(
Manager.Instance.IsPaused,
Manager.Instance.SelectedPlayer,
Manager.Instance.SelectedPlayer?.Network?.Owner?.DisplayName,
Manager.Instance.Players.Count,
Input.UsingController
);
}
}