Files
2026-07-09 21:33:33 +02:00

120 lines
4.5 KiB
C#

using System;
using Sirenix.OdinInspector;
using UnityEngine.UIElements;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Unit;
namespace VOID.UserInterface.Game.Party
{
/// <summary>
/// Manages all visuals inside <see cref="UnitObject"/> portrait, including: image, border and healthbar
/// </summary>
public class UnitPortraitUI
{
[ShowInInspector, ReadOnly] public UnitObject unit { get; private set; }
public event Action<UnitObject> OnClick;
// Visual Elements
public VisualElement templateElement { get; private set; }
private Button _portrait;
private ProgressBar _healthBar;
private Label _healthLabel;
/// <summary>
/// Initializes <see cref="UnitPortraitUI"/> on existing potrait visual element.
/// </summary>
/// <param name="unitPortraitTemplate">Existing template to use for this portrait</param>
public void Init(VisualElement unitPortraitTemplate)
{
// Find all important elements
templateElement = unitPortraitTemplate;
_portrait = templateElement.Q<Button>("portrait");
_healthBar = templateElement.Q<ProgressBar>("health-bar");
_healthLabel = templateElement.Q<Label>("health-label");
templateElement.RegisterCallback(new EventCallback<MouseDownEvent>(_ => OnClick?.Invoke(unit)), TrickleDown.TrickleDown);
// Binding component to element
templateElement.dataSource = this;
templateElement.pickingMode = PickingMode.Position;
}
/// <summary>
/// Initializes completly new <see cref="UnitPortraitUI"/> inside given parent.
/// </summary>
/// <param name="parentElement">Create new potratit as child in given parent.</param>
public void InitNew(VisualElement parentElement)
{
// Find all important elements
var newTemplateElement = GameUI.current.unitPortraitTemplate.CloneTree().contentContainer;
newTemplateElement.AddToClassList("unit-portrait");
newTemplateElement.AddToClassList("unit-portrait-small");
parentElement.Add(newTemplateElement);
Init(newTemplateElement);
}
/// <summary>
/// Display given <see cref="UnitObject"/> in this portrait.
/// </summary>
public void SetUnit(UnitObject unitToSet)
{
// Remove everything about previous Unit
UnsetUnit();
// New Unit assigned - start listeners and wait
unit = unitToSet;
unit.basicEvents.onCurrentResourceChange.AddListener(OnBasicResourceChange);
// Set Unit's portrait
_portrait.style.backgroundImage = new StyleBackground(unit.basicData.image);
UnitPortraitHealthChange();
}
/// <summary>
/// Clear currently displaying <see cref="UnitObject"/> in this portrait.
/// </summary>
public void UnsetUnit()
{
// There is no unit currently
if (!unit) return;
// Remove all listeners, then remove assigned Unit
unit.basicEvents.onCurrentResourceChange.RemoveListener(OnBasicResourceChange);
unit = null;
// Make UI invisible and unset portrait
_portrait.style.backgroundImage = null;
}
/// <summary>
/// Completly destroy this potratit.
/// </summary>
public void Destroy()
{
unit.basicEvents.onCurrentResourceChange.RemoveListener(OnBasicResourceChange);
templateElement.parent.Remove(templateElement);
}
private void OnBasicResourceChange(BasicResourceChangeEvent basicResourceChangeEvent)
{
// Update HealthBar length
if (basicResourceChangeEvent.type is BasicResourceType.Health)
{
UnitPortraitHealthChange();
}
}
private void UnitPortraitHealthChange()
{
// Update HealthBar length
_healthBar.value = unit.basicData.currentResources.Get(BasicResourceType.Health) / unit.basicData.maxResources.Get(BasicResourceType.Health) * 100;
// Update HealthBar label
_healthLabel.text = $"{unit.basicData.currentResources.Get(BasicResourceType.Health)}/{unit.basicData.maxResources.Get(BasicResourceType.Health)}";
}
}
}