How to make a simple click and drag inventory

Godot Version

4.2

Question

Hi, guys. I’m a bit new here so if the format’s off, sorry about that.

Right now I’m trying to make something akin to a point-and-click adventure game where the player ahs to find certain items and put them in their inventory.

The inventory appears in the top left corner of the screen, and I’m trying to make so that if the player drags the item to the inventory, it then becomes added to one of the slots.

The logic I had behind this process was that the item would be dragged to the inventory window in a collision signal and then that item would then delete from the scene and become part of the inventory as one of the inventory slots. But fiddling with it now that may not be the case.

Sorry if this seems like a newbie question, I’ve just been messing around with this for a while now and am not sure how to go about this portion of the project.

Here’s the code for the item (a cake):

extends Node2D



class_name Item


@export var item_name: String = ""
@export var icon: Texture2D
@export var is_stackable: bool = false
@export var itemresource: Item
@onready var window : Panel = get_node("inventorywindow")

@onready var inventoryarea : StaticBody2D = get_node("invarea/inventoryarea")
@onready var cake : Item = get_node("cake/StaticBody2D/cake/Sprite2D")


var can_grab = false
var grabbed_offset = Vector2()
var spawn_position = Vector2(722,364)

func _input_event(viewport, event, shape_idx):
	if event is InputEventMouseButton:
		can_grab = event.pressed
		grabbed_offset = position - get_global_mouse_position()

func _process(delta):
	if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT) and can_grab:
		position = get_global_mouse_position() + grabbed_offset
	else : global_position = spawn_position


func _on_cake_body_entered(body):
	if body.name == "inventoryarea" :
		$Timer.start()
		

func _on_Timer_timeout():
	queue_free()


func _on_invarea_mouse_entered():
		if MOUSE_BUTTON_LEFT and cake:
			var cake = get_node("cake/StaticBody2D/cake/Sprite2D")
			cake.queue_free()

I hope I made things a little clearer and thanks in advance!

To implement drag-and-drop functionality, you need to override these built-in virtual methods:

  1. Validating drag targets (_can_drop_data)
  2. Initiating drag operations (_get_drag_data)
  3. Handling final drop events (_drop_data)
1 Like

Thanks for the reply. Would these functions go into the inventory script? If so, would it be into the inventory window or just the inventory slots themselves?

These functions go on the items being clicked on and dragged. However, they are only available on the green Control nodes. If you are not using those you will need to implement a custom system.

1 Like

Hm, I already made the item a 2D Node in an Area 2D space. Should I look into a custom system? Or would it be easier to simply change the node type of the two and recreate the scene using a Control Node?

The built in drag and drop system in Godot isn’t that great. It depends on what you want to do with the drag and drop system. For example, the actual node doesn’t move with the built in system, you’re supposed to make a ghost preview node that follows the mouse.

1 Like

Yeah, I think I encountered a tutorial that was centered around getting a ghost-preview for clickable nodes. The Drag-and-drop system I had in mind was one that could interact with both the UI and the 2D Environment, so dragging an item, like an apple, from a tree into an inventory screen, or having a key in that inventory and using it to unlock a gate in-game.

Yeah if you use the built in system you’ll need to hide the original node when you’re dragging it and show it again if the drag fails, or delete it when the drag succeeds.

1 Like

Gotcha. I guess my main concern is the actual item showing up in the inventory once you drag the node to the inventory screen. What I’m guessing that I have to do is somehow have the node both delete itself once it collides with the inventory screen and have the item show up in the inventory slot, but I’m not exactly sure how I would go about that part coding-wise.

I think it would be better to delete the node after the player releases the mouse click button. Then you can check whether it’s over an inventory slot or not

1 Like