using UnityEngine; using TMPro; using DG.Tweening; namespace Ashwild.UI { /// /// A single line in the player presence feed (e.g. "Alex a rejoint la partie"). Fades itself in, /// holds, fades out, then self-destructs — the parent holder's layout group handles stacking, so /// this only ever animates its own alpha and never fights the layout for position. /// [DisallowMultipleComponent] [RequireComponent(typeof(CanvasGroup))] public class PresenceFeedEntry : MonoBehaviour { #region Serialized Fields [Header("References")] [Tooltip("The label that shows the join/leave message.")] [SerializeField] private TMP_Text label; [Tooltip("Faded in and out over the entry's lifetime. Auto-fetched from this object if left empty.")] [SerializeField] private CanvasGroup canvasGroup; #endregion #region State /// /// The full lifecycle tween (fade in → hold → fade out → destroy), killed on teardown. /// private Sequence lifecycle; #endregion #region Unity Lifecycle /// /// Caches the CanvasGroup when it wasn't wired in the inspector. /// private void Awake() { if (canvasGroup == null) canvasGroup = GetComponent(); } /// /// Kills the lifecycle tween so it never targets a destroyed object. /// private void OnDestroy() { lifecycle?.Kill(); } #endregion #region Public API /// /// Fills in the message and colour, then runs the fade-in → hold → fade-out → destroy sequence. /// Safe to call once right after instantiation. /// public void Play(string message, Color color, float holdDuration, float fadeInDuration, float fadeOutDuration) { if (label != null) { label.text = message; label.color = color; } canvasGroup.alpha = 0f; lifecycle = DOTween.Sequence(); lifecycle.Append(canvasGroup.DOFade(1f, fadeInDuration).SetEase(Ease.OutQuad)); lifecycle.AppendInterval(holdDuration); lifecycle.Append(canvasGroup.DOFade(0f, fadeOutDuration).SetEase(Ease.InQuad)); lifecycle.OnComplete(() => Destroy(gameObject)); } #endregion } }