Trying to assign a scene as drag_preview

Godot Version

4.2.2

Question

After trying my hand at a custom drag-n-drop solution, I’ve been pointed towards the built-in drag and drop feature, which seems to work great. However, I now seem to have encountered a paradox with it.

I’m trying to set a drag preview which would show an item and its amount. This seems to be a job for a scene with two Controls: a TextureRect and a Label (my SlotUI will do). However, in order to set their texture and text, respectively, I need to reference those sub-nodes. If I create/instantiate a new SlotUI, it’s not inside the tree so I can’t rely on @onready and reference the sub-nodes. If I use a pre-existing slot (transaction_slot in this example), then it breaks the rule “drag preview must not be inside a tree”, and the editor gives me the relevant error. Is there a way out of this paradox?

1 Like

A node and it’s subtree is initialized when it is added to a tree. Not just the scene tree. For example, the TextureRect and Label are all ready as children of the SlotUI instance.

You could reach in to transaction slot ui like:

var preview = load('res://SlotUI.tscn').instantiate()
preview.get_node('item_icon').texture = #...
preview.get_node('amount_label').text = #...

As I read your example, I see that you do SlotUI.new() which is just instancing the SlotUI script. You probably mean to do load('res://SlotUI.tscn').instantiate() to create the associated scene. You could, of course, setup the nodes in line, but that’s what scenes are for.

One other option is to add this pattern to your SlotUI script:

var item_icon: TextureRect:
	get:
		if item_icon == null:
			item_icon = get_node_or_null('item_icon')
		return item_icon

var amount_label: Label:
	get:
		if amount_label == null:
			amount_label = get_node_or_null('amount_label')
		return amount_label
1 Like

Thanks a lot, this works! I didn’t realize the difference between “the tree” and “a tree”. That getter pattern looks like a great workaround for freshly-instantiated nodes; in my latest test the slot didn’t initialize its @onready vars, but the getter handled the references perfectly. I’ll definitely be using it whenever I’m not sure about tree structure or don’t want to “await ready”. Thanks again, this’ll help me really streamline that inventory!

1 Like