A Razor UI panel for the Character Editor escape menu. It shows resume/quit/navigation buttons, an experimental tab, and a confirmation prompt when there are unsaved edits before navigating away.
@using System
@using Sandbox
@using Sandbox.UI
@namespace CharacterEditor
@inherits Panel
<root>
@if(IsOpen)
{
<div class="menu-shade"><div class="menu-card">
@if(IsConfirming)
{
<h2>Discard unsaved edits?</h2><p>Your saved characters will stay as they are.</p>
<button onclick=@CancelNavigation>Keep editing</button>
<button class="primary" onclick=@ConfirmNavigation>Discard edits and continue</button>
}
else
{
<div class="menu-title">Character Editor</div>
<div class="menu-tabs"><button class=@(!Experimental?"chosen":"") onclick=@(()=>Experimental=false)>Menu</button>@if(EnableExperiments){<button class=@(Experimental?"chosen":"") onclick=@(()=>Experimental=true)>Experimental</button>}</div>
@if(Experimental && EnableExperiments)
{
<h2>Experiments</h2><p>Development tools and research. These do not create saved characters.</p>
<button onclick=@(()=>RequestNavigation(OpenLab))>Face lab</button>
}
else
{
<button class="primary" onclick=@Close>Resume</button>
<button onclick=@(()=>RequestNavigation(MainMenu))>Main menu</button>
<button onclick=@(()=>RequestNavigation(()=>Game.Close()))>Quit to s&box</button>
}
<div class="menu-hint">Escape to return</div>
}
</div></div>
}
</root>
@code {
public Action MainMenu { get; set; }
public Action OpenLab { get; set; }
public Func<bool> HasUnsavedEdits { get; set; }
public bool EnableExperiments { get; set; }
public bool IsOpen { get; private set; }
public bool IsConfirming => pending is not null;
bool Experimental;
Action pending;
public void Toggle()
{
if (IsConfirming)
CancelNavigation();
else if (IsOpen)
Close();
else
{
IsOpen = true;
Experimental = false;
}
}
public void Close()
{
IsOpen = false;
Experimental = false;
pending = null;
}
public void RequestNavigation(Action action)
{
if (action is null)
return;
if (HasUnsavedEdits?.Invoke() == true)
pending = action;
else
{
Close();
action();
}
}
public void CancelNavigation()
{
pending = null;
Close();
}
public void ConfirmNavigation()
{
var action = pending;
Close();
action?.Invoke();
}
protected override int BuildHash() => HashCode.Combine(IsOpen, Experimental, IsConfirming, EnableExperiments);
}