First commit for private source control. Older commits available on Github.
This commit is contained in:
205
Assets/Scripts/Game/Cinematics/SplashScreens.cs
Normal file
205
Assets/Scripts/Game/Cinematics/SplashScreens.cs
Normal file
@@ -0,0 +1,205 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using BriarQueen.Framework.Services.Game;
|
||||
using BriarQueen.Game.Cinematics.Data;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using NaughtyAttributes;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
using VContainer;
|
||||
|
||||
namespace BriarQueen.Game.Cinematics
|
||||
{
|
||||
public class SplashScreens : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
[ReorderableList]
|
||||
private List<CinematicPanel> _splashScreens = new();
|
||||
|
||||
[SerializeField]
|
||||
private Image _activeSplashScreen;
|
||||
|
||||
[Header("Playback")]
|
||||
[Tooltip("Small fade for polish. Set to 0 for hard cuts.")]
|
||||
[SerializeField]
|
||||
private float _fadeDuration = 0.15f;
|
||||
|
||||
[SerializeField]
|
||||
private bool _skipInvalidPanels = true;
|
||||
|
||||
private CancellationTokenSource _cts;
|
||||
private GameService _gameService;
|
||||
private bool _isPlaying;
|
||||
|
||||
[Inject]
|
||||
public void Construct(GameService gameService)
|
||||
{
|
||||
_gameService = gameService;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
public void Play()
|
||||
{
|
||||
if (_isPlaying)
|
||||
return;
|
||||
|
||||
Debug.Log("[SplashScreens] Playing splash screens.");
|
||||
|
||||
_isPlaying = true;
|
||||
_cts?.Dispose();
|
||||
_cts = new CancellationTokenSource();
|
||||
|
||||
RunSequence(_cts.Token).Forget();
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
if (!_isPlaying)
|
||||
return;
|
||||
|
||||
_isPlaying = false;
|
||||
|
||||
try
|
||||
{
|
||||
_cts?.Cancel();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
finally
|
||||
{
|
||||
_cts?.Dispose();
|
||||
_cts = null;
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTaskVoid RunSequence(CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
Debug.Log("[SplashScreens] Splash screen sequence started.");
|
||||
|
||||
if (_activeSplashScreen == null)
|
||||
{
|
||||
Debug.LogWarning("[SplashScreens] Active splash Image is not assigned.");
|
||||
await EndSplashScreens();
|
||||
return;
|
||||
}
|
||||
|
||||
var cg = _activeSplashScreen.GetComponent<CanvasGroup>();
|
||||
if (cg == null)
|
||||
cg = _activeSplashScreen.gameObject.AddComponent<CanvasGroup>();
|
||||
|
||||
cg.alpha = 0f;
|
||||
_activeSplashScreen.enabled = true;
|
||||
|
||||
if (_splashScreens == null || _splashScreens.Count == 0)
|
||||
{
|
||||
Debug.LogWarning("[SplashScreens] No splash panels configured.");
|
||||
await EndSplashScreens();
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < _splashScreens.Count; i++)
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
var panel = _splashScreens[i];
|
||||
if (panel == null || panel.CinematicImage == null)
|
||||
{
|
||||
if (_skipInvalidPanels)
|
||||
continue;
|
||||
|
||||
Debug.LogWarning($"[SplashScreens] Splash panel at index {i} is null or missing image.");
|
||||
continue;
|
||||
}
|
||||
|
||||
_activeSplashScreen.sprite = panel.CinematicImage;
|
||||
|
||||
if (_fadeDuration > 0f)
|
||||
await FadeTo(cg, 1f, _fadeDuration, token);
|
||||
else
|
||||
cg.alpha = 1f;
|
||||
|
||||
var hold = Mathf.Max(0f, panel.DisplayTime);
|
||||
if (hold > 0f)
|
||||
await UniTask.Delay(TimeSpan.FromSeconds(hold), cancellationToken: token);
|
||||
|
||||
if (_fadeDuration > 0f)
|
||||
await FadeTo(cg, 0f, _fadeDuration, token);
|
||||
else
|
||||
cg.alpha = 0f;
|
||||
}
|
||||
|
||||
await EndSplashScreens();
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[SplashScreens] Sequence failed: {ex}");
|
||||
|
||||
try
|
||||
{
|
||||
await EndSplashScreens();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isPlaying = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTask FadeTo(CanvasGroup cg, float target, float duration, CancellationToken token)
|
||||
{
|
||||
var start = cg.alpha;
|
||||
|
||||
if (Mathf.Approximately(start, target))
|
||||
{
|
||||
cg.alpha = target;
|
||||
return;
|
||||
}
|
||||
|
||||
var t = 0f;
|
||||
while (t < duration)
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
t += Time.deltaTime;
|
||||
var p = Mathf.Clamp01(t / duration);
|
||||
cg.alpha = Mathf.Lerp(start, target, p);
|
||||
|
||||
await UniTask.NextFrame(token);
|
||||
}
|
||||
|
||||
cg.alpha = target;
|
||||
}
|
||||
|
||||
private async UniTask EndSplashScreens()
|
||||
{
|
||||
if (_gameService != null)
|
||||
{
|
||||
await _gameService.LoadUIAndMainMenuScene();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("[SplashScreens] GameService is null; cannot load UI/MainMenu scene.");
|
||||
}
|
||||
|
||||
const string bootstrapSceneName = "00_Bootstrap";
|
||||
var scene = SceneManager.GetSceneByName(bootstrapSceneName);
|
||||
if (scene.IsValid() && scene.isLoaded)
|
||||
await SceneManager.UnloadSceneAsync(bootstrapSceneName);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user