using RuntimeData;
using TH1_Logic.Core;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace TH1_UI.View.Top
{
public class UITopTopBarView : Base.View
{
private const string TopBarAnimTimerMessage = "UITopTopBarView TopBarAnim";
private const float CoinSelfCheckInterval = 0.5f;
private int _topBarAnimVersion;
private bool _coinAnimActive;
private float _coinAnimEndTime;
private float _nextCoinSelfCheckTime;
//public Button closeButton;
public ViDelegateAssisstant.Dele OnBtnCloseClick;
public TextMeshProUGUI Faith;
public TextMeshProUGUI Turn;
public TextMeshProUGUI Coin;
public TextMeshProUGUI CoinPerTurn;
public Transform CoinTransform;
public Transform FaithTransform;
public TextMeshProUGUI Tech;
public TextMeshProUGUI TechPerTurn;
public Transform TechTransform;
public TextMeshProUGUI Culture;
public TextMeshProUGUI CulturePerTurn;
public Transform CultureTransform;
public RectTransform FatherPanel;
public GameObject PerfectTime;
public enum TopBarPanelType
{
Coin,
Faith,
Tech,
Culture
}
protected override void OnInit()
{
base.OnInit();
//closeButton.onClick.RemoveAllListeners();
//closeButton.onClick.AddListener(() => { OnBtnCloseClick.Invoke(); });
//CheckPanel.InitStart(RefreshStatus);
// 确保所有Transform初始时都是active的,等待数据显示逻辑来控制
// 这样可以防止Prefab中误设为inactive导致无法显示
if (CultureTransform != null)
CultureTransform.gameObject.SetActive(true);
if (TechTransform != null)
TechTransform.gameObject.SetActive(true);
}
//通常一局只会set一次,每次都是完全清空,然后绑定新的一个对局的按钮
public void SetContent()
{
UpdateAllInstant();
// 首次SetContent时强制重建布局,确保所有Panel的位置和大小正确
RebuildCoinPanelLayout();
}
public void UpdateAllInstant()
{
//注意 开局首次调用本函数,所有city都是空,percoin和pertech perculture都是0,需要controller里的每个update函数来刷新的
if (Main.MapData?.PlayerMap?.SelfPlayerData == null) return;
CancelTopBarAnim();
// PerfectTime:仅在Perfect模式下显示
if (PerfectTime != null)
PerfectTime.SetActive(Main.MapData.MapConfig.GameMode == GameMode.PERFECT);
Turn.text = (Main.MapData.PlayerMap.SelfPlayerData.Turn + 1).ToString();
Faith.text = Main.MapData.PlayerMap.SelfPlayerData.PlayerScore.ToString();
SetCoinText(Main.MapData.PlayerMap.SelfPlayerData.PlayerCoin);
CoinPerTurn.text =
"" +
Main.PlayerLogic.GetPlayerCoinPerTurn(Main.MapData,Main.MapData.PlayerMap.SelfPlayerData.Id)
+ "";
RebuildCoinPanelLayout();
var techPerTurn =
Main.PlayerLogic.GetPlayerTechPointPerTurn(Main.MapData, Main.MapData.PlayerMap.SelfPlayerData.Id);
// 强制根据数据显示/隐藏Tech模块
bool techNeedShow = (techPerTurn > 0 || Main.MapData.PlayerMap.SelfPlayerData.PlayerTechPoint > 0);
if (TechTransform != null)
{
bool wasActive = TechTransform.gameObject.activeSelf;
TechTransform.gameObject.SetActive(techNeedShow);
if (wasActive != techNeedShow)
{
LayoutRebuilder.ForceRebuildLayoutImmediate(FatherPanel);
}
if (techNeedShow)
{
Tech.text = Main.MapData.PlayerMap.SelfPlayerData.PlayerTechPoint.ToString();
TechPerTurn.text = "" + techPerTurn + "";
}
}
var culturePerTurn =
Main.PlayerLogic.GetPlayerCulturePointPerTurn(Main.MapData, Main.MapData.PlayerMap.SelfPlayerData.Id);
// 强制根据数据显示/隐藏Culture模块
bool cultureNeedShow = (culturePerTurn > 0 || Main.MapData.PlayerMap.SelfPlayerData.PlayerCultureInfo.PlayerCulture > 0);
//cultureNeedShow = true;
if (CultureTransform != null)
{
bool wasActive = CultureTransform.gameObject.activeSelf;
CultureTransform.gameObject.SetActive(cultureNeedShow);
if (wasActive != cultureNeedShow)
{
LayoutRebuilder.ForceRebuildLayoutImmediate(FatherPanel);
}
if (cultureNeedShow)
{
Culture.text = Main.MapData.PlayerMap.SelfPlayerData.PlayerCultureInfo.PlayerCulture.ToString();
CulturePerTurn.text = "" + culturePerTurn + "";
}
}
}
public void CloseView()
{
//AudioManager.Instance.StopMusic();
}
private void Update()
{
if (Time.time < _nextCoinSelfCheckTime) return;
_nextCoinSelfCheckTime = Time.time + CoinSelfCheckInterval;
SelfCheckCoinText();
}
public void UpdateTurn()
{
Turn.text = (Main.MapData.PlayerMap.SelfPlayerData.Turn + 1).ToString();
}
public void UpdateCoin()
{
if (Main.MapData?.PlayerMap?.SelfPlayerData == null) return;
CancelTopBarAnim();
if (!int.TryParse(Coin.text, out var old))
old = Main.MapData.PlayerMap.SelfPlayerData.PlayerCoin;
float delay = Table.Instance.AnimDataAssets.ProjectileCoinMoveTime;
if (old > Main.MapData.PlayerMap.SelfPlayerData.PlayerCoin) delay = 0f;
TopBarAnim(Coin,old,Main.MapData.PlayerMap.SelfPlayerData.PlayerCoin,delay,TopBarPanelType.Coin);
}
public void UpdateTech()
{
if (Main.MapData?.PlayerMap?.SelfPlayerData == null) return;
var techPerTurn =
Main.PlayerLogic.GetPlayerTechPointPerTurn(Main.MapData, Main.MapData.PlayerMap.SelfPlayerData.Id);
//如果techTransform应该显示的状态和实际状态不一致,更新其显示状态
bool needShow = (techPerTurn > 0 || Main.MapData.PlayerMap.SelfPlayerData.PlayerTechPoint > 0);
if (needShow != TechTransform.gameObject.activeSelf)
{
TechTransform.gameObject.SetActive(techPerTurn > 0);
LayoutRebuilder.ForceRebuildLayoutImmediate(FatherPanel);
}
if (needShow)
{
Tech.text = Main.MapData.PlayerMap.SelfPlayerData.PlayerTechPoint.ToString();
TechPerTurn.text = "" + techPerTurn + "";
}
}
public void UpdateCulture()
{
if (Main.MapData?.PlayerMap?.SelfPlayerData == null) return;
var culturePerTurn =
Main.PlayerLogic.GetPlayerCulturePointPerTurn(Main.MapData, Main.MapData.PlayerMap.SelfPlayerData.Id);
// 强制根据数据显示/隐藏Culture模块
bool needShow = (culturePerTurn > 0 || Main.MapData.PlayerMap.SelfPlayerData.PlayerCultureInfo.PlayerCulture > 0);
if (CultureTransform != null)
{
bool wasActive = CultureTransform.gameObject.activeSelf;
CultureTransform.gameObject.SetActive(needShow);
if (wasActive != needShow)
{
LayoutRebuilder.ForceRebuildLayoutImmediate(FatherPanel);
}
if (needShow)
{
Culture.text = Main.MapData.PlayerMap.SelfPlayerData.PlayerCultureInfo.PlayerCulture.ToString();
CulturePerTurn.text = "" + culturePerTurn + "";
}
}
}
public void UpdateFaith()
{
if (Main.MapData?.PlayerMap?.SelfPlayerData == null) return;
if (!int.TryParse(Faith.text, out var old)) return;
//不允许脱离action逻辑修改mapData
//Main.PlayerLogic.CalcAllPlayerScore(Main.MapData);
Faith.text = Main.MapData.PlayerMap.SelfPlayerData.PlayerScore.ToString();
/*float delay = Table.Instance.AnimDataAssets.ProjectileCoinMoveTime;
if (old > Main.MapData.PlayerMap.SelfPlayerData.PlayerScore) delay = 0f;
TopBarAnim(Faith,old,Main.MapData.PlayerMap.SelfPlayerData.PlayerScore,delay);
*/
}
private void TopBarAnim(TextMeshProUGUI targetText, int oldValue,int targetValue,float startDelay,TopBarPanelType panelType)
{
var animVersion = _topBarAnimVersion;
int maxTime = 100;
int now = oldValue;
int time = Mathf.Abs(targetValue - oldValue);
int step = targetValue > oldValue ? 1 : -1;
if (time > maxTime)
{
time = maxTime;
step = (targetValue - oldValue) / time;
}
if (time == 0)
{
SetTopBarAnimText(targetText, targetValue, panelType);
return;
}
if (panelType == TopBarPanelType.Coin)
{
_coinAnimActive = true;
_coinAnimEndTime = Time.time + Mathf.Max(0f, startDelay) + (time - 1) * 0.03f + 0.1f;
}
for (int s = 0; s < time; s++)
{
now += step;
//如果时长太长,直接跳到结果
//final Check用来在最后一帧强制对其真实数值coin 或者faith
bool finalCheck = false;
if (s == time - 1)
{
now = targetValue;
finalCheck = true;
}
var panel = panelType;
var text = targetText;
var tmp = now;
var tmps = Mathf.Min(s,200);
Timer.Instance.TimerRegister(this, () =>
{
if (animVersion != _topBarAnimVersion) return;
SetTopBarAnimText(text, tmp, panel);
if (finalCheck)
{
if(panel == TopBarPanelType.Coin && Main.MapData != null)
{
SetTopBarAnimText(text, Main.MapData.PlayerMap.SelfPlayerData.PlayerCoin, panel);
_coinAnimActive = false;
}
}
},tmps * 0.03f + startDelay , TopBarAnimTimerMessage);
}
}
private void CancelTopBarAnim()
{
_topBarAnimVersion++;
_coinAnimActive = false;
Timer.Instance?.CancelByMessage(TopBarAnimTimerMessage);
}
private void SelfCheckCoinText()
{
if (Main.MapData?.PlayerMap?.SelfPlayerData == null || Coin == null) return;
if (_coinAnimActive)
{
if (Time.time <= _coinAnimEndTime) return;
CancelTopBarAnim();
}
var realCoin = Main.MapData.PlayerMap.SelfPlayerData.PlayerCoin;
if (int.TryParse(Coin.text, out var showCoin) && showCoin == realCoin) return;
CancelTopBarAnim();
SetCoinText(realCoin);
}
public void UpdateCoinPerTurn()
{
if (Main.MapData?.PlayerMap?.SelfPlayerData == null) return;
CoinPerTurn.text = "" + Main.PlayerLogic.GetPlayerCoinPerTurn(Main.MapData,Main.MapData.PlayerMap.SelfPlayerData.Id) + "";
RebuildCoinPanelLayout();
}
private void RebuildCoinPanelLayout()
{
RebuildTopBarLayout(
Coin != null ? Coin.rectTransform : null,
CoinPerTurn != null ? CoinPerTurn.rectTransform : null,
CoinTransform as RectTransform);
}
private void SetTopBarAnimText(TextMeshProUGUI targetText, int value, TopBarPanelType panelType)
{
if (panelType == TopBarPanelType.Coin)
{
SetCoinText(value);
return;
}
if (targetText == null) return;
targetText.text = value.ToString();
}
private void SetCoinText(int value)
{
if (Coin == null) return;
Coin.text = value.ToString();
Coin.ForceMeshUpdate();
RebuildTopBarLayout(Coin.rectTransform, CoinTransform as RectTransform);
}
private void RebuildTopBarLayout(params RectTransform[] rebuildRoots)
{
foreach (var root in rebuildRoots)
{
if (root != null)
LayoutRebuilder.ForceRebuildLayoutImmediate(root);
}
if (FatherPanel != null)
LayoutRebuilder.ForceRebuildLayoutImmediate(FatherPanel);
}
}
}