using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; using static SimpleInventorySystem.InventorySystem; namespace SimpleInventorySystem { [RequireComponent(typeof (GridLayoutGroup))] public class GridUI : MonoBehaviour { private LayoutElement layoutElement; private GridLayoutGroup gridLayout; public GameObject CellPrefab; public bool generateCells; // will autopopulate grid public SlotUI[] slots; [HideInInspector] public ItemUI associatedItemUI; [SerializeField] public Size gridSize; internal void ChangeGridLayoutSize(int rows, int columns) { gridSize.Width = rows; gridSize.Height = columns; } private Cell[,] cells; [HideInInspector] public GameObject testItem; [HideInInspector] public GameObject[] testItems; [HideInInspector] public List itemsOnGrid; private Size cellSize; public Size CellSize { get { return cellSize; } } private Vector2 nextAvailableCellCoords; private void Awake() { if(cells == null) { SetUpCellsArray(); } } private bool cellsInitialized; public void SetAssociatedItemUI(ItemUI itemUI) { associatedItemUI = itemUI; } public bool IsAssociatedItem(ItemUI itemUI) { return associatedItemUI == itemUI; } void SetUpCellsArray() { gridLayout = GetComponent(); if (gridSize.Width == 0 && gridLayout.constraint == GridLayoutGroup.Constraint.FixedColumnCount) { gridSize.Width = gridLayout.constraintCount; } else if (gridSize.Height == 0 && gridLayout.constraint == GridLayoutGroup.Constraint.FixedRowCount) { gridSize.Height = gridLayout.constraintCount; } if (gridSize.Width == 0 || gridSize.Height == 0) { Debug.LogError("GridUI needs a defined width and height, or width or height needs to be constrained through the GridLayoutGroup component."); } //Debug.Log("GridUI: GridSize: " + gridSize.Width + ", " + gridSize.Height); cells = new Cell[gridSize.Height, gridSize.Width]; } void GenerateCells() { SetUpCellsArray(); if (CellPrefab != null) { /*foreach(Transform child in transform) { // TODO: make sure to unequip items currently in the grid Destroy(child); }*/ //Debug.Log(gridSize.Width + ", " + gridSize.Height); for (int y = 0; y < gridSize.Height; y++) { for (int x = 0; x < gridSize.Width; x++) { // TODO: load inventory from data here upon intialization GameObject cell = GameObject.Instantiate(CellPrefab, this.transform); cell.transform.localScale = new Vector3(1f, 1f, 1f); SlotUI slot = cell.GetComponentInChildren(); // WARNING: All cell prefabs must now have a slot //if (cell.GetComponentInChildren() != null) //{ slot.grid = this; slot.AllowedItemTags = new List(); slot.AllowedItemTags.Add(ItemTags.Any); cells[y, x] = new Cell(x, y, slot, false); //cells[y, x].GetSlot().SetCell(cells[y, x]); //Debug.Log("Foo: " + (slot == null)); //Debug.Log("Bar: " + (cells[y, x].GetSlot().cell == null)); //cells[y, x].inUse = false; //} } } cellsInitialized = true; /*if (cells != null && cells[0, 0] != null && testItem != null) { Debug.Log("Add item"); Cell cell = cells[0, 0]; GameObject item = Instantiate(testItem); cell.slot.DropOntoSlot(item); //item.transform.SetParent(.gameObject.transform); }*/ /*if (testItems != null) { int i = 0; int x = 0, y = 0; int lootCount = 1; foreach (GameObject testItem in testItems) { bool dropped = false; GameObject item = null; try { do { x = i % gridSize.Width; y = i / gridSize.Width; item = Instantiate(testItem); item.name = item.name + " " + lootCount; dropped = cells[y, x].slot.DropOntoSlot(item); if (!dropped) { Destroy(item); } else { lootCount++; item.transform.localScale = new Vector3(1, 1, 1); } i++; } while (!dropped); } catch (IndexOutOfRangeException err) { Debug.LogWarning("GridUI: " + x + ", " + y); } if (item == null) { Debug.LogWarning("Could not add all test items"); break; } // TODO: Make sure this works as expected nextAvailableCellCoords = new Vector2(i % gridSize.Width, i / gridSize.Width); } }*/ } } public IEnumerator PopulateItemsWithNewInventory(List items) { //Debug.Log("Populating Inventory"); yield return new WaitForFixedUpdate(); //InitializeCells(); int i = 0; int x = 0, y = 0; foreach (ItemUI item in items) { //Debug.Log(item.itemName); bool dropped = false; try { do { x = i % gridSize.Width; y = i / gridSize.Width; dropped = cells[y, x].slot.DropOntoSlot(item.gameObject); if (!dropped) { //Destroy(item); } else { item.transform.localScale = new Vector3(1, 1, 1); } i++; } while (!dropped); } catch (IndexOutOfRangeException err) { Debug.LogWarning("GridUI: " + x + ", " + y); } if (item == null) { Debug.LogWarning("Could not add all test items"); break; } // TODO: Make sure this works as expected nextAvailableCellCoords = new Vector2(i % gridSize.Width, i / gridSize.Width); } } public bool DropItemOnGrid(GameObject item) { if (item != null) { int i = 0; int limit = 100000; int x = (int)nextAvailableCellCoords.x, y = (int)nextAvailableCellCoords.y; bool dropped = false; try { do { x = i % gridSize.Width; y = i / gridSize.Width; if (cells == null) { if (generateCells) { GenerateCells(); } else if (!cellsInitialized) { SetUpCellsArray(); LocateSlotsForCells(); } } //Debug.Log($"GridUI: Is Slot null? {cells[y, x] == null}"); dropped = cells[y, x].slot.DropOntoSlot(item); if (!dropped) { } else { item.transform.localScale = new Vector3(1, 1, 1); // TODO: Make sure this works as expected nextAvailableCellCoords = new Vector2(i % gridSize.Width, i / gridSize.Width); return true; } i++; if(i == limit) { //Debug.Log("Limit reached"); } } while (!dropped && i < cells.Length && i < limit); // TODO: perhaps add a check to make sure i has not exceeded the total number of slots } catch (IndexOutOfRangeException err) { Debug.LogWarning("GridUI: " + x + ", " + y); return false; } return false; } else { //Debug.LogWarning("GridUI: Could not add item to grid."); return false; } } public void AddItemToGrid(ItemUI item) { if (!itemsOnGrid.Contains(item)) { itemsOnGrid.Add(item.GetComponent()); } } public bool ContainsItemFromGrid(ItemUI item) { return itemsOnGrid.Contains(item); } public void RemoveItemFromGrid(ItemUI item) { if (itemsOnGrid.Contains(item)) { itemsOnGrid.Remove(item.GetComponent()); } } // Start is called before the first frame update void Start() { InitializeCells(); } void InitializeCells() { if (!generateCells) { if (!cellsInitialized) { LocateSlotsForCells(); } } else { GenerateCells(); } } void LocateSlotsForCells() { //if (slots != null) for (int i = 0; i < gridLayout.transform.childCount; i++) { int x = i % gridSize.Width; int y = (i - x) / gridSize.Width; if (cells[y, x] != null) { continue; } Transform child = gridLayout.transform.GetChild(i); SlotUI slot = child.GetComponentInChildren(); if (slot != null) { cells[y, x] = new Cell(x, y, slot, true); slot.SetCell(cells[y, x]); slot.grid = this; if (slot.width > 1 || slot.height > 1) { for (int j = 0; j < slot.height; j++) { for (int k = 1; k < slot.width; k++) { cells[y + j, x + k] = new Cell(x + k, y + j, slot, false); } } } //Debug.Log("START: " + (slot.cell == null)); } else { cells[y, x] = null;// new Cell(null, false, false); // Setting null so that we can reserve memory } } cellsInitialized = true; } internal void HideSlotsOfItem(ItemUI itemDrop) { if(itemDrop != null) { itemDrop.HideSlots(); } } public bool CanMoveInCells(ItemUI item, SlotUI slot, List occupiedCells = null) { if (slot == null || slot.cell == null || (slot.cell.inUse && (slot.GetItemUI() != null && !slot.GetItemUI().Stackable)) || (associatedItemUI == item)) { //Debug.Log("GridUI: CanMoveInCells(): " + slot.gameObject.name + ": A" + (slot.cell == null)); return false; } else if (slot.IsSingleCellSlot() && item.IsSingleCellItem() && (!slot.cell.inUse || (slot.StackItemsOnSlot && slot.GetItemUI().name == item.name))) { //Debug.Log("GridUI: CanMoveInCells(): " + slot.gameObject.name + ": B"); //if (!slot.cell.inUse) return true; //else // return false; } else if (cells != null) { List oCells = new List(); if(occupiedCells != null) { oCells = occupiedCells; } Size size = item.SizeAfterOrientation(); // for (int h = 0; h < slot.height; h++){ // for (int w = 0; w < slot.width; w++) for (int h = 0; h < size.Height; h++) { for (int w = 0; w < size.Width; w++) { if(slot.cell.Y + h >= gridSize.Height || slot.cell.X + w >= gridSize.Width) { //Debug.Log("GridUI: CanMoveInCells(): " + slot.gameObject.name + ": D"); return false; } Cell cell = cells[slot.cell.Y + h, slot.cell.X + w]; if (cell != null && cell.inUse) { //Debug.Log(cell != null); //Debug.Log(cell.inUse); //Debug.Log("GridUI: CanMoveInCells(): " + slot.gameObject.name + ": E"); return false; } oCells.Add(cell); } } //Debug.Log(occupiedCells.Count); //Debug.Log("GridUI: CanMoveInCells(): " + slot.gameObject.name + ": F"); //Debug.Log(oCells.Count); return true; } //Debug.Log("GridUI: CanMoveInCells(): " + slot.gameObject.name + ": G"); return false; } // Update is called once per frame void Update() { } public class Cell { protected int x, y; public int X { get { return x; } } public int Y { get { return y; } } public SlotUI slot; public bool ownsSlot; public bool inUse; public ItemUI item; public Cell(int x, int y, SlotUI slot, bool ownsSlot) { this.x = x; this.y = y; this.slot = slot; slot.SetCell(this); inUse = false; this.ownsSlot = ownsSlot; } public bool HasSlot() { return slot != null; } public SlotUI GetSlot() { return slot; } } } }