Inventory. Part two - toggles panel. Log #14 (Unity, C#)
25.02.2018

    In previous log I described inventory and its parts. Today I will focus on toggle panel for enabling and disabling panels in item list. Solution is quite complicated I think, but I am fine with it if it works. If player is in inventory and clicks on toggle with left mouse button (LMB), corresponding panel will enebale or disable. But this choice is only temporary, til player reopens inventory again - all toggles will be disabled again (supposing that inventory is empty). So I added option to choose favorite panels. It can be activated by middle mouse button (MMB, usually wheel). Choice will be saved even after closed inventory. So player will have entire control.

    First step is setting the toggles appearing, distinguish between enabled and disabled toggles. Basicly toggle takes care of itself, I will only change graphics. To field Target graphic I drag sprites downloaded from game-icons.net, change color to shade of yellow and into panel OnValueChanged(Boolean) I add new event, drag there panel corresponding to my toggle, then choose GameObject>SetActive. This enables or disables whole panel as object. As disabled toggle I add under object of my toggle, new Image, rename it to ImageIsOn, chenge its color to dark grey and drag it on field Graphic in Toggle component of my toggle. I add another Image as favorite indicator, as Target graphic I set my rectangle created in the vector editor and set Type to Filled, Method to Radial 90, Origin to Top Right and value to 0.5, then check clockwise and aspect ratio fields. This creates small triangle in the bottom right corner of my toggle - indicator of favorite toggle. Now, panels will enable and disable when choosing toggles. 

    For main logic I create script InventoryToggle, which I drag on every toggle, this will store information whether toggle is activated or not, and if this toggle is favorite. This information stores property inFavorites. As I mentioned earlier, favorite toggles I set by MMB, in code I use function OnPointerClick(PointerEventData), which requires interface IPointerClickHandler, and pass the button data via eventData.button, that was clicked on. MMB is presented as PointerEventData.InputButton.Middle. Indicator of favorite toggle I enable by GetComponent<Image>().enabled. I also set panel active after MMB click, by calling method SetActive().

 

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class InventoryToggle : MonoBehaviour, IPointerClickHandler
{
    public bool inFavorites { get; private set; }

    void Awake()
    {
        inFavorites = false;
        ResetFavorite(false);
    }

    public void SetActive()
    {
        GetComponent<Toggle>().isOn = true;
    }

    public void SetInactive()
    {
        GetComponent<Toggle>().isOn = false;
    }

    public void ResetFavorite(bool favorie)
    {
        transform.GetChild(2).GetComponent<Image>().enabled = favorie;
        if(favorie) SetActive();
    }

    public void OnPointerClick(PointerEventData eventData)
    {
        if (eventData.button == PointerEventData.InputButton.Middle)
        {
            inFavorites = !inFavorites;
            if (inFavorites)
            {
                SetActive();
                transform.GetChild(2).GetComponent<Image>().enabled = true;
            }
            else
            {
                transform.GetChild(2).GetComponent<Image>().enabled = false;
            }
        }
    }
}

 

    I will return to method ResetFavorite(bool) later. In method Awake() I set inFavorites to false. Lately I will store all choices in file, so favorite toggles choices will stay as player want, even after loading game. To managing all toggles logic I create new script Toggles and drag it on my Toggles panel. In Start() method I store all toggles through foreach iteration. Foreach can iterate through type Transform and returns all its children Transforms. In my case all toggles with InventoryToggle script. Other methods in this script deal with reseting all toggles (favorites and toggles itself) - ResetFavoriteToggles() and ResetActive() eventually activating by SetFavoriteToggles() and SetActiveToggle(string). Why do I reset toggles? Because everytime I add or remove item from inventory, list will update. And also because inventory window will be used for chests and storages too. But about this later. There is Toggle.cs

 

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Toggles : MonoBehaviour
{
    List<Toggle> _toggles { get; set; }
    public Transform toggles;

    void Start()
    {
        _toggles = new List<Toggle>();
        foreach (Transform toggle in toggles)
        {
            _toggles.Add(toggle.GetComponent<Toggle>());
        }
    }

    public void SetActiveToggle(string toggleName)
    {
        foreach (Toggle _toggle in _toggles)
        {
            if (_toggle.transform.name == toggleName)
            {
                _toggle.GetComponent<InventoryToggle>().SetActive();
            }
        }
    }

    public void ResetFavoriteToggles()
    {
        foreach (Toggle _toggle in _toggles)
        {
            _toggle.GetComponent<InventoryToggle>().ResetFavorite(false);
        }
    }

    public void SetFavoriteToggles()
    {
        foreach (Toggle _toggle in _toggles)
        {
            _toggle.GetComponent<InventoryToggle>().ResetFavorite(_toggle.GetComponent<InventoryToggle>().inFavorites);
        }
    }
    public void ResetActive()
    {
        foreach (Toggle toggle in _toggles)
        {
            toggle.GetComponent<InventoryToggle>().SetInactive();
        }
    }
}

 

    So where do I use all these methods? For managing inventory I add new script InventoryManager, where will be all inventory logics. For now its only toggles reset and update, but it will extend later. Same as player menu, InventoryManager is a singelton. Now I store reference to my toggle panel which I drag in inspector on Toggles filed. Now I create two methods SetToggles() and UpdateList(). In update method I call SetToggles() in which I reset toggles and then set favorites by method toggles.ResetToggles() and toggles.SetFavoriteToggles(). I have separated logics and graphics, but the logics work with graphics a lot, therefore I create new variable InventoryGUManager invnetoryGUIManager into whcih I store my component created in previous log. In method Awake() I call inventoryGUIManager.HideInventory() to hide inventory after game starts. InventoryManager will also open my inventory so I create method OpenOnventory() in which I call my UpdateList() method and inventoryGUIManager.ShowInventory() right after it. Of course I have to delete HideInventory() from Awake() in InventoryGUIManager and set event, in OnClick() panel in Inventory_button for player menu, to InventoryManager>OpenInventory().

 

using UnityEngine;

public class InventoryManager : MonoBehaviour
{
    public static InventoryManager Instance { get; private set; }

    InventoryGUIManager inventoryGUIManager;
    public Toggles toggles;

    void Awake()
    {
        if (Instance == null)
            Instance = this;
        else if (Instance != this)
            Destroy(gameObject);

        inventoryGUIManager = GetComponent<InventoryGUIManager>();
        inventoryGUIManager.HideInventory();
    }

    public void OpenInventory()
    {
        UpdateList();
        inventoryGUIManager.ShowInventory();
    }

    void SetToggles(Inventory inventory)
    {
        toggles.ResetActive();
        toggles.SetFavoriteToggles();
    }

    void UpdateList()
    {
        SetToggles();
    }
}

 

    Now inventory will be opened without panels, but I can activate any with LMB, or add to favorites by MMB. The ones not being in favorites will be disabled after reopening inventory.

 

 

Next log I will focus on inventory when opening another storage (non player inventory) as chest, merchant or warehouse.