Files
ft/Client/Assets/Scripts/UI/PinballUncountable/PinballUnCountableProgressBarView.cs
2026-06-29 21:18:33 +08:00

301 lines
12 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 DG.Tweening;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using asap.core;
using PinballUncountable;
using UniRx;
using System.Threading.Tasks;
using System;
using Game;
using GameCore;
using game;
public class PinballUncountableProgressBarView : MonoBehaviour
{
[SerializeField] private Image[] bars;
[SerializeField] private PinballUncountableProgressRewardItemView[] rewards;
[SerializeField] private OfferTreasureAscentGrandRewardView grandRewardView;
[SerializeField] private RectTransform scroller;
[SerializeField] private float startPos = 1246.9f, gap = 188f;
[SerializeField] private TMP_Text textScore, textRewardCount;
[SerializeField] private PinballUncountableGaugeAnimationView gauge;
private int _scoreDisplay, _scoreLogic, _idx;
private readonly int _displayCount = 3;
private Tween _tween = null;
private readonly Queue<int> _scoreQueue = new Queue<int>();
private bool _isProcessingQueue = false;
// public bool IsProcessingQueue => _isProcessingQueue;
private void Awake()
{
var manager = GContext.container.Resolve<Manager>();
manager.EventAggregator.GetEvent<EventExit>().Subscribe(OnScore).AddTo(this);
}
public void Init(int idx, List<PinballUncountableProgressRewardData> items)
{
var manager = GContext.container.Resolve<Manager>();
_idx = idx;
if (items.Count < rewards.Length)
Debug.LogError($"Rewards count {items.Count}, less than {rewards.Length}.", this);
for (int i = 0; i < rewards.Length; i++)
rewards[i].Init(items[i]);
grandRewardView.Init(items[^1].Item, manager.InflationRate);
_scoreLogic = manager.Score;
_scoreDisplay = _scoreLogic;
SetScrollerToIdx(idx);
(var barIdx, var percentage) = manager.TableContext.GetBarProgressDataFromScore(_scoreDisplay);
SetBarsByScore(barIdx, percentage);
SetScoreText(manager.TableContext.GetScopeScoreFromActualScore(_scoreLogic), manager.TableContext.GetCurrentMaxScore(_scoreLogic));
UpdateRewardCount(0, rewards.Length + 1);
for (int i = items.Count - 1; i >= 0; i--)
{
if (items[i].IsReceived)
{
UpdateRewardCount(i + 1, rewards.Length + 1);
break;
}
}
// _maxScore = manager.TableContext.GetMaxScore(manager.Score);
}
private void ResetProgressBar()
{
var manager = GContext.container.Resolve<Manager>();
_idx = 0;
var items = manager.TableContext.GetRewardsData(manager.InflationRate, manager.Score);
if (items.Count < rewards.Length)
Debug.LogError($"Rewards count {items.Count}, less than {rewards.Length}.", this);
for (int i = 0; i < rewards.Length; i++)
rewards[i].Init(items[i]);
SetScrollerToIdx(0);
SetBarsByScore(0, 0);
SetScoreText(0, manager.TableContext.GetCurrentMaxScore(_scoreLogic));
foreach (var reward in rewards)
reward.SetReceived(false);
grandRewardView.Init(items[^1].Item, manager.InflationRate);
grandRewardView.SetClaimed(false);
// _maxScore = manager.TableContext.GetMaxScore(manager.Score);
}
/// <summary>
/// Update score text, update score progress bar, and while at it, if a new reward is to be given, tick it and move the scroller
/// </summary>
/// <param name="e">The incoming exit event</param>
private void OnScore(EventExit e)
{
var manager = GContext.container.Resolve<Manager>();
var score2Add = manager.TableContext.GetScoreFromExitIndex(e.ExitIdx);
_scoreLogic += score2Add;
_scoreQueue.Enqueue(_scoreLogic);
gauge.OnAddScore(score2Add);
ProcessQueue();
}
private async void ProcessQueue()
{
if (_isProcessingQueue)
return;
var manager = GContext.container.Resolve<Manager>();
_isProcessingQueue = true;
while (_scoreQueue.Count > 0)
{
var targetScore = _scoreQueue.Dequeue();
await MoveBarsByScoreAsync(targetScore);
}
_isProcessingQueue = false;
}
#region ScoreText
private void SetScoreText(int score, int maxScore)
{
textScore.text = score.ToString() + "/" + maxScore.ToString();
}
#endregion
#region Bars
private void SetBarsByScore(int idx, float percentage)
{
var manager = GContext.container.Resolve<Manager>();
// (var idx, var percentage) = manager.TableContext.GetBarProgressDataFromScore(score);
for (int i = 0; i < bars.Length; i++)
{
if (i < idx)
bars[i].fillAmount = 1;
else if (i == idx)
bars[i].fillAmount = percentage;
else
bars[i].fillAmount = 0;
}
}
[SerializeField] private float barSpeed = 1f;
private async Task MoveBarsByScoreAsync(int targetScore)
{
try
{
var manager = GContext.container.Resolve<Manager>();
(var oldIdx, var oldPercentage) = manager.TableContext.GetBarProgressDataFromScore(_scoreDisplay);
(var newIdx, var newPercentage) = manager.TableContext.GetBarProgressDataFromScore(targetScore);
// Debug.Log($"[PinballUncountable] From {_scoreDisplay} To {targetScore} !");
if (oldIdx == newIdx)
{
// Debug.Log("[PinballUncountable] BarMove: Same!");
await bars[oldIdx].DOFillAmount(newPercentage, (newPercentage - oldPercentage) / barSpeed).SetId(this).AsyncWaitForCompletion();
MoveScrollerToIdx(oldIdx);
_scoreDisplay = targetScore;
SetScoreText(manager.TableContext.GetScopeScoreFromActualScore(targetScore), manager.TableContext.GetCurrentMaxScore(targetScore));
}
else if (oldIdx < newIdx)
{
// Debug.Log("[PinballUncountable] BarMove: Next!");
await bars[oldIdx].DOFillAmount(1, (1 - oldPercentage) / barSpeed).SetId(this).AsyncWaitForCompletion();
await SetReceived(oldIdx);
MoveScrollerToIdx(oldIdx);
for (int i = oldIdx + 1; i < newIdx; i++)
{
await bars[i].DOFillAmount(1, 1 / barSpeed).SetId(this).AsyncWaitForCompletion();
await SetReceived(i);
MoveScrollerToIdx(i);
}
await bars[newIdx].DOFillAmount(newPercentage, newPercentage / barSpeed).SetId(this).AsyncWaitForCompletion();
MoveScrollerToIdx(newIdx);
_scoreDisplay = targetScore;
SetScoreText(manager.TableContext.GetScopeScoreFromActualScore(targetScore), manager.TableContext.GetCurrentMaxScore(targetScore));
}
else
{
// Debug.Log("[PinballUncountable] BarMove: Twist!");
await bars[oldIdx].DOFillAmount(1, (1 - oldPercentage) / barSpeed).SetId(this).AsyncWaitForCompletion();
SetScoreText(manager.TableContext.GetCurrentMaxScore(_scoreDisplay), manager.TableContext.GetCurrentMaxScore(_scoreDisplay));
await SetReceived(oldIdx);
Debug.Log("[OfferTreasureAscent] Show special panel.");
var openGo = await UIManager.Instance.ShowUINotLoading(UITypes.PinballUncountableBoxPanel);
await openGo.GetComponent<OfferTreasureAscentGrandRewardPopup>().PlayAnimation();
UIManager.Instance.DestroyUI(UITypes.PinballUncountableBoxPanel);
// 等待玩家在奖励弹窗中点击领取后再继续:订阅一次 FishingTurnTableContinueMultiDraw弹窗关闭时会发布该事件
var claimTcs = new TaskCompletionSource<bool>();
IDisposable claimSub = null;
claimSub = GContext.OnEvent<FishingTurnTableContinueMultiDraw>()
.Take(1)
.Subscribe(_ =>
{
claimTcs.TrySetResult(true);
claimSub?.Dispose();
});
GContext.Publish(new ShowData(grandRewardView.RewardItems));
GContext.Publish(new ShowData());
await claimTcs.Task;
claimSub?.Dispose();
MoveScrollerToIdx(oldIdx);
for (int i = oldIdx + 1; i < bars.Length; i++)
{
await bars[i].DOFillAmount(1, 1 / barSpeed).SetId(this).AsyncWaitForCompletion();
await SetReceived(i);
MoveScrollerToIdx(i);
}
ResetProgressBar();
for (int i = 0; i < newIdx; i++)
{
await bars[i].DOFillAmount(1, 1 / barSpeed).SetId(this).AsyncWaitForCompletion();
await SetReceived(i);
MoveScrollerToIdx(i);
}
await bars[newIdx].DOFillAmount(newPercentage, newPercentage / barSpeed).SetId(this).AsyncWaitForCompletion();
MoveScrollerToIdx(newIdx);
_scoreDisplay = targetScore;
SetScoreText(manager.TableContext.GetScopeScoreFromActualScore(targetScore), manager.TableContext.GetCurrentMaxScore(targetScore));
}
}
catch (Exception e)
{
Debug.LogError(e);
}
}
#endregion
#region Scroller
private void MoveScrollerToIdx(int idx)
{
idx -= 1;
idx = Mathf.Clamp(idx, 0, rewards.Length - _displayCount);
_idx = idx;
// scroller.anchoredPosition = new Vector2(startPos - gap * idx, scroller.anchoredPosition.y);
_tween?.Kill();
_tween = scroller.DOAnchorPosX(startPos - gap * idx, 0.5f);
// Debug.Log($"[PinballUncountable] move to {idx}");
}
private void SetScrollerToIdx(int idx)
{
idx = Mathf.Clamp(idx, 0, rewards.Length - _displayCount);
_idx = idx;
scroller.anchoredPosition = new Vector2(startPos - gap * idx, scroller.anchoredPosition.y);
}
#endregion
#region Reward
// UGLY: may be able to separate final reward display
private async Task SetReceived(int idx)
{
if (idx < 0 || idx > rewards.Length)
return;
if (idx == rewards.Length)
{
Debug.Log("[PinballUncountable] SetReceived: Final reward!!!!!!!!!!");
grandRewardView.SetClaimed();
GContext.Publish(new EventUISound("audio_ui_reward_claim"));
UpdateRewardCount(idx + 1, rewards.Length + 1);
// await Task.Delay(TimeSpan.FromSeconds(2f));
return;
}
if (rewards[idx] == null)
return;
rewards[idx].SetReceived(true);
GContext.Publish(new EventUISound("audio_ui_reward_claim"));
UpdateRewardCount(idx + 1, rewards.Length + 1);
await Task.Delay(TimeSpan.FromSeconds(0.5f));
}
#endregion
private void UpdateRewardCount(int receivedRewardCount, int maxRewardCount)
{
// textRewardCount.text = $"我拿到了{receivedRewardCount}/{maxRewardCount},缺少多语言";
textRewardCount.text = LocalizationMgr.GetFormatTextValue("UI_EventPinballUncountableCowboyPanel_2", receivedRewardCount, maxRewardCount);
}
#if UNITY_EDITOR
[SerializeField] private int testScore;
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
MoveScrollerToIdx(_idx + 1);
}
if (Input.GetKeyDown(KeyCode.R))
{
scroller.anchoredPosition = new Vector2(startPos, 0);
_idx = 0;
}
// if (Input.GetKeyDown(KeyCode.B))
// {
// SetBarsByScore(testScore);
// }
}
// private void OnGUI()
// {
// GUI.Box(new Rect(20, 20, 200, 20), $"IsProcessingQueue: {_isProcessingQueue}");
// }
#endif
}