Clicks are getting eaten by a Button that was supposed to be freed from tree [DONE]

Godot Version

Godot 4.4

Question

UPDATE: I got it running… I apparently made a blunder to set the child node to process- ‘Always’ not the parent node so when the game gets paused on instantiation, it looked like the issue was because of previously freed control nodes… lol.

Hey everyone, I hope you can help or provide insights!

To give a short idea, I’m making an action rouge ish like top view game, there’s 3 waves in total and everytime the boss spawns during mid wave and post wave once all enemies died, my goal is to instantiate a short dialogue scene that you can go through with clicks if that makes sense…

The current flow of the game is: Starting screen/menu to game start > Dialogue scene as prologue > move to main scene > weapon selection ui instantiates > wave starts > half wave < – issue happens where the button coming from weapon selection ui is eating all clicks as soon as the dialogue scene comes up making the player unable to move further to the game at all.

What I did so far:

  1. Ensure that most of the control nodes are on ignore
  2. add _gui_input function in my dialogue scene
  3. Made my dialogue scene with layer 10, my weapon selection scene with 0 and my in game ui(health bars and the like) with layer 1
  4. During weapon selection, before the button’s completely queued I change the visibility to false and the mouse filter to either pass or ignore (tried both, nothing worked)
  5. Make sure the weapon selection scene is no longer in the tree

I’d also like to note that I lowered the wave to 10 mobs to make sure everything’s working during the testing phase so I’m thinking maybe I’m clearing half the wave too fast? I’m not sure.

Is there any other troubleshooting I can do to determine where this is coming from? I can’t say I’m knowledgeable with inputs/ui at all. Appreciate all the help, here’s my weapon selection ui code:

extends CanvasLayer


var main_character: PlayerStats = preload("res://resources/player_stats_manager.tres")
var new_resource = PlayerStats
#Button switchers 
@export var wep1_info: Label
@export var wep1_image: NinePatchRect
@export var wep2_info: Label
@export var wep2_image: NinePatchRect
@export var wep3_info: Label
@export var wep3_image: NinePatchRect
@onready var culp = $EmbraceMarginContainer2/MainBoxContainer/MainHBoxContainer/Background/VBoxContainer/Weapon2SelectButton

func visibility_toggle(object):
	if object.visible == true: 
		object.visible = false
	else:
		object.visible = true

func _ready() -> void:
	new_resource = main_character.duplicate()

# Switcher buttons 
# Exchulibladder 

func _on_wep_1_info_button_1_pressed() -> void:
	visibility_toggle(wep1_info)
	visibility_toggle(wep1_image)


func _on_wep_1_info_button_2_pressed() -> void:
	visibility_toggle(wep1_info)
	visibility_toggle(wep1_image)

#Embrace
func _on_wep_2_info_button_1_pressed() -> void:
	visibility_toggle(wep2_info)
	visibility_toggle(wep2_image)


func _on_wep_2_info_button_2_pressed() -> void:
	visibility_toggle(wep2_info)
	visibility_toggle(wep2_image)


#Hanger
func _on_wep_3_info_button_1_pressed() -> void:
	visibility_toggle(wep3_info)
	visibility_toggle(wep3_image)


func _on_wep_3_info_button_2_pressed() -> void:
	visibility_toggle(wep3_info)
	visibility_toggle(wep3_image)

#Main Buttons 

#func _ready() -> void:
	#print(main_character.selected_weapon)
#

func _on_weapon_1_select_button_pressed() -> void:
	main_character.selected_weapon = WeaponsManager.weapon_list["exchu"]
	GameManager.true_end = true
	GameManager.current_wave = 1
	GameManager.weapon_select = true
	WeaponsManager.weapon_selected = "exchu"
	$"../Player/Player".setup_stats()
	#get_parent().get_node("Player").setup_stats()
	queue_free()
	
# I test everything here, nothing worked 
func _on_weapon_2_select_button_pressed() -> void:
	main_character.selected_weapon = WeaponsManager.weapon_list["embrace"]
	print(culp.mouse_filter)
	GameManager.good_end = true
	GameManager.current_wave = 1
	GameManager.weapon_select = true
	WeaponsManager.weapon_selected = "embrace"
	#get_parent().get_par("Player").setup_stats()
	$"../Player/Player".setup_stats()
	culp.visible = false

	culp.mouse_filter = Control.MOUSE_FILTER_PASS
	print(culp.mouse_filter)
	print('is button visible? :', culp.visible)
	print('is button in tree? :', culp.is_inside_tree())
	culp.disabled = true
	print('is button disabled?: ', culp.disabled)
	queue_free()
	


