A UI PanelComponent for a transition overlay that draws a centered square 'wipe' using viewport-height units. It exposes a Cover float (0..1) and computes inline style for the square size; it overrides BuildHash to quantise and include visibility to force rebuilds correctly.
@using System.Globalization
@using Sandbox
@using Sandbox.UI
@inherits PanelComponent
@namespace BlockParty
@attribute [StyleSheet( "TransitionOverlay.razor.scss" )]
@* Stage-transition "wipe": a centred square (original Swatches.Fade colour) that GameManager
grows to cover the view when leaving a stage and shrinks to reveal the next one. Port of the
original BaseStage FadeIn/FadeOut rects. Sized in viewport-height units so it stays square and
exactly covers the 240x240 play region (full screen height) regardless of aspect ratio. *@
<root>
@if ( Cover > 0.0001f )
{
<div class="square" style="@SquareStyle()"></div>
}
</root>
@code
{
/// <summary>How much of the view the square covers, 0 (nothing) .. 1 (full play region).</summary>
public float Cover { get; set; }
private string SquareStyle()
{
// vh keeps the square sized to the viewport HEIGHT on both axes, so it stays square and
// covers the full-height 240x240 play area (the pillarbox stays the camera clear colour).
string v = ( Cover * 100f ).ToString( "0.###", CultureInfo.InvariantCulture );
return $"width: {v}vh; height: {v}vh;";
}
// Rebuild as the square scales; quantised so we don't rebuild on sub-pixel changes.
// IMPORTANT: also hash the visibility flag (Cover > 0.0001f). Without it, a Cover in
// (0.0001, 0.0025) quantises to the SAME 0 bucket as Cover == 0, yet the markup still draws a
// ~1px square there. When a reveal's last sub-frame lands in that window and the next frame
// snaps Cover to 0, the hash wouldn't change, so the panel never rebuilds and the tiny dark
// square stays stuck dead-centre until the panel is recreated. Hashing visibility guarantees the
// final "draw -> hide" step always rebuilds and clears it.
protected override int BuildHash() => System.HashCode.Combine( (int)(Cover * 400f), Cover > 0.0001f );
}