using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using UnityEngine.Serialization; public class UIInventory : MonoBehaviour { [SerializeField] private InventorySO _currentInventory = default; [SerializeField] private UIInventoryItem _itemPrefab = default; [SerializeField] private GameObject _contentParent = default; [FormerlySerializedAs("_inspectorFiller")] [SerializeField] private UIInventoryInspector _inspectorPanel = default; [FormerlySerializedAs("_tabFiller")] [SerializeField] private UIInventoryTabs _tabsPanel = default; [FormerlySerializedAs("_buttonFiller")] [SerializeField] private UIActionButton _actionButton = default; InventoryTabSO _selectedTab = default; [SerializeField] List _tabTypesList = new List(); private int selectedItemId = -1; [FormerlySerializedAs("_instanciatedItems")] [SerializeField] private List _availableItemSlots = default; [SerializeField] private VoidEventChannelSO _onInteractionEndedEvent = default; [SerializeField] private ItemEventChannelSO _useItemEvent = default; [SerializeField] private IntEventChannelSO _restoreHealth = default; [SerializeField] private ItemEventChannelSO _equipItemEvent = default; [SerializeField] private ItemEventChannelSO _cookRecipeEvent = default; [SerializeField] private InputReader _inputReader = default; public UnityAction Closed; bool _isNearPot = false; private void OnEnable() { //Check if the event exists to avoid errors _actionButton.Clicked += OnActionButtonClicked; _tabsPanel.TabChanged += OnChangeTab; _onInteractionEndedEvent.OnEventRaised += InteractionEnded; for (int i = 0; i < _availableItemSlots.Count; i++) { _availableItemSlots[i].ItemSelected += InspectItem; } _inputReader.TabSwitched += OnSwitchTab; } private void OnDisable() { _actionButton.Clicked -= OnActionButtonClicked; _tabsPanel.TabChanged -= OnChangeTab; for (int i = 0; i < _availableItemSlots.Count; i++) { _availableItemSlots[i].ItemSelected -= InspectItem; } _inputReader.TabSwitched -= OnSwitchTab; } void OnSwitchTab(float orientation) { if (orientation != 0) { bool isLeft = orientation < 0; int initialIndex = _tabTypesList.FindIndex(o => o == _selectedTab); if (initialIndex != -1) { if (isLeft) { initialIndex--; } else { initialIndex++; } initialIndex = Mathf.Clamp(initialIndex, 0, _tabTypesList.Count - 1); } OnChangeTab(_tabTypesList[initialIndex]); } } public void FillInventory(InventoryTabType _selectedTabType = InventoryTabType.CookingItem, bool isNearPot = false) { _isNearPot = isNearPot; if ((_tabTypesList.Exists(o => o.TabType == _selectedTabType))) { _selectedTab = _tabTypesList.Find(o => o.TabType == _selectedTabType); } else { if (_tabTypesList != null) { if (_tabTypesList.Count > 0) { _selectedTab = _tabTypesList[0]; } } } if (_selectedTab != null) { SetTabs(_tabTypesList, _selectedTab); List listItemsToShow = new List(); listItemsToShow = _currentInventory.Items.FindAll(o => o.Item.ItemType.TabType == _selectedTab); FillInvetoryItems(listItemsToShow); } else { Debug.LogError("There's no selected tab "); } } void InteractionEnded() { _isNearPot = false; } void SetTabs(List typesList, InventoryTabSO selectedType) { _tabsPanel.SetTabs(typesList, selectedType); } void FillInvetoryItems(List listItemsToShow) { if (_availableItemSlots == null) _availableItemSlots = new List(); int maxCount = Mathf.Max(listItemsToShow.Count, _availableItemSlots.Count); for (int i = 0; i < maxCount; i++) { if (i < listItemsToShow.Count) { //fill bool isSelected = selectedItemId == i; _availableItemSlots[i].SetItem(listItemsToShow[i], isSelected); } else if (i < _availableItemSlots.Count) { //Desactive _availableItemSlots[i].SetInactiveItem(); } } HideItemInformation(); //unselect selected Item if (selectedItemId >= 0) { UnselectItem(selectedItemId); selectedItemId = -1; } //hover First Element if (_availableItemSlots.Count > 0) { _availableItemSlots[0].SelectFirstElement(); } } void UpdateItemInInventory(ItemStack itemToUpdate, bool removeItem) { if (_availableItemSlots == null) _availableItemSlots = new List(); if (removeItem) { if (_availableItemSlots.Exists(o => o._currentItem == itemToUpdate)) { int index = _availableItemSlots.FindIndex(o => o._currentItem == itemToUpdate); _availableItemSlots[index].SetInactiveItem(); } } else { int index = 0; //if the item has already been created if (_availableItemSlots.Exists(o => o._currentItem == itemToUpdate)) { index = _availableItemSlots.FindIndex(o => o._currentItem == itemToUpdate); } //if the item needs to be created else { //if the new item needs to be instantiated if (_currentInventory.Items.Count > _availableItemSlots.Count) { //instantiate UIInventoryItem instantiatedPrefab = Instantiate(_itemPrefab, _contentParent.transform) as UIInventoryItem; _availableItemSlots.Add(instantiatedPrefab); } //find the last instantiated game object not used index = _currentInventory.Items.Count; } //set item bool isSelected = selectedItemId == index; _availableItemSlots[index].SetItem(itemToUpdate, isSelected); } } public void InspectItem(ItemSO itemToInspect) { if (_availableItemSlots.Exists(o => o._currentItem.Item == itemToInspect)) { int itemIndex = _availableItemSlots.FindIndex(o => o._currentItem.Item == itemToInspect); //unselect selected Item if (selectedItemId >= 0 && selectedItemId != itemIndex) UnselectItem(selectedItemId); //change Selected ID selectedItemId = itemIndex; //show Information ShowItemInformation(itemToInspect); //check if interactable bool isInteractable = true; _actionButton.gameObject.SetActive(true); if (itemToInspect.ItemType.ActionType == ItemInventoryActionType.Cook) { isInteractable = _currentInventory.hasIngredients(itemToInspect.IngredientsList) && _isNearPot; } else if (itemToInspect.ItemType.ActionType == ItemInventoryActionType.DoNothing) { isInteractable = false; _actionButton.gameObject.SetActive(false); } //set button _actionButton.FillInventoryButton(itemToInspect.ItemType, isInteractable); } } void ShowItemInformation(ItemSO item) { bool[] availabilityArray = _currentInventory.IngredientsAvailability(item.IngredientsList); _inspectorPanel.FillInspector(item, availabilityArray); _inspectorPanel.gameObject.SetActive(true); } void HideItemInformation() { _actionButton.gameObject.SetActive(false); _inspectorPanel.gameObject.SetActive(false); } void UnselectItem(int itemIndex) { if (_availableItemSlots.Count > itemIndex) { _availableItemSlots[itemIndex].UnselectItem(); } } void UpdateInventory() { FillInventory(_selectedTab.TabType, _isNearPot); } void OnActionButtonClicked() { //find the selected Item if (_availableItemSlots.Count > selectedItemId && selectedItemId > -1) { //find the item ItemSO itemToActOn = new ItemSO(); itemToActOn = _availableItemSlots[selectedItemId]._currentItem.Item; //check the selected Item type //call action function depending on the itemType switch (itemToActOn.ItemType.ActionType) { case ItemInventoryActionType.Cook: CookRecipe(itemToActOn); break; case ItemInventoryActionType.Use: UseItem(itemToActOn); break; case ItemInventoryActionType.Equip: EquipItem(itemToActOn); break; default: break; } } } void UseItem(ItemSO itemToUse) { if (itemToUse.HealthResorationValue > 0) { _restoreHealth.RaiseEvent(itemToUse.HealthResorationValue); } _useItemEvent.RaiseEvent(itemToUse); //update inventory UpdateInventory(); } void EquipItem(ItemSO itemToUse) { Debug.Log("Equip ITEM " + itemToUse.name); _equipItemEvent.RaiseEvent(itemToUse); } void CookRecipe(ItemSO recipeToCook) { //get item _cookRecipeEvent.RaiseEvent(recipeToCook); //update inspector InspectItem(recipeToCook); //update inventory UpdateInventory(); } void OnChangeTab(InventoryTabSO tabType) { FillInventory(tabType.TabType, _isNearPot); } public void CloseInventory() { Closed.Invoke(); } }