280 lines
7.0 KiB
C#
280 lines
7.0 KiB
C#
|
|
using System.Collections.Generic;
|
||
|
|
using UnityEngine;
|
||
|
|
using UnityEngine.UI;
|
||
|
|
|
||
|
|
public class TalentTreeUI : MonoBehaviour
|
||
|
|
{
|
||
|
|
public TalentManager manager;
|
||
|
|
public PlayerStats playerStats;
|
||
|
|
|
||
|
|
[Header("Tree")]
|
||
|
|
public GameObject panelRoot;
|
||
|
|
public RectTransform lineRoot;
|
||
|
|
public RectTransform nodesRoot;
|
||
|
|
public TalentNodeUI nodePrefab;
|
||
|
|
public TalentTooltipUI tooltip;
|
||
|
|
|
||
|
|
[Header("Panels")]
|
||
|
|
public Text titleText;
|
||
|
|
public Text pointsText;
|
||
|
|
public Text controlsText;
|
||
|
|
public StatsPanelUI statsPanel;
|
||
|
|
|
||
|
|
[Header("Buttons")]
|
||
|
|
public Button saveButton;
|
||
|
|
public Button loadButton;
|
||
|
|
public Button resetButton;
|
||
|
|
|
||
|
|
public bool openOnStart;
|
||
|
|
|
||
|
|
private readonly List<TalentNodeUI> nodes = new List<TalentNodeUI>();
|
||
|
|
private readonly List<LineConnectorUI> lines = new List<LineConnectorUI>();
|
||
|
|
private bool isOpen;
|
||
|
|
|
||
|
|
private void Awake()
|
||
|
|
{
|
||
|
|
if (manager == null)
|
||
|
|
{
|
||
|
|
manager = FindObjectOfType<TalentManager>();
|
||
|
|
}
|
||
|
|
|
||
|
|
if (playerStats == null)
|
||
|
|
{
|
||
|
|
playerStats = FindObjectOfType<PlayerStats>();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void OnEnable()
|
||
|
|
{
|
||
|
|
if (manager != null)
|
||
|
|
{
|
||
|
|
manager.OnTalentStateChanged += Refresh;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void OnDisable()
|
||
|
|
{
|
||
|
|
if (manager != null)
|
||
|
|
{
|
||
|
|
manager.OnTalentStateChanged -= Refresh;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void Start()
|
||
|
|
{
|
||
|
|
BindButtons();
|
||
|
|
BuildTree();
|
||
|
|
Refresh();
|
||
|
|
SetOpen(openOnStart);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void Update()
|
||
|
|
{
|
||
|
|
if (Input.GetKeyDown(KeyCode.K))
|
||
|
|
{
|
||
|
|
Toggle();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Toggle()
|
||
|
|
{
|
||
|
|
SetOpen(!isOpen);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void SetOpen(bool open)
|
||
|
|
{
|
||
|
|
isOpen = open;
|
||
|
|
if (panelRoot != null)
|
||
|
|
{
|
||
|
|
panelRoot.SetActive(open);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (open)
|
||
|
|
{
|
||
|
|
Refresh();
|
||
|
|
UpdateLines();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public void BuildTree()
|
||
|
|
{
|
||
|
|
ClearChildren(nodesRoot);
|
||
|
|
ClearChildren(lineRoot);
|
||
|
|
nodes.Clear();
|
||
|
|
lines.Clear();
|
||
|
|
|
||
|
|
if (manager == null || nodePrefab == null || nodesRoot == null)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
Dictionary<TalentData, TalentNodeUI> nodeByTalent = new Dictionary<TalentData, TalentNodeUI>();
|
||
|
|
for (int i = 0; i < manager.allTalents.Count; i++)
|
||
|
|
{
|
||
|
|
TalentData talent = manager.allTalents[i];
|
||
|
|
if (talent == null)
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
TalentNodeUI node = Instantiate(nodePrefab, nodesRoot);
|
||
|
|
node.gameObject.SetActive(true);
|
||
|
|
node.tooltip = tooltip;
|
||
|
|
node.Setup(talent, manager);
|
||
|
|
|
||
|
|
RectTransform rectTransform = node.transform as RectTransform;
|
||
|
|
if (rectTransform != null)
|
||
|
|
{
|
||
|
|
rectTransform.anchoredPosition = talent.treePosition;
|
||
|
|
}
|
||
|
|
|
||
|
|
nodes.Add(node);
|
||
|
|
nodeByTalent[talent] = node;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (lineRoot == null)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int i = 0; i < manager.allTalents.Count; i++)
|
||
|
|
{
|
||
|
|
TalentData talent = manager.allTalents[i];
|
||
|
|
if (talent == null || talent.prerequisites == null)
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int prerequisiteIndex = 0; prerequisiteIndex < talent.prerequisites.Length; prerequisiteIndex++)
|
||
|
|
{
|
||
|
|
TalentData prerequisite = talent.prerequisites[prerequisiteIndex];
|
||
|
|
if (prerequisite == null || !nodeByTalent.ContainsKey(prerequisite) || !nodeByTalent.ContainsKey(talent))
|
||
|
|
{
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
LineConnectorUI line = CreateLine(lineRoot, prerequisite, nodeByTalent[prerequisite], nodeByTalent[talent]);
|
||
|
|
lines.Add(line);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
UpdateLines();
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Refresh()
|
||
|
|
{
|
||
|
|
if (titleText != null)
|
||
|
|
{
|
||
|
|
titleText.text = "Дерево талантов";
|
||
|
|
}
|
||
|
|
|
||
|
|
if (pointsText != null)
|
||
|
|
{
|
||
|
|
int points = manager != null ? manager.GetAvailableTalentPoints() : 0;
|
||
|
|
pointsText.text = $"Очки талантов: {points}";
|
||
|
|
}
|
||
|
|
|
||
|
|
if (controlsText != null)
|
||
|
|
{
|
||
|
|
controlsText.text = "K - дерево X - +50 XP T - +1 очко E - кристалл F5 - сохранить F9 - загрузить Backspace - сброс";
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int i = 0; i < nodes.Count; i++)
|
||
|
|
{
|
||
|
|
if (nodes[i] != null)
|
||
|
|
{
|
||
|
|
nodes[i].Refresh();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (statsPanel != null)
|
||
|
|
{
|
||
|
|
statsPanel.Refresh();
|
||
|
|
}
|
||
|
|
|
||
|
|
UpdateLines();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void BindButtons()
|
||
|
|
{
|
||
|
|
if (saveButton != null)
|
||
|
|
{
|
||
|
|
saveButton.onClick.RemoveAllListeners();
|
||
|
|
saveButton.onClick.AddListener(() =>
|
||
|
|
{
|
||
|
|
if (manager != null)
|
||
|
|
{
|
||
|
|
manager.SaveProgress();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
if (loadButton != null)
|
||
|
|
{
|
||
|
|
loadButton.onClick.RemoveAllListeners();
|
||
|
|
loadButton.onClick.AddListener(() =>
|
||
|
|
{
|
||
|
|
if (manager != null)
|
||
|
|
{
|
||
|
|
manager.LoadProgress();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
if (resetButton != null)
|
||
|
|
{
|
||
|
|
resetButton.onClick.RemoveAllListeners();
|
||
|
|
resetButton.onClick.AddListener(() =>
|
||
|
|
{
|
||
|
|
if (manager != null)
|
||
|
|
{
|
||
|
|
manager.ResetProgress();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private LineConnectorUI CreateLine(RectTransform parent, TalentData childTalent, TalentNodeUI startNode, TalentNodeUI endNode)
|
||
|
|
{
|
||
|
|
GameObject lineObject = new GameObject($"Line_{startNode.talent.talentId}_to_{childTalent.talentId}", typeof(RectTransform), typeof(Image), typeof(LineConnectorUI));
|
||
|
|
lineObject.transform.SetParent(parent, false);
|
||
|
|
|
||
|
|
Image image = lineObject.GetComponent<Image>();
|
||
|
|
Color color = childTalent.branchColor;
|
||
|
|
image.color = new Color(color.r, color.g, color.b, 0.72f);
|
||
|
|
image.raycastTarget = false;
|
||
|
|
|
||
|
|
LineConnectorUI connector = lineObject.GetComponent<LineConnectorUI>();
|
||
|
|
connector.lineImage = image;
|
||
|
|
connector.thickness = 5f;
|
||
|
|
connector.dynamicUpdate = true;
|
||
|
|
connector.SetEndpoints(startNode.transform as RectTransform, endNode.transform as RectTransform);
|
||
|
|
return connector;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void UpdateLines()
|
||
|
|
{
|
||
|
|
Canvas.ForceUpdateCanvases();
|
||
|
|
for (int i = 0; i < lines.Count; i++)
|
||
|
|
{
|
||
|
|
if (lines[i] != null)
|
||
|
|
{
|
||
|
|
lines[i].UpdateLine();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void ClearChildren(RectTransform root)
|
||
|
|
{
|
||
|
|
if (root == null)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int i = root.childCount - 1; i >= 0; i--)
|
||
|
|
{
|
||
|
|
Destroy(root.GetChild(i).gameObject);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|