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

154 lines
5.7 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Item;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Objects.Unit.Actions;
using VOID.Generic.Objects.Unit.Events;
using VOID.UserInterface.Game.Interfaces;
using VOID.UserInterface.Game.Util;
namespace VOID.UserInterface.Game
{
/// <summary>
/// Manages all visuals in one instance of <see cref="OtherUnitBackpackUI"/>.
/// </summary>
public class OtherUnitBackpackUI : MonoBehaviour, IHasWindow
{
public static readonly List<OtherUnitBackpackUI> CurrentList = new();
// WindowUI
public WindowUI windowUI { get; private set; }
// ContainerObject, its content to which this UI is connected and also unit who opened it
public UnitObject unit { get; private set; }
private UnitObjectBackpack _unitBackpack;
private UnitObject _openedBy;
// Visual Elements
private VisualElement _rootElement;
private VisualElement _slotsElement;
private SlotUI[] _slots;
private void Awake()
{
CurrentList.Add(this);
var uiDocument = gameObject.GetComponent<UIDocument>();
var template = uiDocument.rootVisualElement;
// Find all important elements
_rootElement = template.Q("root-container");
_slotsElement = template.Q("slots");
windowUI = gameObject.GetComponent<WindowUI>();
// Remove place holders
_slotsElement.Clear();
windowUI.OnClose += Close;
_rootElement.dataSource = this;
_rootElement.pickingMode = PickingMode.Position;
}
/// <summary>
/// Opens newly initialized <see cref="OtherUnitBackpackUI"/> <see cref="VisualElement"/>.
/// This should be called from <see cref="OtherUnitBackpackManagerUI"/>.
/// </summary>
public void Open(UnitObject unit, UnitObject openedBy)
{
this.unit = unit;
_unitBackpack = unit.unitBackpack;
_openedBy = openedBy;
_slots = new SlotUI[_unitBackpack.items.Length];
for (var i = 0; i < _unitBackpack.items.Length; i++)
SetSlot(i, _unitBackpack.items[i]);
unit.unitEvents.onClosedByOtherUnit.AddListener(OnClose);
unit.unitEvents.onBackpackResize.AddListener(OnResize);
unit.unitEvents.onBackpackSwap.AddListener(OnSwap);
unit.unitEvents.onBackpackPick.AddListener(OnMoveIn);
unit.unitEvents.onBackpackDrop.AddListener(OnMoveOut);
windowUI.SetTitle(unit.basicData.finalName);
// Make sure it is visible
_rootElement.style.display = DisplayStyle.Flex;
}
/// <summary>
/// Orders player's active <see cref="UnitObject"/> to <see cref="CloseOtherUnitAction"/>.
/// This action will close <see cref="WindowUI"/> which execute <see cref="OnClose"/>.
/// </summary>
public void Close()
{
new CloseOtherUnitAction(_openedBy, unit).DoIt();
}
private void OnClose(CloseOtherUnitEvent closeOtherUnitEvent)
{
unit.unitEvents.onClosedByOtherUnit.RemoveListener(OnClose);
unit.unitEvents.onBackpackResize.RemoveListener(OnResize);
unit.unitEvents.onBackpackSwap.RemoveListener(OnSwap);
unit.unitEvents.onBackpackPick.RemoveListener(OnMoveIn);
unit.unitEvents.onBackpackDrop.RemoveListener(OnMoveOut);
windowUI.OnClose -= Close;
_rootElement.parent.parent.Remove(_rootElement.parent);
CurrentList.Remove(this);
Destroy(this);
}
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++)
RemoveSlot(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++)
SetSlot(i, null);
}
private void OnSwap(BackpackSwapEvent backpackSwapEvent)
{
SetSlot(backpackSwapEvent.firstSlotIndex, backpackSwapEvent.firstItem);
SetSlot(backpackSwapEvent.secondSlotIndex, backpackSwapEvent.secondItem);
}
private void OnMoveIn(BackpackPickEvent backpackPickEvent)
{
SetSlot(backpackPickEvent.slotIndex, backpackPickEvent.item);
}
private void OnMoveOut(BackpackDropEvent backpackDropEvent)
{
SetSlot(backpackDropEvent.slotIndex, null);
}
private void SetSlot(int slotIndex, ItemObject item)
{
// Create new VisualElement if not exists
if (_slots[slotIndex] is null)
{
_slots[slotIndex] = new SlotUI();
_slots[slotIndex].InitNew(_slotsElement, SlotType.OtherUnitBackpackSlot, slotIndex, "Slot-" + slotIndex);
}
// Put item's icon or else remain default
_slots[slotIndex].Set(item);
}
private void RemoveSlot(int slotIndex)
{
_slots[slotIndex].Destroy();
}
}
}