203 lines
6.7 KiB
C#
203 lines
6.7 KiB
C#
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using TMPro;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
|
||
namespace Watermelon
|
||
{
|
||
/// <summary>
|
||
/// Concrete <see cref="UIPage"/> that implements <see cref="IRewardsPopup"/> and displays a
|
||
/// grid of reward previews with fade-in/scale animations.
|
||
/// Registers itself with the <see cref="RewardsPopup"/> static facade on <see cref="Init"/> so that
|
||
/// <see cref="RewardsHolder"/> instances remain decoupled from this specific UIPage class.
|
||
/// Grid cell size adapts automatically: 300×300 for ≤6 items, 200×200 for larger sets.
|
||
/// </summary>
|
||
public class UIRewardsPopup : UIPage, IRewardsPopup
|
||
{
|
||
public override bool IsPopup => true;
|
||
[SerializeField] Image backgroundImage;
|
||
[SerializeField] RectTransform rewardsContainerTransform;
|
||
[SerializeField] GridLayoutGroup rewardsGridLayoutGroup;
|
||
[SerializeField] GameObject rewardUIPrefab;
|
||
[SerializeField] TMP_Text tapToClaimText;
|
||
|
||
[Space]
|
||
[SerializeField] Sprite defaultRewardSprite;
|
||
|
||
private SimpleCallback closeCallback;
|
||
private RewardUIData[] rewards;
|
||
|
||
private TweenCase fadeTweenCase;
|
||
|
||
private float rewardItemScale = 1f;
|
||
|
||
public override void Init()
|
||
{
|
||
RewardsPopup.Register(this);
|
||
|
||
backgroundImage.AddEvent(UnityEngine.EventSystems.EventTriggerType.PointerUp, (data) => OnCloseButtonClicked());
|
||
}
|
||
|
||
public bool Display(List<IRewardPreview> previews, SimpleCallback closeCallback)
|
||
{
|
||
this.closeCallback = closeCallback;
|
||
|
||
RewardUIData[] oldRewards = rewards;
|
||
if (!oldRewards.IsNullOrEmpty())
|
||
{
|
||
foreach (RewardUIData reward in oldRewards)
|
||
reward?.Destroy();
|
||
}
|
||
|
||
previews = previews.OrderBy(x => x.SortingOrder).ToList();
|
||
|
||
RewardUIData[] newRewards = new RewardUIData[previews.Count];
|
||
for (int i = 0; i < newRewards.Length; i++)
|
||
{
|
||
IRewardPreview preview = previews[i];
|
||
|
||
GameObject uiPrefab = preview.GetCustomUIPrefab();
|
||
if (uiPrefab == null)
|
||
uiPrefab = rewardUIPrefab;
|
||
|
||
GameObject uiObject = Instantiate(uiPrefab, rewardsContainerTransform);
|
||
uiObject.transform.ResetLocal();
|
||
|
||
UIRewardPreviewItem previewItem = uiObject.GetComponent<UIRewardPreviewItem>();
|
||
previewItem.Init(preview, defaultRewardSprite);
|
||
|
||
newRewards[i] = new RewardUIData(previewItem, preview);
|
||
}
|
||
|
||
rewards = newRewards;
|
||
|
||
UIController.ShowPage<UIRewardsPopup>();
|
||
|
||
return true;
|
||
}
|
||
|
||
protected override void OnShow()
|
||
{
|
||
float appearanceDelay = 0.1f;
|
||
|
||
if (!rewards.IsNullOrEmpty())
|
||
{
|
||
UpdateDynamicSize();
|
||
|
||
for (int i = 0; i < rewards.Length; i++)
|
||
{
|
||
RewardUIData reward = rewards[i];
|
||
|
||
UIRewardPreviewItem item = reward.Item;
|
||
item.transform.localScale = Vector3.one * rewardItemScale;
|
||
|
||
item.CanvasGroup.alpha = 0.0f;
|
||
|
||
reward.FadeTweenCase = item.CanvasGroup.DOFade(1.0f, 0.45f, appearanceDelay * (i + 1), unscaledTime: true);
|
||
|
||
reward.ScaleTweenCase = item.Image.DOScale(1.1f, 0.15f, appearanceDelay * (i + 1), unscaledTime: true).SetEasing(Ease.Type.SineOut).OnComplete(() =>
|
||
{
|
||
reward.ScaleTweenCase = item.Image.DOScale(0.95f, 0.2f, unscaledTime: true).OnComplete(() =>
|
||
{
|
||
reward.ScaleTweenCase = item.Image.DOScale(1f, 0.1f, unscaledTime: true).SetEasing(Ease.Type.SineOut);
|
||
});
|
||
});
|
||
}
|
||
}
|
||
|
||
float tapTextDelay = rewards.IsNullOrEmpty() ? 0f : appearanceDelay * rewards.Length + 0.5f;
|
||
|
||
tapToClaimText.color = tapToClaimText.color.SetAlpha(0f);
|
||
fadeTweenCase = tapToClaimText.DOFade(1f, 0.2f, tapTextDelay, unscaledTime: true).SetEasing(Ease.Type.CubicInOut);
|
||
|
||
NotifyOpened();
|
||
}
|
||
|
||
public void UpdateDynamicSize()
|
||
{
|
||
if (rewards.Length <= 6)
|
||
{
|
||
rewardsGridLayoutGroup.cellSize = new Vector2(300f, 300f);
|
||
rewardItemScale = 1f;
|
||
}
|
||
else
|
||
{
|
||
rewardsGridLayoutGroup.cellSize = new Vector2(200f, 200f);
|
||
rewardItemScale = 0.8f;
|
||
}
|
||
}
|
||
|
||
protected override void OnHide()
|
||
{
|
||
float animationDuration = 0f;
|
||
|
||
if (!rewards.IsNullOrEmpty())
|
||
{
|
||
animationDuration = 0.3f;
|
||
|
||
for (int i = 0; i < rewards.Length; i++)
|
||
{
|
||
RewardUIData reward = rewards[i];
|
||
|
||
UIRewardPreviewItem item = reward.Item;
|
||
item.CanvasGroup.alpha = 1f;
|
||
|
||
reward.FadeTweenCase = item.CanvasGroup.DOFade(0f, 0.28f, unscaledTime: true);
|
||
|
||
reward.ScaleTweenCase = item.Image.DOScaleY(1.1f, 0.05f, 0.1f, unscaledTime: true).SetEasing(Ease.Type.SineIn).OnComplete(() =>
|
||
{
|
||
reward.ScaleTweenCase = item.Image.DOScaleY(0f, 0.15f, unscaledTime: true).SetEasing(Ease.Type.SineOut);
|
||
});
|
||
}
|
||
}
|
||
|
||
Tween.DelayedCall(animationDuration, () =>
|
||
{
|
||
closeCallback?.Invoke();
|
||
NotifyClosed();
|
||
}, unscaledTime: true);
|
||
}
|
||
|
||
private void OnDestroy()
|
||
{
|
||
fadeTweenCase.KillActive();
|
||
|
||
if (!rewards.IsNullOrEmpty())
|
||
{
|
||
foreach (RewardUIData reward in rewards)
|
||
reward?.Destroy();
|
||
}
|
||
}
|
||
|
||
private void OnCloseButtonClicked()
|
||
{
|
||
UIController.HidePage(this);
|
||
}
|
||
|
||
public class RewardUIData
|
||
{
|
||
public readonly UIRewardPreviewItem Item;
|
||
public readonly IRewardPreview Preview;
|
||
|
||
public TweenCase FadeTweenCase;
|
||
public TweenCase ScaleTweenCase;
|
||
|
||
public RewardUIData(UIRewardPreviewItem item, IRewardPreview preview)
|
||
{
|
||
Item = item;
|
||
Preview = preview;
|
||
}
|
||
|
||
public void Destroy()
|
||
{
|
||
if (Item != null && Item.gameObject != null)
|
||
GameObject.Destroy(Item.gameObject);
|
||
|
||
FadeTweenCase.KillActive();
|
||
ScaleTweenCase.KillActive();
|
||
}
|
||
}
|
||
}
|
||
}
|