282 lines
11 KiB
C#
282 lines
11 KiB
C#
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);
|
||
}
|
||
}
|
||
}
|
||
}
|