using System.Collections.Generic; using Sirenix.OdinInspector; using Sirenix.Utilities; using UnityEngine; using UnityEngine.UIElements; using VOID.Generic.Objects.Abstract.Events; using VOID.Generic.Objects.Unit; using VOID.UserInterface.Game.Util; using VOID.ScriptableObjects; namespace VOID.UserInterface.Game.Party { /// /// Manages all visual elements for one in , including: portrait and statuses /// public class PartyUnitUI : MonoBehaviour { [ShowInInspector, ReadOnly] public UnitObject unit { get; private set; } // Visual Elements private VisualElement _templateElement; private VisualElement _statusRow; private UnitPortraitUI _unitPortraitUI; private Dictionary _statuses = new(); /// /// Initializes whole , should be executed from . /// /// visual element which already exists and will be used. public void Init(VisualElement partyUnitTemplate) { // Find all important elements _templateElement = partyUnitTemplate; _statusRow = _templateElement.Q("status-row"); _unitPortraitUI = new UnitPortraitUI(); _unitPortraitUI.Init(_templateElement.Q("unit-portrait")); _templateElement.style.display = DisplayStyle.None; // Clear all placeholder statuses _statusRow.Clear(); } /// /// Given will be used in this visual element. /// Which means its portrait, statuses and health will be displayed. /// public void SetUnit(UnitObject unit) { // Remove everything about previous Unit UnsetUnit(); // New Unit assigned - start listeners and wait this.unit = unit; this.unit.basicEvents.onStatusStart.AddListener(OnUnitStatusStart); this.unit.basicEvents.onStatusEnd.AddListener(OnUnitStatusEnd); // Make UI visible and set Unit's portrait _templateElement.style.display = DisplayStyle.Flex; // For all statuses that already exists we need to initialize them manually this.unit.statusManager.GetStatuses().ForEach(status => OnUnitStatusStart(new StatusEvent { obj = unit, status = status })); _unitPortraitUI.SetUnit(unit); } /// /// Clears and hides this element. /// public void UnsetUnit() { // There is no unit currently if (!unit) return; // Remove all listeners, then remove assigned Unit unit.basicEvents.onStatusStart.RemoveListener(OnUnitStatusStart); unit.basicEvents.onStatusEnd.RemoveListener(OnUnitStatusEnd); unit = null; // Make UI invisible and unset portrait _templateElement.style.display = DisplayStyle.None; // Remove mapping _statuses = null; // Clear all statuses _statusRow.Clear(); _unitPortraitUI.UnsetUnit(); } /// /// Adds class "active" which usually will be used, by portret of player's currently active /// public void SetActive(bool active = true) { _templateElement.EnableInClassList("active", active); } private void OnUnitStatusStart(StatusEvent statusEvent) { if (statusEvent.status.hidden) return; var statusUI = new StatusUI(); statusUI.InitNew(_statusRow, statusEvent.status); _statuses.Add(statusEvent.status, statusUI); } private void OnUnitStatusEnd(StatusEvent statusEvent) { if (statusEvent.status.hidden) return; _statuses.GetValueOrDefault(statusEvent.status)?.Destroy(); _statuses.Remove(statusEvent.status); } } }