Hide or free control on click?

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


I have a control node where I have overwritten the _gui_input(ev) function to determine when the control node on click.

This works, the only problem is that I want to hide or free this control node when this happens. But as soon I call hide() or queue_free() on the node in this function the processing of the input event isn’t stopped anymore afterwards, which means the input processing is continued (_gui_input(ev) and then function _unhandled_input is called on other nodes) , which is not intended in my case.

I already tried calling accept_event() and get_tree().set_input_as_handled() without success.

What else could I try to stop the processing of the input?

In Godot 3.0.6, I tried to reproduce this:

extends ColorRect

func _gui_input(event):
	if event is InputEventMouseButton:
		if event.pressed:
			print("Received pressed event")

And it correctly prints only when visible. I don’t know how you got this to happen on your side.

However, if you mean that input continues to propagate after reaching this control, I also tried putting a Button node behind it, and it also did not press it, as expected.

Zylann | 2018-12-20 23:45

Thanks for your answer, but I see I may failed in making clear my issue. What you describe isn’t what I need, my problem is with the order Godot is spreading the input event:

enter image description here

InputEvent — Godot Engine (3.0) documentation in English says, that the engine first calls _input, which I don’t use in my case. Then the Control._input_event(ev) is called on the tree. There I have one control node which overrides this function to hide itself (either by executing hide() or queue_free())

I have another node which has some code in _unhandled_input(ev), which should only get called if no control._input_event(ev) accepts the event. Now the problem: When I queue_free() or hide() the control node in the Control._input_event(ev), Godot doesn’t mark the input_event as handled, no matter if I call accept_event() or not. This causes my _unhandled_input(ev) function in the other node to be called, which is not what I want. If I comment out the queue_free(), then unhandled_input(ev) doesn’t get called. So it’s definitely those two functions that cause my issue. I’m not sure if that’s intended behaviour or a bug. Either way, I am looking for a way to work around that.

Hope it makes more sense now.

TobiLa | 2018-12-21 00:05

Hmm if the control hides itself by handling the event, then _unhandled_input should not be called, since… well it was handled by the hiding control^^

I tried that too by adding _unhandled_input to another script on another node:

func _unhandled_input(event):
	if event is InputEventMouseButton:
		if event.pressed:
			print("Received unhandled click")

and it does not get called when I press my mouse button to hide the control in front. It does get called only if I click again, after it was hidden.

queue_free may be a little different because it performs destruction of the node later, so event propagation might behave differently if the event is not marked as andled. However, I didn’t notice a difference when trying that instead of hide().

Basically I’m still unable to reproduce the case of “1 click causes both _gui_input in the front node and _unhandled_input in the node behind”. Do you have an example project reproducing this?

Zylann | 2018-12-21 00:18