using asap.core; using Assets.Scripts.UI.AnimationSimulator; using cfg; using DG.Tweening; using Game; using System; using System.Collections.Generic; using System.Threading.Tasks; using UI.Wheel; using UnityEngine; namespace Assets.Scripts.UI.AdWheel { public class AdWheelRewardComponent : AbstractWheelRewardComponent { #region ui private GameObject fx_spin; private GameObject fx_arrow_spin; private Animation lightAni; private AnimationState wheelClipLoop; private Transform zhizhenTrans; private Dictionary _fxNameObjs = new Dictionary(); #endregion private float lastValue; private int currentSegment = 0; private int lastSegment = 0; private Tweener _tweener; protected override string StartSound => "audio_ui_bonuswheel_arrow_spin_start"; protected override string LoopedSound => "audio_ui_bonuswheel_arrow_spin_loop"; protected override string EndSound => "audio_ui_bonuswheel_arrow_spin_end"; protected override void Awake() { base.Awake(); fx_spin = this.gameObject.FindChildGameObject("fx_ui_bonuswheel_spin")?.gameObject; fx_arrow_spin = this.gameObject.FindChildGameObject("fx_ui_bonuswheel_arrow_spin")?.gameObject; lightAni = this.gameObject.FindChildGameObject("p_light")?.GetComponent(); zhizhenTrans = this.gameObject.FindChildGameObject("zhizhen")?.GetComponent(); for (int i = 1; i <= 3; i++) { var key = $"fx_ui_bonuswheel_reward_claim_0{i}"; if (_fxNameObjs.ContainsKey(key)) continue; var fx = this.gameObject.FindChildGameObject(key)?.gameObject; if (fx == null) continue; fx.SetActive(false); _fxNameObjs.Add(key, fx); } } protected override void Start() { base.Start(); lightAni.Play("light_idle"); } protected override void InitUI() { base.InitUI(); fx_spin.SetActive(false); fx_arrow_spin.SetActive(false); wheelClipLoop = lightAni?["light_spin_loop"]; } public override void SetData(List rewards) { for (int i = 0; i < rewards.Count && i < wheelRewardCells.Length; i++) { wheelRewardCells[i].SetData(rewards[i]); } } public override void ShowUI() { foreach (var rewardCell in wheelRewardCells) { rewardCell.ShowUI(); } } protected override void EffectStart() { base.EffectStart(); InitPointerAni(); _ = LightStarAni(); foreach (var fx in _fxNameObjs) fx.Value?.SetActive(false); fx_arrow_spin.SetActive(true); } protected override void EffectUpdate(float currentVelocity, float currentValue) { base.EffectUpdate(currentVelocity, currentValue); SetClipLoopSpeed(currentVelocity); PointerAni(currentValue, currentVelocity); } protected override async Task EffectEnd(IWheelReward reward) { fx_spin.SetActive(false); fx_arrow_spin.SetActive(false); if (_fxNameObjs.TryGetValue(reward.Fx, out var value)) value.SetActive(true); zhizhenTrans.rotation = Quaternion.Euler(0, 0, 0); if (!string.IsNullOrEmpty(reward.Audio)) { GContext.Publish(new EventUISound(reward.Audio)); } await base.EffectEnd(reward); lightAni.Play("light_idle"); } protected override async Task DelayShow() { await base.DelayShow(); fx_spin?.SetActive(true); } protected override void RevertTargetEndCallbcak() { base.RevertTargetEndCallbcak(); _ = LightEndAni(); } #region private private void SetClipLoopSpeed(float currentVelocity) { wheelClipLoop.speed = Mathf.Max(Mathf.Abs(currentVelocity / 360), 0.1f); } private async Task LightStarAni() { var time = lightAni["light_spin_start"].length; lightAni.Play("light_spin_start"); await Awaiters.Seconds(time); lightAni.Play("light_spin_loop"); } private async Task LightEndAni() { float remainingTime = wheelClipLoop.length * (1f - wheelClipLoop.normalizedTime); await Awaiters.Seconds(remainingTime); var clipEndTime = lightAni["light_spin_end"].length; lightAni.Play("light_spin_end"); await Awaiters.Seconds(clipEndTime); var clipRewardTime = lightAni["light_reward"].length; lightAni.Play("light_reward"); } #endregion #region CD Shark Animation public async Task PlayCdEffect(Action endCallback) { InitPointerAni(); GContext.Publish(new EventUISound("audio_ui_bonuswheel_arrow_spin_stuck")); var param = new AnimationSimulatorComponent.Parameter(); param.scale = 360; param.customVelocity = cdEffectVelocity; param.startValue = rewardContainer.eulerAngles.z; param.updateCallback = (float currentVelocity, float currentValue) => { EffectUpdate(currentVelocity, currentValue); }; await simulator.SharkAni(param); endCallback?.Invoke(); } #endregion #region Pointer Animation private void InitPointerAni() { var currentValue = rewardContainer.eulerAngles.z; lastValue = currentValue; lastSegment = GetSegment(currentValue); } private void PointerAni(float currentValue, float currentVelocity) { currentSegment = GetSegment(currentValue); lastSegment = GetSegment(lastValue); var normalizeCurrentAngle = NormalizeAngle(currentValue); if (currentSegment != lastSegment) { int direction = GetCrossDirection(lastSegment, currentSegment); var time = wheelAngle / currentVelocity; var pointerTargetAngle = Mathf.Abs(Mathf.Clamp01(normalizeCurrentAngle / wheelAngle) * pointerAngle); zhizhenTrans.DORotate(new Vector3(0, 0, direction * pointerTargetAngle), time) .OnComplete(() => { _tweener?.Kill(); _tweener = zhizhenTrans.DORotate(Vector3.zero, revertAngleTime); }); } lastValue = currentValue; } private int GetSegment(float angle) { float normalizedAngle = NormalizeAngle(angle); return Mathf.FloorToInt(normalizedAngle / SegmentAngle); } private float NormalizeAngle(float angle) { angle %= FULL_CIRCLE; if (angle < 0) angle += FULL_CIRCLE; return angle; } private int GetCrossDirection(int fromSegment, int toSegment) { int diff = toSegment - fromSegment; if ((fromSegment == MaxSegment && toSegment == 0) || (fromSegment == 0 && toSegment == MaxSegment)) diff = -diff; return diff < 0 ? 1 : -1; } #endregion } }