I found this Question without any answer, and wanted something very similar. I'm a beginner with Godot but still came up with something that works for me, not sure if it would hold up or is proper.
It is unfortunately not a straight up answer to OP's problem, but looking at other threads on this forum it seems acceptable to post related answers and solutions as well. And perhaps one can extrapolate from my answer to find the answer to OP's question too?
Clone & Run
You can grab the working code from here: https://github.com/jeroenheijmans/sample-godot-drag-drop-from-control-to-node2d
Demo
Left are the Control items to drag around.
Middle has a Node2D
section.
Right side has a Control
based drop zone.

Gist
The essence of the repository linked above is:
- Encapsulate the
Node2D
stuff in a SubViewport
node that's again a child of a SubViewportContainer
node;
- Implement the
_drop_data(...)
function on the SubViewportcontainer
;
- Make it "drop" the actual stuff as a child of the
Node2D
stuff
Script on toolbox_item
items:
extends Control
func _get_drag_data(_position):
var icon = TextureRect.new()
var preview = Control.new()
icon.texture = %TextureRect.texture
icon.position = icon.texture.get_size() * -0.5
icon.modulate = modulation
preview.add_child(icon)
set_drag_preview(preview)
return { item_id = "godot_icon" }
Script on the SubViewportContainer
that contains a SubViewport
which contains the Node2D
with its physics bodies:
extends SubViewportContainer
func _can_drop_data(at_position, data):
return data.item_id == "godot_icon" # Your logic here
func _drop_data(at_position, data):
var component = RigidBody2D.new()
component.position = at_position
var sprite = Sprite2D.new()
sprite.texture = load("res://icon.svg")
component.add_child(sprite)
var shape = CollisionShape2D.new()
var rect = RectangleShape2D.new()
rect.size = Vector2(64, 64)
shape.shape = rect
component.add_child(shape)
%Node2D.add_child(component) # Or any child Node2D you want
Drop logic on the Control
of your choosing could be along these lines, for my Panel
Control script it was:
extends Panel
func _can_drop_data(at_position, data):
return data.item_id == "godot_icon"
func _drop_data(at_position, data):
var component = TextureRect.new()
component.texture = load("res://icon.svg")
component.position = at_position - (component.texture.get_size() * 0.5)
add_child(component)
Finally
I want to repeat my disclaimer: I'm a beginner with Godot. However, I still hope this may help someone.