using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; using static SimpleInventorySystem.GridUI; using System; namespace SimpleInventorySystem { [RequireComponent(typeof(RectTransform), typeof(CanvasGroup))] public class ItemUI : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler { [Header("Item Attributes")] public string itemName; public Image image; public RarityType rarity; public ItemTags ItemTag = ItemTags.Any; public int StackLimit = 1; public int width; public int height; public float weight; public float monetaryValue; [Header("Container Prefab")] public GameObject containerUIPrefab; [Header("Required Component Links")] public Image backdropImage; public RectTransform emptyGridContainer; // Hidden public variables [HideInInspector] public bool interactable = true; [HideInInspector] public Canvas overrideSortingCanvas; [HideInInspector] public bool Equipped; [HideInInspector] public List ContainedItems = new List(); [HideInInspector] public ItemUI ParentContainer; [HideInInspector] public GameObject container; [HideInInspector] public Canvas canvas; [HideInInspector] public bool PickedUpOnFrame; [HideInInspector] public List ContextWindows = new List(); [HideInInspector] public StorageWindowUI StorageWindow; [HideInInspector] public bool IsLinkedSlotClone; [HideInInspector] public LimitStackSlotCapacity limitStackSlotCapacity; internal void ResetTransform() { RectTransform rect = GetComponent(); rect.anchorMin = rect.anchorMax = rect.pivot = new Vector2(0, 1); rect.anchoredPosition = new Vector2(); imageSizeOnGrid = new Size(width * InventorySystem.instance.DefaultSizeOnGrid.Width, height * InventorySystem.instance.DefaultSizeOnGrid.Height); rect.sizeDelta = new Vector2(imageSizeOnGrid.Width, imageSizeOnGrid.Height); } [HideInInspector] public PickUp pickUp; [HideInInspector] public TargetAttachment targetAttachment; // private variables private Vector2 oldImageSizeDelta; private Vector2 oldSizeDelta; private RectTransform rectTransform; private CanvasGroup canvasGroup; private float scale = 1f; private SlotUI slot; private Cell[] cells; private bool isDragging; private Size imageSizeOnGrid; private Orientation imageOrientation = Orientation.Portrait; private RenderItemUIProperty renderProp; public Inventory Inventory; // archived variables //public Item itemPrefab; //public variables public SlotUI previousSlot { get; private set; } public bool Stackable { get { return StackLimit > 1; } } private int count; public int Count { get { return count; } set { if (!Stackable) { count = 1; } else { count = value; } SetRenderItemUIPropertyValue(); } } public bool PointerIsHoveredOver { get { return InventorySystem.IsMouseOverItemUITop(this); } } //public Item item; private void Awake() { rectTransform = GetComponent(); if (image == null) { Image[] images = transform.GetComponentsInChildren(); for(int i = 0; i < images.Length; i++) { if(images[i] == GetComponent()) { continue; } image = transform.GetComponentInChildren(); break; } } if(image == null) { Debug.LogError("ItemUI: Item needs a child with an Image component."); } canvasGroup = GetComponent(); renderProp = GetComponent(); limitStackSlotCapacity = GetComponent(); if (width <= 0 || height <= 0) { Debug.LogError("Inventory ItemUI must contain a positive integer value for Width and Height: " + name); } int eulerAngle = Mathf.Abs(Mathf.CeilToInt(transform.rotation.eulerAngles.z)); switch (eulerAngle) { case 270: imageOrientation = (height > width) ? Orientation.Portrait : Orientation.Landscape; break; case 180: imageOrientation = (width > height) ? Orientation.Landscape : Orientation.Portrait; break; case 90: imageOrientation = (height > width) ? Orientation.Portrait : Orientation.Landscape; break; default: imageOrientation = (width > height) ? Orientation.Landscape : Orientation.Portrait; break; } //InstantiateItem(); } public Rarity GetRarity() { Debug.Log(rarity); return InventorySystem.instance.GetRarityFromList(rarity); } /// /// Returns an integer number if it has a container with a GridUI. the number returned is either -1 if no gridUI exists, or the capacity in terms of 1x1 cells. /// /// public int ContainerCapacity() { GridUI gridUI = null; if(container != null && container.TryGetComponent(out gridUI)) { return gridUI.gridSize.Width * gridUI.gridSize.Height; } return -1; } private void SetRenderItemUIPropertyValue() { if (renderProp != null) { renderProp.value = Count.ToString(); } } public void InstantiateItem() { //if (item == null && itemPrefab != null) //{ // item = Instantiate(itemPrefab); //} } public SlotUI GetSlotUI() { return slot; } public void OnBeginDrag(PointerEventData eventData) { } public void OnDrag(PointerEventData eventData) { } public void OnEndDrag(PointerEventData eventData) { //rectTransform.localPosition = new Vector3(0, 0); } public bool Equip() { foreach (TagSlotPairing tsp in InventorySystem.instance.TagSlotPairings) { if (!tsp.CanEquip(this)) { UnsetSlot(); bool value = tsp.DropOntoSlot(this); if (!value) { ReturnToSlot(); } else { return true; } } } return false; } public bool Store() { foreach (TagSlotGridPairing tsgp in InventorySystem.instance.TagSlotGridPairings) { if (tsgp.CanStore (this)) { UnsetSlot(); bool value = tsgp.DropOntoGrid(this); if (!value) { ReturnToSlot(); } else { return true; } } } return false; } public void DropItemOntoSlot() { //Debug.Log("OnEndDrag"); if (image != null) { canvasGroup.alpha = 1f; image.maskable = true; } canvasGroup.blocksRaycasts = true; isDragging = false; if (!slot.useImageAsSlotHolder) ShowEmptyGrid(); else HideEmptyGrid(); InventorySystem.instance.DraggedItem = null; if (slot == null) { Debug.Log("ItemUI: OnEndDrag: Returning to parent"); //ReturnToSlot(); } else { // TODO: this need improvement Equipped = slot.EquipSlot; } if (StorageWindow != null && StorageWindow.gameObject.activeSelf) { StorageWindow.dragWindowUI.CloseWindow(); } if (Inventory == null) { InventorySystem.instance.player.inventory.AddOwnership(this, null); } else if (Inventory != InventorySystem.instance.player.inventory) { Inventory.RemoveOwnership(this, Inventory); } } public void GrabAndDragItem() { if (!isDragging && interactable) { Debug.Log("GRAB AND DRAG"); //Debug.Log("OnPointerDown"); //Debug.Log("OnBeginDrag"); canvasGroup.alpha = .7f; canvasGroup.blocksRaycasts = false; transform.SetParent(canvas.transform); rectTransform.anchorMin = new Vector2(0, 1); rectTransform.anchorMax = new Vector2(0, 1); rectTransform.pivot = new Vector2(0, 1); image.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, oldImageSizeDelta.x); image.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, oldImageSizeDelta.y); rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, oldSizeDelta.x); rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, oldSizeDelta.y); emptyGridContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, oldSizeDelta.x); emptyGridContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, oldSizeDelta.y); backdropImage.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, oldSizeDelta.x); backdropImage.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, oldSizeDelta.y); UnsetSlot(); HideEmptyGrid(); isDragging = true; InventorySystem.instance.DraggedItem = this; PickedUpOnFrame = true; // Destroy each associated window, since we won't rely on windows if we are moving this item for(int i = ContextWindows.Count - 1; i >= 0; i--) { ContextWindows[i].SetActive(true); } ContextWindows.Clear(); } } public void UnsetSlot() { if (slot != null) { previousSlot = slot; slot.RemoveDragDropItem(); slot = null; } if (cells != null) { foreach (Cell c in cells) { if (c != null) { c.inUse = false; //c.overlapped = false; //s.ShowImage(); if (c.GetSlot() != null && c.GetSlot() != this.slot) { c.GetSlot().UnsetCell();// RemoveDragDropItem(true); } } } cells = null; } } public void AddToContainedItems(ItemUI item) { ContainedItems.Add(item); item.ParentContainer = this; } public void RemoveFromContainedItems(ItemUI item) { ContainedItems.Remove(item); item.ParentContainer = null; } public void OnPointerDown(PointerEventData eventData) { if (eventData.button == PointerEventData.InputButton.Left) { GrabAndDragItem(); } } public void OnPointerClick(PointerEventData eventData) { if(eventData.button == PointerEventData.InputButton.Left) { GrabAndDragItem(); } else if (eventData.button == PointerEventData.InputButton.Right) { InventorySystem.instance.OpenContextMenu(this); } /*else if (eventData.button == PointerEventData.InputButton.Right) { InventorySystem.instance.OpenContextMenu(this); }*/ } public void FitImageInSlot(Vector2 size) { Debug.Log("FitImageInSlot: " + image.transform.name); float ratio = size.y / image.rectTransform.sizeDelta.y; rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, size.x); rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, size.y); image.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, size.x); image.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, size.y); backdropImage.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, size.x); backdropImage.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, size.y); emptyGridContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, size.x); emptyGridContainer.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, size.y); /* image.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, size.y);// = new Vector2(image.rectTransform.sizeDelta.x * ratio, size.y); Debug.Log(oldImageSizeDelta + ", " + oldSizeDelta); this.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, size.y); ;*/ //image.transform.localScale *= ratio; //this.scale = scale; //image.transform.localScale *= scale; } public void SetSlot(SlotUI slot) { this.slot = slot; } // TODO: Make sure it was dropped somewhere, if not, return it to the original parent public void ReturnToSlot() { if (previousSlot != null && !isDragging) { Debug.Log("RETURNED: " + previousSlot.gameObject.name); previousSlot.DropOntoSlot(this.gameObject); } } // Start is called\ before the first frame update void Start() { InitializeImageSize(); // TODO: Possibly have item image scale into slot here. imageSizeOnGrid = new Size(width * InventorySystem.instance.DefaultSizeOnGrid.Width, height * InventorySystem.instance.DefaultSizeOnGrid.Height); if (canvas == null) { canvas = SimpleInventorySystem.InventorySystem.instance.inventoryUI; } if (Count == 0) { Count = 1; } SetRenderItemUIPropertyValue(); Rarity r = GetRarity(); if (backdropImage == null) { backdropImage = transform.GetComponent(); } if (backdropImage == null) { Debug.LogError("ItemUI: Item needs at least an Image component."); } else if (r != null) { backdropImage.color = new Color(r.color.r, r.color.g, r.color.b, InventorySystem.instance.ItemBackdropTransparency); } //backdropImage.sprite.rect. /*overrideSortingCanvas = gameObject.AddComponent(); if(overrideSortingCanvas != null) { overrideSortingCanvas.overrideSorting = true; overrideSortingCanvas.sortingLayerID = 5; //overrideSortingCanvas.sortingLayerName = "ItemUI"; }*/ } public void InitializeImageSize() { oldImageSizeDelta = image.rectTransform.sizeDelta; oldSizeDelta = this.rectTransform.sizeDelta; if (oldImageSizeDelta == Vector2.zero) { oldImageSizeDelta = oldSizeDelta; } if (oldSizeDelta == Vector2.zero) { oldSizeDelta = oldImageSizeDelta; } } public Orientation ImageOrientation() { return imageOrientation; } public Size SizeAfterOrientation() { Debug.Log(imageOrientation); if (imageOrientation == Orientation.Landscape) { if (width >= height) { return new Size(width, height); } else { return new Size(height, width); } } else { if (height >= width) { return new Size(width, height); } else { return new Size(height, width); } } } public void HideSlots() { if (cells != null) { Cell previousCell = slot.cell; foreach (Cell cell in cells) { if (cell != null) { SlotUI cellSlot = cell.GetSlot(); if (cellSlot != null) { Debug.Log(cellSlot.cell.X + ", " + cellSlot.cell.Y + ", " + (cellSlot.image == previousCell.slot.image)); // && !slot.useImageAsSlotHolder) cellSlot.HideImage(); } } } } } public void HideEmptyGrid() { if (emptyGridContainer != null) { emptyGridContainer.gameObject.SetActive(false); } } public void ShowEmptyGrid() { if (emptyGridContainer != null) { emptyGridContainer.gameObject.SetActive(true); } } public void SetSlots(List cellList) { cells = new Cell[cellList.Count]; for (int i = 0; i < cellList.Count; i++) { if (cellList[i] != null) { cells[i] = cellList[i]; cells[i].inUse = true; } } } public bool IsSingleCellItem() { return width == 1 && height == 1; } public bool AddToStack(int value = 1) { if (Stackable && Count < StackLimit) { Count+=value; return true; } return false; } public bool RemoveFromStack(int value = 1) { if (Stackable && Count > 0) { Count-= value; return true; } return false; } public void UnsetSlots() { cells = null; } void FixedUpdate() { } // Update is called once per frame void Update() { if (isDragging) { // TODO: fix this rectTransform.position = InventorySystem.instance.MouseInCanvasPosition; } if (PointerIsHoveredOver && InventorySystem.instance.PressedEquipItemKey(false)) { Equip(); // TODO: see if more needs to be implemented here. return; } if (PointerIsHoveredOver && InventorySystem.instance.PressedDropItemKey(false)) { DropItemAway(); return; } if (PointerIsHoveredOver && InventorySystem.instance.DraggedItem == null) { if (Input.GetMouseButtonDown(0) && !isDragging && InventorySystem.instance.DraggedItem == null && !slot.DroppedOnFrame) { GrabAndDragItem(); } if (Input.GetMouseButtonDown(1) && InventorySystem.instance.DraggedItem == null) { InventorySystem.instance.OpenContextMenu(this); } } if (Input.GetMouseButtonUp(0)) { PickedUpOnFrame = false; } if (isDragging) { if (image != null) { image.maskable = false; } if (InventorySystem.instance.PressedKeyRotation(true)) { Debug.Log("Rotate"); RectTransform handler = (RectTransform)transform; int eulerAngle = Mathf.Abs(Mathf.CeilToInt(handler.rotation.eulerAngles.z)) - 90; Debug.Log("euler" + eulerAngle); switch (eulerAngle) { case -90: rectTransform.pivot = new Vector2(0, 0); rectTransform.Rotate(new Vector3(0, 0, 1), -90); imageOrientation = (width > height) ? Orientation.Portrait : Orientation.Landscape; break; case 180: rectTransform.pivot = new Vector2(1, 0); handler.Rotate(new Vector3(0, 0, 1), -90); imageOrientation = (width > height) ? Orientation.Landscape : Orientation.Portrait; break; case 90: rectTransform.pivot = new Vector2(1, 1); handler.Rotate(new Vector3(0, 0, 1), -90); imageOrientation = (width > height) ? Orientation.Portrait : Orientation.Landscape; break; default: handler.Rotate(new Vector3(0, 0, 1), -90); handler.localPosition = new Vector3(0, 0, 0); handler.pivot = new Vector2(0, 1); imageOrientation = (width > height) ? Orientation.Landscape : Orientation.Portrait; break; } } } else { if (PointerIsHoveredOver && Input.GetMouseButtonDown(2)) { CreateStorageWindow(); } } } public void CreateStorageWindow() { if(StorageWindow == null || !StorageWindow.gameObject.activeSelf) { Debug.Log("Opening Window"); StorageWindow = InventorySystem.instance.OpenWindow().GetComponent(); if(StorageWindow != null && containerUIPrefab != null && !Equipped) { Debug.Log("Opening Window"); if (container == null) { Debug.Log("Creating new"); container = Instantiate(containerUIPrefab, StorageWindow.StorageContainer.transform, false); //itemUI.container.name = itemUI.container.name + " " + inCount; container.SetActive(true); StorageWindow.gameObject.SetActive(true); StorageWindow.itemUI = this; container.GetComponentInChildren().SetAssociatedItemUI(this); } else { if(container.transform.parent != StorageWindow.StorageContainer.transform) container.transform.SetParent(StorageWindow.StorageContainer.transform, false); container.SetActive(true); StorageWindow.itemUI = this; StorageWindow.gameObject.SetActive(true); } } } } public void DropItemAway() { if (pickUp == null) { // TODO: Create a new pickup for items without a gameobject attached Debug.LogError("No in-world gameobject previously attached with itemUI"); } else { InventorySystem.instance.player.DetachItemGameObject(pickUp.ItemGameObject, this); } isDragging = false; SetOverrideSortingCanvasEnabled(false); InventorySystem.instance.DraggedItem = null; UnsetSlot(); } public void SetOverrideSortingCanvasEnabled(bool value) { /* if(overrideSortingCanvas != null) { overrideSortingCanvas.enabled = value; }*/ } public void SetInteractable(bool value) { interactable = value; } public void OnPointerExit(PointerEventData eventData) { //PointerIsHoveredOver = false; } public void OnPointerEnter(PointerEventData eventData) { //PointerIsHoveredOver = true; } } }