TH1/My project/Assets/Scripts/UI/TechTreeUI.cs
2025-07-16 15:41:43 +08:00

384 lines
18 KiB
C#
Raw 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 System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UI;
using TMPro;
using Animancer;
using Logic;
using Logic.Action;
using Logic.Audio;
using RuntimeData;
using Unity.VisualScripting;
using Logic.Multilingual;
using TH1Renderer;
using TH1Resource;
public class TechTreeUI
{
public GameObject ROTechTreeUI;
public GameObject ROTechCheckPanel;
private Main _main;
private MapData _mapData;
//-------- UI表现层RenderData --------//
public bool TechTreeUIStatus = false;
public bool ShowHideAnimMark = false;
public bool TechTreeUIDataRenderMark = false;
public bool TechCheckPanelStatus = false;
public bool TechCheckPanelShowHideAnimMark = false;
public TechType TechCheckTechType;
//------- 动画数据 ---------//
private bool _isAnimating = false;
private float _fadeTime = 0f;
private bool _isShow = false;
private float _fadeDuration = 0.2f;
private TechType _techTypeChoose;
private int _techNoChooseCost = 0;
bool firstTimeShowPanel = true;
public TechTreeUI(Main main, MapData mapData)
{
_main = main;
_mapData = mapData;
ROTechTreeUI = UIManager.Instance.ROUIManager.transform.Find("TechTreePanel").gameObject;
ROTechCheckPanel = ROTechTreeUI.transform.Find("TechCheckPanel").gameObject;
//绑定关闭按钮点击事件
ROTechTreeUI.transform.Find("CloseButton").GetComponent<Button>().onClick.AddListener(()=>PlayAnimTechTreeHide());
Transform techTree = ROTechTreeUI.transform.Find("TechTree");
HideTechCheckPanel();//隐藏TechCheckPanel
Button techCheckPanelCloseButton = ROTechCheckPanel.transform.Find("ButtonGroup").transform.Find("ButtonCancel").GetComponent<Button>();
Button techCheckPanelReserchButton = ROTechCheckPanel.transform.Find("ButtonGroup").transform.Find("ButtonResearch").GetComponent<Button>();
techCheckPanelCloseButton.onClick.AddListener(HideTechCheckPanel);
techCheckPanelReserchButton.onClick.AddListener(ResearchTech);
//设置每个科技圈圈内显示的图标是什么
foreach (Transform techNode in techTree)
{
TechType techType = techNode.GetComponent<TechTypeMono>().TechType;
var techInfo = Table.Instance.TechDataAssets.GetTechInfo(techType);
if (techInfo.GiantTech)
continue;
Button btn = techNode.GetComponent<Button>();
TextMeshProUGUI txt = techNode.Find("Text").GetComponent<TextMeshProUGUI>();
int rk = 0;
foreach(var techItem in techInfo.techActions)
{
rk++;
Image img = techNode.Find("ImageGroup").transform.Find($"Circle{rk.ToString()}/Image").GetComponent<Image>();
MultilingualManager.Instance.SetUIText(txt, techInfo.TechName);
if (!Table.Instance.ActionDataAssets.GetActionInfo(techItem, out var actionInfo))
continue;
RectTransform rectTransform = img.rectTransform;
rectTransform.pivot = new Vector2(0.5f, 0.5f);
rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
rectTransform.anchoredPosition = Vector2.zero;
rectTransform.anchoredPosition = new Vector2(0, 20);
//如果是会变化的icon
if (actionInfo.VarientIcon)
{
img.sprite = actionInfo.GetIcon(mapData.PlayerMap.SelfPlayerData.PlayerCivId, mapData.PlayerMap.SelfPlayerData.PlayerForceId);
rectTransform.sizeDelta = new Vector2(120, 120);
if (techItem.ActionType == CommonActionType.TrainUnit)
{
rectTransform.sizeDelta = new Vector2(60, 60);
rectTransform.anchoredPosition = new Vector2(0, 0);
}
}
else
{
img.sprite = actionInfo.Icon;
rectTransform.sizeDelta = new Vector2(90, 90);
}
}
for (int j = techInfo.techActions.Count + 1; j <= 3; j++)
//GameObject.Destroy(techNode.Find("ImageGroup").transform.Find($"Circle{j.ToString()}").gameObject);//.SetActive(false);
techNode.Find("ImageGroup").transform.Find($"Circle{j.ToString()}").gameObject.SetActive(false);
//if (techInfo.techActions.Count >= 3)//如果大于等于3还要把imageGroup的尺寸设置小一点避免穿模
// techNode.Find("ImageGroup").transform.localScale = new Vector3(0.9f, 0.9f, 0.9f);
}
}
//当需要更新渲染科技树的时候调用
public void RenderUpdateTechTreeData()
{
Transform techTree = ROTechTreeUI.transform.Find("TechTree");
//techCheckPanel = techTreeUI.transform.Find("TechCheckPanel").gameObject;
foreach (Transform techNode in techTree)
{
TechType techType = techNode.GetComponent<TechTypeMono>().TechType;
var techInfo = Table.Instance.TechDataAssets.GetTechInfo(techType);
Button btn = techNode.GetComponent<Button>();
TextMeshProUGUI txt = techNode.Find("Text").GetComponent<TextMeshProUGUI>();
//TechType techType = Table.Instance.LegacyTechListToTechType(techNo);
btn.onClick.AddListener(() => SetTechCheckPanelShowHide(true,techType));
//Debug.Log(techType);
//如果该科技已经学习
if (Main.MapData.PlayerMap.SelfPlayerData.TechTree.CheckIfHasTech(techType))
{
Image img = techNode.transform.Find("Background").GetComponent<Image>();
img.sprite = ResourceCache.Instance.SpriteCache.TechCompleteBackground;
techNode.Find("costNumber").gameObject.SetActive(false);
techNode.Find("star").gameObject.SetActive(false);
//如果不是giant科技就把下面3个circle对象的背景都变成绿的已完成
if(!techInfo.GiantTech)
for (int i = 1; i <= techInfo.techActions.Count; i++)
{
techNode.transform.Find($"ImageGroup/Circle{i}")?.GetComponent<Image>().gameObject.SetActive(true);
if (techNode.transform.Find($"ImageGroup/Circle{i}") != null)
techNode.transform.Find($"ImageGroup/Circle{i}").GetComponent<Image>().sprite = ResourceCache.Instance.SpriteCache.TechCompleteBackground;
}
}
else
//如果该科技未解锁
if (Main.MapData.PlayerMap.SelfPlayerData.TechTree.CheckIfTechUnsee(techType))
{
Image img = techNode.Find("Background").GetComponent<Image>();
img.sprite = ResourceCache.Instance.SpriteCache.TechLockedBackground;
techNode.Find("costNumber").gameObject.SetActive(false);
techNode.Find("star").gameObject.SetActive(false);
for (int i = 1; i <= techInfo.techActions.Count; i++)
techNode.transform.Find($"ImageGroup/Circle{i}")?.GetComponent<Image>().gameObject.SetActive(false);
}
else //if(Main.MapData.PlayerMap.SelfPlayerData.TechTree.CheckIfTechCanLearn(techType))
//如果该科技可以学习
{
TextMeshProUGUI costTxt = techNode.Find("costNumber").GetComponent<TextMeshProUGUI>();
//计算目前该tech的学习成本=科技基础cost * 城市数 + 4
var img = techNode.Find("Background").GetComponent<Image>();
img.sprite = ResourceCache.Instance.SpriteCache.TechAvailableBackground;
int tmpCost = (Main.MapData.GetCityCount(Main.MapData.PlayerMap.SelfPlayerData.Id)
* techInfo.CostLevel + 4);
costTxt.text = tmpCost.ToString();
if (tmpCost > Main.MapData.PlayerMap.SelfPlayerData.PlayerWealth)
costTxt.color = Color.red;
else costTxt.color = Color.white;
costTxt.gameObject.SetActive(true);
techNode.Find("star").gameObject.SetActive(true);
for (int i = 1; i <= techInfo.techActions.Count; i++)
techNode.transform.Find($"ImageGroup/Circle{i}")?.GetComponent<Image>().gameObject.SetActive(true);
}
}
}
public void Update(MapData mapData)
{
//如果则当前不需要显示直接return
if (!ROTechTreeUI.activeSelf && !TechTreeUIStatus)
return;
//先更新data
if (TechTreeUIDataRenderMark)
{
RenderUpdateTechTreeData();
TechTreeUIDataRenderMark = false;
}
//处理动画播放or关闭动画
if (ROTechTreeUI.activeSelf != TechTreeUIStatus && ShowHideAnimMark)
{
ShowHideAnimMark = false;
if(TechTreeUIStatus)
PlayAnimTechTreeShow();
else PlayAnimTechTreeHide();
}
//处理techcheckpanel的fade动画
if (TechCheckPanelStatus != ROTechCheckPanel.activeSelf && TechCheckPanelShowHideAnimMark)
{
TechCheckPanelShowHideAnimMark = false;
if (TechCheckPanelStatus)
ShowTechCheckPanel(mapData, TechCheckTechType);
else
HideTechCheckPanel();
}
}
public void RenderUpdateTechCheckPanel(MapData mapData)
{
TechInfo techInfo = Table.Instance.TechDataAssets.GetTechInfo(_techTypeChoose);
PlayerData selfPlayer = Main.MapData.PlayerMap.SelfPlayerData;
ROTechCheckPanel.SetActive(true);
//记录一下目前点击的techNo和费用以供点击Research时判断使用
_techNoChooseCost = (Main.MapData.GetCityCount(selfPlayer.Id) * techInfo.CostLevel + 4);
TextMeshProUGUI title = ROTechCheckPanel.transform.Find("Title").GetComponent<TextMeshProUGUI>();
TextMeshProUGUI cost = ROTechCheckPanel.transform.Find("Title").transform.Find("costNumber").GetComponent<TextMeshProUGUI>();
cost.text = _techNoChooseCost.ToString();
MultilingualManager.Instance.SetUIText(title, techInfo.TechName);
//title.text = techInfo.TechName;
//设置研发按钮的表现
ROTechCheckPanel.transform.Find("ButtonGroup").transform.Find("ButtonResearch").gameObject.SetActive(true);
int itemsCount = techInfo.techActions.Count;
Transform items = ROTechCheckPanel.transform.Find("UnlockItems");
int rk = 0;
foreach(var techItem in techInfo.techActions)
{
++rk;
Transform child = items.GetChild(rk - 1);
child.gameObject.SetActive(true);
Image img = child.Find("Image").GetComponent<Image>();
if (!Table.Instance.ActionDataAssets.GetActionInfo(techItem, out var actionInfo))
return;
if (actionInfo.VarientIcon)
img.sprite = actionInfo.GetIcon(mapData.PlayerMap.SelfPlayerData.PlayerCivId,mapData.PlayerMap.SelfPlayerData.PlayerForceId);
else
img.sprite = actionInfo.Icon;
//Resources.Load<Sprite>(Table.Instance.QueryTechImageSrc(techNo, i, selfPlayer.PlayerForceId,selfPlayer.PlayerCivId));
TextMeshProUGUI txt = child.Find("Text").GetComponent<TextMeshProUGUI>();
MultilingualManager.Instance.SetUIText(txt, actionInfo.ActionName);
}
for(int i = itemsCount; i< 3; i++)
{
Transform child = items.GetChild(i);
child.gameObject.SetActive(false);
}
//如果已经研发完成
if (selfPlayer.TechTree.CheckIfHasTech(_techTypeChoose))
{
title.text += "(已完成)";
ROTechCheckPanel.transform.Find("ButtonGroup").transform.Find("ButtonResearch").gameObject.SetActive(false);
ROTechCheckPanel.transform.Find("Title").transform.Find("costNumber").gameObject.SetActive(false);
ROTechCheckPanel.transform.Find("Title").transform.Find("star").gameObject.SetActive(false);
}
else
//如果还没解锁
if (selfPlayer.TechTree.CheckIfTechUnsee(_techTypeChoose))
{
if (techInfo.GiantTech)
title.text = "研发该区任意3科技后解锁";
else
title.text += "(需完成前置科技)";
ROTechCheckPanel.transform.Find("ButtonGroup").transform.Find("ButtonResearch").gameObject.SetActive(false);
ROTechCheckPanel.transform.Find("Title").transform.Find("costNumber").gameObject.SetActive(true);
ROTechCheckPanel.transform.Find("Title").transform.Find("star").gameObject.SetActive(true);
}
else
//如果可以研发但是买不起则cost显示红色按钮disable
if (selfPlayer.PlayerWealth < _techNoChooseCost)
{
title.text += "(费用不足)";
cost.color = Color.red;
ROTechCheckPanel.transform.Find("ButtonGroup").transform.Find("ButtonResearch").GetComponent<Button>().interactable = false;
ROTechCheckPanel.transform.Find("Title").transform.Find("costNumber").gameObject.SetActive(true);
ROTechCheckPanel.transform.Find("Title").transform.Find("star").gameObject.SetActive(true);
}
//其他情况,那只能是可以研发了这一种情况了
else
{
cost.color = Color.white;
ROTechCheckPanel.transform.Find("ButtonGroup").transform.Find("ButtonResearch").GetComponent<Button>().interactable = true;
ROTechCheckPanel.transform.Find("Title").transform.Find("costNumber").gameObject.SetActive(true);
ROTechCheckPanel.transform.Find("Title").transform.Find("star").gameObject.SetActive(true);
}
}
//点击某个科技树后显示科技树状态
public void ShowTechCheckPanel(MapData mapData, TechType techType)//techNo是0开始的顺序编号techId是不连续的,11,121,这种代号
{
_techTypeChoose = techType;
RenderUpdateTechCheckPanel(mapData);
//播放fadeIn动画
AnimancerComponent animancer = ROTechCheckPanel.GetComponent<AnimancerComponent>();
AnimationClip animationB = Resources.Load<AnimationClip>("Animations/UI/TechButton/TechCheckPanelFadeIn");
animancer.Play(animationB);
}
public void HideTechCheckPanel()
{
AnimancerComponent animancer = ROTechCheckPanel.GetComponent<AnimancerComponent>();
AnimationClip animationB = Resources.Load<AnimationClip>("Animations/UI/TechButton/TechCheckPanelFadeOut"); // 需要播放的动画片段
animancer.Play(animationB); // 直接播放动画B
Timer.Instance.TimerRegister(ROTechTreeUI, OnTechCheckPanelFadeOutComplete, 0.2f);
}
public void SetTechCheckPanelShowHide(bool status,TechType techType = TechType.None)
{
TechCheckPanelStatus = status;
TechCheckPanelShowHideAnimMark = true;
TechCheckTechType = techType;
}
public void ResearchTech()
{
//钱不够就不能研发。这种情况理应不会发生
if (Main.MapData.PlayerMap.SelfPlayerData.PlayerWealth < _techNoChooseCost)
return;
Main.PlayerLogic.ResearchTech(Main.MapData,Main.MapData.PlayerMap.SelfPlayerData,_techTypeChoose,_techNoChooseCost);
SetTechCheckPanelShowHide(false);
RenderUpdateTechTreeData();
UIManager.Instance.TopBarUI.RenderMark = true;
}
private void PlayAnimTechTreeShow()
{
ROTechTreeUI.SetActive(true);
AnimancerComponent animancer = ROTechTreeUI.GetComponent<AnimancerComponent>();
AnimationClip animationB = Resources.Load<AnimationClip>("Animations/UI/TechTreePanelFadeIn"); // 需要播放的动画片段
animancer.Play(animationB); // 直接播放动画B
//播放音乐
AudioManager.Instance.PlayMusic("RemiliaEgyptian", 1f, 0.3f, true);
}
private void PlayAnimTechTreeHide()
{
AnimancerComponent animancer = ROTechTreeUI.GetComponent<AnimancerComponent>();
AnimationClip animationB = Resources.Load<AnimationClip>("Animations/UI/TechTreePanelFadeOut"); ; // 需要播放的动画片段
animancer.Play(animationB); // 直接播放动画B
UIManager.Instance.BottomBarUI.SetBottomBarShowHide(true);
Timer.Instance.TimerRegister(ROTechTreeUI, OnFadeOutComplete,0.2f);
//停止播放音乐
AudioManager.Instance.StopMusic();
}
//对外方法设置techtree为show或者hide
public void SetTechTreeShowHide(bool status)
{
ShowHideAnimMark = true;
TechTreeUIStatus = status;
if (status)
TechTreeUIDataRenderMark = true;
}
private void OnFadeOutComplete()
{
ROTechTreeUI.SetActive(false);
}
private void OnTechCheckPanelFadeOutComplete()
{
ROTechCheckPanel.SetActive(false);
}
}