private void AttemptSwap(InventorySlotUI destination, InventorySlotUI source)
    {
        // Provisionally remove item from both sides.
        var removedSourceNumber      = source.GetNumber();
        var removedSourceItem        = source.GetItem();
        var removedDestinationNumber = destination.GetNumber();
        var removedDestinationItem   = destination.GetItem();

        source.RemoveItems(removedSourceNumber);
        destination.RemoveItems(removedDestinationNumber);

        var sourceTakeBackNumber      = CalculateTakeBack(removedSourceItem, removedSourceNumber, source, destination);
        var destinationTakeBackNumber = CalculateTakeBack(removedDestinationItem, removedDestinationNumber, destination, source);

        // Do take backs (if needed)
        if (sourceTakeBackNumber > 0)
        {
            source.AddItems(removedSourceItem, sourceTakeBackNumber);
            removedSourceNumber -= sourceTakeBackNumber;
        }
        if (destinationTakeBackNumber > 0)
        {
            destination.AddItems(removedDestinationItem, destinationTakeBackNumber);
            removedDestinationNumber -= destinationTakeBackNumber;
        }

        // Abort if we can't do a successful swap
        if (source.MaxAcceptable(removedDestinationItem) < removedDestinationNumber ||
            destination.MaxAcceptable(removedSourceItem) < removedSourceNumber ||
            removedSourceNumber == 0)
        {
            if (removedDestinationNumber > 0)
            {
                destination.AddItems(removedDestinationItem, removedDestinationNumber);
            }
            if (removedSourceNumber > 0)
            {
                source.AddItems(removedSourceItem, removedSourceNumber);
            }
            return;
        }

        // Do swaps
        if (removedDestinationNumber > 0)
        {
            source.AddItems(removedDestinationItem, removedDestinationNumber);
        }
        if (removedSourceNumber > 0)
        {
            destination.AddItems(removedSourceItem, removedSourceNumber);
        }
    }
    private bool AttemptSimpleTransfer(InventorySlotUI destination)
    {
        var draggingItem   = startMoveSlot.GetItem();
        var draggingNumber = startMoveSlot.GetNumber();

        var acceptable = destination.MaxAcceptable(draggingItem);
        var toTransfer = Mathf.Min(acceptable, draggingNumber);

        if (toTransfer > 0)
        {
            startMoveSlot.RemoveItems(toTransfer);
            destination.AddItems(draggingItem, toTransfer);
            return(false);
        }

        return(true);
    }
    private int CalculateTakeBack(InventoryItem removedItem, int removedNumber, InventorySlotUI removeSource, InventorySlotUI destination)
    {
        var takeBackNumber           = 0;
        var destinationMaxAcceptable = destination.MaxAcceptable(removedItem);

        if (destinationMaxAcceptable < removedNumber)
        {
            takeBackNumber = removedNumber - destinationMaxAcceptable;

            var sourceTakeBackAcceptable = removeSource.MaxAcceptable(removedItem);

            // Abort and reset
            if (sourceTakeBackAcceptable < takeBackNumber)
            {
                return(0);
            }
        }
        return(takeBackNumber);
    }