Files
VOIDRPG/Assets/92 - UserInterface/Generic/Game/Party/PartyUnitUI.cs
T
2026-07-09 21:33:33 +02:00

115 lines
4.2 KiB
C#

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
{
/// <summary>
/// Manages all visual elements for one <see cref="UnitObject"/> in <see cref="PartyUI"/>, including: portrait and statuses
/// </summary>
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<BasicStatus, StatusUI> _statuses = new();
/// <summary>
/// Initializes whole <see cref="PartyUnitUI"/>, should be executed from <see cref="PartyUI"/>.
/// </summary>
/// <param name="partyUnitTemplate">visual element which already exists and will be used.</param>
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();
}
/// <summary>
/// Given <see cref="UnitObject"/> will be used in this visual element.
/// Which means its portrait, statuses and health will be displayed.
/// </summary>
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);
}
/// <summary>
/// Clears and hides this element.
/// </summary>
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();
}
/// <summary>
/// Adds class "active" which usually will be used, by portret of player's currently active <see cref="UnitObject"/>
/// </summary>
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);
}
}
}