Godot's built in drag & drop system + mouse offset question

Godot Version

4.3

Hi!
This is more of a two-in-one type post, I hope you’ll bear with me :slight_smile:

I’m trying to learn Godot’s built in drag and drop system for control nodes and I’m having some trouble finding resources that I can confidently understand. I would really love if someone could go over my code and tell me if my notes are correct (also there are 2 questions at the bottom, marked with capital QUESTION)

Furthermore, I’m trying to implement a way that the Texture won’t snap to it’s pivot point when clicked (by using a mouse_offset variable). But no matter what I’ve tried I can’t seem to get it working, some of my tries even resulted in a worse distance from the cursor. Can someone please tell me what I’m doing wrong here? (Marked the code with: PROBLEM CODE)

my code for checking + the questions/problem code:

extends TextureRect

# Copy, check if can paste, then paste = illusion of drag and drop

# Triggers when you click and drag
func _get_drag_data(at_position: Vector2): # Should return data
	# __________________________________________
	# Create preview of what we're dragging 
	var preview_texture = TextureRect.new()
	# Define it's properties so we can see it:
	preview_texture.texture = self.texture #make it's texture THIS node's texture
	
	# add the preview to the scene tree (doesn't make visible yet)
	var preview = Control.new() 
	preview.add_child(preview_texture)
	
	# Set mouse offset - PROBLEM CODE
	var mouseOffset :Vector2 = get_global_mouse_position() - global_position
	preview_texture.position = Vector2(get_global_mouse_position() - mouseOffset) # PROBLEM CODE
	
	# make preview visible as drag preview
	set_drag_preview(preview) # set_drag_preview must accept a control node
	# __________________________________________
	
	# delete texture from original data holder (illusion that we picked it up)
	self.texture = null
	
	#return what we want to "drag" (basically copy)
	return preview_texture.texture
	# since we're deleting the og texture we'll return the copy we made in the preview func

	
# Triggers when you hover over another node with dragged item
func _can_drop_data(at_position: Vector2, data: Variant): # should return a bool
	# data is what we're dragging / hovering over? - QUESTION!!!
	# Check whether the data can be applied to what we're hovering over
	# (basically checks if can succesfully paste)
	return data is Texture2D # Will return true/false
	
# Triggers when you drop held item
func _drop_data(at_position: Vector2, data: Variant) -> void:
	# data is what we're dragging/ hovering over? - QUESTION!!!
	# Assign that dragged data over what we're hovering over (paste)
	self.texture = data

Any help is appreciated,
Thank you for reading!

_get_drag_data - That will be in the node you want to drag, receive the relative position the dragging started, return the data you want to be passed for the other nodes.

_can_drop_data - This function will be in the nodes that can receive any dragging data, called when the mouse moves inside the Control rect while you’re dragging, receive the relative dragging position and the data. Basically you’re asking for this node: “I have this data at this position, can you handle/accept this data?” Return true if yes, false otherwise.

_drop_data - This function will be in the nodes that can receive any dragging data, will be only called if two conditions are reached: _can_drop_data needs to return true and you release the dragging into this node, will give you the relative position of the drag release and the data.


About the offset, try replace this:

# Set mouse offset - PROBLEM CODE
	var mouseOffset :Vector2 = get_global_mouse_position() - global_position
	preview_texture.position = Vector2(get_global_mouse_position() - mouseOff

For this:
preview_texture.position -= get_rect().size/2

1 Like

Thank you!

So the data : variant in those last two functions is whatever we’re dragging.

And I’m guessing it’s possible to have the _get_drag_data() in the same script as the _can_drop_data() and _drop_data() as long as whatever we’re dragging can move freely back and forth (like in the GUI Drag and Drop Demo by Godot).

Also thank you for solving the mouseOffset problem!
When I tried to use get_rect().size/2 before I didn’t add the - sign in the equation so the offset just came out worse. I see now :slight_smile: