projectEli/Assets/Inventory System/Scripts/UI/SlotUI.cs

652 lines
22 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System;
using static SimpleInventorySystem.GridUI;
namespace SimpleInventorySystem
{
public class SlotUI : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
[Header("Slot Attributes")]
public int width;
public int height;
public Image image;
public bool useImageAsSlotHolder;
public bool EquipSlot;
public bool FitItemImageInSlotImage = false;
[Header("Slot-to-Item Compatibility")]
public bool IgnoreItemSize;
public List<ItemTags> AllowedItemTags;
public List<ItemTags> DisallowedItemTags;
public List<SlotUI> HasSlotsBelongingToItem;
// Hidden In Inspector
[HideInInspector] public Stack<ItemUI> stackedItems = new Stack<ItemUI>(); // WARNING: Stack can give some odd troubles with the raycast, consider revision or consideration.
[HideInInspector] public LimitStackSlot limitStackSlot;
[HideInInspector] public LimitStackSlotManager limitStackSlotManager;
[HideInInspector] public bool DroppedOnFrame;
[HideInInspector] public List<SlotUI> LinkedSlots = new List<SlotUI>();
[HideInInspector] public List<GroupSlotUI> groupSlots;
[HideInInspector] public GridUI grid;
[HideInInspector] public GridUI.Cell cell;
[HideInInspector] public ChangeSlotTitle changeSlotTitle;
public bool CellInUse;
[HideInInspector] public float imageScale = 1f; // TODO: See if this is still necessary
[HideInInspector] public bool StackItemsOnSlot; // TODO: Figure out if this should be kept hidden
// private variables
[SerializeField]
private ItemUI itemUI
{
get
{
if (stackedItems.Count == 0)
{
return null;
}
//// Debug.Log("Peek: " + stackedItems.Peek().gameObject.name);
return stackedItems.Peek();
}
}
private AppendUI appendUI;
private LinkedSlotUI linkedSlotUI;
private bool droppedStackOntoEmptySlot;
private RenderItemUIProperty renderProp;
private SlotUI BelongsToItemInSlot;
// public variables
public bool PointerIsHoveredOver { get { return InventorySystem.IsMouseOverUI(gameObject); } }
public ItemUI GetItemUI()
{
return itemUI;
}
/*public void OnDrop(PointerEventData eventData)
{
//
//("OnDrop");
if (eventData.pointerDrag != null && AllowedDraggable(eventData.pointerDrag))
{
DropOntoSlot(eventData.pointerDrag);
}
}*/
public bool AllowedDraggable(GameObject gameObject)
{
return gameObject.GetComponent<ItemUI>() != null;
}
public bool IsLinkedSlot()
{
return linkedSlotUI != null;
}
public bool DropOntoSlot(GameObject item, bool dropStack = true)
{
ItemUI itemDrop = item.GetComponent<ItemUI>();
ItemTags itemTag = itemDrop.ItemTag;
bool allowed = AllowedItemTags == null || AllowedItemTags.Count == 0 || AllowedItemTags.Contains(ItemTags.Any) || AllowedItemTags.Contains(itemTag);
bool disallowed = DisallowedItemTags.Contains(itemTag);
if (!allowed || disallowed)
{
return false;
}
if (itemDrop.Stackable && StackItemsOnSlot)
{
Debug.LogWarning("Item stacks are incompattible with slot stacking.");
return false;
}
if (limitStackSlot != null && limitStackSlot.HasReachedLimit())
{
return false;
}
if (IsLinkedSlot())
{
/*GameObject newItemDrop = Instantiate(item);
itemDrop = newItemDrop.GetComponent<ItemUI>();
itemDrop.IsLinkedSlotClone = true;*/
}
List<Cell> occupiedCells = new List<Cell>();
/// STACKING
/// This section concerns item stacks, not slot stacking
if (!itemDrop.IsLinkedSlotClone && ((HasStack() && itemUI != null /*&& itemUI.itemPrefab == itemDrop.itemPrefab*/ && itemUI.itemName == GetItemUI().itemName) || !dropStack))
{
// Debug.Log("Handling Stack");
int maxStackDrop = 1;
if (dropStack)
{
maxStackDrop = itemDrop.Count;
if (maxStackDrop > itemUI.StackLimit - itemUI.Count)
{
maxStackDrop = itemDrop.Count - itemUI.Count;
}
}
if (itemUI != null)
{
if (itemUI.AddToStack(maxStackDrop))
{
// Debug.Log("Add to stack");
itemDrop.RemoveFromStack(maxStackDrop);
if (appendUI != null && appendUI.StackAppend)
{
appendUI.AppendUIToTransform(itemDrop);
}
return true;
}
}
else
{
// Debug.Log("Stack handling");
GameObject GO = Instantiate(item, transform, false);
GO.transform.localPosition = new Vector3(0, 0, 0);
ItemUI oldItemDrop = itemDrop;
itemDrop = GO.GetComponent<ItemUI>();
if (itemDrop.AddToStack(maxStackDrop))
{
oldItemDrop.RemoveFromStack(maxStackDrop);
}
else
{
return false;
}
}
}
// Debug.Log(grid);
bool dropCheck = (grid != null && grid.CanMoveInCells(itemDrop, this, occupiedCells)) ||
(grid == null && !cell.inUse && (IgnoreItemSize || (cell.slot.width >= itemDrop.SizeAfterOrientation().Width && !cell.inUse && cell.slot.height >= itemDrop.SizeAfterOrientation().Height)));
// Debug.Log("Drop Check: " + dropCheck);
//// Debug.Log("DropCheck" + (grid == null && !cell.inUse && (IgnoreItemSize || (cell.slot.width >= itemDrop.SizeAfterOrientation().Width && !cell.inUse && cell.slot.height >= itemDrop.SizeAfterOrientation().Height))));
/*// Debug.Log("GridUI: DropOntoSlot(): " + gameObject.name + ": " + "dropCheck: " + dropCheck);
// Debug.Log("GridUI: DropOntoSlot(): " + gameObject.name + ": " + "allowed: " + allowed);*/
if (dropCheck)
{
if ((occupiedCells != null && occupiedCells.Count > 1) || StackItemsOnSlot)
{
// Debug.Log("SlotUI: " + occupiedCells.Count);
itemDrop.SetSlots(occupiedCells);
}
else
{
// Debug.Log("In Use");
cell.inUse = true;
CellInUse = cell.inUse;
}
Transform parent = transform;
if (useImageAsSlotHolder && image != null)
{
parent = image.gameObject.transform;
}
item.GetComponent<Transform>().SetParent(parent);
item.GetComponent<RectTransform>().anchoredPosition = GetComponent<RectTransform>().anchoredPosition;
//item.GetComponent<RectTransform>().pivot = new Vector2(0, 1);
itemDrop.SetSlot(this);
stackedItems.Push(itemDrop);
// Debug.Log("SlotUI:Drop:" + itemUI + ", " + itemDrop);
itemUI.DropItemOntoSlot(FitItemImageInSlotImage);
if (FitItemImageInSlotImage)
itemDrop.FitImageInSlot(new Vector2(Math.Abs(image.GetComponent<RectTransform>().sizeDelta.x), Math.Abs(image.GetComponent<RectTransform>().sizeDelta.y)));
if (itemUI.Stackable)
{
droppedStackOntoEmptySlot = true;
}
if (!IsLinkedSlot())
{
foreach (SlotUI ls in LinkedSlots)
{
if (ls == this)
{
Debug.LogWarning("No self-referencing for this array ;)");
continue;
}
//ls.DropOntoSlot(item);
}
}
if (grid != null)
{
grid.HideSlotsOfItem(itemDrop);
}
if (!useImageAsSlotHolder)
{
HideImage();
}
foreach (GroupSlotUI groupSlot in groupSlots)
{
if (groupSlot != null)
{
groupSlot.OnItemDropped();
}
}
if (appendUI != null)
{
// Debug.Log("Test");
appendUI.AppendUIToTransform(itemUI);
}
if (limitStackSlotManager != null)
{
limitStackSlotManager.SetStackSlotLimit(itemUI);
}
if (limitStackSlot != null)
{
limitStackSlot.Increment();
}
if (BelongsToItemInSlot != null && BelongsToItemInSlot.GetItemUI() != null)
{
BelongsToItemInSlot.GetItemUI().AddToContainedItems(itemUI);
}
if (changeSlotTitle != null)
{
changeSlotTitle.ChangeTitle(itemDrop.ItemTag);
}
if (HasSlotsBelongingToItem != null)
{
foreach (ItemUI i in itemUI.ContainedItems)
{
foreach(SlotUI s in HasSlotsBelongingToItem)
{
if (s.AllowedItemTags.Contains(i.ItemTag))
{
s.AddContainedItemToSlot(i);
break;
}
}
}
}
SetRenderItemUIPropertyValue();
return true;
}
else if (itemDrop.previousSlot != this)
{
// TODO: See why this is outputting at beginning, probably from test objects in Loot
//Debug.LogWarning("SlotUI: Failed to drop. dropCheck: " + dropCheck + ", allowed: " + allowed);
// return item to previous parent
itemDrop.ReturnToSlot();
return false;
//// Debug.Log("Resetting parent");
}
else
{
//Debug.LogWarning("SlotUI: Failed to drop. dropCheck: " + dropCheck + ", allowed: " + allowed);
Debug.LogError("SlotUI: Something wrong has happened.");
return false;
}
}
void Awake()
{
/*if (image == null)
{
Image[] images = GetComponentsInChildren<Image>(); // This will retrieve the first instance of an image in the FIRST child with the component
//// Debug.Log(images.Length);
if (images.Length > 0)
{
if (images[0].transform == transform)
{
if (images.Length > 1)
{
image = images[1];
}
}
else
{
image = images[0];
}
}
}*/
if (grid == null)
grid = GetComponentInParent<GridUI>();
// Check again
if (grid == null)
{
cell = new Cell(0, 0, this, true);
}
if (TryGetComponent(out AppendUI aui))
{
appendUI = aui;
}
if (TryGetComponent(out LinkedSlotUI lui))
{
linkedSlotUI = lui;
}
if (TryGetComponent(out RenderItemUIProperty rp))
{
renderProp = GetComponent<RenderItemUIProperty>();
SetRenderItemUIPropertyValue();
}
if (TryGetComponent(out LimitStackSlot lss))
{
limitStackSlot = lss;
}
if (TryGetComponent(out LimitStackSlotManager lssm))
{
limitStackSlotManager = lssm;
}
if (TryGetComponent(out ChangeSlotTitle cst))
{
changeSlotTitle = cst;
}
}
private void SetRenderItemUIPropertyValue()
{
if (renderProp != null)
{
renderProp.value = stackedItems.Count.ToString();
}
}
public void AddContainedItemToSlot(ItemUI item)
{
HideImage();
if (limitStackSlot != null)
{
limitStackSlot.Increment();
}
stackedItems.Push(item);
item.transform.SetParent(transform, false);
item.gameObject.SetActive(true);
/*
foreach(ItemUI item in )
{
itemUI.transform.SetParent(itemUI.ParentContainer.transform, false);
itemUI.gameObject.SetActive(false);
stackedItems.Pop();
}*/
SetRenderItemUIPropertyValue();
}
public void RemoveContainedItemsFromSlot()
{
ShowImage();
while (stackedItems.Count > 0)
{
if (limitStackSlot != null)
{
limitStackSlot.Decrement();
}
if (itemUI.ParentContainer == null)
{
Debug.LogWarning("This should not be null");
}
if (itemUI.ParentContainer != null)
itemUI.transform.SetParent(itemUI.ParentContainer.transform, false);
itemUI.gameObject.SetActive(false);
ItemUI oldItem = stackedItems.Pop();
oldItem.SetSlot(this);
}
SetRenderItemUIPropertyValue();
}
public void RemoveDragDropItem()
{
if (BelongsToItemInSlot != null && BelongsToItemInSlot.GetItemUI() != null)
{
BelongsToItemInSlot.GetItemUI().RemoveFromContainedItems(itemUI);
}
if (HasSlotsBelongingToItem != null)
{
foreach (SlotUI s in HasSlotsBelongingToItem)
{
s.RemoveContainedItemsFromSlot();
}
}
if (appendUI != null)
{
appendUI.RemoveUIFromTransform(itemUI);
}
if (limitStackSlot != null)
{
limitStackSlot.Decrement();
}
if (limitStackSlotManager != null)
{
limitStackSlotManager.UnsetStackSlotLimit();
}
if(changeSlotTitle != null)
{
changeSlotTitle.ResetTitle();
}
foreach (SlotUI linked in LinkedSlots)
{
linked.RemoveDragDropItem();
}
stackedItems.Pop();
foreach (GroupSlotUI groupSlot in groupSlots)
{
groupSlot.OnItemRemoved();
}
UnsetCell();
SetRenderItemUIPropertyValue();
}
public void UnsetCell()
{
if(itemUI == null)
{
ShowImage();
if (cell != null)
{
cell.inUse = false;
CellInUse = cell.inUse;
}
}
}
public bool CanDropOntoSlot()
{
bool groupSlotsCheck = false;
if (groupSlots.Count == 0)
groupSlotsCheck = true;
else
{
foreach (GroupSlotUI groupSlotUI in groupSlots)
{
if (groupSlotUI.IsSlotInShowGameObjects(this) && groupSlotUI.ConditionMet())
{
groupSlotsCheck = true;
break;
}
}
}
// TODO: add check for Limit Slot Stack here
return (GetItemUI() == null || IsStacking()) && groupSlotsCheck;
}
public bool IsSingleCellSlot()
{
return width == 1 && height == 1;
}
public bool HasStack()
{
return itemUI != null && itemUI.Stackable;
}
public bool IsStacking()
{
return StackItemsOnSlot;
}
// Start is called before the first frame update
void Start()
{
if (HasSlotsBelongingToItem.Count > 0)
{
foreach (SlotUI s in HasSlotsBelongingToItem)
{
s.BelongsToItemInSlot = this;
}
}
else
{
HasSlotsBelongingToItem = null;
}
}
// Update is called once per frame
void Update()
{
if (InventorySystem.instance.PressedDropItemKey(false) || InventorySystem.instance.PressedEquipItemKey(false))
{
//// Debug.Log("pressed");
return;
}
if (PointerIsHoveredOver)
{
ItemUI droppedItem = InventorySystem.instance.DraggedItem;
if (droppedItem != null && !droppedItem.PickedUpOnFrame)
{
if (Input.GetMouseButtonDown(0))
{
DroppedOnFrame = true;
ItemUI potentialContainerItem = cell.item;
if (potentialContainerItem != null && potentialContainerItem.DropItemInStorageContainer(droppedItem))
{
// todo: do something, or not, idk
// Debug.Log("This should have dropped into a storage container");
}
else
{
bool callback = DropOntoSlot(droppedItem.gameObject, true);
if (callback && droppedItem.Stackable)
{
if (droppedItem.Count <= 0)
{
Destroy(droppedItem.gameObject);
}
else if (itemUI.Count < droppedItem.Count && !droppedStackOntoEmptySlot)
{
InventorySystem.instance.DraggedItem = droppedItem;
droppedStackOntoEmptySlot = false;
}
}
}
}
else if (Input.GetMouseButtonDown(1) && droppedItem.Stackable)
{
DroppedOnFrame = true;
// Debug.Log("Right Click");
if (DropOntoSlot(droppedItem.gameObject, false))
{
if (droppedItem.Count <= 0)
{
Destroy(droppedItem.gameObject);
}
else
{
InventorySystem.instance.DraggedItem = droppedItem;
droppedItem.transform.SetParent(InventorySystem.instance.inventoryUI.transform);
droppedStackOntoEmptySlot = false;
}
}
}
}
}
// TODO: make sure the key combo works as expected
if (Input.GetMouseButtonUp(0))
{
DroppedOnFrame = false;
}
}
public void SetCell(Cell cell)
{
this.cell = cell;
}
internal void HideImage()
{
if (image != null)
{
image.color = new Color(image.color.r, image.color.g, image.color.b, 0f);
//image.enabled = false;
//image.color = new Color(image.color.r, image.color.g, image.color.b, 1);
}
}
internal void ShowImage()
{
if (image != null)
{
//image.color = new Color(image.color.r, image.color.g, image.color.b, 0);
image.color = new Color(image.color.r, image.color.g, image.color.b, 1);
}
}
public void OnPointerExit(PointerEventData eventData)
{
//PointerIsHoveredOver = false;
}
public void OnPointerEnter(PointerEventData eventData)
{
//PointerIsHoveredOver = true;
}
}
}