How to connect signal from another scene that is instanced through code

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By LockManipulator
Sprite
    ScrollContainer
            VBoxContainer

This is how I’ve got it laid out in EmailBox.tscn, the sprite is the background. I add nodes to VBoxContainer through code (script is attached to Sprite):

#EmailBox.gd
onready var email = preload("res://Email.tscn")
    var i = 0
for item in GlobalVars.cur_player["email names"]: #for each item in this list
	var email_button = email.instance()
    var email_text = email_button.get_node("Label")
    email_text.text = GlobalVars.cur_player["email contents"][i]
	$ScrollContainer/VBoxContainer.add_child(email_button) #add node as child of vboxcontainer
    i += 1
var empty_email = emptyemail.instance()
$ScrollContainer/VBoxContainer.add_child(empty_email) #because you can't see the last item in a scrollcontainer, adds empty item at the end to bump up the last item I want the user to see

Email.tscn is laid out like this:

Control
    TextureButton
    label

And the script attached to the top node of Email.tscn is

#Email.gd
extends Control

signal view_email

func _ready():
	pass


func _on_Button_pressed():
	emit_signal("view_email")

Basically, I want a bunch of control nodes (the node from Email.tscn) instanced. Each of those have a button. When the user clicks the button, I want to connect that to EmailBox.gd (the script attached to EmailBox.tscn). Also, does each instanced button have a different name? Because I want every button except the one that was clicked, freed. Adding in:

get_tree().get_current_scene().get_node("EmailBox/ScrollContainer/VBoxContainer/Control").connect("view_email", self, "view_email")

at the end of the for loop in EmailBox.gd and a function view_email() only makes the first instanced button call the function view_email(). I need them to all call view_email() and free all the other buttons that were not clicked.

:bust_in_silhouette: Reply From: hilfazer

All children of same parent have unique names. Godot takes care of that. But you don’t need to get nodes by their paths, you can access them directly via reference:

email_button.connect("view_email", self, "view_email")

You can store your Email.tscn nodes in some member variable like:

   var emailButtons  = []

and remove buttons that aren’t pressed like this:

func removeUnpressedButtons():
	var remainingButtons = []

	for email_button in emailButtons :
		if email_button.get_node("TextureButton").pressed:
			remainingButtons.append(email_button)
		else:
			email_button.queue_free()

	emailButtons  = remainingButtons

It’s not exactly what you’ve asked for since buttons are not deleted by other buttons but maybe it’s good enough for you.

Did it work? I have a very similar setup. Its is a level select screen in which, I instance buttons. And on button_pressed, I want to emit a signal name level_info with the some values stored in the level_button

func load_buttons():
	var levels = GameDataManager.level_info[lvl_type].keys();
	var counter = 0
	for level in levels:
		var button =  load('res://scenes/lvl_button.tscn').instance()
		container_for_buttons.add_child(button, true)
		var curr_button = container_for_buttons.get_child(counter)
		curr_button.level_loading(lvl_type, level);
		curr_button.setup()
		curr_button.connect('level_info', self , 'on_level_info')
		print(is_connected('level_info', self , 'on_level_info'))
		counter += 1;


func on_level_info(curr_type, curr_num):
	print('yes')

In the lvl_button scene

func _on_TextureButton_pressed():
	if level_enabled:
		emit_signal("level_info", level_name, level_type, level_to_laod)
		print('emitted')
		get_parent().emit_signal('save_scroll_value')

But, its not working, I know this is old but can you help/

hamza_memon | 2020-06-16 04:01