Files
A-Fairytale-Gone-Bad-Briar-…/Assets/Scripts/UI/HUD/HUDContainer.cs

282 lines
8.1 KiB
C#

using System;
using System.Threading;
using BriarQueen.Framework.Managers.UI;
using BriarQueen.Framework.Managers.UI.Base;
using Cysharp.Threading.Tasks;
using PrimeTween;
using UnityEngine;
using UnityEngine.UI;
using VContainer;
namespace BriarQueen.UI.HUD
{
/// <summary>
/// Minimal HUD holder:
/// - Registers itself with UIManager
/// - Handles HUD visibility (alpha tween only)
/// </summary>
public class HUDContainer : MonoBehaviour, IHud
{
private const float DISPLAY_TIME = 4f;
[Header("UI")]
[SerializeField]
private CursorTooltip _cursorTooltip;
[SerializeField]
private InteractTextUI _interactText;
[Header("Inventory")]
[SerializeField]
private InventoryBar _inventoryBar;
[Header("Components")]
[SerializeField]
private CanvasGroup _mainCanvasGroup;
[SerializeField]
private CanvasGroup _interactTextCanvasGroup;
[Header("Tweens")]
[SerializeField]
private TweenSettings _tweenSettings = new()
{
duration = 0.2f,
ease = Ease.InOutSine,
useUnscaledTime = true
};
[SerializeField]
private GraphicRaycaster _graphicRaycaster;
public GraphicRaycaster Raycaster => _graphicRaycaster;
private CancellationTokenSource _cancellationTokenSource;
private Sequence _hudSequence;
private CancellationTokenSource _interactCancellationTokenSource;
private Sequence _interactErrorSequence;
private UIManager _uiManager;
public CursorTooltip CursorTooltip => _cursorTooltip;
public InventoryBar InventoryBar => _inventoryBar;
private void Awake()
{
if (_mainCanvasGroup != null)
{
_mainCanvasGroup.alpha = 1f;
_mainCanvasGroup.interactable = true;
_mainCanvasGroup.blocksRaycasts = true;
}
if (_interactTextCanvasGroup != null)
{
_interactTextCanvasGroup.alpha = 0f;
_interactTextCanvasGroup.blocksRaycasts = false;
_interactTextCanvasGroup.interactable = false;
}
}
private void OnDestroy()
{
StopTween();
StopInteractErrorTween();
}
[Inject]
public void Construct(UIManager uiManager)
{
_uiManager = uiManager;
}
// --------------------
// Visibility
// --------------------
public async UniTask DisplayInteractText(string interactText)
{
if (_interactTextCanvasGroup == null || _interactText == null)
return;
// Cancel any in-flight error display and restart from current alpha.
StopInteractErrorTween();
// Set text immediately.
var text = interactText ?? string.Empty;
_interactText.SetText(text);
_interactCancellationTokenSource = new CancellationTokenSource();
var token = _interactCancellationTokenSource.Token;
// Make sure it can show (but don't let it steal clicks).
_interactTextCanvasGroup.blocksRaycasts = false;
_interactTextCanvasGroup.interactable = false;
var fadeIn = new TweenSettings<float>
{
startValue = _interactTextCanvasGroup.alpha,
endValue = 1f,
settings = _tweenSettings
};
var fadeOut = new TweenSettings<float>
{
startValue = 1f,
endValue = 0f,
settings = _tweenSettings
};
try
{
// Fade in
_interactErrorSequence = Sequence.Create(useUnscaledTime: true)
.Group(Tween.Alpha(_interactTextCanvasGroup, fadeIn));
await _interactErrorSequence.ToUniTask(cancellationToken: token);
_interactTextCanvasGroup.alpha = 1f;
// Hold
if (DISPLAY_TIME > 0f)
await UniTask.Delay(TimeSpan.FromSeconds(DISPLAY_TIME), DelayType.UnscaledDeltaTime,
cancellationToken: token);
// Fade out
_interactErrorSequence = Sequence.Create(useUnscaledTime: true)
.Group(Tween.Alpha(_interactTextCanvasGroup, fadeOut));
await _interactErrorSequence.ToUniTask(cancellationToken: token);
_interactTextCanvasGroup.alpha = 0f;
}
catch (OperationCanceledException)
{
// If interrupted by a newer DisplayError call or destroy, just stop cleanly.
}
finally
{
if (_interactCancellationTokenSource != null)
{
_interactCancellationTokenSource.Dispose();
_interactCancellationTokenSource = null;
}
_interactErrorSequence = default;
}
}
public async UniTask Show()
{
if (_mainCanvasGroup == null)
return;
StopTween();
_cancellationTokenSource = new CancellationTokenSource();
_mainCanvasGroup.blocksRaycasts = true;
_mainCanvasGroup.interactable = true;
var alphaTween = new TweenSettings<float>
{
startValue = _mainCanvasGroup.alpha,
endValue = 1f,
settings = _tweenSettings
};
_hudSequence = Sequence.Create(useUnscaledTime: true)
.Group(Tween.Alpha(_mainCanvasGroup, alphaTween));
try
{
await _hudSequence.ToUniTask(cancellationToken: _cancellationTokenSource.Token);
}
catch (OperationCanceledException)
{
// interrupted by Hide / destroy — safe to ignore
}
_mainCanvasGroup.alpha = 1f;
}
public async UniTask Hide()
{
if (_mainCanvasGroup == null)
return;
StopTween();
_cancellationTokenSource = new CancellationTokenSource();
_mainCanvasGroup.blocksRaycasts = false;
_mainCanvasGroup.interactable = false;
var alphaTween = new TweenSettings<float>
{
startValue = _mainCanvasGroup.alpha,
endValue = 0f,
settings = _tweenSettings
};
_hudSequence = Sequence.Create(useUnscaledTime: true)
.Group(Tween.Alpha(_mainCanvasGroup, alphaTween));
try
{
await _hudSequence.ToUniTask(cancellationToken: _cancellationTokenSource.Token);
}
catch (OperationCanceledException)
{
// interrupted — safe
}
_mainCanvasGroup.alpha = 0f;
}
private void StopTween()
{
if (_hudSequence.isAlive)
_hudSequence.Stop();
_hudSequence = default;
if (_cancellationTokenSource != null)
{
_cancellationTokenSource.Cancel();
_cancellationTokenSource.Dispose();
_cancellationTokenSource = null;
}
}
private void StopInteractErrorTween()
{
if (_interactErrorSequence.isAlive)
_interactErrorSequence.Stop();
_interactErrorSequence = default;
if (_interactCancellationTokenSource != null)
{
try
{
_interactCancellationTokenSource.Cancel();
}
catch
{
}
_interactCancellationTokenSource.Dispose();
_interactCancellationTokenSource = null;
}
}
private void OnMapClicked()
{
// Placeholder for later:
// - open map window
// - toggle map overlay
}
}
}