Event propagation in control node

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Daniel Mircea
:warning: Old Version Published before Godot 3 was released.

I got a control node with several children such as container and panel nodes.

I want to bind the events for the mouse_enter and mouse_exit actions. Is there a way to listen to these events on a parent node rather than adding event listeners on each element and its children?

Like connecting all the elements to a single callback for mouse_enter signal?

eons | 2017-07-13 22:05

@eons, not sure I understand. But elaborate further, the only option I see is to create a recursive function that connects all Control child nodes to my mouse enter and exit callbacks.
It’s trivial to write, but I thought I would ask here of alternatives as it feels like a code smell.

Daniel Mircea | 2017-07-13 22:17

I think your idea of writing a function to walk through the children and connect each one’s signal is probably the cleanest way to do it.

In theory, I suppose you could define your own control (as a separate scene) that connected the signals in the _ready() function, and then instance that to populate your UI. But that would only save you any effort if all of your control nodes were of a single type. If you have several different types of nodes, it’s way more trouble than it’s worth.

breadbox | 2017-07-14 06:44

Yes, iterating over all the concerning elements -on ready- and connecting them (maybe with a reference as extra parameter) to a single callback may be the simplest and best way, that can be done with the visual editor too (just use a string or int as extra parameter for ID).

eons | 2017-07-15 02:50

:bust_in_silhouette: Reply From: Daniel Mircea

Based on the feedback received, this is how I’ve implemented the solution:

func connect_node_and_children(node, string_signal, target, string_method):
	if node.is_type("Control"):
		node.connect(string_signal, target, string_method)
	for child in node.get_children():
		connect_node_and_children(child, string_signal, target, string_method)

So calling the actual function is done like this:
(of course It assumes I’ve created an _on_mouse_enter method)

connect_node_and_children(get_node("sidebar"), "mouse_enter", self, "_on_mouse_enter")