Disabling input on a Control and all its children

Godot Version

4.2.2

Question

I’ve got a Control with a number of children that include buttons, and in certain circumstances I briefly animate it (currently just fades, but in the future I may want to move it too). I want to disable input on everything childed to that Control it while it’s animating, but I’m not sure what the most efficient way to do this is.

I tried experimenting with mouse_filter and focus_mode on the parent Control, but neither of those seem to do anything with child nodes. I was hoping for something that works the way visible does, where toggling it also affects all children without modifying their individual states.

Is there anything like that, or do I need to recursively go through all children and set them individually each time I toggle interactivity? That would seem to require I manually track any individual children or subgroups I might want to set separately from parent-level changes, which wouldn’t be the case if the parent behaviour overrode but didn’t overwrite the child state (as with visible).

Use Node.propagate_call and Control.set_mouse_filter

you_control_parent.propagate_call("set_mouse_filter", [Control.MOUSE_FILTER_IGNORE])

Node — Godot Engine (stable) documentation in English
Control — Godot Engine (stable) documentation in English

1 Like

That works well! Good to know, thanks. For anyone working in C#, it seems converting an Enum to the Variant that the argument collection expects isn’t straightforward, so this is how I ended up formatting it:

parent.PropagateCall("set_mouse_filter", new(){(int)Control.MouseFilterEnum.Ignore});

That said, I’m concerned about what happens if I re-enable things by propagating Stop to all children, since I’d be changing a lot of children that weren’t meant to be interactive, such as Labels that default to Ignore, and Containers that default to Pass. My current simple case doesn’t show any immediate issues, so maybe those control’s just can’t do anything and therefore don’t interfere, but it seems a bit risky to be changing the value directly on a bunch of children whose filters don’t need to change from default. Or is that not quite how propagation works?

I guess the only solid way around that would be to recursively check all the children and only disable those that don’t have the desired filter, cache them and their value prior to changing them, and restore the cached values later when re-enabling the group.

If you don’t need to click in any of these nodes that you’ll propagate the call, you probably won’t find any problem, but if you need to interact with your mouse with some node changed to ignore (ex: You have as child of the parent node that propagate the call a TextEdit node and needs to write something in this node) in this case you won’t be able to focus the node clicking on them