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

211 lines
6.8 KiB
C#

using System;
using JetBrains.Annotations;
using Sirenix.OdinInspector;
using UnityEngine;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Container.Events;
using VOID.Generic.Objects.Item;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Util;
using Object = UnityEngine.Object;
namespace VOID.Generic.Objects.Container
{
[Serializable]
public class ContainerObjectContent : ObjectComponent<ContainerObject>
{
#region Initialize
protected override void SelfInitialize()
{
// Empty GameObject where all items from backpack are "attached"
_content = new GameObject("_content");
_content.transform.parent = parent.gameObject.transform;
_content.transform.localPosition = Vector3.zero;
}
protected override void Initialize()
{
// Instantiate all prefabs
for (var i = 0; i < _items.Length; i++)
{
if (!_items[i]) continue;
var item = _items[i];
_items[i] = null;
// Selected item is ASSET (prefab), we need to instantiate it first
if (!item.gameObject.scene.IsValid())
item = Object.Instantiate(item.gameObject).GetComponent<ItemObject>();
// Instantiate prefab and get references to its GameObject and ItemObject
MoveIn(i, item);
}
Resize();
}
#endregion
private GameObject _content;
// Items in content (list of ItemObjects and their GameObjects)
[SerializeField, DisableInPlayMode] private ItemObject[] _items = Array.Empty<ItemObject>();
public ItemObject[] items => _items;
public void MoveIn(int itemIndex, ItemObject item, UnitObject byWho = null)
{
if (items.Length <= itemIndex)
Resize(itemIndex);
if (items[itemIndex])
{
MoveIn(item, byWho);
return;
}
items[itemIndex] = item;
var moveInEvent = new ContainerMoveInEvent
{
byWho = byWho,
item = item,
slotIndex = itemIndex,
container = parent,
};
parent.containerEvents.onMoveIn.Invoke(moveInEvent);
item.itemEvents.onMovedIntoContainer.Invoke(moveInEvent);
var itemGameObject = item.gameObject;
itemGameObject.transform.parent = _content.transform;
itemGameObject.transform.localPosition = Vector3.zero;
itemGameObject.transform.localRotation = new Quaternion();
item.basicEvents.onRemove.AddListener(OnItemRemove);
Resize();
}
public void MoveIn(ItemObject item, UnitObject byWho = null)
{
// Find first free slot in backpack
var firstFreeIndex = Array.IndexOf(items, null);
// No free slots, we need to resize array
if (firstFreeIndex == -1)
{
firstFreeIndex = items.Length;
Resize();
}
MoveIn(firstFreeIndex, item, byWho);
}
public void MoveOut(int itemIndex, UnitObject byWho = null)
{
var tempMoveOutItem = items[itemIndex];
items[itemIndex].basicEvents.onRemove.RemoveListener(OnItemRemove);
items[itemIndex] = null;
var moveOutEvent = new ContainerMoveOutEvent
{
byWho = byWho,
item = tempMoveOutItem,
slotIndex = itemIndex,
container = parent,
};
parent.containerEvents.onMoveOut.Invoke(moveOutEvent);
tempMoveOutItem.itemEvents.onMovedOutOfContainer.Invoke(moveOutEvent);
var tempItemGameObject = tempMoveOutItem.gameObject;
tempItemGameObject.gameObject.transform.parent = null;
tempItemGameObject.gameObject.transform.position = parent.transform.position;
Resize();
}
public void MoveOut(ItemObject item, UnitObject byWho = null)
{
MoveOut(Array.IndexOf(items, item), byWho);
}
public void Swap(int firstItemIndex, int secondItemIndex, UnitObject byWho = null)
{
Resize(Math.Max(firstItemIndex, secondItemIndex));
(items[firstItemIndex], items[secondItemIndex]) = (items[secondItemIndex], items[firstItemIndex]);
var swapEvent = new ContainerSwapEvent
{
byWho = byWho,
firstSlotIndex = firstItemIndex,
firstItem = items[firstItemIndex],
secondSlotIndex = secondItemIndex,
secondItem = items[secondItemIndex],
};
parent.containerEvents.onSwap.Invoke(swapEvent);
Resize();
}
public void Sort(Func<ItemObject, IComparable> valueGetter, SortDirectionType sortDirection, [CanBeNull] UnitObject byWho = null) {
ItemObjectSortUtil.Sort(ref _items, valueGetter, sortDirection);
var containerSortEvent = new ContainerSortEvent {
container = parent,
byUnit = byWho
};
parent.containerEvents.onSort.Invoke(containerSortEvent);
Resize();
}
private void OnItemRemove(RemoveEvent removeEvent)
{
var removedItem = removeEvent.obj as ItemObject;
MoveOut(removedItem);
}
public void Resize(int minSize = 0, int rowSize = 10)
{
var beforeSlotCount = items.Length;
var lastItemIndex = 0;
// Find last slotIndex with existing item (not null)
for (var i = beforeSlotCount - 1; i >= 0; i--)
{
lastItemIndex = i;
if (items[i] is not null) break;
}
// Count how many slots backpack will have after resize
var afterSlotCount = Mathf.CeilToInt((Mathf.Max(lastItemIndex, minSize) + rowSize) / (float)rowSize) * rowSize;
// Size not changed, do nothing
if (beforeSlotCount == afterSlotCount) return;
// Resize backpack's arrays
var tempItems = items;
Array.Resize(ref tempItems, afterSlotCount);
_items = tempItems;
var containerResizeEvent = new ContainerResizeEvent
{
container = parent,
beforeSlotCount = beforeSlotCount,
afterSlotCount = afterSlotCount,
lastItemIndex = lastItemIndex,
};
parent.containerEvents.onResize.Invoke(containerResizeEvent);
}
}
}