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);
}
}
}