func _on_weapon_3_select_button_pressed() -> void:
	main_character.selected_weapon = WeaponsManager.weapon_list["hanger"]
	GameManager.bad_end = true
	GameManager.current_wave = 1
	GameManager.weapon_select = true
	WeaponsManager.weapon_selected = "hanger"
	$"../Player/Player".setup_stats()
	queue_free()

And this is my dialogue scene:

extends Control

@export var speaker_name: Label
@export var dialogue_label: Label
@export var hbox_cont: HBoxContainer

var current_index := 0
var dialogue: Array
var is_last_dialogue:= false
var _input_enabled := true
signal pre_dialogue_finished
signal finished

func _set_current_index(index: int):
	var idx = dialogue[index]
	speaker_name.text = str(dialogue[current_index].speaker)
	dialogue_label.text = dialogue[current_index].line

	if idx["speaker"] == "Ami":
		hbox_cont.alignment = BoxContainer.ALIGNMENT_BEGIN
	else:
		hbox_cont.alignment = BoxContainer.ALIGNMENT_END


func _gui_input(event: InputEvent) -> void:
	if event.is_action_pressed("primary(mouse)"):
		event.accept()

func _unhandled_input(event: InputEvent) -> void:
	if not _input_enabled:
		return
	
	if Input.is_action_just_pressed("primary(mouse)"):
		current_index += 1
		if current_index < dialogue.size():
			_set_current_index(current_index)
		else:
			if !GameManager.pre_game_start:
				#_input_enabled = false
				pre_dialogue_finished.emit()
			elif !is_last_dialogue:
				#_input_enabled = false
				is_last_dialogue = true
				await TransitionsManager.fade_in()
				get_tree().change_scene_to_file("res://scenes/level_parent.tscn")
				queue_free()
				#move_to_main_game.emit()
			else:
				#_input_enabled = true
				current_index = 0
				finished.emit()
				queue_free()

func move_to_main_level():
	if is_last_dialogue:
		await TransitionsManager.fade_in()
		get_tree().change_scene_to_file("res://scenes/level_parent.tscn")
		queue_free()
		
func pre_start_dialogue():
	_input_enabled = true
	dialogue = Dialogue.pre_game

func set_current_dialogue(wave: int, part: int):
	match [wave, part]:
		[1, 1]:
			dialogue = Dialogue.pre_wave_one
		[1, 2]:
			dialogue = Dialogue.post_wave_one
		[2, 1]:
			dialogue = Dialogue.pre_wave_two
		[2, 1]:
			dialogue = Dialogue.post_wave_two
		[3, 1]:
			dialogue = Dialogue.pre_wave_three
		_:
			dialogue = []
		
	current_index = 0
	if dialogue.size() > 0:
		_set_current_index(current_index)
	else:
		push_error("Dialogue array empty for wave %d part %d" % [wave, part])


func _ready() -> void:
	await TransitionsManager.fade_out()
	
	if !GameManager.game_started:
		dialogue = Dialogue.prologue

	if dialogue.is_empty():
		return

	_set_current_index(current_index)

	set_process(true)

	#
#func _process(delta: float) -> void:
	#dialogue_start(1, "pre")


func _on_pre_dialogue_finished() -> void:

	await TransitionsManager.fade_in()
	speaker_name.text = ""
	dialogue_label.text = ""
	pre_start_dialogue()
	current_index = 0
	_set_current_index(current_index)
	GameManager.pre_game_start = true
	await TransitionsManager.fade_out()


func _on_move_to_main_game() -> void:
	move_to_main_level()

And in my debugger > misc, it prints as:

/root/LevelParent/WeaponSelectionUI/EmbraceMarginContainer2/MainBoxContainer/MainHBoxContainer/Background/VBoxContainer/Weapon2SelectButton

Thank you!!

Don’t forget to format your code with backticks (it’s on this key: ~)
Three backticks will format your code:

function()

Thank you, I totally missed that!