211 lines
6.8 KiB
C#
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);
|
|
}
|
|
}
|
|
} |