using System; using DG.Tweening; using UnityEngine; namespace AibisDream.UI { public class TerminalPanelAnimator : MonoBehaviour { [SerializeField] private CanvasGroup canvasGroup; [SerializeField] private RectTransform sweep; [Header("终端风格")] [SerializeField, Range(0f, 1f)] private float visibleAlpha = 0.88f; [SerializeField] private float fadeDuration = 0.06f; [SerializeField] private Ease showEase = Ease.Linear; [SerializeField] private Ease hideEase = Ease.Linear; [SerializeField] private float sweepDuration = 0.08f; private Tween _activeTween; private void Awake() { if (canvasGroup == null) { canvasGroup = GetComponent(); } } /// 淡入完成回调。 /// 在 SetActive 之前执行的内容准备(赋值、布局等)。 public void Show(Action onComplete = null, Action prepare = null) { _activeTween?.Kill(); prepare?.Invoke(); if (canvasGroup != null) { canvasGroup.alpha = 0f; canvasGroup.interactable = false; canvasGroup.blocksRaycasts = false; } PrepareSweep(); gameObject.SetActive(true); Canvas.ForceUpdateCanvases(); if (canvasGroup == null) { onComplete?.Invoke(); return; } var sequence = DOTween.Sequence().SetUpdate(true); sequence.Join(canvasGroup.DOFade(visibleAlpha, fadeDuration).SetEase(showEase)); if (sweep != null) { sequence.Join(sweep.DOAnchorPosX(0f, sweepDuration).SetEase(Ease.Linear)); } sequence.OnComplete(() => { canvasGroup.interactable = true; canvasGroup.blocksRaycasts = true; onComplete?.Invoke(); }); _activeTween = sequence; } public void Hide(Action onComplete = null) { _activeTween?.Kill(); if (canvasGroup == null) { gameObject.SetActive(false); onComplete?.Invoke(); return; } canvasGroup.interactable = false; canvasGroup.blocksRaycasts = false; _activeTween = canvasGroup .DOFade(0f, fadeDuration) .SetEase(hideEase) .SetUpdate(true) .OnComplete(() => { gameObject.SetActive(false); onComplete?.Invoke(); }); } private void PrepareSweep() { if (sweep == null) { return; } var width = ((RectTransform)transform).rect.width; sweep.anchoredPosition = new Vector2(-width * 0.08f, sweep.anchoredPosition.y); } } }