using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using asap.core; using EventSmash.Manager; using game; using UnityEngine; using UnityEngine.UI; using TMPro; using Activity; using GameCore; using TimeManager; using UniRx; using UIExtend.Component; using Game; namespace EventSmash.UIPanel { public class EventSmashPanel : BasePanel { #region 组件 private TMP_Text _tokenText; private Image _tokenIcon; private TMP_Text _txtTime; private EventSmashProgressCell[] _progressCells; private EventSmashCell[] _cellPrefabs; private RewardFlyBatchController _rewardFlyBatch; private Button _btnSmashAll; private Button _btnClose; private Button _btnInfo; private Button _btnAdd; private Button _btnBattlePass; [Header("九格全开通关(节点名 Image_door_mask)")] [Tooltip("通关遮罩激活后,经过此时长再 RefreshData")] [SerializeField] private float _stageCompleteRefreshDataDelay = 0.3f; [Tooltip("已确定领奖队列非空但 ShowUI 异步时,最多再等这么久直到 RewardPopup 显示;仅影响「有弹窗」分支")] [SerializeField] private float _rewardPopupAsyncOpenMaxWaitSeconds = 2f; [Tooltip("Legacy Animation 的 clip 名,或 Animator 的状态名(哈希);留空则播默认片段 / 第 0 层默认态")] [SerializeField] private string _doorMaskAnimClipName = "EventSmashScrapStageRefresh"; // Prefab/场景里序列化的字符串会覆盖上面默认值;通关遮罩应对齐 Animation 里的「关卡刷新」clip(如 EventSmashScrapStageRefresh),勿填 ProgressCell 的 EventSmashScrapPiplineCheckRefresh。 private GameObject _imageDoorMask; #endregion private EventSmashManager _manager; private EventSmashData _data; private IDeferredRewardStashService _stashService; /// 与砸罐回调同帧写入, 首帧后读取并清除;不依赖 Manager 跨帧标志。 private bool _stageCompletePendingDoorAnim; /// 按收集线加锁:不同 collectionId 可并行领奖/涨条;同一条仍串行(避免同一进度条并发写)。 private readonly object _collectionLocksRoot = new object(); private readonly Dictionary _collectionClaimLocks = new Dictionary(); /// 引导表 GuidanceGroupDefine 首步 panelName 须与此一致(与预制体名 EventSmashScrapPanel 对齐)。 private const string SmashScrapGuidePanelKey = "EventSmashScrapPanel"; #region 生命周期 private void Awake() { _txtTime = gameObject.FindChildGameObject("text_time").GetComponent(); _tokenText = gameObject.FindChildGameObject("txt_num").GetComponent(); _tokenIcon = gameObject.FindChildGameObject("Img_ticket").GetComponent(); _progressCells = gameObject.GetComponentsInChildren(true); _cellPrefabs = gameObject.GetComponentsInChildren(true); _rewardFlyBatch = gameObject.GetComponentInChildren(true); _rewardFlyBatch.SetActive(true); _btnSmashAll = gameObject.FindChildGameObject("btn_smash_all").GetComponent