UI/ScreenFadeHud.razor

A UI Razor component that draws a fullscreen black fade when ScreenFade.Active is true. It includes EnsureHost to create a GameObject host and a ScreenPanel with ZIndex 110, updates the ScreenFade clock each frame, formats opacity for CSS, and provides a BuildHash for repaint optimization.

Native Interop
@using Sandbox;
@using Sandbox.UI;
@using NZombies;
@inherits PanelComponent

@*
    SCREEN FADE — black over everything, fading (`ScreenFade`): the spawn-in's fade to black as the countdown ends, and its slow
    fade up into the game.

    ⛔ ITS OWN SCREEN PANEL, ZIndex 110 — above the lobby's and the dev menu's (100). The fade to black happens while the lobby
    is still up, and a black drawn under it would hide nothing. Built from code, as the perf HUD's is (`EnsureHost`): the scene
    file is never rewritten, and a code-built host is built again when a hotload takes it.
*@

<root>
    @if ( ScreenFade.Active )
    {
        <div class="black" style="opacity: @(Css( ScreenFade.Opacity ))"></div>
    }
</root>

@code
{
    static GameObject _host;

    /// <summary>
    /// Make sure something draws the fade: a screen panel of its own, over every other. Called every frame a fade is on, from
    /// the one update that runs in every mode (`LobbyMenu.OnUpdate`); does nothing once the host exists.
    /// </summary>
    public static void EnsureHost()
    {
        if ( _host.IsValid() ) return;

        var scene = Game.ActiveScene;
        if ( !scene.IsValid() ) return;

        _host = scene.CreateObject();
        _host.Name = "Screen Fade";
        _host.Flags |= GameObjectFlags.NotSaved;

        var screen = _host.Components.Create<ScreenPanel>();
        screen.ZIndex = 110;

        _host.Components.Create<ScreenFadeHud>();
    }

    /// <summary>The fade's own clock: the spawn-in's tremor fires from here on its beat (`ScreenFade.Tick`).</summary>
    protected override void OnUpdate()
    {
        ScreenFade.Tick();
    }

    /// <summary>⚠️ A POINT FOR THE DECIMAL, whatever the machine's language — this goes into a style.</summary>
    static string Css( float v ) => v.ToString( "0.###", System.Globalization.CultureInfo.InvariantCulture );

    /// <summary>⚠️ REBUILDS IN 60 STEPS OF OPACITY — smooth over a three-second fade, and nothing at all once it is clear.</summary>
    protected override int BuildHash() => System.HashCode.Combine( ScreenFade.Active, (int)(ScreenFade.Opacity * 60f) );
}