Drag and Drop Inventory with LibGDX (Part III)

Compared to the other parts of this series, this one will contain less code, but will add a lot of functionality! We will make the inventory interactive by making the items draggable.

The DragAndDrop class

Drag and drop functionality is usually always avoided since it is very difficult to implement. LibGDX on the other hand provides a neat little class to handle it: DragAndDrop. Unfortunately there is not much documentation about it besides the JavaDoc and this test.

Basically a DragAndDrop handles all you need for the input processing like hovering, clicking and dragging. All one has to do, is define Targets and Sources. A Source can define a Payload, which can be any Object. In our case this will be a Slot.

The SlotSource

With the above description, understanding the following code should be a piece of cake!

public class SlotSource extends Source {

    private Slot sourceSlot;

    public SlotSource(SlotActor actor) {
        this.sourceSlot = actor.getSlot();

    public Payload dragStart(InputEvent event, float x, float y, int pointer) {
        if (sourceSlot.getAmount() == 0) {
            return null;

        Payload payload = new Payload();
        Slot payloadSlot = new Slot(sourceSlot.getItem(), sourceSlot.getAmount());

        TextureAtlas icons = LibgdxUtils.assets.get("icons/icons.atlas", TextureAtlas.class);
        TextureRegion icon = icons.findRegion(payloadSlot.getItem().getTextureRegion());

        Actor dragActor = new Image(icon);

        Actor validDragActor = new Image(icon);

        Actor invalidDragActor = new Image(icon);

        return payload;

    public void dragStop(InputEvent event, float x, float y, int pointer, Payload payload, Target target) {
        Slot payloadSlot = (Slot) payload.getObject();
        // the payload was dropped over a valid target
        if (target != null) {
            Slot targetSlot = ((SlotActor) target.getActor()).getSlot();
            // if the item is the same, stack it
            if (targetSlot.getItem() == payloadSlot.getItem() || targetSlot.getItem() == null) {
                targetSlot.add(payloadSlot.getItem(), payloadSlot.getAmount());
            } else {
                // the item is not the same, thus switch the items
                Item targetType = targetSlot.getItem();
                int targetAmount = targetSlot.getAmount();
                targetSlot.add(payloadSlot.getItem(), payloadSlot.getAmount());
                sourceSlot.add(targetType, targetAmount);
        } else {
            // the payload was not dropped over a target, thus put it back to where it came from
            sourceSlot.add(payloadSlot.getItem(), payloadSlot.getAmount());

The SlotTarget

The code for the target is even less complicated, since most of the logic is already handled by the SlotSource.

public class SlotTarget extends Target {

    private Slot targetSlot;

    public SlotTarget(SlotActor actor) {
        targetSlot = actor.getSlot();

    public boolean drag(Source source, Payload payload, float x, float y, int pointer) {
        Slot payloadSlot = (Slot) payload.getObject();

        // in case we drag something over this target, we highlight it a bit

        // returning true means that this is a valid target
        return true;

    public void drop(Source source, Payload payload, float x, float y, int pointer) {
        // we already handle all of this in dragStop in the Source

    public void reset(Source source, Payload payload) {


Putting it all together

For now we have just defined some classes, but we haven’t actually used them yet. In the previous parts of this series, there have already been some places where those classes were used, but it wasn’t clear yet what they did.

The following was found in the constructor of the InventoryActor and creates a SlotSource and a SlotTarget for every slot.

for (Slot slot : inventory.getSlots()) {
    SlotActor slotActor = new SlotActor(skin, slot);
    dragAndDrop.addSource(new SlotSource(slotActor));
    dragAndDrop.addTarget(new SlotTarget(slotActor));

And the InventoryActor got the DragAndDrop supplied by the InventoryScreen:

DragAndDrop dragAndDrop = new DragAndDrop();
inventoryActor = new InventoryActor(new Inventory(), dragAndDrop, skin);

That’s it already! Everything else is handled by the sources, targets and DragAndDrop.


In Part IV we will add the last finishing touch. Tooltips!

Leave a Reply

Your email address will not be published. Required fields are marked *