Generated buttons and referencing

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

Hello,

this is my first project in Godot and I am using GDScript.
Used version: 4.0.3

I tried to create a menu, that has as many buttons as elements, in this case captains,
are existing.
These buttons I generate with a for-loop.

If a captain is clicked, the image of the button shall be loaded into the captain preview.
To achieve this, I tried to use the “connect” feature, later discovering that Godot 4
changed the behavior of “connect” and I should use this in another way with signals.

I read the tutorial and other answers about signals, but I have still difficulties to
wrap my head around this feature.

Can someone give me a hint?
Elements of the scene:

FleetSetup - Type Control
	Captain_List - Type GridContainer
	Ship_Pair - Button

The used code, set in FleetSetup.tscn:

extends Control

var Captains_To_Load = []
var Selected_Pair = "1"

func _ready():
	_get_all_captains_from_dir()
	_load_captain_selection()

func _get_all_captains_from_dir():
	var Captains_Dir = DirAccess.open("res://SinglePlayer/Captains/")
	if Captains_Dir:
		Captains_Dir.list_dir_begin()
		var Current_Captain = Captains_Dir.get_next()
		while Current_Captain != "":
			if Current_Captain.get_extension().to_lower() in "png":
				print(Current_Captain)
				Captains_To_Load.append(Current_Captain)
			Current_Captain = Captains_Dir.get_next()
	else:
			print("Something bad happened at loading captain images")

func _load_captain_selection():
	#Declare all the vars potentially needed for a captain
	var Captain_Grid_Container
	Captain_Grid_Container = get_node("Captain_List")
	
	var Captain_Image
	var Captain_Choice_Button
	var Captain_Texture
	var Captain_Texture_Widht
	var Captain_Texture_Height
	
	for Current_Captain_To_Load in Captains_To_Load.size():
		Captain_Image = Image.load_from_file("res://SinglePlayer/Captains/" + Captains_To_Load[Current_Captain_To_Load])
		Captain_Texture = ImageTexture.create_from_image(Captain_Image)
		Captain_Texture_Widht = Captain_Image.get_size().x
		Captain_Texture_Height = Captain_Image.get_size().y
		Captain_Grid_Container.columns += 1
		Captain_Choice_Button=Button.new()
		Captain_Choice_Button.icon=Captain_Texture
		Captain_Choice_Button.disabled=false
		Captain_Choice_Button.name=str(Captain_Image)
		Captain_Choice_Button.custom_minimum_size.x=Captain_Texture_Widht
		Captain_Choice_Button.custom_minimum_size.y=Captain_Texture_Height
		Captain_Choice_Button.size.x=Captain_Texture_Widht
		Captain_Choice_Button.size.y=Captain_Texture_Height
		Captain_Choice_Button.expand_icon=true
		Captain_Choice_Button.layout_direction=Control.LAYOUT_DIRECTION_INHERITED
		Captain_Grid_Container.add_child(Captain_Choice_Button)
		var Captain_Current_Button=get_node("/root/FleetSetup/Captain_List/"+str(Captain_Image))
		Captain_Current_Button.connect("pressed", _set_captain_of_pair)
		
func _set_captain_of_pair():
	var Captain_Preview=get_node("Ship_Pair_"+Selected_Pair).get_child(1).name
	var Captain_Image_To_Set=get_node(Captain_Choice_Button.That.Had.Been.Clicked.On.texture)
	Captain_Preview.icon=Captain_Image_To_Set
:bust_in_silhouette: Reply From: a_world_of_madness

If you want the callback function (_set_captain_of_pair) to know which button triggered it, you can use a lambda function when connecting the signal, and bind variables there to pass on to _set_captain_of_pair


Captain_Current_Button.connect("pressed", func(): _set_captain_of_pair(Captain_Current_Button))

func _set_captain_of_pair(Pressed_Button):
   # Pressed_Button is now the button that called this function

In the above code, func(): _set_captain_of_pair(Captain_Current_Button) is used to create an unique callback for each button, with the current value of Captain_Current_Button being stored for when the method is called.

Thank you very much for the hint!

dspnp | 2023-06-14 17:34