296 lines
9.5 KiB
C#
296 lines
9.5 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using BITKit;
|
|
using BITKit.Entities;
|
|
using BITKit.Mod;
|
|
using BITKit.UX;
|
|
using BITKit.WorldNode;
|
|
using Cysharp.Threading.Tasks;
|
|
using Net.Project.B.Interaction;
|
|
using Net.Project.B.Inventory;
|
|
using Net.Project.B.Item;
|
|
using Net.Project.B.UX;
|
|
using Project.B.Entities;
|
|
using Project.B.Player;
|
|
using UnityEngine;
|
|
using UnityEngine.InputSystem;
|
|
using UnityEngine.UIElements;
|
|
|
|
namespace Project.B.UX
|
|
{
|
|
public class UXInventorySwap : UIToolKitPanel,IUXInventorySwap
|
|
{
|
|
public override bool AllowCursor => true;
|
|
public override bool CloseWhenClickOutside => true;
|
|
|
|
private readonly IUXItemInspector _itemInspector;
|
|
private readonly IUXKeyMap<InputAction> _uxKeyMap;
|
|
private readonly IPlayerFactory _playerFactory;
|
|
private readonly IWorldInteractionService _interactionService;
|
|
private readonly IEntitiesService _entitiesService;
|
|
protected override string DocumentPath => "ui_inventory_swap";
|
|
|
|
private VisualTreeAsset _template;
|
|
|
|
[Inject]
|
|
private IPlayerInventory _playerInventory;
|
|
|
|
[UXBindPath("self-container")]
|
|
private VisualElement _selfContainer;
|
|
|
|
[UXBindPath("target-container")]
|
|
private VisualElement _targetContainer;
|
|
|
|
[UXBindPath("weapon-container",true)]
|
|
private VisualElement _weaponContainer;
|
|
|
|
[UXBindPath("preview-container", true)]
|
|
private VisualElement _previewContainer;
|
|
|
|
[UXBindPath("self-label")]
|
|
private Label _selfLabel;
|
|
|
|
[UXBindPath("target-label")]
|
|
private Label _targetLabel;
|
|
|
|
private IRuntimeItemContainer _targetItemContainer;
|
|
|
|
public UXInventorySwap(IUXService uxService, IPlayerFactory playerFactory, IWorldInteractionService interactionService, IEntitiesService entitiesService, IUXKeyMap<InputAction> uxKeyMap, IUXItemInspector itemInspector) : base(uxService)
|
|
{
|
|
_playerFactory = playerFactory;
|
|
_interactionService = interactionService;
|
|
_entitiesService = entitiesService;
|
|
_uxKeyMap = uxKeyMap;
|
|
_itemInspector = itemInspector;
|
|
OnInitiatedAsync += InitiatedAsync;
|
|
|
|
_playerFactory.OnEntityCreated += OnEntityCreated;
|
|
|
|
_interactionService.OnInteraction += OnInteraction;
|
|
}
|
|
|
|
private void OnInteraction(object arg1, IWorldInteractable arg2, WorldInteractionProcess arg3, object arg4)
|
|
{
|
|
if (arg3 is WorldInteractionProcess.Performed or WorldInteractionProcess.System is false) return;
|
|
|
|
if (_entitiesService.TryGetEntity(arg2.Id, out var entity) is false) return;
|
|
|
|
if (entity.ServiceProvider.QueryComponents(out IRuntimeItemContainer container) is false) return;
|
|
|
|
_targetItemContainer = container;
|
|
|
|
UXService.Entry(this);
|
|
}
|
|
|
|
private UniTask OnEntityCreated(string arg1, IEntity arg2)
|
|
{
|
|
arg2.Inject(this);
|
|
return UniTask.CompletedTask;
|
|
}
|
|
|
|
private async UniTask InitiatedAsync()
|
|
{
|
|
_template =await ModService.LoadAsset<VisualTreeAsset>("ux_item_template");
|
|
|
|
_weaponContainer ??= _targetContainer;
|
|
|
|
if (_previewContainer is not null)
|
|
{
|
|
_previewContainer.style.backgroundImage = null;
|
|
}
|
|
}
|
|
|
|
public override async UniTask EntryAsync()
|
|
{
|
|
_selfContainer.Clear();
|
|
_weaponContainer.Clear();
|
|
_targetContainer.Clear();
|
|
|
|
await base.EntryAsync();
|
|
|
|
await Rebuild();
|
|
}
|
|
|
|
private async UniTask Rebuild()
|
|
{
|
|
_selfContainer.Clear();
|
|
_weaponContainer.Clear();
|
|
_targetContainer.Clear();
|
|
|
|
if(_targetItemContainer is null)return;
|
|
|
|
foreach (var item in _playerInventory.Container.GetItems())
|
|
{
|
|
var container = _selfContainer.Create(_template);
|
|
|
|
container.parent.SetEnabled(_targetItemContainer.AllowAdd);
|
|
|
|
UXInventoryUtils.Setup(container, item).Forget();
|
|
|
|
container.Get<Button>().clicked += () =>
|
|
{
|
|
try
|
|
{
|
|
if (_playerInventory.Container.Remove(item.Id) is false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (_targetItemContainer.Add(item) is false)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
catch (PlayerInventoryAddItemOverridden)
|
|
{
|
|
|
|
}
|
|
Rebuild().Forget();
|
|
};
|
|
|
|
Setup(container,item);
|
|
|
|
container.Get<Button>().RegisterCallback<MouseDownEvent>(evt =>
|
|
{
|
|
if(evt.button is not 1)return;
|
|
|
|
ContextMenuBuilder
|
|
.Create()
|
|
.BuildText("操作")
|
|
.BuildAction("检视", () =>_itemInspector.Inspect(item))
|
|
.BuildAction("丢下", () =>
|
|
{
|
|
if (_playerInventory.Container.Drop(item.Id))
|
|
{
|
|
Rebuild().Forget();
|
|
}
|
|
|
|
})
|
|
.Build();
|
|
});
|
|
}
|
|
|
|
|
|
foreach (var item in _targetItemContainer.GetItems())
|
|
{
|
|
var scriptableItem =await UXInventoryUtils.GetScriptableItem(item.ScriptableId);
|
|
|
|
var container =(scriptableItem is ScriptableWeapon{WeaponSlot:1 or 2} ? _weaponContainer : _targetContainer).Create(_template);
|
|
|
|
container.parent.SetEnabled(_targetItemContainer.AllowRemove);
|
|
|
|
UXInventoryUtils.Setup(container,item).Forget();
|
|
|
|
container.Get<Button>().clicked += Take;
|
|
|
|
Setup(container,item);
|
|
|
|
container.Get<Button>().RegisterCallback<MouseDownEvent>(evt =>
|
|
{
|
|
ContextMenuBuilder
|
|
.Create()
|
|
.BuildText("操作")
|
|
.BuildAction("检视", () =>_itemInspector.Inspect(item))
|
|
.BuildAction("拿起", Take)
|
|
.Build();
|
|
});
|
|
|
|
var isWide = scriptableItem is ScriptableWeapon { WeaponSlot: (int)PlayerWeaponSlot.Primary or (int)PlayerWeaponSlot.Secondary or (int)PlayerWeaponSlot.Sidearm};
|
|
|
|
if (isWide)
|
|
{
|
|
container.style.width = 200;
|
|
}
|
|
|
|
void Take()
|
|
{
|
|
try
|
|
{
|
|
if (_targetItemContainer.Remove(item.Id) is false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (_playerInventory.Container.Add(item) is false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
}
|
|
catch (PlayerInventoryAddItemOverridden)
|
|
{
|
|
|
|
}
|
|
Rebuild().Forget();
|
|
}
|
|
}
|
|
|
|
return;
|
|
|
|
void Setup(VisualElement container, IRuntimeItem runtimeItem)
|
|
{
|
|
if(_previewContainer is null)return;
|
|
|
|
async void Callback(PointerEnterEvent x)
|
|
{
|
|
var item = await UXInventoryUtils.GetScriptableItem(runtimeItem.ScriptableId);
|
|
|
|
_previewContainer.style.backgroundImage = new(item.Icon);
|
|
}
|
|
|
|
container.Get<Button>().RegisterCallback<PointerEnterEvent>(Callback);
|
|
}
|
|
|
|
}
|
|
|
|
protected override void OnPanelEntry()
|
|
{
|
|
base.OnPanelEntry();
|
|
InputActionGroup.RegisterCallback(_uxKeyMap.CancelKey, OnReturn);
|
|
InputActionGroup.RegisterCallback(_uxKeyMap.InventoryKey, OnReturn);
|
|
|
|
if (_targetItemContainer is not null)
|
|
{
|
|
_targetItemContainer.IsBusy.AddElement(this);
|
|
}
|
|
}
|
|
|
|
protected override void OnPanelExit()
|
|
{
|
|
base.OnPanelExit();
|
|
InputActionGroup.UnRegisterCallback(_uxKeyMap.CancelKey, OnReturn);
|
|
InputActionGroup.UnRegisterCallback(_uxKeyMap.InventoryKey, OnReturn);
|
|
|
|
_selfContainer.Clear();
|
|
_targetContainer.Clear();
|
|
_weaponContainer.Clear();
|
|
|
|
if (_targetItemContainer is not null)
|
|
{
|
|
_targetItemContainer.IsBusy.RemoveElement(this);
|
|
}
|
|
}
|
|
|
|
private void OnReturn(InputAction.CallbackContext obj)
|
|
{
|
|
if (obj.JustPressed() is false) return;
|
|
|
|
|
|
UXService.Return();
|
|
}
|
|
|
|
public override void Dispose()
|
|
{
|
|
base.Dispose();
|
|
OnInitiatedAsync -= InitiatedAsync;
|
|
|
|
_playerFactory.OnEntityCreated -= OnEntityCreated;
|
|
|
|
|
|
_interactionService.OnInteraction -= OnInteraction;
|
|
}
|
|
}
|
|
|
|
}
|