DiamondPanel.Transition.cs
using System;
using Sandbox;
namespace Diamonds;
public sealed partial class DiamondPanel
{
const float TransitionFadeOut = 0.1f, TransitionFadeIn = 0.25f;
// Hotload leaves new fields at their defaults, so idle must be the default state.
bool transitionActive, transitionSwitched, transitionToGame;
float transitionTime;
/// <summary>A title/game switch is fading the old screen out or the new one in.</summary>
public bool Transitioning => transitionActive;
/// <summary>The old screen is still fading out; the switch has not happened yet.</summary>
public bool TransitionPending => transitionActive && !transitionSwitched;
/// <summary>The pending or current switch leads into a game rather than the title.</summary>
public bool TransitionToGame => transitionToGame;
/// <summary>Fade to black, then switch between the title and a new game and fade back in.</summary>
void BeginTransition( bool toGame )
{
if ( TransitionPending ) return;
// Interrupting a fade-in continues from its current darkness rather than popping.
transitionTime = transitionActive ? TransitionDarkness * TransitionFadeOut : 0;
transitionActive = true;
transitionSwitched = false;
transitionToGame = toGame;
}
public void CancelTransition() => transitionActive = false;
public void UpdateTransition( float delta )
{
if ( !transitionActive ) return;
delta = MathF.Max( 0, delta );
if ( !transitionSwitched )
{
transitionTime += delta;
if ( transitionTime < TransitionFadeOut ) return;
// Start the fade-in fully black; the switch frame's own cost must not skip it.
transitionTime = TransitionFadeOut;
transitionSwitched = true;
if ( transitionToGame )
{
// A completed restart hold fades out under the black; the new game starts without it.
ClearRestartHold();
TitleScreen = false;
PlayRequested?.Invoke();
}
else LeaveRequested?.Invoke();
return;
}
// Cap hitch frames (such as the first gameplay frame) so the fade-in stays visible.
transitionTime += MathF.Min( delta, 1f / 30 );
if ( transitionTime >= TransitionFadeOut + TransitionFadeIn ) transitionActive = false;
}
float TransitionDarkness => !transitionActive ? 0
: !transitionSwitched ? Math.Clamp( transitionTime / TransitionFadeOut, 0, 1 )
: Math.Clamp( 1 - (transitionTime - TransitionFadeOut) / TransitionFadeIn, 0, 1 );
void DrawTransition( Painter p )
{
float darkness = TransitionDarkness;
if ( darkness <= 0 ) return;
p.Fill = Color.Black.WithAlpha( darkness );
p.Stroke = Stroke.None;
p.Rect( p.Bounds );
}
}