578 lines
17 KiB
C#
578 lines
17 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using System;
|
|
using DG.Tweening;
|
|
using UnityEngine.Rendering.Universal;
|
|
using UnityEngine.UI;
|
|
using UnityEngine.EventSystems;
|
|
|
|
public class TreeControl : MonoSingleton<TreeControl>
|
|
{
|
|
[Header("面板UI")]
|
|
public GameObject CanvasUI;
|
|
private CanvasGroup canvasGroup;
|
|
private Sequence showSequence; // 缓存的打开动画序列
|
|
private Sequence hideSequence; // 缓存的关闭动画序列
|
|
[Header("树节点头部")]
|
|
public TechItem HeadItem;
|
|
[Header("解锁亮光强度")]
|
|
public float MaxLightNum;
|
|
[Header("解锁线宽度")]
|
|
public float MaxLineWidth;
|
|
[Header("未解锁亮光强度")]
|
|
public float MinLightNum;
|
|
[Header("未解锁线宽度")]
|
|
public float MinLineWidth;
|
|
[Header("点击所需时间")]
|
|
public float NeedTimes;
|
|
private Transform NodePa;
|
|
private Dictionary<Transform, TechItem> BlindItem;
|
|
private Dictionary<TechItem, Transform> BlindObj;
|
|
public Dictionary<string, TechItem> TechItems;
|
|
|
|
private Action FollowLineStyle;
|
|
private Action MainStyle;
|
|
|
|
private float currenttimes;
|
|
[HideInInspector]
|
|
public GameObject currentobj;
|
|
private TechItem currentItem;
|
|
|
|
private Dictionary<string, Action> NodeEvent;
|
|
|
|
public Material LockLinematerial;//亮线
|
|
public Material UnLockLineMaterial;//暗线
|
|
public GameObject lineObj;
|
|
|
|
public List<UI_InformationPanel.BTInfo> NoTechInfo;
|
|
|
|
public bool DebugRemainUnLock = false;
|
|
|
|
public Image TimeImage;//时间冷却图像
|
|
public override void Awake()
|
|
{
|
|
base.Awake();
|
|
canvasGroup = CanvasUI.transform.GetComponent<CanvasGroup>();
|
|
CanvasUI.SetActive(false);
|
|
// 创建动画序列
|
|
CreateSequences();
|
|
|
|
NodePa = transform.Find("节点组");
|
|
BlindItem = new Dictionary<Transform, TechItem>();
|
|
BlindObj = new Dictionary<TechItem, Transform>();
|
|
TechItems = new Dictionary<string, TechItem>();
|
|
Instance.UINameOpen(false);
|
|
}
|
|
private void Start()
|
|
{
|
|
InfoBlind(HeadItem);
|
|
CreatTree(HeadItem);
|
|
|
|
}
|
|
private void Update()
|
|
{
|
|
FollowLineStyle?.Invoke();
|
|
MainStyle?.Invoke();
|
|
|
|
|
|
|
|
|
|
// Vector3 pos = Camera.main.WorldToViewportPoint (CanvasUI.transform.position);
|
|
// pos.x = Mathf.Clamp01(pos.x);
|
|
// pos.y = Mathf.Clamp01(pos.y);
|
|
// CanvasUI.transform.position = Camera.main.ViewportToWorldPoint(pos);
|
|
}
|
|
#region 初始化
|
|
|
|
private void InfoBlind(TechItem techItem)
|
|
{
|
|
if(!DebugRemainUnLock)techItem.LockOver = false;
|
|
Debug.LogWarning("====" + techItem.itemName);
|
|
Transform trans = NodePa.Find(techItem.itemName);
|
|
|
|
Debug.LogWarning("---" + trans.name);
|
|
if (!BlindItem.ContainsKey(trans))
|
|
{
|
|
TechItems[techItem.itemName]= techItem;
|
|
Debug.Log(techItem.itemName + " keji add " + trans.name);
|
|
BlindItem.Add(trans, techItem);
|
|
BlindObj.Add(techItem, trans);
|
|
foreach (var item in techItem.children)
|
|
{
|
|
InfoBlind(item);
|
|
}
|
|
trans.Find("科技名UI/名字").GetComponent<Text>().text = techItem.itemName;
|
|
}
|
|
}
|
|
public void CreatTree(TechItem techItem, HashSet<string> names = null)
|
|
{
|
|
if (names == null)
|
|
{
|
|
names = new HashSet<string>();
|
|
}
|
|
if (!names.Contains(techItem.itemName))
|
|
{
|
|
names.Add(techItem.itemName);
|
|
BlindLineConnect(techItem);
|
|
foreach (var item in techItem.children)
|
|
{
|
|
CreatTree(item, names);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
private void LightNode(TechItem techItem)
|
|
{
|
|
Transform SelfTrans = BlindObj[techItem];
|
|
Light2D light = SelfTrans.GetComponent<Light2D>();
|
|
LightOpenALL(light);
|
|
}
|
|
|
|
private void NoLightNode(TechItem techItem)
|
|
{
|
|
Transform trans = BlindObj[techItem];
|
|
Light2D light = trans.GetComponent<Light2D>();
|
|
LightClose(light);
|
|
}
|
|
/// <summary>
|
|
/// 已解锁亮光
|
|
/// </summary>
|
|
private void LightOpenALL(Light2D light)
|
|
{
|
|
Debug.Log("已经解锁亮光");
|
|
light.intensity = MaxLightNum;
|
|
|
|
}
|
|
/// <summary>
|
|
/// 未解锁-小亮
|
|
/// </summary>
|
|
/// <param name="light"></param>
|
|
private void LightClose(Light2D light)
|
|
{
|
|
light.intensity = MinLightNum;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 绑定线
|
|
/// </summary>
|
|
private void BlindLineConnect(TechItem techItem)
|
|
{
|
|
Transform SelfTrans = BlindObj[techItem];
|
|
// 遍历所有父节点
|
|
if (techItem.parent != null && techItem.parent.Count > 0)
|
|
{
|
|
// 遍历所有父节点
|
|
for (int i = 0; i < techItem.parent.Count; i++)
|
|
{
|
|
TechItem parent = techItem.parent[i];
|
|
|
|
if (BlindObj.TryGetValue(parent, out Transform SelfTransPa))
|
|
{
|
|
// 创建一个空的子物体用于存放 LineRenderer
|
|
GameObject lineRendererObject = Instantiate(lineObj, SelfTransPa);
|
|
lineRendererObject.name = SelfTrans.name;
|
|
lineRendererObject.transform.localPosition = Vector3.zero; // 确保位置保持一致
|
|
|
|
// 为这个新创建的子物体添加 LineRenderer
|
|
LineRenderer newLineRenderer = lineRendererObject.GetComponent<LineRenderer>();
|
|
|
|
// 为该父节点的连接线添加 LineFollow 逻辑
|
|
FollowLineStyle += () => LineFollow(SelfTrans, newLineRenderer);
|
|
LineBuild(newLineRenderer, techItem.LockOver);
|
|
if (techItem.MainTech && BlindItem[SelfTransPa].MainTech)//两个都是主干
|
|
{
|
|
lineRendererObject.SetActive(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if (techItem == HeadItem) // 处理头节点的情况
|
|
{
|
|
Transform SelfTransPa = SelfTrans.parent;
|
|
LineRenderer newLineRenderer = SelfTransPa.GetComponent<LineRenderer>();
|
|
|
|
LineBuild(newLineRenderer, techItem.LockOver);
|
|
FollowLineStyle += () => LineFollow(SelfTrans, newLineRenderer);
|
|
}
|
|
}
|
|
|
|
if (techItem.LockOver) // 已解锁直接点亮
|
|
{
|
|
|
|
GetLightAnimation(techItem);
|
|
}
|
|
else
|
|
{
|
|
NoLightNode(techItem);
|
|
}
|
|
|
|
if (techItem.MainTech || techItem.LockOver)
|
|
{
|
|
SelfTrans.gameObject.SetActive(true);
|
|
}
|
|
else
|
|
{
|
|
SelfTrans.gameObject.SetActive(false);
|
|
}
|
|
|
|
}
|
|
|
|
private void LineBuild(LineRenderer lineRenderer, bool islock)
|
|
{
|
|
if (islock)
|
|
{
|
|
lineRenderer.startWidth = MaxLineWidth;
|
|
lineRenderer.endWidth = MaxLineWidth;
|
|
lineRenderer.material = LockLinematerial;
|
|
}
|
|
else
|
|
{
|
|
lineRenderer.startWidth = MinLineWidth;
|
|
lineRenderer.endWidth = MinLineWidth;
|
|
lineRenderer.material = UnLockLineMaterial;
|
|
}
|
|
}
|
|
private void LineFollow(Transform target, LineRenderer line)
|
|
{
|
|
Vector3 pos = line.transform.InverseTransformPoint(target.position);
|
|
line.SetPosition(1, pos);
|
|
}
|
|
|
|
#endregion
|
|
#region 判断能否点亮
|
|
|
|
public void BtnDowm() // 鼠标点到了
|
|
{
|
|
string str = "";
|
|
if (currentobj != null)
|
|
{
|
|
TechItem techItem = BlindItem[currentobj.transform];
|
|
if (!techItem.LockOver) // 自身未解锁
|
|
{
|
|
if (GodComeTIemsEnough(techItem, ref str))
|
|
{
|
|
if (techItem.ResourceEnough()) // 资源足够
|
|
{
|
|
|
|
if (techItem == HeadItem) // 如果是头节点
|
|
{
|
|
currenttimes = 0;
|
|
MainStyle = KeepTime;
|
|
currentobj.GetComponent<DoweenAnimator>().enabled = true;
|
|
Debug.Log("点亮");
|
|
}
|
|
else
|
|
{
|
|
if (AreAllParentsUnlocked(techItem)) // 检查所有父节点是否已解锁
|
|
{
|
|
currenttimes = 0;
|
|
MainStyle = KeepTime;
|
|
currentobj.GetComponent<DoweenAnimator>().enabled = true;
|
|
Debug.Log("点亮");
|
|
}
|
|
else str = "相邻节点未解锁完";
|
|
}
|
|
CanvasUI.transform.Find("内容").GetComponent<Text>().color = Color.yellow;
|
|
}
|
|
else CanvasUI.transform.Find("内容").GetComponent<Text>().color = Color.red;
|
|
}
|
|
}
|
|
}
|
|
ChangeCanvasContect(str);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 检查所有父节点是否都已解锁
|
|
/// </summary>
|
|
private bool AreAllParentsUnlocked(TechItem techItem)
|
|
{
|
|
if (techItem.parent == null || techItem.parent.Count == 0)
|
|
return true; // 如果没有父节点,返回 true
|
|
|
|
foreach (var parent in techItem.parent)
|
|
{
|
|
if (!parent.LockOver) // 只要有一个父节点未解锁,就返回 false
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true; // 如果所有父节点都已解锁,返回 true
|
|
}
|
|
private bool GodComeTIemsEnough(TechItem techItem, ref string str)
|
|
{
|
|
List<GodComingTimes> gods = YiShiUI.Instance.godComingTimes;
|
|
for (int i = 0; i < gods.Count; i++)
|
|
{
|
|
if (gods[i].godType == techItem.GodTimes.godType)
|
|
{
|
|
if (gods[i].Count >= techItem.GodTimes.Count)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
str = "降神次数不足!" + gods[i].GetGodName() + ":(" + gods[i].Count + "/" + techItem.GodTimes.Count + ")";
|
|
return false;
|
|
}
|
|
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
public void BtnUp()//鼠标释放或者点亮了
|
|
{
|
|
TimeImage.fillAmount = 0;
|
|
MainStyle = null;
|
|
if (currentobj != null && currentobj.TryGetComponent(out DoweenAnimator doween))
|
|
{
|
|
doween.enabled = false;
|
|
}
|
|
currentobj = null;
|
|
}
|
|
public void KeepTime()//计时
|
|
{
|
|
currenttimes += Time.deltaTime;
|
|
TimeImage.transform.position = currentobj.transform.position;
|
|
TimeImage.fillAmount = currenttimes / NeedTimes;
|
|
if (currenttimes >= NeedTimes)
|
|
{
|
|
PlayEvent(BlindItem[currentobj.transform].itemName);
|
|
GetLightAnimation(BlindItem[currentobj.transform]);
|
|
CutReource();
|
|
BtnUp();
|
|
}
|
|
}
|
|
|
|
private void GetLightAnimation(TechItem techItem)//点亮效果
|
|
{
|
|
if (techItem == HeadItem)
|
|
{
|
|
if (transform.Find("节点组").TryGetComponent(out LineRenderer line))
|
|
{
|
|
|
|
LineBuild(line, true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (TechItem item in techItem.parent)
|
|
{
|
|
Transform pa = BlindObj[item];
|
|
Transform child = pa.Find(techItem.itemName);
|
|
child.gameObject.SetActive(true);
|
|
if (child.TryGetComponent(out LineRenderer lineone))
|
|
{
|
|
LineBuild(lineone, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
Transform currentobj = BlindObj[techItem];
|
|
|
|
if (currentobj.TryGetComponent(out Light2D light2D))
|
|
{
|
|
LightOpenALL(light2D);
|
|
}
|
|
CanvasUI.transform.Find("内容").GetComponent<Text>().text = "";
|
|
Refreshtech(currentobj.transform);
|
|
}
|
|
|
|
private void CutReource() //消耗资源
|
|
{
|
|
BlindItem[currentobj.transform].LockTech();
|
|
}
|
|
#endregion
|
|
#region CanvasUI动画
|
|
|
|
|
|
/// <summary>
|
|
/// 创建动画序列,用于打开和关闭 UI
|
|
/// </summary>
|
|
private void CreateSequences()
|
|
{
|
|
|
|
// 打开动画序列
|
|
showSequence = DOTween.Sequence()
|
|
.AppendCallback(() => CanvasUI.SetActive(true))
|
|
.Append(canvasGroup.DOFade(1, 0.1f))
|
|
.OnComplete(() =>
|
|
{
|
|
canvasGroup.interactable = true;
|
|
canvasGroup.blocksRaycasts = true;
|
|
})
|
|
.Pause() // 暂停动画
|
|
.SetAutoKill(false); // 防止动画自动销毁
|
|
|
|
// 关闭动画序列
|
|
hideSequence = DOTween.Sequence()
|
|
.Append(canvasGroup.DOFade(0, 0.1f))
|
|
.OnComplete(() =>
|
|
{
|
|
canvasGroup.interactable = false;
|
|
canvasGroup.blocksRaycasts = false;
|
|
CanvasUI.SetActive(false);
|
|
})
|
|
.Pause() // 暂停动画
|
|
.SetAutoKill(false); // 防止动画自动销毁
|
|
}
|
|
|
|
|
|
public void ChangeUIcontect(Transform trans) //ui内容改变
|
|
{
|
|
currentItem = BlindItem[trans];
|
|
}
|
|
|
|
public void ChangeCanvasContect(string str)
|
|
{
|
|
TechItem techItem = currentItem;
|
|
CanvasUI.transform.Find("名字").GetComponent<Text>().text = techItem.itemName;
|
|
CanvasUI.transform.Find("描述").GetComponent<Text>().text = techItem.Describe;
|
|
CanvasUI.transform.Find("功能").GetComponent<Text>().text = techItem.FunDescription;
|
|
string contectstr = "";
|
|
if (str != "") contectstr = "[" + str + "]" + "\n"; ;
|
|
for (int i = 0; i < techItem.needReources.Count; i++)
|
|
{
|
|
string kindname = techItem.needReources[i].kind.ToString();
|
|
string countstr = techItem.needReources[i].Count.ToString();
|
|
contectstr += countstr ;
|
|
}
|
|
if (!techItem.LockOver)
|
|
{
|
|
CanvasUI.transform.Find("内容").GetComponent<Text>().text = contectstr;
|
|
CanvasUI.transform.Find("ICON").gameObject.SetActive(true);
|
|
}
|
|
else
|
|
{
|
|
CanvasUI.transform.Find("内容").GetComponent<Text>().text = "";
|
|
CanvasUI.transform.Find("ICON").gameObject.SetActive(false);
|
|
}
|
|
|
|
}
|
|
/// <summary>
|
|
/// 打开 UI
|
|
/// </summary>
|
|
public void ActiveUITrue(Vector3 pos)
|
|
{
|
|
|
|
CanvasUI.transform.position = new Vector3(pos.x, pos.y, CanvasUI.transform.position.z);
|
|
CanvasUI.SetActive(true);
|
|
canvasGroup.alpha = 0;
|
|
// 如果关闭动画正在播放,停止它
|
|
if (hideSequence.IsActive() && hideSequence.IsPlaying())
|
|
{
|
|
hideSequence.Restart();
|
|
hideSequence.Pause();
|
|
}
|
|
|
|
// 播放打开动画
|
|
showSequence.Restart();
|
|
UINameOpen(false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 关闭 UI
|
|
/// </summary>
|
|
public void ActiveUIFalse()
|
|
{
|
|
// 如果打开动画正在播放,停止它
|
|
if (showSequence.IsActive() && showSequence.IsPlaying())
|
|
{
|
|
showSequence.Restart();
|
|
showSequence.Pause();
|
|
}
|
|
|
|
// 播放关闭动画
|
|
hideSequence.Restart();
|
|
UINameOpen(true);
|
|
}
|
|
|
|
public void UINameOpen(bool open)
|
|
{
|
|
foreach (Transform child in transform.Find("节点组"))
|
|
{
|
|
child.Find("科技名UI").gameObject.SetActive(open);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region 节点解锁事件
|
|
|
|
public void AddEvent(string EventName, Action action)
|
|
{
|
|
if (NodeEvent == null)
|
|
{
|
|
NodeEvent = new Dictionary<string, Action>();
|
|
}
|
|
if (NodeEvent.TryGetValue(EventName, out Action events))
|
|
{
|
|
events += action;
|
|
NodeEvent[EventName] = events;
|
|
}
|
|
else
|
|
{
|
|
NodeEvent.Add(EventName, action);
|
|
}
|
|
}
|
|
|
|
public string[] GetDescription(string techName)
|
|
{
|
|
TechItem item = TechItems[techName];
|
|
return new[] { item.Describe, item.FunDescription };
|
|
}
|
|
|
|
|
|
private void PlayEvent(string EventName)
|
|
{
|
|
if (NodeEvent.TryGetValue(EventName, out Action action))
|
|
{
|
|
Debug.LogWarning("触发");
|
|
action?.Invoke();
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("不存在该事件名");
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
|
|
public void Refreshtech(Transform trans) //子节点是否能打开
|
|
{
|
|
foreach (Transform child in trans)
|
|
{
|
|
if (child.name != "科技名UI")
|
|
{
|
|
child.gameObject.SetActive(true);
|
|
Debug.LogWarning(child.name);
|
|
transform.Find("节点组/" + child.name).gameObject.SetActive(true);
|
|
|
|
}
|
|
}
|
|
}
|
|
public UI_InformationPanel.BTInfo GetTechInfo(string name)
|
|
{
|
|
Debug.Log("Kejishu "+name);
|
|
if (TechItems.ContainsKey(name))
|
|
{
|
|
TechItem ti= TechItems[name];
|
|
return new UI_InformationPanel.BTInfo(ti.itemName, ti.FunDescription, ti.Describe);
|
|
}
|
|
else
|
|
{
|
|
foreach (UI_InformationPanel.BTInfo bti in NoTechInfo)
|
|
{
|
|
if (bti.BITName == name) return bti;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
}
|
|
|
|
}
|