/// <summary>
        /// Reset the location to when we started dragging
        /// </summary>
        void resetToOriginalPosition()
        {
            containingInventory = originalContainerInventory;
            // if we have to switch the grid back, make sure to re-size and scale
            if (originalContainerInventory != Player.InventoryTypes.GridPack && originalParent != parentController.rectTransform.parent)
            {
                parentController.rectTransform.SetParent(originalParent);
                parentController.rectTransform.anchorMax = originalMaxAnchor;
                parentController.rectTransform.anchorMin = originalMinAnchor;
                parentController.resize(originalScale.x);
            }

            // reset other values
            transform.position = originalLocation;
            parentController.setOpacity(originalOpacity);
            if (wasShapedOriginally != parentController.isShaped)
            {
                parentController.setShaped(wasShapedOriginally);
            }

            // re-parent the indicator to the grid
            if (containingInventory == Player.InventoryTypes.GridPack)
            {
                parentController.parentQuantityIndicatorTo(Universe.LocalPlayerManager.PackGridController.transform);
            }

            // if we expanded a slot and we're resetting, reset the slot
            Universe.LocalPlayerManager.ItemHotBarController.resetExpandedBarSlots();
        }
 /// <summary>
 /// initialize this for the given item
 /// </summary>
 /// <param name="parent"></param>
 /// <param name="stackId"></param>
 public void initialize(ItemIconController parent, int stackId, Coordinate gridLocation, Player.InventoryTypes containingInventory)
 {
     parentController          = parent;
     this.stackId              = stackId;
     this.originalGridLocation = gridLocation;
     this.containingInventory  = containingInventory;
 }
        /// <summary>
        /// Turn dragging on
        /// </summary>
        void enableDrag()
        {
            // record original values
            originalParent             = transform.parent;
            originalLocation           = transform.position;
            originalScale              = parentController.currentSize;
            originalContainerInventory = containingInventory;
            ItemBeingDragged           = this;
            isBeingDragged             = true;
            originalOpacity            = parentController.currentOpacity;
            wasShapedOriginally        = containingInventory == Player.InventoryTypes.GridPack
        ? true
        : false;

            /// update for dragging
            parentController.setOpacity(1);
            // if the pack menu is open it can manage all of the dragging
            if (Universe.LocalPlayerManager.PackGridController.packMenuIsOpen && containingInventory != Player.InventoryTypes.GridPack)
            {
                parentController.resize();
                // save and replace the anchor values
                originalMaxAnchor = parentController.rectTransform.anchorMax;
                originalMinAnchor = parentController.rectTransform.anchorMin;
                Vector2 gridSize = Universe.LocalPlayerManager.PackGridController.getGridSquareSize();
                parentController.rectTransform.anchorMin = Vector2.zero;
                parentController.rectTransform.anchorMax = gridSize + gridSize;

                // re-parent to the open grid
                containingInventory = Player.InventoryTypes.GridPack;
                parentController.rectTransform.SetParent(Universe.LocalPlayerManager.PackGridController.gridTransform);
            }
        }
        /// <summary>
        /// try to add an item to an inventory at the given spot.
        /// </summary>
        /// <param name="item">The item to try to add</param>
        /// <param name="inventoryType">The inventoy to add to</param>
        /// <param name="pivotLocation">the place in the inventory we're adding to</param>
        /// <param name="succesfullyAddedItem">the item stack that was added successfully</param>
        /// <returns>Any leftovers or replaced items</returns>
        public virtual Item tryToAddToInventoryAt(Item item, Player.InventoryTypes inventoryType, Coordinate pivotLocation, out Item succesfullyAddedItem)
        {
            succesfullyAddedItem = null;
            switch (inventoryType)
            {
            case Player.InventoryTypes.GridPack:
                return(player.packInventory.tryToAdd(item, pivotLocation, out succesfullyAddedItem));

            case Player.InventoryTypes.HotBar:
                return(player.hotBarInventory.tryToAdd(item, pivotLocation, out succesfullyAddedItem));

            default: return(null);
            }
        }
        /// <summary>
        /// add this item to the given inventory at the given slot
        /// </summary>
        /// <param name="gridItemLocation"></param>
        void tryToAddToInventoryGridSlot(Player.InventoryTypes inventoryType, Coordinate gridItemLocation)
        {
            // make sure it's not the same spot.
            if (!(originalContainerInventory == inventoryType && gridItemLocation.Equals(originalGridLocation)))
            {
                Item thisItem  = Universe.LocalPlayerManager.removeFromInventoryAt(originalContainerInventory, originalGridLocation);
                Item leftovers = Universe.LocalPlayerManager.tryToAddToInventoryAt(thisItem, inventoryType, gridItemLocation, out _);
                // if we have leftovers, put them back, reset things, and update the inventory
                if (leftovers != null)
                {
                    Universe.LocalPlayerManager.tryToAddToInventoryAt(leftovers, originalContainerInventory, originalGridLocation, out _);
                }
            }

            resetToOriginalPosition();
        }
        /// <summary>
        /// Try to remove an item from the player inventory
        /// </summary>
        /// <param name="inventoryType"></param>
        /// <param name="pivotLocation"></param>
        /// <returns></returns>
        public virtual Item removeFromInventoryAt(Player.InventoryTypes inventoryType, Coordinate pivotLocation)
        {
            Item removedItem;

            switch (inventoryType)
            {
            case Player.InventoryTypes.GridPack:
                removedItem = player.packInventory.removeAt(pivotLocation);
                break;

            case Player.InventoryTypes.HotBar:
                removedItem = player.hotBarInventory.removeAt(pivotLocation);
                break;

            default: return(null);
            }

            return(removedItem);
        }
        /// <summary>
        /// Make a new item icon for the given item
        /// </summary>
        /// <returns></returns>
        public static ItemIconController Make(
            Item item,
            Transform parent        = null,
            bool loadShapedIcon     = false,
            bool isDraggable        = false,
            int stackIndex          = GridBasedInventory.EmptyGridSlot,
            Coordinate gridLocation = default,
            Player.InventoryTypes parentInventory = Player.InventoryTypes.None
            )
        {
            // make the icon under the given parent, or alone if we want
            GameObject icon = parent != null
        ? Instantiate(ItemDataMapper.ItemIconPrefab, parent)
        : Instantiate(ItemDataMapper.ItemIconPrefab);

            // move to the top
            if (parent != null)
            {
                icon.transform.SetAsFirstSibling();
            }

            ItemIconController iconController = icon.GetComponent <ItemIconController>();

            iconController.item            = item;
            iconController.backgroundImage = icon.transform.Find("Icon Background").GetComponent <Image>();

            /// add the drag controller.
            if (isDraggable)
            {
                iconController.dragController = icon.AddComponent <ItemInventoryDragController>();
                iconController.dragController.initialize(iconController, stackIndex, gridLocation, parentInventory);
            }

            // try to get the sprite
            if (item != null)
            {
                Sprite itemSprite = ItemDataMapper.GetIconFor(item);
                /// if we found a sprite
                if (itemSprite != null)
                {
                    /// load the regular icon
                    iconController.defaultIconScaler = icon.transform.Find("Small Icon Scaler").gameObject;
                    GameObject sprite = Instantiate(new GameObject(), iconController.defaultIconScaler.transform);
                    sprite.layer = 5;
                    SpriteRenderer spriteRenderer = sprite.AddComponent <SpriteRenderer>();
                    spriteRenderer.sprite = itemSprite;
                    // if we didn't, use the object as an icon.
                }
                else
                {
                    iconController.defaultIconScaler = icon.transform.Find("Model Icon Scaler").gameObject;
                    GameObject itemModel = Instantiate(ItemDataMapper.GetModelFor(item), iconController.defaultIconScaler.transform);
                    iconController.itemModelRenderers = itemModel.GetComponentsInChildren <Renderer>();
                }

                /// if we're also loading the shaped icon:
                if (loadShapedIcon)
                {
                    // get the shaped scaler
                    iconController.shapedIconScaler = icon.transform.Find("Shaped Icon Scaler").gameObject;

                    // make the prototype image object
                    GameObject imageObject = new GameObject {
                        layer = 5
                    };
                    imageObject.AddComponent <Image>();
                    // resize the sprite according to it's shape size.
                    RectTransform rectTransform = imageObject.GetComponent <RectTransform>();
                    rectTransform.anchorMax = (item.type.ShapeSize - item.type.ShapePivot).Vec2;
                    rectTransform.anchorMin = ((0, 0) - item.type.ShapePivot).Vec2;
                    rectTransform.SetLTRB(0);

                    // if we need a new icon for the shaped icon than the basic square icon, get it
                    if (item.type.ShapeSize > (1, 1))
                    {
                        Sprite shapedIcon      = ItemDataMapper.GetIconFor(item, true);
                        Image  shapedIconImage = Instantiate(imageObject, iconController.shapedIconScaler.transform).GetComponent <Image>();
                        shapedIconImage.sprite = shapedIcon;
                    }

                    // add the outline
                    Image outline = Instantiate(imageObject, iconController.shapedIconScaler.transform).GetComponent <Image>();
                    outline.sprite = ItemDataMapper.GetShapedOutlineFor(item);
                    outline.color  = new Color(1, 1, 0);
                }

                // set the correct icon scaler active
                iconController.defaultIconScaler.SetActive(true);

                /// set up the stack indicator
                iconController.itemStackSizeIndicator     = icon.transform.Find("Stack Quantity Indicator").GetComponent <RectTransform>();
                iconController.itemStackSizeIndicatorText = iconController.itemStackSizeIndicator.GetComponentInChildren <Text>();
                iconController.updateStackCount();
                if (item.type.StackSize > 1)
                {
                    iconController.itemStackSizeIndicator.gameObject.SetActive(true);
                }
            }
            else
            {
                iconController.itemStackSizeIndicator     = icon.transform.Find("Stack Quantity Indicator").GetComponent <RectTransform>();
                iconController.itemStackSizeIndicatorText = iconController.itemStackSizeIndicator.GetComponentInChildren <Text>();
                iconController.updateStackCount();
            }

            return(iconController);
        }
 /// <summary>
 /// Make an event of this kind
 /// </summary>
 /// <param name="player"></param>
 /// <param name="item"></param>
 public LocalPlayerInventoryItemsRemovedEvent(Coordinate[] modifiedPivots, Player.InventoryTypes updatedInventoryType)
 {
     this.modifiedPivots       = modifiedPivots;
     this.updatedInventoryType = updatedInventoryType;
 }