/// <summary>
    ///
    /// </summary>
    protected float DoItemsFoldout(Rect pos, SerializedProperty prop)
    {
        m_InitialY = pos.y;

        pos.height = 16;

        vp_Inventory inventory = ((vp_Inventory)prop.serializedObject.targetObject);

        GUI.backgroundColor = Color.white;

        pos.y +=
            ((
                 (inventory.ItemInstances.Count > 0) ||
                 (inventory.UnitBankInstances.Count > 0) ||
                 (inventory.InternalUnitBanks.Count > 0)) ?
             5 : -5);
        pos.x     += 20;
        pos.width -= 15;

        // --- draw internal unit banks ---

        for (int v = 0; v < inventory.InternalUnitBanks.Count; v++)
        {
            vp_UnitBankInstance ibank = inventory.InternalUnitBanks[v];

            if ((ibank == null) || (ibank.UnitType == null))
            {
                inventory.InternalUnitBanks.Remove(ibank);
                inventory.Refresh();
                continue;
            }

            string name = ibank.UnitType.ToString();
            name = name.Remove(name.IndexOf(" (")) + "s (Internal UnitBank)";

            int unitCount = inventory.GetItemCount(ibank.UnitType);

            vp_PropertyDrawerUtility.ItemCard(pos,
                                              ((ibank == null) ? null : ibank.UnitType.Icon),
                                              name,
                                              ((ibank == null) ? null : ibank.UnitType),
                                              ref unitCount,
                                              "Units",
                                              delegate()
            {
                inventory.TrySetUnitCount(ibank.UnitType, unitCount);
            },
                                              ref NO_VALUE,
                                              "",
                                              null,
                                              delegate()
            {
                m_UnitBankToRemove = ibank;
            });

            pos.y += 21;
        }

        // --- draw item unit bank instances (such as weapons) ---

        for (int v = 0; v < inventory.UnitBankInstances.Count; v++)
        {
            vp_UnitBankInstance bank = inventory.UnitBankInstances[v];

            int unitCount = bank.Count;

            if ((bank == null) || (bank.Type == null))
            {
                inventory.UnitBankInstances.Remove(bank);
                inventory.Refresh();
                continue;
            }

            string name = bank.Type.ToString();

            if (vp_PropertyDrawerUtility.ItemCard(pos,
                                                  ((bank == null) ? null : bank.Type.Icon),
                                                  name,
                                                  ((bank == null) ? null : bank.Type),
                                                  ref unitCount,
                                                  "Units",
                                                  delegate()
            {
                inventory.TrySetUnitCount(bank, unitCount);
            },
                                                  ref bank.ID,
                                                  "ID",
                                                  null, // no need to act on value change since it is handled by the ref above
                                                  delegate()
            {
                m_UnitBankToRemove = bank;
            }))
            {
                inventory.ClearItemDictionaries();
                inventory.SetDirty();
            }

            pos.y += 21;
        }

        // --- draw item instances ---

        for (int v = 0; v < inventory.ItemInstances.Count; v++)
        {
            vp_ItemInstance item = inventory.ItemInstances[v];

            if ((item == null) || (item.Type == null))
            {
                inventory.ItemInstances.Remove(item);
                inventory.Refresh();
                continue;
            }

            string name = item.Type.ToString();

            if (vp_PropertyDrawerUtility.ItemCard(pos,
                                                  ((item == null) ? null : item.Type.Icon),
                                                  name,
                                                  ((item == null) ? null : item.Type),
                                                  ref item.ID,
                                                  "ID",
                                                  null, // no need to act on value change since it is handled by the ref above
                                                  ref NO_VALUE,
                                                  "",
                                                  null,
                                                  delegate()
            {
                m_ItemToRemove = item;
            }, 45))
            {
                inventory.ClearItemDictionaries();
                inventory.SetDirty();
            }

            pos.y += 21;
        }

        // --- draw 'add object' box ---

        pos.y += 16;

        vp_PropertyDrawerUtility.AddObjectBox(pos, "n ItemType", typeof(vp_ItemType), delegate(Object itemType)
        {
            if (itemType is vp_UnitBankType)
            {
                vp_UnitBankType bank = (vp_UnitBankType)itemType;
                int cap = inventory.GetItemCap((vp_UnitBankType)itemType);

                if ((cap == -1) || (inventory.GetItemCount((vp_UnitBankType)itemType) < cap))
                {
                    if (!inventory.TryGiveUnitBank(bank, bank.Capacity, 0))
                    {
                        EditorUtility.DisplayDialog(m_InventoryFullCaption, string.Format(m_InventoryFullMessage, itemType), "OK");
                    }
                }
                else
                {
                    EditorUtility.DisplayDialog(m_InventoryFullCaption, string.Format(m_InventoryFullMessage, itemType), "OK");
                }
            }
            else if (itemType is vp_UnitType)
            {
                if (!inventory.HaveInternalUnitBank((vp_UnitType)itemType))
                {
                    vp_UnitType unitType = (vp_UnitType)itemType;
                    if (!inventory.TryGiveUnits(unitType, 10))
                    {
                        EditorUtility.DisplayDialog(m_InventoryFullCaption, string.Format(m_InventoryFullMessage, itemType), "OK");
                    }
                }
                else
                {
                    EditorUtility.DisplayDialog(m_UnitBankAlreadyExistsCaption, string.Format(m_UnitBankAlreadyExistsMessage, itemType), "OK");
                }
            }
            else
            {
                if (!inventory.TryGiveItem((vp_ItemType)itemType, 0))
                {
                    EditorUtility.DisplayDialog(m_InventoryFullCaption, string.Format(m_InventoryFullMessage, itemType), "OK");
                }
            }
            EditorUtility.SetDirty(inventory);
            inventory.Refresh();
        });

        pos.y += vp_PropertyDrawerUtility.CalcAddObjectBoxHeight - 5;

        // handle removed items
        if (m_UnitBankToRemove != null)
        {
            inventory.TryRemoveUnitBank(m_UnitBankToRemove);
            m_UnitBankToRemove = null;
        }
        else if (m_ItemToRemove != null)
        {
            inventory.TryRemoveItem(m_ItemToRemove);
            m_ItemToRemove = null;
        }

        return(pos.y - m_InitialY);
    }
    /// <summary>
    ///
    /// </summary>
    float DoItemsFoldout(Rect pos, SerializedProperty prop)
    {
        m_InitialY = pos.y;

        pos.height = 16;

        vp_Inventory inventory = ((vp_Inventory)prop.serializedObject.targetObject);


        pos.x += 4;
        bool prev = inventory.CapsEnabled;

        inventory.CapsEnabled = EditorGUI.Toggle(pos, "Enabled", inventory.CapsEnabled);
        if (prev != inventory.CapsEnabled)
        {
            inventory.Refresh();
        }

        pos.y      += 16;
        GUI.enabled = inventory.CapsEnabled;

        prev = inventory.AllowOnlyListed;
        inventory.AllowOnlyListed = EditorGUI.Toggle(pos, "Allow only listed types", inventory.AllowOnlyListed);
        if (prev != inventory.AllowOnlyListed)
        {
            inventory.Refresh();
        }

        pos.y +=
            ((inventory.m_ItemCapInstances.Count > 0) ? 16 : 11);
        pos.x     += 16;
        pos.width -= 15;

        // --- draw item caps ---

        for (int v = 0; v < inventory.m_ItemCapInstances.Count; v++)
        {
            vp_Inventory.ItemCap itemCap = inventory.m_ItemCapInstances[v];

            if ((itemCap != null) && (itemCap.Type != null))
            {
                string name     = itemCap.Type.ToString();
                int    NO_VALUE = -1;
                vp_PropertyDrawerUtility.ItemCard(pos,
                                                  itemCap.Type.Icon,
                                                  name,
                                                  itemCap.Type,
                                                  ref itemCap.Cap,
                                                  "Cap",
                                                  delegate()
                {
                    inventory.SetItemCap(itemCap.Type, itemCap.Cap);
                    if (itemCap.Type is vp_UnitType)
                    {
                        inventory.Refresh();
                    }
                },
                                                  ref NO_VALUE,
                                                  null,
                                                  null,
                                                  delegate()
                {
                    m_CapToRemove = itemCap;
                });
                pos.y += 21;
            }
        }

        // --- draw 'add object' box ---

        pos.y += 16;

        vp_PropertyDrawerUtility.AddObjectBox(pos, "n ItemType", typeof(vp_ItemType), delegate(Object itemType)
        {
            if (inventory.GetItemCap((vp_ItemType)itemType) != -1 && !inventory.AllowOnlyListed)
            {
                EditorUtility.DisplayDialog(m_ItemCapAlreadyExistsCaption, string.Format(m_ItemCapAlreadyExistsMessage, itemType), "OK");
            }

            int defaultCap = 10;
            if (itemType is vp_UnitBankType)
            {
                defaultCap = 1;
            }
            else if (itemType is vp_UnitType)
            {
                defaultCap = 100;
            }
            inventory.SetItemCap((vp_ItemType)itemType, defaultCap);
            inventory.Refresh();
        });

        pos.y += vp_PropertyDrawerUtility.CalcAddObjectBoxHeight - 5;

        // handle removed item caps
        if (m_CapToRemove != null)
        {
            inventory.m_ItemCapInstances.Remove(m_CapToRemove);
            m_CapToRemove = null;
        }

        GUI.enabled = true;

        return(pos.y - m_InitialY);
    }
    /// <summary>
    ///
    /// </summary>
    float DoItemsFoldout(Rect pos, SerializedProperty prop)
    {
        initialY = pos.y;

        pos.height = 16;

        vp_Inventory inventory = ((vp_Inventory)prop.serializedObject.targetObject);

        // while the space foldout is open, we always refresh inventory
        // once per second, in order to catch changes to unit counts
        EditorUtility.SetDirty(prop.serializedObject.targetObject);
        if (System.DateTime.Now > m_NextAllowedAutoRefreshTime)
        {
            inventory.Refresh();
            m_NextAllowedAutoRefreshTime = System.DateTime.Now + System.TimeSpan.FromMilliseconds(1000);
        }

        pos.x += 4;
        bool prev = inventory.SpaceEnabled;

        inventory.SpaceEnabled = EditorGUI.Toggle(pos, "Enabled", inventory.SpaceEnabled);
        if (prev != inventory.SpaceEnabled)
        {
            inventory.Refresh();
        }

        pos.y      += 16;
        GUI.enabled = inventory.SpaceEnabled;

        pos.width -= 15;

        // --- draw ---

        vp_Inventory.Mode prevM = inventory.SpaceMode;
        inventory.SpaceMode = (vp_Inventory.Mode)EditorGUI.EnumPopup(pos, "Mode", inventory.SpaceMode);
        if (prevM != inventory.SpaceMode)
        {
            inventory.TotalSpace = Mathf.Max(0.0f, inventory.TotalSpace);
            inventory.Refresh();
        }
        pos.y += 16;

        float prevC = inventory.TotalSpace;

        inventory.TotalSpace = EditorGUI.FloatField(pos, /*((inventory.SpaceMode == vp_Inventory.Mode.Mass) ? "Mass" : "Volume") + */ "Capacity", inventory.TotalSpace);
        if (prevC != inventory.TotalSpace)
        {
            inventory.TotalSpace = Mathf.Max(0.0f, inventory.TotalSpace);
            inventory.Refresh();
        }
        pos.y += 19;

        pos.x     += 16;
        pos.width -= 21;
        string percent = ((inventory.UsedSpace / inventory.TotalSpace) * 100.0f).ToString("F1");

        percent = percent.Replace(".0", "");
        if (inventory.TotalSpace > 0.0f)
        {
            EditorGUI.ProgressBar(pos, (inventory.UsedSpace / inventory.TotalSpace), "Used: " + inventory.UsedSpace + "/" + inventory.TotalSpace + " (" + percent + "%)");
        }
        else
        {
            EditorGUI.ProgressBar(pos, 1.0f, "Unusable");
        }

        pos.y += 26;

        GUI.enabled = true;

        return(pos.y - initialY);
    }