using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; using System; using static SimpleInventorySystem.GridUI; using TMPro; namespace SimpleInventorySystem { public class SlotUI : MonoBehaviour { [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 AllowedItemTags; public List DisallowedItemTags; public List HasSlotsBelongingToItem; [Header("Required Component Links")] public TextMeshProUGUI stackSlotCountText; // Hidden In Inspector [HideInInspector] public Stack stackedItems = new Stack(); // WARNING: Stack can give some odd troubles with the raycast, consider revision or consideration. [HideInInspector] public LimitStackSlot limitStackSlot; [HideInInspector] public LimitStackItemManager limitStackItemManager; [HideInInspector] public bool DroppedOnFrame; public List 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 bool droppedStackOntoEmptySlot; //private RenderItemUIProperty renderProp; private SlotUI BelongsToItemInSlot; // public variables public bool PointerIsHoveredOver { get { return InventorySystem.IsMouseOverUI(gameObject); } } public ItemUI GetItemUI() { return itemUI; } public bool AllowedDraggable(GameObject gameObject) { return gameObject.GetComponent() != null; } public bool DropOntoSlot(GameObject item, bool dropStack = true) { ItemUI itemDrop = item.GetComponent(); ItemTags itemTag = itemDrop.ItemTag; bool allowed = AllowedItemTags == null || AllowedItemTags.Count == 0 || AllowedItemTags.Contains(ItemTags.Any) || AllowedItemTags.Contains(itemTag); bool disallowed = DisallowedItemTags == null || 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(itemDrop)) { return false; } //Debug.Log($"SlotUI:Is LimitStackItem Manager null? {limitStackItemManager == null}"); List occupiedCells = new List(); /// STACKING /// This section concerns item stacks, not slot stacking if (itemDrop.Stackable && ((HasStack() && itemDrop.itemName == GetItemUI().itemName) || !dropStack)) { Debug.Log("DropStack" + 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(); 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 != 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; } //Debug.Log($"Using Image as Slot Holder: {useImageAsSlotHolder}"); Transform parent = transform; if (useImageAsSlotHolder && image != null) { //Debug.Log("Using Image as Slot Holder"); parent = image.gameObject.transform; } item.GetComponent().SetParent(parent); item.GetComponent().anchoredPosition = GetComponent().anchoredPosition; //item.GetComponent().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().sizeDelta.x), Math.Abs(image.GetComponent().sizeDelta.y))); if (itemUI.Stackable) { droppedStackOntoEmptySlot = true; } if (grid != null) { grid.HideSlotsOfItem(itemDrop); //Debug.Log("Grid is not null"); grid.AddItemToGrid(item.GetComponent()); } if (!useImageAsSlotHolder) { HideImage(); } else { } foreach (GroupSlotUI groupSlot in groupSlots) { if (groupSlot != null) { groupSlot.OnItemDropped(); } } if (appendUI != null) { // Debug.Log("Test"); appendUI.AppendUIToTransform(itemUI); } if (limitStackItemManager != null) { limitStackItemManager.SetStackSlotLimit(itemUI); } if (limitStackSlot != null) { limitStackSlot.SetCount(); limitStackSlot.Increment(itemUI); } 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.NestedItems) { 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 (grid == null) grid = GetComponentInParent(); // Check again if (grid == null) { cell = new Cell(0, 0, this, true); } if (TryGetComponent(out AppendUI aui)) { appendUI = aui; } SetRenderItemUIPropertyValue(); if (TryGetComponent(out LimitStackSlot lss)) { limitStackSlot = lss; } if (TryGetComponent(out ChangeSlotTitle cst)) { changeSlotTitle = cst; } } private void SetRenderItemUIPropertyValue() { if (stackSlotCountText != null) { stackSlotCountText.text = stackedItems.Count.ToString(); } } public void AddContainedItemToSlot(ItemUI item) { HideImage(); //DropOntoSlot(item.gameObject); stackedItems.Push(item); if(useImageAsSlotHolder && image != null) { item.transform.SetParent(image.transform, false); } else { 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(); if (groupSlots != null) { foreach (GroupSlotUI gs in groupSlots) { gs.OnItemDropped(); } } if (limitStackSlot != null) { limitStackSlot.SetCount(); } } public void RemoveContainedItemsFromSlot() { ShowImage(); while (stackedItems.Count > 0) { /*if (limitStackSlot != null) { limitStackSlot.Decrement(itemUI); }*/ 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); } if (limitStackSlot != null) { limitStackSlot.SetCount(); } if (groupSlots != null) { foreach (GroupSlotUI gs in groupSlots) { gs.OnItemRemoved(); } } 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(itemUI); } if (limitStackItemManager != null) { limitStackItemManager.UnsetStackSlotLimit(); } if(changeSlotTitle != null) { changeSlotTitle.ResetTitle(); } stackedItems.Pop(); foreach (GroupSlotUI groupSlot in groupSlots) { groupSlot.OnItemRemoved(); } if (limitStackSlot != null) { limitStackSlot.SetCount(); } 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); } } internal void ShowImage() { if (image != null) { image.color = new Color(image.color.r, image.color.g, image.color.b, 1); } } } }