using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
/// <summary>
/// Manages the UI display for the skill tree, dynamically creating buttons
/// and updating their state based on player progression.
/// </summary>
public class SkillTreeUI : MonoBehaviour
{
[Header("UI References")]
[Tooltip("The parent transform where all skill buttons will be instantiated.")]
public Transform skillButtonParent;
[Tooltip("The prefab for a single skill button.")]
public GameObject skillButtonPrefab;
[Tooltip("Text element to display the player's available skill points.")]
public TextMeshProUGUI availableSkillPointsText;
[Header("Skill Info Pop-up")]
[Tooltip("The panel that displays the skill information.")]
public GameObject skillInfoPopupPanel;
[Tooltip("Text element for the skill's name in the pop-up.")]
public TextMeshProUGUI skillNameText;
[Tooltip("Text element for the skill's description in the pop-up.")]
public TextMeshProUGUI skillDescriptionText;
[Tooltip("Text element for the skill's cost in the pop-up.")]
public TextMeshProUGUI skillCostText;
[Tooltip("The button to learn the skill from the pop-up.")]
public Button learnSkillButton;
private SkillTreeManager skillTreeManager;
private PlayerProgression playerProgression;
private Dictionary<string, GameObject> skillButtons = new Dictionary<string, GameObject>();
private string activeSkillID;
private void Start()
{
// Get references to the singleton managers
skillTreeManager = SkillTreeManager.Instance;
playerProgression = PlayerProgression.Instance;
if (skillTreeManager == null || playerProgression == null)
{
Debug.LogError("Required managers not found. Ensure SkillTreeManager and PlayerProgression are in the scene.");
return;
}
// Subscribe to events to refresh the UI
skillTreeManager.OnSkillLearned.AddListener(RefreshUI);
playerProgression.OnSkillPointChanged.AddListener(RefreshUI);
PopulateSkillTreeUI();
RefreshUI();
// Hide the pop-up panel at the start
if (skillInfoPopupPanel != null)
{
skillInfoPopupPanel.SetActive(false);
}
}
private void OnDestroy()
{
// Unsubscribe from events to prevent memory leaks
if (skillTreeManager != null)
{
skillTreeManager.OnSkillLearned.RemoveListener(RefreshUI);
}
if (playerProgression != null)
{
playerProgression.OnSkillPointChanged.RemoveListener(RefreshUI);
}
}
/// <summary>
/// Instantiates buttons for all skills defined in the Skill Tree ScriptableObject.
/// </summary>
private void PopulateSkillTreeUI()
{
// This line was updated to get the ScriptableObject directly from the manager.
SkillTree skillTreeData = skillTreeManager.GetComponent<SkillTreeManager>().skillTreeData;
foreach (Skill skill in skillTreeData.skills)
{
GameObject newButton = Instantiate(skillButtonPrefab, skillButtonParent);
skillButtons[skill.skillID] = newButton;
// Get the button's components
Button buttonComponent = newButton.GetComponent<Button>();
TextMeshProUGUI skillNameText = newButton.GetComponentInChildren<TextMeshProUGUI>();
Image skillIcon = newButton.GetComponentInChildren<Image>(); // Assuming the image is a child
// Set the skill button's text and icon
if (skillNameText != null) skillNameText.text = skill.skillName;
if (skillIcon != null && skill.icon != null) skillIcon.sprite = skill.icon;
// Add a listener to the button's click event
buttonComponent.onClick.AddListener(() => OnSkillButtonClicked(skill.skillID));
}
}
/// <summary>
/// Refreshes the state of all skill buttons based on player progression.
/// </summary>
private void RefreshUI()
{
// Update the available skill points text
if (availableSkillPointsText != null)
{
availableSkillPointsText.text = $"Skill Points: {playerProgression.GetSkillPoints()}";
}
foreach (var pair in skillButtons)
{
string skillID = pair.Key;
GameObject buttonObject = pair.Value;
Button buttonComponent = buttonObject.GetComponent<Button>();
// Check if the skill has been learned
if (skillTreeManager.IsSkillLearned(skillID))
{
// Skill is learned: Disable the button and change its appearance
buttonComponent.interactable = false;
buttonComponent.image.color = Color.gray; // Example: change color to gray
}
else
{
// Skill is not learned: Check if it's learnable
bool canLearn = CanLearnSkill(skillID);
buttonComponent.interactable = canLearn;
// Example: change color to green if learnable, red if not
buttonComponent.image.color = canLearn ? Color.green : Color.red;
}
}
}
/// <summary>
/// Checks if a skill is currently learnable (has prerequisites and skill points).
/// </summary>
private bool CanLearnSkill(string skillID)
{
Skill skillData = skillTreeManager.GetSkillData(skillID);
if (skillData == null) return false;
// Check if player has enough skill points
if (playerProgression.GetSkillPoints() < skillData.skillPointCost)
{
return false;
}
// Check if prerequisites are met
foreach (string prereqID in skillData.prerequisites)
{
if (!skillTreeManager.IsSkillLearned(prereqID))
{
return false;
}
}
return true;
}
/// <summary>
/// Called when a skill button is clicked.
/// </summary>
/// <param name="skillID">The unique ID of the skill associated with the button.</param>
private void OnSkillButtonClicked(string skillID)
{
// Show the info pop-up instead of trying to learn immediately.
ShowSkillPopup(skillID);
}
/// <summary>
/// Displays the skill info pop-up and populates it with data.
/// </summary>
/// <param name="skillID">The ID of the skill to display.</param>
public void ShowSkillPopup(string skillID)
{
Skill skillData = skillTreeManager.GetSkillData(skillID);
if (skillData == null) return;
// Store the active skill ID to learn it later
activeSkillID = skillID;
// Populate the pop-up with skill data
skillNameText.text = skillData.skillName;
skillDescriptionText.text = skillData.description;
skillCostText.text = $"Cost: {skillData.skillPointCost} SP";
// Enable the "Learn" button if the skill is learnable
learnSkillButton.interactable = CanLearnSkill(skillID);
// Show the panel
skillInfoPopupPanel.SetActive(true);
}
/// <summary>
/// Called by the UI button to attempt learning the active skill.
/// </summary>
public void LearnSkillFromPopup()
{
skillTreeManager.TryLearnSkill(activeSkillID);
skillInfoPopupPanel.SetActive(false);
}
/// <summary>
/// Hides the skill info pop-up.
/// </summary>
public void HideSkillPopup()
{
skillInfoPopupPanel.SetActive(false);
}
}
Comments