projectEli/Assets/Inventory System/Scripts/UI/ItemUI.cs
2023-01-24 23:14:16 -08:00

783 lines
26 KiB
C#

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<ItemUI> ContainedItems = new List<ItemUI>();
[HideInInspector] public ItemUI ParentContainer;
[HideInInspector] public GameObject container;
[HideInInspector] public Canvas canvas;
[HideInInspector] public bool PickedUpOnFrame;
[HideInInspector] public List<GameObject> ContextWindows = new List<GameObject>();
[HideInInspector] public StorageWindowUI StorageWindow;
[HideInInspector] public bool IsLinkedSlotClone;
[HideInInspector] public LimitStackSlotCapacity limitStackSlotCapacity;
internal void ResetTransform()
{
RectTransform rect = GetComponent<RectTransform>();
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<RectTransform>();
if (image == null)
{
Image[] images = transform.GetComponentsInChildren<Image>();
for(int i = 0; i < images.Length; i++)
{
if(images[i] == GetComponent<Image>())
{
continue;
}
image = transform.GetComponentInChildren<Image>();
break;
}
}
if(image == null)
{
Debug.LogError("ItemUI: Item needs a child with an Image component.");
}
canvasGroup = GetComponent<CanvasGroup>();
renderProp = GetComponent<RenderItemUIProperty>();
limitStackSlotCapacity = GetComponent<LimitStackSlotCapacity>();
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);
}
/// <summary>
/// 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.
/// </summary>
/// <returns></returns>
public int ContainerCapacity()
{
GridUI gridUI = null;
if(container != null && container.TryGetComponent<GridUI>(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();
Debug.Log(tsp.slot.gameObject.name);
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(bool fitImageInSlot = false)
{
//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);
}
if (!fitImageInSlot)
{
ApplyRectTransformResize();
}
}
public void ApplyRectTransformResize()
{
ResetTransform();
}
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<Image>();
}
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<Canvas>();
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)
{
// && !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<Cell> 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))
{
Debug.Log("Should be throwing away...");
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<StorageWindowUI>();
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<GridUI>().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;
}
}
}