How do I execute code after return?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By ro0nik

Lately I’ve run into some problems using Godot’s built in drag and drop functions. I would like to delete the node right after I start dragging, but I also need the data from the node. I would like to queue_free the node in _get_drag_data() (Godot 4), but I first have to return the data. If I queue_free the node in the _get_drag_data(), it now doesn’t exist therefore I can’t return the data within the script. Is there a better workflow for this or is there a way to execute code after I return the data? I’ve had to resort to setting a kill timer which makes the code lengthy and clunky.

extends Control

var is_active = false
var item_data

func _set_image():
$MarginContainer/Shape_Image.texture = load(item_data.shape_image)

func _clear_slot():
$MarginContainer/Shape_Image.texture = null
is_active = false
item_data = null

func _get_drag_data(position):
if is_active == true:
	var kill_timer = Timer.new()
	kill_timer.connect("timeout",Callable(self,"_clear_slot"))
	kill_timer.wait_time = 0.2
	kill_timer.one_shot = true
	add_child(kill_timer)
	kill_timer.start()
	return item_data

I’ll qualify this by saying that I’m not familiar with Godot 4’s drag/drop…

It’s not clear what item_data consists of. Can you not simply…

  • Create a copy of item_data
  • Remove the node
  • Return the copied item_data

jgodfrey | 2023-01-18 22:34

Hmmm. It’s also not clear why you want/need to delete the node at the start of the drag? On the surface, that seems strange…

jgodfrey | 2023-01-18 23:32

I have been experimenting with a controller class that sits outside/above the active scene (Autoload). I guess I could copy the data into that then retrieve it when needed.

The goal of removing the node is:

  • An object/scene “item” is spawned on screen. (item contains data)
  • When the item is dragged the data is loaded into the drag operation and the item scene is removed.
  • The data can now be dropped into an inventory or dropped back into the initial spawn area. Either way, while dragging, the play cannot see the item in the spawn area. (Typing this I realize I can just hide the node instead of removing it completely.)

I suppose I can design my code differently to fit the situation. I was just curious if there was a function or new approach to drag and drop that I was missing. Thanks for the insight!

ro0nik | 2023-01-19 00:07

What if You start dragging and change your mind ? I think You shouldn’t queue item free at the very beginning of drag. Make it invisible, or transfer it into intermittent medium, like Dictionary.

Inces | 2023-01-21 09:50

That’s the problem that I was running into. I got it to work with the controller class I mentioned. It works similarly to the way Unreal Engine uses its class structure.

  • Made a custom ‘Controller’ class/script.
  • Put it in the Autoload list.
  • Controller script contains a ‘Payload’ dictionary that can store any data passed.
  • On drag, save the data to the ‘Payload’ and delete the node being dragged.
  • Now if the drag succeeds or fails I still have access to the data and can choose what to do with it.

Worked for me :slight_smile:

ro0nik | 2023-01-22 04:32

:bust_in_silhouette: Reply From: ro0nik

[The Method I Chose]

“… I got it to work with the controller class I mentioned. It works similarly to the way Unreal Engine uses its class structure.”

  • Made a custom ‘Controller’ class/script.
  • Put it in the Autoload list.
  • Controller script contains a ‘Payload’ dictionary that can store any data passed.
  • On drag, save the data to the ‘Payload’ and delete the node being dragged.
  • Now if the drag succeeds or fails I still have access to the data and can choose what to do with it.

Worked for me :slight_smile:

:bust_in_silhouette: Reply From: zhyrin

queue_free() doesn’t free the node, it queues it up for deletion. I would think that you can still work with it until the end of the frame.
Have you tried calling queue_free deferred? That way you run your code and the node will try to free itself in the next frame.