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

167 lines
6.1 KiB
C#

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEngine.InputSystem;
using BITKit;
using BITKit.UX;
using BITKit.Entities;
using UnityEngine.AddressableAssets;
namespace BITFALL.UX
{
public class Inventory : UIToolKitPanel,IWeightedCallback,IPlayerEquipCallback
{
[Header(Constant.Header.Input)]
public InputActionReference inventoryAction;
public InputActionReference returnAction;
public InputActionGroup inputActionGroup = new();
[Header(Constant.Header.Components)]
public UXBar weightBar;
[Header(Constant.Header.Prefabs)]
public VisualTreeAsset containerTemplate;
public VisualTreeAsset cellTemplate;
public VisualTreeAsset itemTemplate;
[Header(Constant.Header.Components)]
public UXImage containerRoot;
public UXImage serializableRoot;
public UXFactory factory;
[Header(Constant.Header.InternalVariables)]
private readonly Dictionary<int, UXContainer> containers = new();
private readonly Dictionary<string, UXContainer> equipContainers = new();
private readonly IntervalUpdate returnInterval = new(0.1f);
private IBasicItemContainer inventory;
private IPlayerEquipContainer equipContainer;
private IEntity _entity;
protected override async void Awake()
{
base.Awake();
inputActionGroup.RegisterCallback(returnAction, OnReturn);
inputActionGroup.RegisterCallback(inventoryAction, OnInventory);
foreach (var x in await ReflectionHelper.GetTypes<IEquipmentSlot>())
{
var element = document.rootVisualElement.Q(x.Name);
if (element is null) continue;
UXContainer uxContainer = new(element);
equipContainers.Add(x.Name, uxContainer);
element.RegisterCallback<MouseDownEvent>(mouseEvent =>
{
switch (mouseEvent.button)
{
case 0:
break;
case 1:
equipContainer.TryDeEquip(System.Activator.CreateInstance(x) as IEquipmentSlot);
break;
}
});
}
}
protected override void OnEntryOrExit(bool isEntry)
{
inputActionGroup.allowInput.SetElements(this, isEntry);
returnInterval.Reset();
}
protected override void OnEnable()
{
base.OnEnable();
IEntity.OnPlayerInitializedLocalPlayer += OnPlayerInitializedLocalPlayer;
}
protected override void OnDisable()
{
base.OnDisable();
IEntity.OnPlayerInitializedLocalPlayer -= OnPlayerInitializedLocalPlayer;
}
private void OnPlayerInitializedLocalPlayer(IEntity entity)
{
entity.RegisterCallback<IWeightedCallback>(this);
entity.RegisterCallback<IPlayerEquipCallback>(this);
inventory = entity.Get<IBasicItemContainer>();
equipContainer = entity.Get<IPlayerEquipContainer>();
inventory.OnAdd += OnAdd;
inventory.OnRemove += OnRemove;
inventory.OnSet += OnSet;
_entity = entity;
}
private void OnInventory(InputAction.CallbackContext context)
{
if (context.JustPressed())
UXService.Entry<HUD>();
}
private void OnReturn(InputAction.CallbackContext context)
{
if (context.JustPressed())
UXService.Entry<HUD>();
}
public void OnWeighted(float current, float max)
{
weightBar.SetDirect( current is 0 ? 0 :(current / max).Fix(),$"{current}/{max}");
}
private void OnAdd(IBasicItem item)
{
var asset = Addressables.LoadAssetAsync<AssetableItem>(item.AdressablePath).WaitForCompletion();
var uxContainer = factory.Create();
uxContainer.icon.style.backgroundImage = asset.SquareIcon;
uxContainer.contextLabel.text = asset.Name;
uxContainer.button.clicked += () =>
{
UseItem(item);
};
uxContainer.visualElement.RegisterCallback<MouseDownEvent>(x =>
{
if (x.button is 1)
{
ContextMenuBuilder
.Create()
.BuildAction("使用", () => UseItem(item))
.BuildAction("丢下", () => DropItem(item))
.Build();
}
});
containers.Add(item.Id, uxContainer);
}
private void OnRemove(IBasicItem item)
{
if (!containers.TryGetValue(item.Id, out var uxContainer)) return;
factory.Remove(uxContainer);
containers.Remove(item.Id);
}
private void OnSet(IBasicItem item)
{
if (!containers.TryGetValue(item.Id, out var uxContainer)) return;
if(item.TryGetProperty<int>(out var count))
{
uxContainer.numberLabel.text = count.ToString();
}
}
private void UseItem(IBasicItem item)
{
_entity.Get<IRequestor<IBasicItem>>().Excute(item);
}
private void DropItem(IBasicItem item)
{
inventory.Drop(item.Id);
}
void IPlayerEquipCallback.OnEquip(IEquipmentSlot slot, IBasicItem item)
{
var asset = item.GetAssetable();
if (equipContainers.TryGetValue(slot.GetType().Name, out var container))
{
container.icon.style.backgroundImage = asset.SquareIcon;
}
}
void IPlayerEquipCallback.DeEquip(IEquipmentSlot slot, IBasicItem item)
{
if(equipContainers.TryGetValue(slot.GetType().Name,out var container))
{
container.icon.style.backgroundImage = null;
}
}
}
}