Files
2026-07-09 21:33:33 +02:00

199 lines
8.0 KiB
C#

using System;
using JetBrains.Annotations;
using UnityEngine;
using UnityEngine.UIElements;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Item;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Objects.Unit.Events;
using VOID.Generic.Player;
using VOID.Generic.Player.Input;
using VOID.UserInterface.Game.Interfaces;
using VOID.UserInterface.Game.Util;
namespace VOID.UserInterface.Game
{
public class BackpackUI : MonoBehaviour, IHasWindow
{
public static BackpackUI current { get; private set; }
// WindowUI
public WindowUI windowUI { get; private set; }
// Active Unit and his Backpack
private UnitObject _unit;
private UnitObjectBackpack _backpack;
// Visual Elements
private VisualElement _rootElement;
private VisualElement _slotsElement;
private SlotUI[] _slots;
// References
private ShortcutsInputManager _shortcutsInputManager;
private PlayerController _playerController;
// Sort buttons
private Button _sortButton;
private void Awake() {
current = this;
var uiDocument = gameObject.GetComponent<UIDocument>();
var templateElement = uiDocument.rootVisualElement;
// Find all important elements
_rootElement = templateElement.Q("root-backpack");
_slotsElement = templateElement.Q("slots");
windowUI = gameObject.GetComponent<WindowUI>();
// Sort buttons
_sortButton = templateElement.Q<Button>("Sort");
// Clear placeholders
_slotsElement.Clear();
_rootElement.dataSource = this;
_rootElement.pickingMode = PickingMode.Position;
}
private void Start() {
_shortcutsInputManager = ShortcutsInputManager.current;
_playerController = PlayerController.current;
// Toggle show/hide when pressing shortcut for backpack
_shortcutsInputManager.inventory.performed += _ => windowUI.Toggle();
windowUI.OnOpen += OnOpen;
windowUI.OnClose += OnClose;
// Sort buttons
_sortButton.clicked += () => {
var worldBound = _sortButton.worldBound;
var positionToDisplayDropdown = new Vector2(worldBound.x, worldBound.y + worldBound.height);
DropdownUI.current.Prepare(positionToDisplayDropdown);
DropdownUI.current.AddOption("Name ↑", () => _backpack.Sort(item => item.basicData.finalName, SortDirectionType.Ascending));
DropdownUI.current.AddOption("Name ↓", () => _backpack.Sort(item => item.basicData.finalName, SortDirectionType.Descending));
DropdownUI.current.AddOption("Price ↑", () => _backpack.Sort(item => item.itemData.finalValue, SortDirectionType.Ascending));
DropdownUI.current.AddOption("Price ↓", () => _backpack.Sort(item => item.itemData.finalValue, SortDirectionType.Descending));
DropdownUI.current.AddOption("Weight ↑", () => _backpack.Sort(item => item.itemData.finalWeight, SortDirectionType.Ascending));
DropdownUI.current.AddOption("Weight ↓", () => _backpack.Sort(item => item.itemData.finalWeight, SortDirectionType.Descending));
DropdownUI.current.AddOption("Quality ↑", () => _backpack.Sort(item => item.itemData.quality.index, SortDirectionType.Ascending));
DropdownUI.current.AddOption("Quality ↓", () => _backpack.Sort(item => item.itemData.quality.index, SortDirectionType.Descending));
DropdownUI.current.Open();
};
windowUI.SetTitle("Backpack");
// Hidden by default
windowUI.Close();
}
public void Toggle() => windowUI.Toggle();
public void Open() => windowUI.Open();
public void Close() => windowUI.Close();
private void OnOpen() {
// References to active unit
_unit = PlayerController.current.activeUnit;
_backpack = _unit.unitBackpack;
// Refresh UI when we change active unit
_playerController.OnActiveUnitChange += OnActiveUnitChange;
// Initialize array with same amount of slots as backpack
_slots = new SlotUI[_backpack.items.Length];
// Initialize all VisualElements
for (var i = 0; i < _backpack.items.Length; i++)
UpdateSlotUI(i, _backpack.items[i]);
// Listen to all changes in backpack and update UI
_unit.unitEvents.onBackpackPick.AddListener(OnPick);
_unit.unitEvents.onBackpackDrop.AddListener(OnDrop);
_unit.unitEvents.onBackpackSwap.AddListener(OnSwap);
_unit.unitEvents.onBackpackSort.AddListener(OnSort);
_unit.unitEvents.onBackpackResize.AddListener(OnResize);
}
private void OnClose() {
// Stop listening
_playerController.OnActiveUnitChange -= OnActiveUnitChange;
// Backpack closed, no need to listen for backpack changes
if (_unit) {
_unit.unitEvents.onBackpackPick.RemoveListener(OnPick);
_unit.unitEvents.onBackpackDrop.RemoveListener(OnDrop);
_unit.unitEvents.onBackpackSwap.RemoveListener(OnSwap);
_unit.unitEvents.onBackpackSort.RemoveListener(OnSort);
_unit.unitEvents.onBackpackResize.RemoveListener(OnResize);
}
// Remove all VisualElement slots
if (_slots != null)
for (var i = 0; i < _slots.Length; i++)
RemoveSlotUI(i);
// Clear variables
_slots = null;
_unit = null;
_backpack = null;
}
private void OnActiveUnitChange(UnitObject unitObject) {
windowUI.Close();
windowUI.Open();
}
private void OnPick(BackpackPickEvent backpackPickEvent) {
UpdateSlotUI(backpackPickEvent.slotIndex, backpackPickEvent.item);
}
private void OnDrop(BackpackDropEvent backpackDropEvent) {
UpdateSlotUI(backpackDropEvent.slotIndex, null);
}
private void OnSwap(BackpackSwapEvent backpackSwapEvent) {
UpdateSlotUI(backpackSwapEvent.firstSlotIndex, backpackSwapEvent.firstItem);
UpdateSlotUI(backpackSwapEvent.secondSlotIndex, backpackSwapEvent.secondItem);
}
private void OnSort(BackpackSortEvent backpackSortEvent) {
var backpackItems = backpackSortEvent.unit.unitBackpack.items;
for (var i = 0; i < backpackItems.Length; i++)
UpdateSlotUI(i, backpackItems[i]);
}
private void OnResize(BackpackResizeEvent backpackResizeEvent) {
// Before resizing - remove all unused slots
if (backpackResizeEvent.beforeSlotCount > backpackResizeEvent.afterSlotCount)
for (var i = backpackResizeEvent.afterSlotCount; i < backpackResizeEvent.beforeSlotCount; i++)
RemoveSlotUI(i);
Array.Resize(ref _slots, backpackResizeEvent.afterSlotCount);
// After resizing - insert empty slots
if (backpackResizeEvent.beforeSlotCount < backpackResizeEvent.afterSlotCount)
for (var i = backpackResizeEvent.beforeSlotCount; i < backpackResizeEvent.afterSlotCount; i++)
UpdateSlotUI(i, null);
}
private void UpdateSlotUI(int slotIndex, [CanBeNull] ItemObject item) {
// Create new VisualElement if not exists
if (_slots[slotIndex] is null) {
_slots[slotIndex] = new SlotUI();
_slots[slotIndex].InitNew(_slotsElement, SlotType.BackpackSlot, slotIndex, "Slot-" + slotIndex);
}
// Put item's icon or else remain default
_slots[slotIndex].Set(item);
}
private void RemoveSlotUI(int slotIndex) {
_slots[slotIndex].Destroy();
}
}
}