+1 vote

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):

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:


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

extends Control

signal view_email

func _ready():

func _on_Button_pressed():

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.

in Engine by (39 points)
edited by

1 Answer

+2 votes

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:

    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.

by (2,274 points)

Did it work? I have a very similar setup. Its is a level select screen in which, I instance buttons. And on buttonpressed, I want to emit a signal name levelinfo 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.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):

In the lvl_button scene

func _on_TextureButton_pressed():
    if level_enabled:
        emit_signal("level_info", level_name, level_type, level_to_laod)

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

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.