using DG.Tweening; using CharacterSystem; using PrizeSystem; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class PrizesPanel : InfoPanel { [Header("Картинки")] [SerializeField] private float recordDuration; [SerializeField] private float recordOpenY; [SerializeField] private float recordCloseY; [SerializeField] private float recordDelay; [Header("Генерация")] [SerializeField] private RectTransform table; [SerializeField] private PrizeRecord recordPrefab; [Header("Модальное окно")] [SerializeField] private float _modalTimeout = 20f; [SerializeField] private float _modalFadeDuration = 0.25f; [SerializeField] private float _modalScale = 1.55f; [SerializeField] private Color _modalBackgroundColor = new(0f, 0f, 0f, 0.8f); private readonly List _records = new(); private CanvasGroup _modalCanvasGroup; private Image _modalBackdrop; private Sequence _modalSequence; private Transform _originalParent; private int _originalSiblingIndex; private Vector2 _originalAnchorMin; private Vector2 _originalAnchorMax; private Vector2 _originalPivot; private Vector2 _originalSizeDelta; private Vector2 _originalAnchoredPosition; private Vector3 _originalScale; private float _lastInputTime; private bool _modalOpen; private bool _modalTransitioning; public override bool BlocksNavigation => _modalOpen; public override float closeDelay => (Mathf.Max(infoDuration, buttonDuration, titleDuration) + _records.Count * recordDelay + titleDuration) / closeSpeedMultiplier; private void Update() { if (!_modalOpen || _modalTransitioning) return; if (In.AnyButton()) _lastInputTime = Time.unscaledTime; if (Time.unscaledTime - _lastInputTime >= _modalTimeout) CloseModal(); } public override void Initialize() { } public override void Interact() { if (_modalTransitioning) return; if (_modalOpen) CloseModal(); else OpenModal(); } public override void CloseModal() { if (!_modalOpen || _modalTransitioning) return; _modalTransitioning = true; _modalSequence?.Kill(); _modalSequence = DOTween.Sequence().SetUpdate(true); _modalSequence.Join(_modalCanvasGroup.DOFade(0f, _modalFadeDuration)); _modalSequence.Join(_modalBackdrop.DOFade(0f, _modalFadeDuration)); _modalSequence.Join(root.DOScale(_originalScale * 0.9f, _modalFadeDuration).SetEase(Ease.InBack)); _modalSequence.OnComplete(RestoreAfterModal); _modalSequence.PlayForward(); } protected override void InitializeBeforeOpen() { // Очистить макет for (int i = table.childCount - 1; i >= 0; i--) { Destroy(table.GetChild(i).gameObject); } _records.Clear(); CharacterDefinition[] characters = CharactersController.I.GetDefinitionsArray(); List prizeSets = PrizeSystemManager.PrizeContainer?.Sets; for (int i = 0; i < characters.Length; i++) { PrizeRecord record = Instantiate(recordPrefab, table); IReadOnlyList characterPrizes = i < (prizeSets?.Count ?? 0) ? prizeSets[i]?.Prizes : null; record.Init( i + 1, characters[i].IconSmall, characters[i].CharacterName, characterPrizes); _records.Add(record); } } protected override Sequence GetOpenSequence(float delay) { Sequence seq = DOTween.Sequence(); float t = 0; seq.AppendInterval(delay); seq.Append(root.DOAnchorPos(Vector2.zero, titleDuration)); seq.Append(titleSign.DOAnchorPosY(titleOpenY, titleDuration)); t = delay + titleDuration * 2 - timeOffset; seq.Insert(t, button.DOAnchorPosX(buttonOpenX, buttonDuration)); seq.Insert(t + buttonDuration - timeOffset, info.DOAnchorPosX(infoOpenX, infoDuration).SetEase(Ease.OutBack)); t += recordDelay; for (int i = _records.Count - 1; i >= 0; i--) { var image = _records[i].movableGroup; seq.Insert(t, image.DOAnchorPosY(recordOpenY, recordDuration)); t += recordDelay; } return seq; } protected override Sequence GetCloseSequence(Vector2 position) { Sequence seq = DOTween.Sequence(); seq.Join(info.DOAnchorPosX(infoCloseX, infoDuration)); seq.Join(button.DOAnchorPosX(buttonCloseX, buttonDuration)); seq.Join(titleSign.DOAnchorPosY(titleCloseY, titleDuration)); float time = 0; for (int i = 0; i < _records.Count; i++) { var image = _records[i].movableGroup; seq.Insert(time, image.DOAnchorPosY(recordCloseY, recordDuration)); time += recordDelay; } seq.Append(root.DOAnchorPos(position, titleDuration * 4)); seq.timeScale = closeSpeedMultiplier; return seq; } private void OpenModal() { Canvas canvas = root.GetComponentInParent()?.rootCanvas; if (canvas == null) return; SaveOriginalTransform(); CreateBackdrop(canvas.transform); root.SetParent(canvas.transform, false); root.SetAsLastSibling(); root.anchorMin = Vector2.one * 0.5f; root.anchorMax = Vector2.one * 0.5f; root.pivot = Vector2.one * 0.5f; root.anchoredPosition = Vector2.zero; root.sizeDelta = _originalSizeDelta; root.localScale = _originalScale * (_modalScale * 0.85f); _modalCanvasGroup = root.GetComponent(); if (_modalCanvasGroup == null) _modalCanvasGroup = root.gameObject.AddComponent(); _modalCanvasGroup.alpha = 0f; _modalOpen = true; _modalTransitioning = true; _lastInputTime = Time.unscaledTime; _modalSequence?.Kill(); _modalSequence = DOTween.Sequence().SetUpdate(true); _modalSequence.Join(_modalCanvasGroup.DOFade(1f, _modalFadeDuration)); _modalSequence.Join(_modalBackdrop.DOFade(_modalBackgroundColor.a, _modalFadeDuration)); _modalSequence.Join(root.DOScale(_originalScale * _modalScale, _modalFadeDuration).SetEase(Ease.OutBack)); _modalSequence.OnComplete(() => _modalTransitioning = false); _modalSequence.PlayForward(); } private void SaveOriginalTransform() { _originalParent = root.parent; _originalSiblingIndex = root.GetSiblingIndex(); _originalAnchorMin = root.anchorMin; _originalAnchorMax = root.anchorMax; _originalPivot = root.pivot; _originalSizeDelta = root.sizeDelta; _originalAnchoredPosition = root.anchoredPosition; _originalScale = root.localScale; } private void CreateBackdrop(Transform canvasTransform) { GameObject backdrop = new( "Prizes modal backdrop", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image)); RectTransform backdropRect = backdrop.GetComponent(); backdropRect.SetParent(canvasTransform, false); backdropRect.anchorMin = Vector2.zero; backdropRect.anchorMax = Vector2.one; backdropRect.offsetMin = Vector2.zero; backdropRect.offsetMax = Vector2.zero; backdropRect.SetAsLastSibling(); _modalBackdrop = backdrop.GetComponent(); _modalBackdrop.color = new Color( _modalBackgroundColor.r, _modalBackgroundColor.g, _modalBackgroundColor.b, 0f); _modalBackdrop.raycastTarget = true; } private void RestoreAfterModal() { if (_modalBackdrop != null) Destroy(_modalBackdrop.gameObject); root.SetParent(_originalParent, false); root.SetSiblingIndex(_originalSiblingIndex); root.anchorMin = _originalAnchorMin; root.anchorMax = _originalAnchorMax; root.pivot = _originalPivot; root.sizeDelta = _originalSizeDelta; root.anchoredPosition = _originalAnchoredPosition; root.localScale = _originalScale; _modalCanvasGroup.alpha = 1f; _modalBackdrop = null; _modalOpen = false; _modalTransitioning = false; _modalSequence = null; } }