BITFALL/Assets/Artists/Scripts/UX/UXPlayerEquipSelector.cs

165 lines
5.0 KiB
C#

using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using BITFALL;
using BITFALL.Entities;
using BITFALL.Entities.Equipment;
using BITKit;
using BITKit.Entities;
using BITKit.Entities.Player;
using BITKit.UX;
using UnityEngine;
using UnityEngine.UIElements;
namespace bitfall.UX
{
public class UXPlayerEquipSelector : MonoBehaviour
{
[SerializeField] private UIDocument document;
[SerializeField] private VisualTreeAsset equipmentVisualTreeAsset;
[SerializeField] private VisualTreeAsset equipSelectorVisualTreeAsset;
[SerializeReference, SubclassSelector] private IPlayerService _playerService;
[Inject] private IPlayerEquipSelector _playerEquipSelector;
[Inject] private IEntityEquipmentContainer _equipmentContainer;
[Inject] private IEntityEquipment _equipment;
[Inject] private IKnockdown _knockdown;
[UXBindPath("equipment-container")]
private VisualElement _equipmentContainerElement;
[UXBindPath("equipSelector-container")]
private VisualElement _equipSelectorContainerElement;
private VisualElement _currentEquipElement;
private readonly ConcurrentDictionary<string, VisualElement> _equipmentContainerDictionary = new();
private readonly ConcurrentDictionary<int,VisualElement> _equipSelectorContainerDictionary=new();
private void Start()
{
UXUtils.Inject(this);
_playerService.OnPlayerInitialized += OnStartLocalPlayer;
destroyCancellationToken.Register(() => _playerService.OnPlayerInitialized -= OnStartLocalPlayer);
}
private void OnStartLocalPlayer(Entity obj)
{
obj.Inject(this);
_equipmentContainerElement.Clear();
_equipSelectorContainerElement.Clear();
_playerEquipSelector.OnUpdateEquip += OnUpdateEquip;
_equipmentContainer.OnEquip += OnEquip;
_equipmentContainer.OnDeEquip += OnDeEquip;
_equipment.OnEquip += x => UpdateSelectorFocus();
_equipment.OnUnEquip += x => UpdateSelectorFocus();
_knockdown.OnKnockdown += UpdateSelectorFocus;
_knockdown.OnRevive += UpdateSelectorFocus;
}
private void OnDeEquip(IEquipmentSlot arg1, IBasicItem arg2)
{
if (_equipmentContainerDictionary.TryRemove(arg2.AddressablePath, out var element) is false) return;
element.RemoveFromHierarchy();
UpdateSelectorFocus();
}
private void OnEquip(IEquipmentSlot arg1, IBasicItem arg2)
{
_equipmentContainerDictionary.GetOrAdd(arg2.AddressablePath,
CreateEquipmentContainer);
UpdateSelectorFocus();
}
private void OnUpdateEquip(IDictionary<int, IBasicItem> obj)
{
_equipSelectorContainerElement.Clear();
_equipSelectorContainerDictionary.Clear();
foreach (var (index,x) in obj)
{
var element =_equipSelectorContainerDictionary.GetOrAdd(index,CreateEquipSelectorContainer(x.AddressablePath));
_equipSelectorContainerElement.Add(element);
}
UpdateSelectorFocus();
}
private VisualElement CreateEquipmentContainer(string addressablePath)
{
var item = ItemExtensions.GetAssetable(addressablePath);
var container =
_equipmentContainerElement.Create<VisualElement>(() => equipmentVisualTreeAsset.CloneTree());
var element = BITFALL.UX.UXUtils.CreateItemContainer(container, item);
element.visualElement.userData = addressablePath;
return element;
}
private VisualElement CreateEquipSelectorContainer(string addressablePath)
{
var item = ItemExtensions.GetAssetable(addressablePath);
var container =
_equipSelectorContainerElement.Create<VisualElement>(() => equipSelectorVisualTreeAsset.CloneTree());
var element = BITFALL.UX.UXUtils.CreateItemContainer(container, item);
if (item.RectangleIcon)
element.icon.style.backgroundImage = item.RectangleIcon;
element.visualElement.userData = addressablePath;
return element;
}
private void UpdateSelectorFocus()
{
var current = _equipment.CurrentItem?.AddressablePath ?? string.Empty;
const string active = "active";
_currentEquipElement?.RemoveFromHierarchy();
_currentEquipElement =
_equipSelectorContainerElement.Create<VisualElement>(equipSelectorVisualTreeAsset.CloneTree);
_currentEquipElement.SetActive(false);
var list = new List<VisualElement>();
list.AddRange(_equipmentContainerElement.Children());
list.AddRange(_equipSelectorContainerElement.Children());
list.Add(_currentEquipElement);
foreach (var visualElement in list.Where(visualElement => visualElement.userData is not null))
{
visualElement.EnableInClassList(active,current == (string)visualElement.userData);
var item = ItemExtensions.GetAssetable((string)visualElement.userData);
visualElement.SetEnabled(
!_knockdown.IsKnockdown || item.AllowUseWhileKnocked
);
}
if (_equipment.CurrentItem is not null && _playerEquipSelector.Equipped.Values.All(x => x.AddressablePath != _equipment.CurrentItem.AddressablePath))
{
BITFALL.UX.UXUtils.CreateItemContainer(_currentEquipElement, _equipment.CurrentItem);
_currentEquipElement.SetActive(true);
}
else
{
_currentEquipElement.SetActive(false);
}
}
}
}