A Blazor-style UI panel for the game's home page. Renders the main menu (PLAY, GARAGE, SESSIONS, OPTIONS, QUIT), handles keyboard/controller navigation, visual selection, and activates corresponding actions like navigation, showing server list, settings modal, and quitting the game.
@using Sandbox;
@using Sandbox.UI;
@using Sandbox.UI.Navigation;
@using Microsoft.AspNetCore.Components;
@namespace Machines.UI
@inherits Panel
@attribute [Route( "/" )]
<root class="home-page @(Input.UsingController ? "controller" : "mouse")">
<div class="hero">
<div class="hero-inner">
<span class="brand-text">FACEPUNCH PRESENTS</span>
<div class="title">
<label>MINI</label>
<strong>MOTORS</strong>
</div>
</div>
</div>
<div class="menu">
<a href="/play" class="menu-item primary @Sel( 0 )" onmouseover=@(() => Select( 0 ))>
<span class="menu-label">PLAY</span>
@if ( _selectedIndex == 0 )
{
<InputHint Action="MenuSelect" class="menu-key-glyph" />
}
</a>
<a href="/customize" class="menu-item @Sel( 1 )" onmouseover=@(() => Select( 1 ))>
<span class="menu-label">GARAGE</span>
@if ( _selectedIndex == 1 )
{
<InputHint Action="MenuSelect" Dark=@true class="menu-key-glyph" />
}
</a>
<div class="menu-item @Sel( 2 )" onmouseover=@(() => Select( 2 )) onclick=@Sessions>
<span class="menu-label">SESSIONS</span>
@if ( _selectedIndex == 2 )
{
<InputHint Action="MenuSelect" Dark=@true class="menu-key-glyph" />
}
</div>
<div class="menu-item @Sel( 3 )" onmouseover=@(() => Select( 3 )) onclick=@Options>
<span class="menu-label">OPTIONS</span>
@if ( _selectedIndex == 3 )
{
<InputHint Action="MenuSelect" Dark=@true class="menu-key-glyph" />
}
</div>
<div class="menu-item @Sel( 4 )" onmouseover=@(() => Select( 4 )) onclick=@Quit>
<span class="menu-label">QUIT</span>
@if ( _selectedIndex == 4 )
{
<InputHint Action="MenuSelect" Dark=@true class="menu-key-glyph" />
}
</div>
</div>
<div class="revision">
<RevisionCard />
</div>
<div class="footer">
<div class="hint">
<InputHint Action="MenuUp" class="hint-glyph" />
<InputHint Action="MenuDown" class="hint-glyph" />
<span class="hint-label">NAVIGATE</span>
</div>
<div class="hint">
<InputHint Action="MenuSelect" class="hint-glyph" />
<span class="hint-label">SELECT</span>
</div>
</div>
</root>
@code
{
private const int ItemCount = 5;
private int _selectedIndex;
private string Sel( int index ) => _selectedIndex == index ? "selected" : "";
private void Select( int index )
{
// Mouse hover only applies when not on a controller.
if ( Input.UsingController )
return;
_selectedIndex = index;
}
public override void Tick()
{
base.Tick();
// Only handle input on this page.
if ( this.GetNavigator()?.CurrentUrl != "/home" )
return;
if ( Input.Pressed( "MenuUp" ) )
Move( -1 );
else if ( Input.Pressed( "MenuDown" ) )
Move( +1 );
if ( Input.Pressed( "MenuSelect" ) )
Activate( _selectedIndex );
}
private void Move( int direction )
{
_selectedIndex = (_selectedIndex + direction + ItemCount) % ItemCount;
if ( Input.UsingController )
{
Sound.Play( "element_switch" );
}
}
private void Activate( int index )
{
switch ( index )
{
case 0:
this.Navigate( "/play" );
// Consume so it doesn't bleed into the map selector's ready-up.
Input.Clear( "MenuSelect" );
break;
case 1:
this.Navigate( "/customize" );
Input.Clear( "MenuSelect" );
break;
case 2:
Sessions();
break;
case 3:
Options();
break;
case 4:
Quit();
break;
}
}
private void Sessions()
{
Game.Overlay.ShowServerList( new Sandbox.Modals.ServerListConfig()
{
GamePackageFilter = Game.Ident,
});
}
private void Options()
{
Game.Overlay.ShowSettingsModal();
}
private void Quit()
{
Game.Close();
}
protected override int BuildHash() => System.HashCode.Combine( _selectedIndex, Input.UsingController );
}