First commit for private source control. Older commits available on Github.
This commit is contained in:
181
Assets/Scripts/UI/ScreenFader.cs
Normal file
181
Assets/Scripts/UI/ScreenFader.cs
Normal file
@@ -0,0 +1,181 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using BriarQueen.Framework.Coordinators.Events;
|
||||
using BriarQueen.Framework.Events.UI;
|
||||
using BriarQueen.Framework.Managers.UI.Base;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using PrimeTween;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using VContainer;
|
||||
|
||||
namespace BriarQueen.UI
|
||||
{
|
||||
public class ScreenFader : MonoBehaviour, IScreenFader
|
||||
{
|
||||
private const float ALPHA_EPSILON = 0.001f;
|
||||
|
||||
[Header("UI Elements")]
|
||||
[SerializeField]
|
||||
private CanvasGroup _canvasGroup;
|
||||
|
||||
[Tooltip("Used for black / solid-color fades.")]
|
||||
[SerializeField]
|
||||
private Image _solidImage;
|
||||
|
||||
private Sequence _currentFadeSequence;
|
||||
private EventCoordinator _eventCoordinator;
|
||||
private CancellationTokenSource _fadeCts;
|
||||
|
||||
public bool IsModal => true;
|
||||
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (_canvasGroup == null)
|
||||
Debug.LogError($"{nameof(ScreenFader)} on {name} is missing a CanvasGroup reference.", this);
|
||||
|
||||
SetInteractionState(_canvasGroup != null && _canvasGroup.alpha > ALPHA_EPSILON);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
CancelAndDisposeFadeToken();
|
||||
StopCurrentSequence();
|
||||
}
|
||||
|
||||
// Window Stubs - Fader is Non-Interactive
|
||||
public async UniTask Show()
|
||||
{
|
||||
await FadeToAsync( 1f);
|
||||
}
|
||||
|
||||
public async UniTask Hide()
|
||||
{
|
||||
await FadeFromAsync(1f);
|
||||
}
|
||||
|
||||
[Inject]
|
||||
public void Construct(EventCoordinator eventCoordinator)
|
||||
{
|
||||
Debug.Log("ScreenFader constructed");
|
||||
_eventCoordinator = eventCoordinator;
|
||||
}
|
||||
|
||||
public async UniTask FadeToAsync(float duration)
|
||||
{
|
||||
if (_canvasGroup == null)
|
||||
return;
|
||||
|
||||
_solidImage.color = Color.black;
|
||||
|
||||
BeginNewFade();
|
||||
|
||||
gameObject.SetActive(true);
|
||||
SetInteractionState(true);
|
||||
|
||||
await FadeScreen(1f, duration, _fadeCts.Token);
|
||||
}
|
||||
|
||||
public async UniTask FadeFromAsync(float duration)
|
||||
{
|
||||
if (_canvasGroup == null) return;
|
||||
|
||||
BeginNewFade();
|
||||
|
||||
await FadeScreen(0f, duration, _fadeCts.Token);
|
||||
|
||||
if (!_fadeCts.IsCancellationRequested)
|
||||
{
|
||||
_canvasGroup.alpha = 0f;
|
||||
SetInteractionState(false);
|
||||
}
|
||||
}
|
||||
|
||||
public UniTask FadeToAsync(FadeStyle style, System.Drawing.Color tint, float duration)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private void ApplyTint(FadeStyle style, Color tint)
|
||||
{
|
||||
if (_solidImage != null)
|
||||
{
|
||||
_solidImage.enabled = true;
|
||||
_solidImage.color = Color.black;
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTask FadeScreen(float targetAlpha, float duration, CancellationToken token)
|
||||
{
|
||||
targetAlpha = Mathf.Clamp01(targetAlpha);
|
||||
duration = Mathf.Max(0f, duration);
|
||||
|
||||
var currentAlpha = _canvasGroup.alpha;
|
||||
|
||||
if (Mathf.Abs(currentAlpha - targetAlpha) <= ALPHA_EPSILON)
|
||||
{
|
||||
_canvasGroup.alpha = targetAlpha;
|
||||
SetInteractionState(targetAlpha > ALPHA_EPSILON);
|
||||
return;
|
||||
}
|
||||
|
||||
StopCurrentSequence();
|
||||
|
||||
if (duration <= 0f)
|
||||
{
|
||||
_canvasGroup.alpha = targetAlpha;
|
||||
SetInteractionState(targetAlpha > ALPHA_EPSILON);
|
||||
|
||||
_eventCoordinator?.PublishImmediate(new FadeCompletedEvent());
|
||||
return;
|
||||
}
|
||||
|
||||
_currentFadeSequence = Sequence.Create()
|
||||
.Group(Tween.Alpha(_canvasGroup, targetAlpha, duration, Ease.InOutSine));
|
||||
|
||||
try
|
||||
{
|
||||
await _currentFadeSequence.ToUniTask(cancellationToken: token);
|
||||
|
||||
_canvasGroup.alpha = targetAlpha;
|
||||
SetInteractionState(targetAlpha > ALPHA_EPSILON);
|
||||
|
||||
_eventCoordinator?.PublishImmediate(new FadeCompletedEvent());
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// Another fade interrupted this one. Intentionally ignore completion.
|
||||
}
|
||||
}
|
||||
|
||||
private void BeginNewFade()
|
||||
{
|
||||
CancelAndDisposeFadeToken();
|
||||
StopCurrentSequence();
|
||||
|
||||
_fadeCts = new CancellationTokenSource();
|
||||
}
|
||||
|
||||
private void CancelAndDisposeFadeToken()
|
||||
{
|
||||
if (_fadeCts == null) return;
|
||||
|
||||
if (!_fadeCts.IsCancellationRequested) _fadeCts.Cancel();
|
||||
|
||||
_fadeCts.Dispose();
|
||||
_fadeCts = null;
|
||||
}
|
||||
|
||||
private void StopCurrentSequence()
|
||||
{
|
||||
if (_currentFadeSequence.isAlive) _currentFadeSequence.Stop();
|
||||
}
|
||||
|
||||
private void SetInteractionState(bool isBlocking)
|
||||
{
|
||||
_canvasGroup.interactable = isBlocking;
|
||||
_canvasGroup.blocksRaycasts = isBlocking;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user