using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.UIElements; using VOID.Generic.Dict; using VOID.Generic.Objects.Unit; using VOID.Generic.Objects.Unit.Events; using VOID.Generic.Player; using VOID.Generic.Player.Input; using VOID.UserInterface.Game.Interfaces; using VOID.UserInterface.Game.Util; using VOID.ScriptableObjects.Abilities; namespace VOID.UserInterface.Game { public class AbilityBookUI : MonoBehaviour, IHasWindow { public static AbilityBookUI current { get; private set; } // WindowUI public WindowUI windowUI { get; private set; } // Active Unit and his Backpack private UnitObject _unit; private UnitObjectAbilityBook _abilityBook; // Visual Elements private VisualElement _rootElement; private VisualElement _abilityListElement; private readonly List _abilitySlots = new(); // References private ShortcutsInputManager _shortcutsInputManager; private PlayerController _playerController; private void Awake() { current = this; var uiDocument = gameObject.GetComponent(); var templateElement = uiDocument.rootVisualElement; // Find all important elements _rootElement = templateElement.Q("root-ability-book"); _abilityListElement = templateElement.Q("ability-slots"); _abilityListElement.Clear(); windowUI = gameObject.GetComponent(); _rootElement.dataSource = this; _rootElement.pickingMode = PickingMode.Position; } private void Start() { _shortcutsInputManager = ShortcutsInputManager.current; _playerController = PlayerController.current; // Toggle show/hide when pressing shortcut for ability book _shortcutsInputManager.abilityBook.performed += _ => windowUI.Toggle(); windowUI.OnOpen += OnOpen; windowUI.OnClose += OnClose; windowUI.SetTitle("Ability Book"); // Hidden by default windowUI.Close(); } public void Toggle() => windowUI.Toggle(); public void Open() => windowUI.Open(); public void Close() => windowUI.Close(); private void OnOpen() { // References to active unit _unit = PlayerController.current.activeUnit; _abilityBook = _unit.unitAbilityBook; // Refresh UI when we change active unit _playerController.OnActiveUnitChange += OnActiveUnitChange; // Initialize all VisualElements _abilityBook.abilities.ForEach(AddSlot); // Listen to all changes in backpack and update UI _unit.unitEvents.onAbilityAdded.AddListener(OnAbilityAdded); _unit.unitEvents.onAbilityRemoved.AddListener(OnAbilityRemoved); } private void OnClose() { // Stop listening _playerController.OnActiveUnitChange -= OnActiveUnitChange; // Backpack closed, no need to listen for backpack changes if (_unit) { _unit.unitEvents.onAbilityAdded.RemoveListener(OnAbilityAdded); _unit.unitEvents.onAbilityRemoved.RemoveListener(OnAbilityRemoved); } // Remove all VisualElement slots _abilitySlots.ForEach(slot => slot.Destroy()); // Clear variables _abilitySlots.Clear(); _unit = null; _abilityBook = null; } private void OnActiveUnitChange(UnitObject unitObject) { windowUI.Close(); windowUI.Open(); } private void OnAbilityAdded(AbilityBookAbilityAddedEvent abilityAddedEvent) => AddSlot(abilityAddedEvent.abilityAdded); private void AddSlot(BasicAbility ability) { var newSlot = new SlotUI(); newSlot.InitNew(_abilityListElement, SlotType.AbilityBookSlot, -1); newSlot.Set(ability); _abilitySlots.Add(newSlot); } private void OnAbilityRemoved(AbilityBookAbilityRemovedEvent abilityRemovedEvent) => RemoveSlot(abilityRemovedEvent.abilityRemoved); private void RemoveSlot(BasicAbility ability) { var oldSlot = _abilitySlots.FirstOrDefault(slot => slot.ability == ability); oldSlot?.Destroy(); _abilitySlots.Remove(oldSlot); } } }