Files
ft/Client/Assets/Scripts/EventSmash/UIPanel/EventSmashCell.cs
2026-06-29 21:18:33 +08:00

282 lines
11 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using UnityEngine;
using UnityEngine.UI;
using GameCore;
using asap.core;
using EventSmash.Manager;
using UnityEngine.Playables;
using game;
using System.Threading.Tasks;
using Spine.Unity;
using UIExtend.Component;
namespace EventSmash.UIPanel
{
public class EventSmashCell : MonoBehaviour
{
#region
private Button _clickButton;
private GameObject _unopenedObj;
private RewardItemNew _reward;
private RewardItemNew _reward_permanent;
private GameObject singleOpenObj;
//private GameObject allOpenObj;
private PlayableDirector _director;
private Animation _animation;
private Image _imgItemNormal;
private Image _imgItemFlat;
#endregion
[SerializeField] private PlayableAsset singleOpenTimeLine;
[SerializeField] private PlayableAsset allOpenTimeLine;
private int m_GridIndex;
private ItemData _cachedRewardItem;
private EventSmashData _cachedData;
private Func<int, RewardItemNew, int, Task> _playCollectionRewardFly;
private Func<int, int, bool, Task> _afterCollectionFlyAsync;
public bool IsOpened { get; private set; }
public void SetClickable(bool clickable)
{
if (_clickButton != null) _clickButton.enabled = clickable && !IsOpened;
}
private void Awake()
{
_clickButton = gameObject.FindChildGameObject("btn_click").GetComponent<Button>();
_unopenedObj = gameObject.FindChildGameObject("unopened_obj");
_reward = gameObject.FindChildGameObject("reward").GetComponent<RewardItemNew>();
_reward_permanent = gameObject.FindChildGameObject("reward_permanent").GetComponent<RewardItemNew>();
_director = gameObject.GetComponentInChildren<PlayableDirector>();
_animation = gameObject.FindChildGameObject("root").GetComponent<Animation>();
singleOpenObj = gameObject.FindChildGameObject("img_single_smash_prop");
//allOpenObj = gameObject.FindChildGameObject("img_all_smash");
singleOpenObj.SetActive(false);
_reward.SetActive(false);
var goNormal = gameObject.FindChildGameObject("img_item_normal");
if (goNormal != null)
_imgItemNormal = goNormal.GetComponent<Image>();
var goFlat = gameObject.FindChildGameObject("img_item_flat");
if (goFlat != null)
_imgItemFlat = goFlat.GetComponent<Image>();
}
/// <param name="trySmash">尝试砸罐,成功返回 true</param>
/// <param name="onAnimComplete">动画播完后的回调刷新UI等</param>
/// <param name="playCollectionRewardFly">收集物:由面板 RewardFlyBatchController 飞向进度条collectionId, 起点 reward_permanent, 数量)</param>
/// <param name="afterCollectionFlyAsync">飞向进度条后:(collectionId, 本格收集物数量, 是否单砸);用于进度补间与单砸时领奖条回溯。</param>
public void Initialize(EventSmashData data, int gridIndex, Func<int, bool> trySmash, Action onAnimComplete,
Func<int, RewardItemNew, int, Task> playCollectionRewardFly = null,
Func<int, int, bool, Task> afterCollectionFlyAsync = null)
{
m_GridIndex = gridIndex;
_cachedData = data;
_playCollectionRewardFly = playCollectionRewardFly;
_afterCollectionFlyAsync = afterCollectionFlyAsync;
_imgItemNormal.SetActive(true);
_imgItemFlat.SetActive(false);
CacheRewardItem(data, gridIndex);
IsOpened = data.OpenedGrids.Contains(gridIndex);
if (_clickButton != null)
{
_clickButton.onClick.RemoveAllListeners();
_clickButton.interactable = !IsOpened;
if (!IsOpened)
{
_clickButton.onClick.AddListener(() =>
{
if (trySmash == null || !trySmash(m_GridIndex)) return;
PlayOpen(false, onAnimComplete);
});
}
}
if (IsOpened)
{
_unopenedObj?.SetActive(false);
ShowReward(true);
}
else
{
if (_director != null)
_director.Stop();
singleOpenObj.SetActive(false);
_unopenedObj?.SetActive(true);
if (_reward != null) _reward.gameObject.SetActive(false);
if (_reward_permanent != null) _reward_permanent.gameObject.SetActive(false);
}
ApplyStageItemImages(data);
}
public static void PlayOpenAll(EventSmashCell[] cells, Action onAllComplete)
{
if (cells == null || cells.Length == 0)
{
onAllComplete?.Invoke();
return;
}
int remaining = cells.Length;
void OnOneCellFullyDone()
{
if (--remaining > 0) return;
onAllComplete?.Invoke();
GContext.Publish(new ShowData());
}
foreach (var cell in cells)
{
if (cell == null)
{
OnOneCellFullyDone();
continue;
}
cell.PlayOpen(true, OnOneCellFullyDone);
}
}
private void PlayOpen(bool isSmashAll, Action onComplete = null)
{
if (IsOpened) { onComplete?.Invoke(); return; }
IsOpened = true;
if (_clickButton != null) _clickButton.interactable = false;
var timeline = isSmashAll ? allOpenTimeLine : singleOpenTimeLine;
singleOpenObj.SetActive(!isSmashAll);
if (_director != null && timeline != null)
{
_director.playableAsset = timeline;
_director.stopped += OnStopped;
_director.Play();
void OnStopped(PlayableDirector _)
{
_director.stopped -= OnStopped;
_unopenedObj?.SetActive(false);
ShowReward();
singleOpenObj.SetActive(false);
RunPostOpenSequenceAsync(onComplete, !isSmashAll, isSmashAll);
}
}
else
{
_unopenedObj?.SetActive(false);
ShowReward();
singleOpenObj.SetActive(false);
RunPostOpenSequenceAsync(onComplete, !isSmashAll, isSmashAll);
}
}
/// <param name="suppressShowData">全砸时为 true由 <see cref="PlayOpenAll"/> 在全部结束后再发一次 ShowData。</param>
private async void RunPostOpenSequenceAsync(Action onComplete, bool isSingleSmashOpen, bool suppressShowData)
{
try
{
await PlayRewardSequenceAsync(isSingleSmashOpen);
}
catch (Exception e)
{
Debug.LogError(e);
}
finally
{
onComplete?.Invoke();
if (!suppressShowData)
GContext.Publish(new ShowData());
}
}
/// <summary>按当前关卡下标设置 <see cref="EventSmashMain.StageItemIcon"/> / <see cref="EventSmashMain.StageItemFlatIcon"/>(与 <see cref="EventSmashData.CurrentStageItemSkinName"/> 同规则:<c>CompletedStageCount % 列表长度</c>)。</summary>
private void ApplyStageItemImages(EventSmashData data)
{
if (data?.MainConfig == null)
return;
var main = data.MainConfig;
var ui = GContext.container.Resolve<IUIService>();
if (ui == null)
return;
int completed = data.CompletedStageCount;
if (main.StageItemIcon != null && main.StageItemIcon.Count > 0 && _imgItemNormal != null)
{
int n = main.StageItemIcon.Count;
int idx = completed % n;
if (idx < 0) idx += n;
var icon = main.StageItemIcon[idx];
if (!string.IsNullOrEmpty(icon))
ui.SetImageSprite(_imgItemNormal, icon);
}
if (main.StageItemFlatIcon != null && main.StageItemFlatIcon.Count > 0 && _imgItemFlat != null)
{
int n = main.StageItemFlatIcon.Count;
int idx = completed % n;
if (idx < 0) idx += n;
var icon = main.StageItemFlatIcon[idx];
if (!string.IsNullOrEmpty(icon))
ui.SetImageSprite(_imgItemFlat, icon);
}
}
private void CacheRewardItem(EventSmashData data, int gridIndex)
{
_cachedRewardItem = data.GridRewardMap.TryGetValue(gridIndex, out var itemData) ? itemData : null;
}
private async Task PlayRewardSequenceAsync(bool isSingleSmashOpen)
{
if (_cachedRewardItem == null || _reward == null)
return;
bool isCollection = _cachedRewardItem.id < 0;
if (!isCollection && _animation != null)
await _animation.PlayAndWaitAsync("EventSmashScrapRewardShow");
if (isCollection)
{
_reward.SetActive(false);
if (_playCollectionRewardFly != null)
await _playCollectionRewardFly(_cachedRewardItem.id, _reward_permanent, _cachedRewardItem.count);
if (_afterCollectionFlyAsync != null)
await _afterCollectionFlyAsync(_cachedRewardItem.id, _cachedRewardItem.count, isSingleSmashOpen);
}
}
private void ShowReward(bool isOpened=false)
{
if (_reward == null || _reward_permanent == null || _cachedRewardItem == null) return;
if (_cachedRewardItem.id < 0)
{
int collectionId = _cachedRewardItem.id;
var icon = _cachedData?.MainConfig?.GetCollectionIcon(
_cachedData.Tables.TbEventSmashCollection, collectionId);
if (!string.IsNullOrEmpty(icon))
{
_reward.SetData(icon, "", _cachedRewardItem.count.ToString());
_reward.gameObject.SetActive(!isOpened);
_reward_permanent.SetData(icon, "", _cachedRewardItem.count.ToString());
_reward_permanent.SetReceived(true);
_reward_permanent.gameObject.SetActive(true);
}
}
else
{
_reward.SetData(_cachedRewardItem);
_reward.gameObject.SetActive(!isOpened);
_reward_permanent.SetData(_cachedRewardItem);
_reward_permanent.SetReceived(true);
_reward_permanent.gameObject.SetActive(true);
}
}
}
}