using UnityEngine; using DG.Tweening; namespace Ashwild.UI { /// /// Classifies how a panel affects gameplay when open, so a UI manager can apply the right /// side effects: Default = plain menu panel, Pause = freezes the world / raises GamePaused, /// Inventory = a local UI window where the world keeps running. /// public enum PanelKind { Default, Pause, Inventory } [RequireComponent(typeof(CanvasGroup))] public abstract class UIPanel : MonoBehaviour { /// /// How this panel affects gameplay while open. Overridden by panels that pause the game /// (pause menu) or that are a local window the world keeps running under (inventory). /// public virtual PanelKind Kind => PanelKind.Default; [Header("Animation")] [SerializeField] private float showDuration = 0.25f; [SerializeField] private float hideDuration = 0.15f; [SerializeField] private Ease showEase = Ease.OutBack; [SerializeField] private Ease hideEase = Ease.InQuad; [SerializeField] private float showScaleFrom = 0.9f; protected CanvasGroup canvasGroup; protected RectTransform rect; private Tween currentTween; public bool IsVisible { get; private set; } protected virtual void Awake() { canvasGroup = GetComponent(); rect = GetComponent(); } public virtual void Show() { currentTween?.Kill(); gameObject.SetActive(true); IsVisible = true; canvasGroup.alpha = 0f; canvasGroup.interactable = true; canvasGroup.blocksRaycasts = true; rect.localScale = Vector3.one * showScaleFrom; Sequence s = DOTween.Sequence(); s.Append(canvasGroup.DOFade(1f, showDuration)); s.Join(rect.DOScale(1f, showDuration).SetEase(showEase)); currentTween = s; } public virtual void Hide() { if (!IsVisible) return; currentTween?.Kill(); IsVisible = false; canvasGroup.interactable = false; canvasGroup.blocksRaycasts = false; currentTween = canvasGroup.DOFade(0f, hideDuration) .SetEase(hideEase) .OnComplete(() => gameObject.SetActive(false)); } public virtual void HideInstant() { currentTween?.Kill(); IsVisible = false; canvasGroup.alpha = 0f; canvasGroup.interactable = false; canvasGroup.blocksRaycasts = false; rect.localScale = Vector3.one; gameObject.SetActive(false); } } }