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

165 lines
5.9 KiB
C#
Raw Normal View History

2023-06-08 14:09:50 +08:00
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 : UXPanel,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;
public override async void OnStart()
{
base.OnStart();
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 not null)
{
UXContainer uxContainer = new(element);
equipContainers.Add(x.Name, uxContainer);
element.RegisterCallback<MouseDownEvent>(mouseEvent =>
{
if (mouseEvent.button is 0)
{
}
else if (mouseEvent.button is 1)
{
equipContainer.TryDeEquip(System.Activator.CreateInstance(x) as IEquipmentSlot);
}
});
}
}
}
public override void Set(bool active)
{
base.Set(active);
inputActionGroup.allowInput.SetElements(this, active);
returnInterval.Reset();
}
void OnEnable()
{
IEntity.OnSpawnLocalPlayer += OnSpawnLocalPlayer;
}
void OnDisable()
{
IEntity.OnSpawnLocalPlayer -= OnSpawnLocalPlayer;
}
void OnSpawnLocalPlayer(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;
}
private void OnInventory(InputAction.CallbackContext context)
{
if (context.action.WasPressedThisFrame() && returnInterval)
UXFramework.Enter<HUD>();
}
private void OnReturn(InputAction.CallbackContext context)
{
if (context.started && returnInterval)
UXFramework.Enter<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);
}
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)
{
IEntity.LocalPlayer.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;
}
}
}
}