Encounter / Assets / Scripts / InventoryManagement / DraggableItem.cs
DraggableItem.cs
Raw
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

/// <summary>
/// Handles dragging functionality for items for better GUI inventory managament
/// </summary>
public class DraggableItem : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
    public enum DraggableItemType
    {
        ItemScreenInventory,
        ActiveItemSpot,
        ShopStock,
        InventoryInShop,
        LootStock,
        InventoryInLootScreen
    }

    public DraggableItemType Type;
    [SerializeField] private Image image;
    private Transform parentAfterDrag;
    private Transform refOldParent;
    
    /// <summary>
    /// Sets the new drag location of this object for reference
    /// </summary>
    /// <param name="t">The new parent transform</param>
    public void SetParentDrag(Transform t)
        => parentAfterDrag = t;
    private bool DecipherNewLocation(RectTransform transformHovered)
    {
        DropBox db = parentAfterDrag.GetComponent<DropBox>();
        ItemGUI gui = GetComponent<ItemGUI>();
        InventoryManipulator manipulator = InventoryManipulator.Instance;

        // Moves active item to the general inventory, and marks it with necessary attributes for
        // the inventory spot location
        if (db.Type == DropBox.DropLocations.GeneralItemInventory && Type == DraggableItemType.ActiveItemSpot)
            return manipulator.SwitchActiveToInventory(this.gameObject, db.transform);
        else if (db.Type == DropBox.DropLocations.ActiveItemNecklace && gui.GetAspect() is Apparel neck)
        {
            bool neckCheck = false;
            if (neck.ApparelLocation is ApparelSO.Location.Neck)
                neckCheck = manipulator.SwitchInventoryToActive(this.gameObject, DropBox.DropLocations.ActiveItemNecklace);

            return neckCheck;
        }
        else if (db.Type == DropBox.DropLocations.ActiveItemRingOne && gui.GetAspect() is Apparel ring1)
        {
            bool ringOneCheck = false;
            if (ring1.ApparelLocation is ApparelSO.Location.RingLocOne || ring1.ApparelLocation is ApparelSO.Location.RingLocTwo)
                ringOneCheck = manipulator.SwitchInventoryToActive(this.gameObject, DropBox.DropLocations.ActiveItemRingOne);

            return ringOneCheck;
        }
        else if (db.Type == DropBox.DropLocations.ActiveItemRingTwo && gui.GetAspect() is Apparel ring2)
        {
            bool ringTwoCheck = false;
            if (ring2.ApparelLocation is ApparelSO.Location.RingLocOne || ring2.ApparelLocation is ApparelSO.Location.RingLocTwo)
                ringTwoCheck = manipulator.SwitchInventoryToActive(this.gameObject, DropBox.DropLocations.ActiveItemRingTwo);

            return ringTwoCheck;
        }
        else if (db.Type == DropBox.DropLocations.ActiveItemHelmet && gui.GetAspect() is Apparel headPiece)
        {
            bool headCheck = false;
            if (headPiece.ApparelLocation is ApparelSO.Location.Head)
                headCheck = manipulator.SwitchInventoryToActive(this.gameObject, DropBox.DropLocations.ActiveItemHelmet);

            return headCheck;
        }
        else if (db.Type == DropBox.DropLocations.ActiveItemChest && gui.GetAspect() is Apparel chestPiece)
        {
            bool chestCheck = false;
            if (chestPiece.ApparelLocation is ApparelSO.Location.Chest)            
                chestCheck = manipulator.SwitchInventoryToActive(this.gameObject, DropBox.DropLocations.ActiveItemChest);

            return chestCheck;
        }
        else if (db.Type == DropBox.DropLocations.ActiveItemBoots && gui.GetAspect() is Apparel boots)
        {
            bool bootCheck = false;
            if (boots.ApparelLocation is ApparelSO.Location.Leggings)
                bootCheck = manipulator.SwitchInventoryToActive(this.gameObject, DropBox.DropLocations.ActiveItemBoots);

            return bootCheck;
        }
        else if (db.Type == DropBox.DropLocations.ActiveItemWeapon && gui.GetAspect() is Weapon)
            return manipulator.SwitchInventoryToActive(this.gameObject, DropBox.DropLocations.ActiveItemWeapon);
        else if (db.Type == DropBox.DropLocations.ActiveItemSecWeapon && gui.GetAspect() is Weapon)
            return manipulator.SwitchInventoryToActive(this.gameObject, DropBox.DropLocations.ActiveItemSecWeapon);
        else if (db.Type == DropBox.DropLocations.ActiveItemRelic && gui.GetAspect() is Relic)
            return manipulator.SwitchInventoryToActive(this.gameObject, DropBox.DropLocations.ActiveItemRelic);
        else if ((db.Type == DropBox.DropLocations.ShopStock || transformHovered == db.transform.parent) && !gui.GetAspect().CantBeSold)
        {
            // This guard clause catches if the player attempts to buy their own items or sell the shops items
            if (parentAfterDrag == refOldParent)
                return false;

            TownUI.Instance.SellToVendor(gui.GetItemName());
            // If the indicator of if the object successfully was sold to the vendor is marked as false
            // then this object won't be destroyed and will go back to its old parent
            if (parentAfterDrag != db.transform)
                Destroy(this.gameObject);
            else
                parentAfterDrag = refOldParent;
        }
        else if (db.Type == DropBox.DropLocations.ShopInventory || transformHovered == db.transform.parent)
        {
            // This guard clause catches if the player attempts to buy their own items or sell the shops items
            if (parentAfterDrag == refOldParent)
                return false;

            TownUI.Instance.SellToPlayer(gui.GetItemName());
            // If the indicator of if the object was successfully bought is marked as false
            // then the object won't be destroyed and be transferred back to its old parent
            if (parentAfterDrag != db.transform)
                Destroy(this.gameObject);
            else
                parentAfterDrag = refOldParent;
        }
        else if (db.Type == DropBox.DropLocations.LootStock)
        {
            if (transformHovered.name != "InvenViewport")
                throw new NullReferenceException();
            else
                EnemyUI.Instance.MoveToActiveInven(this.gameObject, gui.GetAspect(), gui.GetItemAmount());
        }
        else if (db.Type == DropBox.DropLocations.LootInventory)
        {
            if (transformHovered.name != "LootViewport")
                throw new NullReferenceException();
            else
                EnemyUI.Instance.MoveToLootingInven(gui.GetAspect(), gui.GetItemAmount());
        }
        else
            return false;

        return true;
    }
    #region Drag Handlers
    public void OnBeginDrag(PointerEventData eventData)
    {
        parentAfterDrag = transform.parent;
        refOldParent = transform.parent;
        if ((int)Type is 1 || (int)Type is 0 || (int)Type is 4 || (int)Type is 5)
            transform.SetParent(transform.root.GetChild(1), false);
        else if ((int)Type is 2 || (int)Type is 3)
            transform.SetParent(transform.root.GetChild(0), false);
        else
            transform.SetParent(transform.root, false);

        transform.SetAsLastSibling();
        image.raycastTarget = false;
    }
    public void OnDrag(PointerEventData eventData)
    {
        Vector3 vector = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        transform.position = new Vector3(vector.x, vector.y, 1f);
    }
    public void OnEndDrag(PointerEventData eventData)
    {
        RectTransform rectTrans;
        try
        {
            rectTrans = eventData.pointerEnter.TryGetComponent(out RectTransform rect) ? rect : null;
            bool deciphered = DecipherNewLocation(rectTrans);

            if (!deciphered)
                throw new NullReferenceException();
        }
        catch (NullReferenceException)
        {
            parentAfterDrag = refOldParent;
        }
        catch (InvalidOperationException)
        {
            parentAfterDrag = refOldParent;
        }
        finally
        {
            // For if the clone object is destroyed
            try
            {
                transform.SetParent(parentAfterDrag, false);
                this.transform.position = new Vector3(this.transform.position.x, this.transform.parent.position.y, 1f);
                
                if (InventoryManipulator.Instance.IsNaked || Globals.InventoryOpened)
                    InventoryManipulator.Instance.CheckNude();

                image.raycastTarget = true;
            }
            catch { }
        }
    }
    #endregion
}