165 lines
5.0 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|