gather-and-defend/Assets/SkillTreeManager.cs
2024-11-14 11:01:21 -05:00

165 lines
5.5 KiB
C#

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Unity.VisualScripting;
#if UNITY_EDITOR
using UnityEditor;
[CustomEditor(typeof(SkillTreeManager))]
public class SkillTreeManagerEditor : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
if (GUILayout.Button("Generate"))
{
(target as SkillTreeManager).Generate();
}
}
}
#endif
public class SkillTreeManager : MonoBehaviour
{
//[SerializeField]
//private
[SerializeField]
private float _lineColorVariation = 0.2f;
[SerializeField]
private float _lineOffset = 5f;
[SerializeField]
private float _lineThickness = 10f;
[SerializeField]
private Vector2 _startPositionOffset = new Vector2(200, 0);
[SerializeField]
Vector2 _distanceBetweenItems = Vector2.one * 200;
[SerializeField]
List<SkillTreeItem> _skillTreeItems;
[SerializeField]
GameObject _skillTreeItemPrefab;
[SerializeField]
GameObject _uiLineRendererPrefab;
[SerializeField]
GameObject _popUpConfigPrefab;
[SerializeField]
GameObject _skillTreeInfoItemPrefab;
[SerializeField]
Transform _nodeContainer;
[SerializeField]
Transform _lineContainer;
private List<SkillTreeItemDisplay> DrawColumn(List<SkillTreeItem> items, List<SkillTreeItemDisplay> created)
{
var testList = new List<SkillSO>();
var returnList = new List<SkillTreeItemDisplay>();
var ancestors = items.Max(current => GetAncestorCount(current));
for (int i = 0; i < items.Count; i++)
{
var item = items[i];
var comp = created.Find(x => x.Data == item);
if (comp)
{
returnList.Add(comp);
continue;
}
var x = _startPositionOffset.x + ancestors * _distanceBetweenItems.x;
var y = _startPositionOffset.y + _distanceBetweenItems.y * i - (items.Count / 2) * _distanceBetweenItems.y;
var pos = new Vector2(x, y);
var instance = Instantiate(_skillTreeItemPrefab, _nodeContainer.transform);
instance.GetComponent<RectTransform>().anchoredPosition = pos;
comp = instance.GetComponent<SkillTreeItemDisplay>();
comp.Data = item;
comp._popUpConf = _popUpConfigPrefab;
created.Add(comp);
returnList.Add(comp);
}
return returnList;
static int GetAncestorCount(SkillTreeItem item, int start = 0)
{
var max = start;
foreach(var ancestor in item.Prerequisites)
{
var count = GetAncestorCount(ancestor, start + 1);
if (count > max) max = count;
}
return max;
}
}
private void Start()
{
Generate();
}
public void Generate()
{
foreach (Transform t in _nodeContainer) DestroyImmediate(t.gameObject);
foreach (Transform t in _lineContainer) DestroyImmediate(t.gameObject);
var dict = new Dictionary<int, HashSet<int>>();
var created = new List<SkillTreeItemDisplay>();
var choices = _skillTreeItems.FindAll(x => x.Prerequisites.Count <= 0);
DrawColumn(choices, created);
for (int i = 0; i < created.Count; i++)
{
var current = created[i];
choices = _skillTreeItems.FindAll(x => x.Prerequisites.Contains(current.Data));
if (choices.Count <= 0) continue;
var column = DrawColumn(choices, created);
}
foreach (var node in created)
{
dict.TryAdd(node.Data.GetHashCode(), new());
Vector2 colorVariation = new Vector2(Random.value - 0.5f, Random.value - 0.5f) * _lineColorVariation;
var rect1 = node.GetComponent<RectTransform>();
var prereqs = created.FindAll(x => x.Data.Prerequisites.Contains(node.Data));
for (int p = 0; p < prereqs.Count; p++)
{
var prereq = prereqs[p];
if (dict[node.Data.GetHashCode()].Contains(prereq.Data.GetHashCode())) continue;
dict[node.Data.GetHashCode()].Add(prereq.Data.GetHashCode());
var rect2 = prereq.GetComponent<RectTransform>();
var delta = rect2.anchoredPosition - rect1.anchoredPosition;
var lineObj = Instantiate(_uiLineRendererPrefab, _lineContainer);
var line = lineObj.GetComponent<UILineRenderer>();
node.RelatedLines.Add(line);
prereq.RelatedLines.Add(line);
line.points.Clear();
line.points.Add(rect1.anchoredPosition + (p * _lineOffset - prereqs.Count * _lineOffset / 2) * Vector2.one);
line.points.Add(rect1.anchoredPosition + (p * _lineOffset - prereqs.Count * _lineOffset / 2) * Vector2.one + Vector2.right * delta.x / 2);
line.points.Add(rect2.anchoredPosition + (p * _lineOffset - prereqs.Count * _lineOffset / 2) * Vector2.one + Vector2.left * delta.x / 2);
line.points.Add(rect2.anchoredPosition + (p * _lineOffset - prereqs.Count * _lineOffset / 2) * Vector2.one);
line.transform.SetAsFirstSibling();
Color.RGBToHSV(line.color, out float H, out float S, out float V);
line.thickness = _lineThickness;
line.color = Color.HSVToRGB(H, S + colorVariation.x, V + colorVariation.y);
}
}
}
}