How to dynamically connect signals

Godot Version

Godot 5

Question

How to dynamically connect multiple Area2D input_event (that are add dynamically to TextureRect) to Control node

extends Control

@onready var edit_space: TextureRect = %EditSpace
@onready var game_root = get_tree().current_scene
@onready var lab: Control = $"."
@onready var lab_tool_box: GridContainer = %LabToolBox
@onready var lab_storage_background: ColorRect = %LabStorageBackground
@export var lab_slot_scene: PackedScene
var zoom = 1.0
var pan_start = Vector2.ZERO
var input_event = null
var dragged_item = null
var offsite: Vector2
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	update_lab_tool_box()
func _on_tab_container_tab_changed(_tab: int) -> void:
	update_lab_tool_box()

func _input(event: InputEvent):
	if edit_space.is_visible_in_tree():
		if event is InputEventMouseButton:
			if event.button_index == MOUSE_BUTTON_WHEEL_UP:
				zoom *= 1.1
				edit_space.scale = Vector2(zoom, zoom)
			elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
				zoom /= 1.1
				edit_space.scale = Vector2(zoom, zoom)
			elif event.button_index == MOUSE_BUTTON_MIDDLE:
				pan_start = get_global_mouse_position()
				input_event = event



func _on_area_2d_input_event(_viewport, _event, _shape_idx):
	print("Area2D clicked!")
	
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta: float) -> void:
	if dragged_item != null:
		dragged_item.global_position = get_global_mouse_position() - offsite
	elif pan_start != Vector2.ZERO:
		edit_space.position += get_global_mouse_position() - pan_start
		pan_start = get_global_mouse_position()
		if !input_event.is_pressed():
			pan_start = Vector2.ZERO
			input_event = null

func update_lab_tool_box():
	if get_child_count() > 0:
		for child in lab_tool_box.get_children():
			lab_tool_box.remove_child(child)
			child.queue_free()
			
	for rank_key in game_root.owned_spell_componants.keys():
		var rank: Array = game_root.owned_spell_componants[rank_key]
		for item in rank:
			var lab_slot = lab_slot_scene.instantiate()
			var slot_container: ColorRect = lab_slot.get_node("%SlotContainer")
			lab_slot.drag_start.connect(_on_drag_start)
			lab_slot.drag_end.connect(_on_drag_end)
			lab_tool_box.add_child(lab_slot)
			slot_container.add_child(item.instantiate())

func _on_drag_start(slot_item: SpellComponant):
	dragged_item = slot_item.duplicate()
	lab.add_child(dragged_item)
	dragged_item.z_index = 200
	offsite = get_global_mouse_position() - slot_item.get_parent().global_position

func _on_drag_end():
	lab.remove_child(dragged_item)
	edit_space.add_child(dragged_item)#dragged_item Node2D
	dragged_item.z_index = 0
	dragged_item.global_position = get_global_mouse_position() - (offsite * edit_space.scale)
	var area2d = dragged_item.get_child(0).get_child(0)
	#area2d.connect("input_event", Callable(self, "_on_area_2d_input_event"))
	#area2d.input_event.connect(func(viewport, event, shape_idx): _on_area_2d_input_event(viewport, event, shape_idx))
	offsite = Vector2(0,0)
	dragged_item = null
	

You can do this line much simpler:

area2d.input_event.connect(_on_area_2d_input_event)

and if you have multiple area2ds (I don’t see them anywhere in your code though), you can do it like that, assuming you will stored them in an array areas:

for area2d: Area2D in areas:
	area2d.input_event.connect(_on_area_2d_input_event)
2 Likes

Every time someone drag an item from lab_slot_scene it’s add to edit_space (they are not in an array)
Thanks anyway

This is a little embarrassing to admit especially that i can’t close this topic
but the problem was in mouse filter

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.