using asap.core; using asap.core.common; using cfg; using DG.Tweening; using System.Collections.Generic; using System.Threading.Tasks; using UnityEngine; using UnityEngine.UI; using GameCore; using System; using Game; using TMPro; public class BatchedRewardFly : MonoBehaviour, IPoolableObject { public Image icon; public Image icon_card; public Image icon_card_logo; public Image icon_card_num; public Image icon_rod; public TMP_Text text_num; public Animation ani; [SerializeField] private GameObject /*fxTrace, */iconRoot, fxRoot; [SerializeField] private CanvasGroup canvasGroup; [SerializeField] private ParticleSystem fxTrail; private const string IN = "rewardfly_show_batched", OUT = "rewardfly_out_batched", OUT_STASH = "rewardfly_out_bag_batched", FLY_BATCHED = "rewardfly_fly_batched", FLY_SINGLE = "rewardfly_fly_single", GeneratedFlag = "[generated]", IN_SINGLE = "rewardfly_show_single"; private IObjectPool _pool; private readonly DefaultRectTr DefaultLocalTextTransform = new DefaultRectTr(); private void OnEnable() { // Debug.Log($"[RewardFly] Enabled.", this); icon.gameObject.SetActive(false); icon_card.gameObject.SetActive(false); icon_rod.gameObject.SetActive(false); } public virtual async Task SingleFlyAsync(BatchedRewardFlyRequest request, RewardFlyAnimationParams para) { // Debug.Log($"[RewardFly] SingleFly"); ani.Play(FLY_SINGLE); SetText(""); canvasGroup.alpha = para.alphaShow; iconRoot.transform.localScale = Vector3.one; if (request.StartPoint.Size != 0.0f) { var sourceScale = GetTransitionScale(request.StartPoint.Size, request.StartPoint.LossyScale); iconRoot.transform.localScale = sourceScale * para.scaleShow * Vector3.one; iconRoot.transform.DOScale(sourceScale, para.ShowDuration).SetEase(para.CurveShow); } else { iconRoot.transform.localScale = para.scaleShow * Vector3.one; iconRoot.transform.DOScale(1, para.ShowDuration).SetEase(para.CurveShow); } if (request.icon != null) SetData(request.icon); else if (string.IsNullOrEmpty(request.iconName)) SetData(request.itemID); else SetData(request.iconName); transform.position = request.StartPoint.Pos; // if (request.sourceTextRt != null) // { // var rt = text_num.transform as RectTransform; // rt.anchorMin = request.sourceTextRt.anchorMin; // rt.anchorMax = request.sourceTextRt.anchorMax; // rt.pivot = request.sourceTextRt.pivot; // rt.anchoredPosition = request.sourceTextRt.anchoredPosition; // rt.sizeDelta = request.sourceTextRt.sizeDelta; // } // else // { // var rt = text_num.transform as RectTransform; // rt.anchorMin = DefaultLocalTextTransform.anchorMin; // rt.anchorMax = DefaultLocalTextTransform.anchorMax; // rt.pivot = DefaultLocalTextTransform.pivot; // rt.anchoredPosition = DefaultLocalTextTransform.anchoredPosition; // rt.sizeDelta = DefaultLocalTextTransform.sizeDelta; // } if (para.IsPlayOpen) { OpenFx(ERewardFlyStage.Show, para.FxSingle, out var fx); ani.Play(IN_SINGLE); await transform.DOMove(request.StartPoint.Pos, para.ShowDuration).SetEase(Ease.InOutSine).AsyncWaitForCompletion(); CloseFx(fx); } string audioFly = para.GetAudioUrl(1, request.Quantity != null && request.Quantity.Value > 1); GContext.Publish(new EventUISound(audioFly)); OpenFx(ERewardFlyStage.Fly, para.FxSingle, out var flyFx); transform.DOMoveX(request.EndPoint.Pos.x, para.FlyDuration).SetEase(para.CurveX); transform.DOMoveY(request.EndPoint.Pos.y, para.FlyDuration).SetEase(para.CurveY); var targetScale = GetTransitionScale(request.EndPoint.Size, request.EndPoint.LossyScale); iconRoot.transform.DOScale(targetScale, para.FlyDuration).SetEase(para.CurveScale); iconRoot.transform.DORotate(Vector3.zero, para.FlyDuration).SetEase(Ease.InOutSine); await Awaiters.Seconds(para.FlyDuration); CloseFx(flyFx); if (!para.IsPlayClose) { return; } OpenFx(request.isDestinationRewardStash ? ERewardFlyStage.OutStash : ERewardFlyStage.Out, para.FxSingle, out var outFx); if (request.isDestinationRewardStash) { ani.Play(OUT_STASH); } else { ani.Play(OUT); } string audioOut = para.GetAudioUrl(2, request.Quantity != null && request.Quantity.Value > 1); GContext.Publish(new EventUISound(audioOut)); await Awaiters.Seconds(para.CloseDuration); CloseFx(outFx); } public virtual async Task BatchShowAsync(BatchedRewardFlyRequest request, RewardFlyAnimationParams para) { // Debug.Log($"[RewardFly] BatchShow"); canvasGroup.alpha = 1f; iconRoot.transform.localScale = Vector3.one; SetText(request.Quantity, request.itemID); float sourceScale = 1; if (request.StartPoint.Size != 0.0f) { sourceScale = GetTransitionScale(request.StartPoint.Size, request.StartPoint.LossyScale); iconRoot.transform.localScale = new Vector3(sourceScale, sourceScale, 1f); } else { iconRoot.transform.localScale = para.scaleShow * Vector3.one; iconRoot.transform.DOScale(1, para.ShowDuration).SetEase(para.CurveShow); } if (request.icon != null) SetData(request.icon); else if (string.IsNullOrEmpty(request.iconName)) SetData(request.itemID); else SetData(request.iconName); transform.position = request.StartPoint.Pos; if (request.sourceTextRt != null) { var rt = text_num.GetComponent(); rt.anchorMin = request.sourceTextRt.anchorMin; rt.anchorMax = request.sourceTextRt.anchorMax; rt.anchoredPosition = request.sourceTextRt.anchoredPosition; rt.sizeDelta = request.sourceTextRt.sizeDelta; rt.pivot = request.sourceTextRt.pivot; } else { var rt = text_num.GetComponent(); rt.anchorMin = DefaultLocalTextTransform.anchorMin; rt.anchorMax = DefaultLocalTextTransform.anchorMax; rt.anchoredPosition = DefaultLocalTextTransform.anchoredPosition; rt.sizeDelta = DefaultLocalTextTransform.sizeDelta; rt.pivot = DefaultLocalTextTransform.pivot; } OpenFx(ERewardFlyStage.Show, para.FxBatched, out var fx); ani.Play(IN); await Task.Delay(TimeSpan.FromSeconds(para.ShowDuration)); CloseFx(fx); } public virtual async Task BatchFlyAsync(BatchedRewardFlyRequest request, RewardFlyAnimationParams para) { // Debug.Log($"[RewardFly] BatchFly"); ani.Play(FLY_BATCHED); SetText(""); canvasGroup.alpha = para.alphaShow; iconRoot.transform.localScale = Vector3.one; if (request.StartPoint.Size != 0.0f) { var sourceScale = GetTransitionScale(request.StartPoint.Size, request.StartPoint.LossyScale) * (request.Quantity != null && request.Quantity.Value > 1 ? para.MultipleIconScaleModifier : 1f); iconRoot.transform.localScale = sourceScale * para.scaleShow * Vector3.one; iconRoot.transform.DOScale(sourceScale, para.ShowDuration).SetEase(para.CurveShow); } else { iconRoot.transform.localScale = para.scaleShow * Vector3.one; iconRoot.transform.DOScale(1, para.ShowDuration).SetEase(para.CurveShow); } if (request.icon != null) SetData(request.icon); else if (string.IsNullOrEmpty(request.iconName)) SetData(request.itemID); else SetData(request.iconName); transform.position = request.StartPoint.Pos; var delta = Vector3.zero; if (para.IsPlayOpen) { if (request.Quantity != null && request.Quantity > 1) { // ani.Play(IN); delta = (Vector3)FtMathUtils.GetCornSpread(para.SpreadHalfAngle, para.SpreadNearRange, para.SpreadFarRange); if (para.MaxTiltAngle > 0) { var angle = UnityEngine.Random.Range(-para.MaxTiltAngle, para.MaxTiltAngle); iconRoot.transform.DORotate(new Vector3(0, 0, angle), para.ShowDuration).SetEase(Ease.InOutSine); } } canvasGroup.DOFadeAlpha(1f, para.ShowDuration).SetEase(para.CurveShow); await transform.DOMove(request.StartPoint.Pos + delta, para.ShowDuration).SetEase(Ease.InOutSine).AsyncWaitForCompletion(); } string audioFly = para.GetAudioUrl(1, request.Quantity != null && request.Quantity.Value > 1); GContext.Publish(new EventUISound(audioFly)); // SetText(""); // ShowTrace(); OpenFx(ERewardFlyStage.Fly, para.FxBatched, out var fx); transform.DOMoveX(request.EndPoint.Pos.x, para.FlyDuration).SetEase(para.CurveX); transform.DOMoveY(request.EndPoint.Pos.y, para.FlyDuration).SetEase(para.CurveY); var targetScale = GetTransitionScale(request.EndPoint.Size, request.EndPoint.LossyScale); iconRoot.transform.DOScale(targetScale, para.FlyDuration).SetEase(para.CurveScale); iconRoot.transform.DORotate(Vector3.zero, para.FlyDuration).SetEase(Ease.InOutSine); await Awaiters.Seconds(para.FlyDuration); CloseFx(fx); if (!para.IsPlayClose) { return; } OpenFx(request.isDestinationRewardStash ? ERewardFlyStage.OutStash : ERewardFlyStage.Out, para.FxBatched, out var outFx); if (request.isDestinationRewardStash) { ani.Play(OUT_STASH); // Debug.Log("[RewardFly] PlayClose OUT_STASH", this); } else { ani.Play(OUT); // Debug.Log("[RewardFly] PlayClose OUT", this); } string audioOut = para.GetAudioUrl(2, request.Quantity != null && request.Quantity.Value > 1); GContext.Publish(new EventUISound(audioOut)); await Awaiters.Seconds(para.CloseDuration); CloseFx(outFx); // Debug.Log("[RewardFly] PlayClose Done", this); } void PlayOpen() { ani.Play("reward_common_open"); } void PlayClose() { ani.Play("reward_common_close"); } void SetData(string iconName) { icon.gameObject.SetActive(true); GContext.container.Resolve().SetImageSprite(icon, iconName, BasePanel.PanelName); } void SetData(Sprite iconSprite) { icon.gameObject.SetActive(true); icon.sprite = iconSprite; } void SetText(string numStr) { text_num.gameObject.SetActive(true); text_num.text = numStr; } void SetText(int? quantity, int itemId) { if (quantity.HasValue && quantity.Value > 1) { var value = quantity.Value; if (itemId == 1002) value = value = ConvertTools.KeepThreeSignificantDigits(value); SetText("x" + ConvertTools.GetNumberString(value)); } else SetText(""); } void SetData(int itemID) { Item item = GContext.container.Resolve().TbItem.GetOrDefault(itemID); if (item.Type == 5 && (item.SubType == 1 || item.SubType == 2)) { IUIService uiService = GContext.container.Resolve(); List BgNameList; if (item.SubType == 1) { var fishCard = GContext.container.Resolve().TbFishCardDrop.GetOrDefault(item.RedirectID); BgNameList = fishCard.BgNameList; } else { var fishCard = GContext.container.Resolve().TbGeneralCardWeight.GetOrDefault(item.RedirectID); BgNameList = fishCard.BgNameList; } uiService.SetImageSprite(icon_card, BgNameList[0], BasePanel.PanelName); uiService.SetImageSprite(icon_card_logo, BgNameList[1], BasePanel.PanelName); uiService.SetImageSprite(icon_card_num, BgNameList[2], BasePanel.PanelName); icon_card.gameObject.SetActive(true); } else if (item.Type == 3 && (item.SubType == 1 || item.SubType == 3)) { icon_rod.gameObject.SetActive(true); GContext.container.Resolve().SetImageSprite(icon_rod, item.Icon, BasePanel.PanelName); } else { icon.gameObject.SetActive(true); GContext.container.Resolve().SetImageSprite(icon, item.Icon, BasePanel.PanelName); } } private float GetTransitionScale(float targetIconSize, float targetLossyScale) { if (!icon.gameObject.TryGetComponent(out var iconRect)) { Debug.Log("[RewardFly] Cannot find icon RectTransform.", this); return 1; } // This is hard core. var res = targetIconSize * targetLossyScale / (iconRect.rect.width * iconRect.lossyScale.x / iconRoot.transform.localScale.x / iconRect.localScale.x); // Debug.Log($"[RewardFly] res {res} = {targetIconSize} * {targetLossyScale} / ({iconRect.rect.width} * {iconRect.lossyScale.x} / {iconRoot.transform.localScale.x} / {iconRect.localScale.x})", this); return res; } public void OnSpawn() { // Debug.Log("[RewardFly] Spawn in Obj pool."); transform.SetParent(UIManager.Instance.RectTrans); transform.localScale = Vector3.one; // text_num.gameObject.SetActive(false); iconRoot.transform.localScale = Vector3.one; // ani.Play(FLY); } public void OnDespawn() { // Debug.Log("[RewardFly] Despawn in Obj pool."); // ShowTrace(false); RemoveGeneratedRenderer(fxRoot); // transform.SetParent(UIManager.Instance.RectTrans); } public void OnPoolCreate(IObjectPool objectPool) { _pool = objectPool; // Debug.Log("[RewardFly] Created in pool."); } public void OnPoolDestroy() { _pool = null; } public void ReturnPool() { _pool?.DespawnObject(this); } private void RemoveGeneratedRenderer(GameObject go) { var cc = go.transform.childCount; if (cc > 0) { for (int i = 0; i < cc; i++) { var child = go.transform.GetChild(i).gameObject; RemoveGeneratedRenderer(child); } } if (go.name.StartsWith(GeneratedFlag)) { Destroy(go); } } private void OpenFx(ERewardFlyStage stage, string[] fxList, out GameObject fx) { fx = null; try { if (fxList != null && fxList.Length > (int)stage) { var tr = transform.Find("FxRoot/" + fxList[(int)stage]); if (tr != null) fx = tr.gameObject; if (fx != null) fx.SetActive(true); else Debug.Log($"[BatchedRewardFly] Fx not found: \"{fxList[(int)stage]}\"", this); } } catch (Exception e) { Debug.Log($"[BatchedRewardFly] OpenFx Error: {e.Message}\n{e.StackTrace}", this); } } private void CloseFx(GameObject fx) { if (fx != null) fx.SetActive(false); } } public enum ERewardFlyStage { Show = 0, Fly = 1, Out = 2, OutStash = 3 } public class DefaultRectTr { public Vector2 anchorMax = 0.5f * Vector2.one; public Vector2 anchorMin = 0.5f * Vector2.one; public Vector2 pivot = 0.5f * Vector2.one; public Vector2 anchoredPosition = new Vector2(0, -94); public Vector2 sizeDelta = new Vector2(166, 56); }