Instanced nodes calling _input function for each instance when clicking

Godot Version

4.4

Question

I’m creating a Debug UI for my game that contains a list of Abilities that have been preloaded into the game. I populate a GridContainer with panels that contain the abilities unique variables. I’m trying to implement a feature where when you click on one of the items in the grid a few label nodes take that items data and displays it.

Currently, I have everything working as intended, but when I click on the ability Item, each item sends their _input function into the labels, resulting in only the oldest Item data being displayed.

In the following image, if i click Fireball, the data is passed to the bottom labels:

But the data from FireBurst is immediately passed after:

Resulting in the following display:

Creating the Items to add to grid (main debugui code):

extends CanvasLayer

@onready var reset_cd_btn: Button = $PanelContainer/VBoxContainer/MarginContainer3/Body/DebugTools/ResetCDBtn
@onready var zero_mana_btn: Button = $PanelContainer/VBoxContainer/MarginContainer3/Body/DebugTools/ZeroManaBtn
@onready var spawn_dummy_btn: Button = $PanelContainer/VBoxContainer/MarginContainer3/Body/DebugTools/SpawnDummyBtn
@onready var name_lbl: Label = $PanelContainer/VBoxContainer/MarginContainer3/Body/PrieviewPanel/MarginContainer/VBoxContainer/Panel2/VBoxContainer/Panel/NameLbl
@onready var tags_lbl: Label = $PanelContainer/VBoxContainer/MarginContainer3/Body/PrieviewPanel/MarginContainer/VBoxContainer/Panel2/VBoxContainer/TagsLbl
@onready var description_lbl: RichTextLabel = $PanelContainer/VBoxContainer/MarginContainer3/Body/PrieviewPanel/MarginContainer/VBoxContainer/Panel2/VBoxContainer/DescriptionLbl
@onready var ability_grid: GridContainer = $PanelContainer/VBoxContainer/MarginContainer3/Body/AbilityBrowser/Panel/ScrollContainer/AbilityGrid
@onready var tag_filter: OptionButton = $PanelContainer/VBoxContainer/MarginContainer3/Body/AbilityBrowser/HBoxContainer/TagFilter
@onready var close_button: Button = $PanelContainer/VBoxContainer/MarginContainer2/Title/CloseButton

@export var abilities : Array[PackedScene]

var ability_dict: Dictionary

func _ready() -> void:
	LoadedAbilities.fill_debug(abilities)
	populate_ability_list()
	Signals.debug_ability_info_pass.connect(_show_data)
	clear_labels()


func _input(event: InputEvent) -> void:
	if event.is_action_pressed("debug_key"):
		visible = !visible

func clear_labels():
	name_lbl.text = ""
	tags_lbl.text = ""
	description_lbl.text = ""

func populate_ability_list():
	for i in abilities.size():
		if abilities[i]:
			var item = abilities[i].instantiate()
			add_child(item)
			if item.display_name:
				
				var dict : Dictionary = {
					"main_tag" : item.main_type,
					"sub_tags" : item.sub_tags,
					"description" : item.description
				}
				ability_dict[item.display_name] = dict
				ability_grid.add_item(item.display_name,item.icon, dict)
			else:
				item.queue_free()
			item.queue_free()

func _show_data(_name: String, _data : Dictionary):
	clear_labels()
	name_lbl.text = _name
	var main_tag : String
	match _data.main_tag:
		0: 
			main_tag = "Attack"
		1:
			main_tag = "Spell"
		3:
			main_tag = "Support"
	var tags : String
	var first : bool = true
	if first:
		tags = main_tag
		!first
	
	for t in _data.sub_tags:
		tags += ", " + str(t)
	
	tags_lbl.text = tags
	description_lbl.text = "[center]" + str(_data.description) + "[/center]"

func _on_item_list_item_selected(index: int) -> void:
	pass # Replace with function body.


func _on_close_button_pressed() -> void:
	visible = false

Code for GridContainer:

extends GridContainer

@export var ability_item : PackedScene




func _ready() -> void:
	Signals.debug_ability_pressed.connect(_show_info)

func add_item(text : String, icon: Texture2D, data : Dictionary):
	var a = ability_item.instantiate() as AbilityItem
	add_child(a)
	a.initialize(text,icon,data)
	

func _show_info(_name,_data):
	Signals.debug_ability_info_pass.emit(_name, _data)

Code for ability_Item:

extends Panel
class_name AbilityItem

@onready var label: Label = $MarginContainer/HBoxContainer/Label
@onready var texture_rect: TextureRect = $MarginContainer/HBoxContainer/TextureRect

var ability_name : String
var data : Dictionary
var icon : Texture2D
var dubug_ui
var name_lbl
var tags_lbl
var description_lbl

func _ready() -> void:
	pass


func initialize(_name: String, _icon : Texture2D, _data):
	ability_name = _name
	label.text = ability_name
	texture_rect.texture = _icon
	data = _data

func _input(event: InputEvent) -> void:
	if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed():
		Signals.debug_ability_pressed.emit(ability_name, data)

Fixed by changing the Item’s _Input to _gui_input and adding accept_event() after the signal:

func _gui_input(event: InputEvent) -> void:
	if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed():
		Signals.debug_ability_pressed.emit(ability_name, data)
		accept_event()
1 Like