UI renderer for the admin menu using an ImGui context. It manages ImGui styling, input capture, per-frame drawing and submits ImGui draw lists to the rendering CommandList tied to the current scene camera, and disposes resources when closed.
using Sandbox;
using Sandbox.Rendering;
using SboxSuperuser.Engine.Admin;
using SboxSuperuser.Engine.Vendor.ImGui;
namespace SboxSuperuser.UI;
internal sealed partial class AdminMenuRenderer : IDisposable
{
private readonly Scene _scene;
private readonly ImGuiContext _context = new();
private readonly CommandList _commands = new( "Superuser admin menu" ) { Flags = CommandList.Flag.Hud };
private readonly AdminInputPanel _input;
private readonly MouseVisibility _previousMouse;
private CameraComponent _camera;
internal AdminMenuModel Model { get; } = new( Superuser.RequestAdminQuery, Superuser.RequestAdminAction );
internal bool Open = true;
internal AdminMenuRenderer( Scene scene )
{
_scene = scene;
_previousMouse = Mouse.Visibility;
_input = new AdminInputPanel( _context.IO ) { Close = () => Open = false };
_context.Style.WindowRounding = 8;
_context.Style.FrameRounding = 4;
_context.Style.WindowPadding = new Vector2( 18, 18 );
_context.Style.ItemSpacing = new Vector2( 10, 9 );
_context.Style.Colors[ (int)ImGuiCol.WindowBg ] = new Vector4( 0.035f, 0.06f, 0.1f, 0.98f );
_context.Style.Colors[ (int)ImGuiCol.TitleBgActive ] = new Vector4( 0.06f, 0.12f, 0.22f, 1 );
_context.Style.Colors[ (int)ImGuiCol.Button ] = new Vector4( 0.10f, 0.22f, 0.38f, 1 );
_context.Style.Colors[ (int)ImGuiCol.ButtonHovered ] = new Vector4( 0.16f, 0.35f, 0.58f, 1 );
}
internal void CaptureInput()
{
Mouse.Visibility = MouseVisibility.Visible;
Input.ClearActions();
Input.AnalogMove = 0;
Input.AnalogLook = default;
if ( Input.EscapePressed )
{
Input.EscapePressed = false;
Open = false;
}
}
internal void Draw()
{
Model.Tick( DateTimeOffset.UtcNow );
var previous = ImGuiContext.Current;
ImGuiContext.Current = _context;
try
{
_context.IO.DeltaTime = MathF.Max( RealTime.Delta, 0.0001f );
_context.IO.MousePos = Mouse.Position;
ImGui.NewFrame();
DrawWindow();
var lists = ImGui.Render();
if ( _camera != _scene.Camera )
{
if ( _camera.IsValid() ) _camera.RemoveCommandList( _commands );
_camera = _scene.Camera;
if ( _camera.IsValid() ) _camera.AddCommandList( _commands, Sandbox.Rendering.Stage.AfterUI, 10000 );
}
_commands.Reset();
using var painter = Painter.Begin( _commands );
foreach ( var list in lists ) list.Render( painter );
}
finally { ImGuiContext.Current = previous; }
}
public void Dispose()
{
_input.Delete();
_commands.Reset();
if ( _camera.IsValid() ) _camera.RemoveCommandList( _commands );
if ( Mouse.Visibility == MouseVisibility.Visible ) Mouse.Visibility = _previousMouse;
ImGuiHost.ClipboardCopyProvider = null;
if ( ReferenceEquals( ImGuiContext.Current, _context ) ) ImGuiContext.Current = null;
}
}