Code/UI/SplashScreen.razor

Razor UI component for a splash screen. It shows an optional background image and logo, renders configurable text lines with color/size, plays an optional sound, fades out, then loads a configured SceneFile or destroys itself.

File Access
@using Sandbox;
@using Sandbox.UI;
@using System.Threading.Tasks;
@using System.Collections.Generic;
@using System;
@inherits PanelComponent

<root class="@(IsFadingOut ? "fade-out" : "fade-in")" style="background-image: @(!string.IsNullOrEmpty(BackgroundImage) ? $"url({BackgroundImage})" : "none");">
    
    <div class="content">
        @* Logo Image (.png / .jpg) *@
        @if (!string.IsNullOrEmpty(LogoImage))
        {
            <img class="logo" src="@LogoImage" />
        }
        
        @* Text Lines *@
        @if (TextLines != null && TextLines.Count > 0)
        {
            <div class="text-container">
                @foreach (var line in TextLines)
                {
                    <label style="color: @line.TextColor.Hex; font-size: @(line.FontSize)px;">
                        @line.Text
                    </label>
                }
            </div>
        }
    </div>

</root>

@code {
    // === CUSTOM DATA CLASS FOR TEXT LINES ===
    
    public class SplashTextLine
    {
        [Property, Description("The text to display.")] 
        public string Text { get; set; } = "NEW LINE";

        [Property, Description("Text color for this specific line.")] 
        public Color TextColor { get; set; } = Color.White;

        [Property, Description("Font size for this specific line.")] 
        public float FontSize { get; set; } = 80f;
    }


    // === IMAGE SETTINGS ===
    
    [Property, ImageAssetPath, Group("Images"), Description("Supports .png and .jpg. If empty, the background will be black.")] 
    public string BackgroundImage { get; set; }

    [Property, ImageAssetPath, Group("Images"), Description("Main logo image (.png / .jpg). Appears above the text if both are set.")] 
    public string LogoImage { get; set; }


    // === TEXT SETTINGS ===

    [Property, Group("Text"), Description("Add text lines with individual settings (color, size).")]
    public List<SplashTextLine> TextLines { get; set; } = new();


    // === AUDIO & SCENE SETTINGS ===

    [Property, Group("Audio"), Description("Select a Sound Event (.sound) that contains your .mp3 or .ogg file.")] 
    public SoundEvent SplashSound { get; set; }

    [Property, Group("Scene"), Description("The scene to load after the splash screen finishes.")] 
    public SceneFile NextScene { get; set; }


    // === LOGIC ===
    
    public bool IsFadingOut { get; set; } = false;

    protected override void OnStart()
    {
        base.OnStart();
        
        // Start the asynchronous sequence
        _ = RunSplashSequence();
    }

    private async Task RunSplashSequence()
    {
        // 1. Wait half a second before starting to avoid stuttering during load
        await Task.Delay(500);

        // 2. Play the assigned sound (.mp3 / .ogg via Sound Event)
        if (SplashSound != null)
        {
            Sound.Play(SplashSound);
        }

        // 3. Wait while the logo/text is visible on the screen (3 seconds)
        await Task.Delay(3000);

        // 4. Trigger the fade-out animation
        IsFadingOut = true;
        StateHasChanged(); // Notify the UI to update CSS classes

        // 5. Wait for the fade-out animation to finish (matches the CSS transition time)
        await Task.Delay(2000);

        // 6. Load the next scene
        if (NextScene != null)
        {
            Scene.Load(NextScene);
        }
        else
        {
            Log.Warning("Next Scene is not assigned in the Splash Screen component!");
            GameObject.Destroy(); // Destroy the component if no scene is assigned
        }
    }
}