first commit
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
using OTGIntegrated.Stats;
|
||||
using UnityEngine;
|
||||
|
||||
namespace OTGIntegrated.Talents
|
||||
{
|
||||
[CreateAssetMenu(fileName = "TalentData", menuName = "OTG Integrated/Talent Data")]
|
||||
public sealed class TalentData : ScriptableObject
|
||||
{
|
||||
public string talentId;
|
||||
public string displayName;
|
||||
[TextArea(2, 5)] public string description;
|
||||
public Sprite icon;
|
||||
[Min(0)] public int cost = 1;
|
||||
public TalentData[] prerequisites;
|
||||
public StatModifier[] modifiers;
|
||||
public Vector2 treePosition;
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(talentId))
|
||||
{
|
||||
talentId = name;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(displayName))
|
||||
{
|
||||
displayName = talentId;
|
||||
}
|
||||
|
||||
cost = Mathf.Max(0, cost);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fdead87a2f17105e3bcc7d1536c493c9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,268 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OTGIntegrated.Core;
|
||||
using OTGIntegrated.Stats;
|
||||
using UnityEngine;
|
||||
|
||||
namespace OTGIntegrated.Talents
|
||||
{
|
||||
public sealed class TalentManager : MonoBehaviour
|
||||
{
|
||||
private const string TalentSourcePrefix = "Talent:";
|
||||
|
||||
public List<TalentData> allTalents = new List<TalentData>();
|
||||
public int availableTalentPoints;
|
||||
|
||||
[SerializeField] private List<string> learnedTalentIds = new List<string>();
|
||||
|
||||
private PlayerStats playerStats;
|
||||
private readonly Dictionary<string, TalentData> talentLookup = new Dictionary<string, TalentData>(StringComparer.Ordinal);
|
||||
|
||||
public event Action OnTalentStateChanged;
|
||||
public IReadOnlyList<string> LearnedTalentIds => learnedTalentIds;
|
||||
|
||||
public void Initialize(PlayerStats stats)
|
||||
{
|
||||
playerStats = stats;
|
||||
BuildLookup();
|
||||
RebuildAllModifiers();
|
||||
RaiseChanged();
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (playerStats == null)
|
||||
{
|
||||
playerStats = GetComponent<PlayerStats>();
|
||||
}
|
||||
|
||||
BuildLookup();
|
||||
}
|
||||
|
||||
public bool IsLearned(TalentData talent)
|
||||
{
|
||||
return IsValidTalent(talent) && learnedTalentIds.Contains(talent.talentId);
|
||||
}
|
||||
|
||||
public bool CanLearn(TalentData talent)
|
||||
{
|
||||
return IsValidTalent(talent) &&
|
||||
!IsLearned(talent) &&
|
||||
availableTalentPoints >= Mathf.Max(0, talent.cost) &&
|
||||
ArePrerequisitesLearned(talent);
|
||||
}
|
||||
|
||||
public bool ArePrerequisitesLearned(TalentData talent)
|
||||
{
|
||||
if (!IsValidTalent(talent))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (talent.prerequisites == null || talent.prerequisites.Length == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < talent.prerequisites.Length; i++)
|
||||
{
|
||||
TalentData prerequisite = talent.prerequisites[i];
|
||||
if (!IsValidTalent(prerequisite) || !IsLearned(prerequisite))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool LearnTalent(TalentData talent)
|
||||
{
|
||||
if (!IsValidTalent(talent))
|
||||
{
|
||||
GameEvents.RaiseNotification("Некорректный талант");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CanLearn(talent))
|
||||
{
|
||||
GameEvents.RaiseNotification(GetBlockingReason(talent));
|
||||
return false;
|
||||
}
|
||||
|
||||
availableTalentPoints -= Mathf.Max(0, talent.cost);
|
||||
learnedTalentIds.Add(talent.talentId);
|
||||
ApplyTalentModifiers(talent);
|
||||
GameEvents.RaiseTalentLearned(talent);
|
||||
GameEvents.RaiseNotification($"Изучен талант: {talent.displayName}");
|
||||
RaiseChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void AddTalentPoints(int amount)
|
||||
{
|
||||
if (amount <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
availableTalentPoints = Mathf.Max(0, availableTalentPoints + amount);
|
||||
GameEvents.RaiseNotification(amount == 1 ? "Получено очко талантов" : $"Получено очков талантов: {amount}");
|
||||
RaiseChanged();
|
||||
}
|
||||
|
||||
public void SetTalentPoints(int points)
|
||||
{
|
||||
availableTalentPoints = Mathf.Max(0, points);
|
||||
RaiseChanged();
|
||||
}
|
||||
|
||||
public TalentData GetTalentById(string talentId)
|
||||
{
|
||||
BuildLookup();
|
||||
if (string.IsNullOrWhiteSpace(talentId))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
talentLookup.TryGetValue(talentId, out TalentData talent);
|
||||
return talent;
|
||||
}
|
||||
|
||||
public string GetBlockingReason(TalentData talent)
|
||||
{
|
||||
if (!IsValidTalent(talent))
|
||||
{
|
||||
return "Некорректные данные таланта";
|
||||
}
|
||||
|
||||
if (IsLearned(talent))
|
||||
{
|
||||
return "Талант уже изучен";
|
||||
}
|
||||
|
||||
if (!ArePrerequisitesLearned(talent))
|
||||
{
|
||||
return GetMissingPrerequisiteText(talent);
|
||||
}
|
||||
|
||||
if (availableTalentPoints < Mathf.Max(0, talent.cost))
|
||||
{
|
||||
return "Недостаточно очков талантов";
|
||||
}
|
||||
|
||||
return "Доступно";
|
||||
}
|
||||
|
||||
public void LoadProgress(int points, List<string> learnedIds)
|
||||
{
|
||||
BuildLookup();
|
||||
availableTalentPoints = Mathf.Max(0, points);
|
||||
learnedTalentIds.Clear();
|
||||
|
||||
if (learnedIds != null)
|
||||
{
|
||||
for (int i = 0; i < learnedIds.Count; i++)
|
||||
{
|
||||
string id = learnedIds[i];
|
||||
if (!string.IsNullOrWhiteSpace(id) && talentLookup.ContainsKey(id) && !learnedTalentIds.Contains(id))
|
||||
{
|
||||
learnedTalentIds.Add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RebuildAllModifiers();
|
||||
RaiseChanged();
|
||||
}
|
||||
|
||||
public void ResetTalents()
|
||||
{
|
||||
learnedTalentIds.Clear();
|
||||
availableTalentPoints = 0;
|
||||
RebuildAllModifiers();
|
||||
RaiseChanged();
|
||||
}
|
||||
|
||||
public void RebuildAllModifiers()
|
||||
{
|
||||
if (playerStats == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
playerStats.RemoveModifiersBySourcePrefix(TalentSourcePrefix);
|
||||
|
||||
for (int i = 0; i < allTalents.Count; i++)
|
||||
{
|
||||
TalentData talent = allTalents[i];
|
||||
if (IsLearned(talent))
|
||||
{
|
||||
ApplyTalentModifiers(talent);
|
||||
}
|
||||
}
|
||||
|
||||
playerStats.RecalculateStats();
|
||||
}
|
||||
|
||||
private void ApplyTalentModifiers(TalentData talent)
|
||||
{
|
||||
if (!IsValidTalent(talent) || playerStats == null || talent.modifiers == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string sourceId = TalentSourcePrefix + talent.talentId;
|
||||
playerStats.RemoveModifiersBySource(sourceId);
|
||||
for (int i = 0; i < talent.modifiers.Length; i++)
|
||||
{
|
||||
StatModifier modifier = talent.modifiers[i];
|
||||
modifier.sourceId = sourceId;
|
||||
playerStats.AddModifier(modifier);
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildLookup()
|
||||
{
|
||||
talentLookup.Clear();
|
||||
for (int i = 0; i < allTalents.Count; i++)
|
||||
{
|
||||
TalentData talent = allTalents[i];
|
||||
if (IsValidTalent(talent))
|
||||
{
|
||||
talentLookup[talent.talentId] = talent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsValidTalent(TalentData talent)
|
||||
{
|
||||
return talent != null && !string.IsNullOrWhiteSpace(talent.talentId);
|
||||
}
|
||||
|
||||
private string GetMissingPrerequisiteText(TalentData talent)
|
||||
{
|
||||
if (talent.prerequisites == null)
|
||||
{
|
||||
return "Требования не выполнены";
|
||||
}
|
||||
|
||||
for (int i = 0; i < talent.prerequisites.Length; i++)
|
||||
{
|
||||
TalentData prerequisite = talent.prerequisites[i];
|
||||
if (!IsValidTalent(prerequisite) || !IsLearned(prerequisite))
|
||||
{
|
||||
return prerequisite != null ? $"Требуется: {prerequisite.displayName}" : "Требуется другой талант";
|
||||
}
|
||||
}
|
||||
|
||||
return "Требования не выполнены";
|
||||
}
|
||||
|
||||
private void RaiseChanged()
|
||||
{
|
||||
GameEvents.RaiseTalentPointChanged(availableTalentPoints);
|
||||
OnTalentStateChanged?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d62f8065fb79868b590633754446f310
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,110 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace OTGIntegrated.Talents
|
||||
{
|
||||
public sealed class TalentNodeUI : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
|
||||
{
|
||||
public Image background;
|
||||
public Text titleText;
|
||||
public Text costText;
|
||||
public Button button;
|
||||
|
||||
private TalentData talent;
|
||||
private TalentManager manager;
|
||||
private TalentTooltipUI tooltip;
|
||||
|
||||
public TalentData Talent => talent;
|
||||
|
||||
public void Initialize(TalentData talent, TalentManager manager, TalentTooltipUI tooltip, Font font)
|
||||
{
|
||||
this.talent = talent;
|
||||
this.manager = manager;
|
||||
this.tooltip = tooltip;
|
||||
|
||||
if (background == null) background = GetComponent<Image>();
|
||||
if (button == null) button = GetComponent<Button>();
|
||||
if (titleText != null)
|
||||
{
|
||||
titleText.font = font != null ? font : Resources.GetBuiltinResource<Font>("Arial.ttf");
|
||||
}
|
||||
|
||||
if (costText != null)
|
||||
{
|
||||
costText.font = font != null ? font : Resources.GetBuiltinResource<Font>("Arial.ttf");
|
||||
}
|
||||
|
||||
if (button != null)
|
||||
{
|
||||
button.onClick.RemoveAllListeners();
|
||||
button.onClick.AddListener(() =>
|
||||
{
|
||||
if (this.manager != null)
|
||||
{
|
||||
this.manager.LearnTalent(this.talent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
if (talent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (titleText != null)
|
||||
{
|
||||
titleText.text = talent.displayName;
|
||||
}
|
||||
|
||||
if (costText != null)
|
||||
{
|
||||
costText.text = talent.cost.ToString();
|
||||
}
|
||||
|
||||
bool learned = manager != null && manager.IsLearned(talent);
|
||||
bool canLearn = manager != null && manager.CanLearn(talent);
|
||||
bool prereqReady = manager != null && manager.ArePrerequisitesLearned(talent);
|
||||
|
||||
if (background != null)
|
||||
{
|
||||
if (learned)
|
||||
{
|
||||
background.color = new Color(0.86f, 0.68f, 0.22f, 0.96f);
|
||||
}
|
||||
else if (canLearn)
|
||||
{
|
||||
background.color = new Color(0.2f, 0.48f, 0.72f, 0.94f);
|
||||
}
|
||||
else if (prereqReady)
|
||||
{
|
||||
background.color = new Color(0.18f, 0.2f, 0.26f, 0.92f);
|
||||
}
|
||||
else
|
||||
{
|
||||
background.color = new Color(0.09f, 0.1f, 0.12f, 0.88f);
|
||||
}
|
||||
}
|
||||
|
||||
if (button != null)
|
||||
{
|
||||
button.interactable = canLearn;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPointerEnter(PointerEventData eventData)
|
||||
{
|
||||
tooltip?.Show(talent, manager);
|
||||
}
|
||||
|
||||
public void OnPointerExit(PointerEventData eventData)
|
||||
{
|
||||
tooltip?.Hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 49565b0125ddc9cec9f37602092608ad
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,39 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace OTGIntegrated.Talents
|
||||
{
|
||||
public sealed class TalentTooltipUI : MonoBehaviour
|
||||
{
|
||||
public GameObject panelRoot;
|
||||
public Text contentText;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (panelRoot == null)
|
||||
{
|
||||
panelRoot = gameObject;
|
||||
}
|
||||
}
|
||||
|
||||
public void Show(TalentData talent, TalentManager manager)
|
||||
{
|
||||
if (talent == null || panelRoot == null || contentText == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string requirement = manager != null ? manager.GetBlockingReason(talent) : string.Empty;
|
||||
contentText.text = $"{talent.displayName}\n\n{talent.description}\n\nСтоимость: {talent.cost}\n{requirement}";
|
||||
panelRoot.SetActive(true);
|
||||
}
|
||||
|
||||
public void Hide()
|
||||
{
|
||||
if (panelRoot != null)
|
||||
{
|
||||
panelRoot.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19522a16ab21edb628b5c527bb3211ba
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,231 @@
|
||||
using System.Collections.Generic;
|
||||
using OTGIntegrated.Save;
|
||||
using OTGIntegrated.Stats;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace OTGIntegrated.Talents
|
||||
{
|
||||
public sealed class TalentTreeUI : MonoBehaviour
|
||||
{
|
||||
public GameObject panelRoot;
|
||||
public RectTransform nodesRoot;
|
||||
public RectTransform lineRoot;
|
||||
public TalentTooltipUI tooltip;
|
||||
public Text titleText;
|
||||
public Text pointsText;
|
||||
public Text statsText;
|
||||
public Button saveButton;
|
||||
public Button loadButton;
|
||||
public Button resetButton;
|
||||
public Button closeButton;
|
||||
public Font uiFont;
|
||||
|
||||
private TalentManager talentManager;
|
||||
private PlayerStats playerStats;
|
||||
private readonly List<TalentNodeUI> nodes = new List<TalentNodeUI>();
|
||||
private readonly List<GameObject> spawnedLines = new List<GameObject>();
|
||||
|
||||
public void Initialize(TalentManager manager, PlayerStats stats)
|
||||
{
|
||||
talentManager = manager;
|
||||
playerStats = stats;
|
||||
|
||||
if (talentManager != null)
|
||||
{
|
||||
talentManager.OnTalentStateChanged -= Refresh;
|
||||
talentManager.OnTalentStateChanged += Refresh;
|
||||
}
|
||||
|
||||
if (playerStats != null)
|
||||
{
|
||||
playerStats.OnStatsChanged -= Refresh;
|
||||
playerStats.OnStatsChanged += Refresh;
|
||||
}
|
||||
|
||||
if (saveButton != null) saveButton.onClick.AddListener(() => FindObjectOfType<SaveSystem>()?.Save());
|
||||
if (loadButton != null) loadButton.onClick.AddListener(() => FindObjectOfType<SaveSystem>()?.Load());
|
||||
if (resetButton != null) resetButton.onClick.AddListener(() => FindObjectOfType<SaveSystem>()?.ResetSave());
|
||||
if (closeButton != null) closeButton.onClick.AddListener(() => FindObjectOfType<OTGIntegrated.UI.UIManager>()?.CloseCurrentWindow());
|
||||
|
||||
BuildTree();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
Refresh();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (talentManager != null)
|
||||
{
|
||||
talentManager.OnTalentStateChanged -= Refresh;
|
||||
}
|
||||
|
||||
if (playerStats != null)
|
||||
{
|
||||
playerStats.OnStatsChanged -= Refresh;
|
||||
}
|
||||
}
|
||||
|
||||
public void BuildTree()
|
||||
{
|
||||
ClearTree();
|
||||
if (talentManager == null || nodesRoot == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Dictionary<TalentData, TalentNodeUI> lookup = new Dictionary<TalentData, TalentNodeUI>();
|
||||
for (int i = 0; i < talentManager.allTalents.Count; i++)
|
||||
{
|
||||
TalentData talent = talentManager.allTalents[i];
|
||||
if (talent == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
TalentNodeUI node = CreateNode(talent);
|
||||
nodes.Add(node);
|
||||
lookup[talent] = node;
|
||||
}
|
||||
|
||||
for (int i = 0; i < talentManager.allTalents.Count; i++)
|
||||
{
|
||||
TalentData talent = talentManager.allTalents[i];
|
||||
if (talent == null || talent.prerequisites == null || !lookup.TryGetValue(talent, out TalentNodeUI node))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int p = 0; p < talent.prerequisites.Length; p++)
|
||||
{
|
||||
TalentData prerequisite = talent.prerequisites[p];
|
||||
if (prerequisite != null && lookup.TryGetValue(prerequisite, out TalentNodeUI prerequisiteNode))
|
||||
{
|
||||
CreateLine(prerequisiteNode.GetComponent<RectTransform>().anchoredPosition, node.GetComponent<RectTransform>().anchoredPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
if (titleText != null)
|
||||
{
|
||||
titleText.text = "Дерево талантов";
|
||||
}
|
||||
|
||||
if (pointsText != null)
|
||||
{
|
||||
int points = talentManager != null ? talentManager.availableTalentPoints : 0;
|
||||
pointsText.text = $"Очки талантов: {points}";
|
||||
}
|
||||
|
||||
if (statsText != null)
|
||||
{
|
||||
statsText.text = playerStats == null
|
||||
? "Характеристики недоступны"
|
||||
: $"Характеристики\nHP: {Mathf.RoundToInt(playerStats.CurrentHealth)} / {Mathf.RoundToInt(playerStats.MaxHealth)}\nMana: {Mathf.RoundToInt(playerStats.CurrentMana)} / {Mathf.RoundToInt(playerStats.MaxMana)}\nDamage: {playerStats.Damage:0.#}\nMove: {playerStats.MoveSpeed:0.#}\nCrit: {playerStats.CriticalChance:P0}\nCooldown: {playerStats.CooldownReduction:P0}";
|
||||
}
|
||||
|
||||
for (int i = 0; i < nodes.Count; i++)
|
||||
{
|
||||
if (nodes[i] != null)
|
||||
{
|
||||
nodes[i].Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TalentNodeUI CreateNode(TalentData talent)
|
||||
{
|
||||
GameObject root = new GameObject(talent.displayName, typeof(RectTransform), typeof(Image), typeof(Button), typeof(TalentNodeUI));
|
||||
root.transform.SetParent(nodesRoot, false);
|
||||
RectTransform rect = root.GetComponent<RectTransform>();
|
||||
rect.sizeDelta = new Vector2(160f, 76f);
|
||||
rect.anchorMin = new Vector2(0.5f, 0.5f);
|
||||
rect.anchorMax = new Vector2(0.5f, 0.5f);
|
||||
rect.anchoredPosition = talent.treePosition;
|
||||
|
||||
Text title = CreateText(root.transform, "Title", talent.displayName, 15, TextAnchor.MiddleCenter);
|
||||
title.rectTransform.anchorMin = new Vector2(0.08f, 0.25f);
|
||||
title.rectTransform.anchorMax = new Vector2(0.92f, 0.9f);
|
||||
title.rectTransform.offsetMin = Vector2.zero;
|
||||
title.rectTransform.offsetMax = Vector2.zero;
|
||||
|
||||
Text cost = CreateText(root.transform, "Cost", talent.cost.ToString(), 14, TextAnchor.MiddleCenter);
|
||||
cost.rectTransform.anchorMin = new Vector2(0.78f, 0.02f);
|
||||
cost.rectTransform.anchorMax = new Vector2(0.98f, 0.3f);
|
||||
cost.rectTransform.offsetMin = Vector2.zero;
|
||||
cost.rectTransform.offsetMax = Vector2.zero;
|
||||
|
||||
TalentNodeUI node = root.GetComponent<TalentNodeUI>();
|
||||
node.background = root.GetComponent<Image>();
|
||||
node.button = root.GetComponent<Button>();
|
||||
node.titleText = title;
|
||||
node.costText = cost;
|
||||
node.Initialize(talent, talentManager, tooltip, uiFont);
|
||||
return node;
|
||||
}
|
||||
|
||||
private void CreateLine(Vector2 start, Vector2 end)
|
||||
{
|
||||
if (lineRoot == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject line = new GameObject("TalentLine", typeof(RectTransform), typeof(Image));
|
||||
line.transform.SetParent(lineRoot, false);
|
||||
spawnedLines.Add(line);
|
||||
Image image = line.GetComponent<Image>();
|
||||
image.color = new Color(0.78f, 0.62f, 0.26f, 0.55f);
|
||||
|
||||
RectTransform rect = line.GetComponent<RectTransform>();
|
||||
Vector2 delta = end - start;
|
||||
rect.anchorMin = new Vector2(0.5f, 0.5f);
|
||||
rect.anchorMax = new Vector2(0.5f, 0.5f);
|
||||
rect.sizeDelta = new Vector2(delta.magnitude, 3f);
|
||||
rect.anchoredPosition = start + delta * 0.5f;
|
||||
rect.localRotation = Quaternion.Euler(0f, 0f, Mathf.Atan2(delta.y, delta.x) * Mathf.Rad2Deg);
|
||||
}
|
||||
|
||||
private Text CreateText(Transform parent, string name, string value, int fontSize, TextAnchor anchor)
|
||||
{
|
||||
GameObject textObject = new GameObject(name, typeof(RectTransform), typeof(Text));
|
||||
textObject.transform.SetParent(parent, false);
|
||||
Text text = textObject.GetComponent<Text>();
|
||||
text.font = uiFont != null ? uiFont : Resources.GetBuiltinResource<Font>("Arial.ttf");
|
||||
text.fontSize = fontSize;
|
||||
text.alignment = anchor;
|
||||
text.color = new Color(0.95f, 0.94f, 0.9f, 1f);
|
||||
text.text = value;
|
||||
text.resizeTextForBestFit = true;
|
||||
text.resizeTextMinSize = 10;
|
||||
text.resizeTextMaxSize = fontSize;
|
||||
return text;
|
||||
}
|
||||
|
||||
private void ClearTree()
|
||||
{
|
||||
for (int i = nodesRoot != null ? nodesRoot.childCount - 1 : -1; i >= 0; i--)
|
||||
{
|
||||
Destroy(nodesRoot.GetChild(i).gameObject);
|
||||
}
|
||||
|
||||
for (int i = 0; i < spawnedLines.Count; i++)
|
||||
{
|
||||
if (spawnedLines[i] != null)
|
||||
{
|
||||
Destroy(spawnedLines[i]);
|
||||
}
|
||||
}
|
||||
|
||||
nodes.Clear();
|
||||
spawnedLines.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5e51febd0e78f304ea44f20db69a102f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user