How to handle input on CollisionObject _input_event before _unhandled_input of a root?

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

I have Node2D which needs to process input events unless they are not processed by its children.

Node2D
-Area2D-1
-Area2D-2
-…

Children need to process input only if the mouse is above them, the root doesn’t care about pointer position. So I use _input_event for children and _unhandled_input for the root. But _input_event is always called after _unhandled_input.

How can I make children process input first?

One of the possible solutions is to make the root Area2D covering the entire viewport, but it looks bad in terms of performance in case of many instances.

Another workaround is to use _unhandled_input on children too and manually check if events position collides with the area. But I don’t know how to convert mouse position to local coordinates because scene tree can have any depth and parent objects can be scaled.

Do you have any ideas?

The first solution also doesn’t work. Parent._input_event is called before child._input_event. Is it intentional or is it a bug?

askhat | 2019-10-17 09:23

:bust_in_silhouette: Reply From: waynelin

I also found it very weird on the input-call behaviors, in which the _input_event for Area2D is always called after _unhandled_input. After I google around, I did not found a proper solution.
Fortunately, after some trick applied, I got a very simple workaround. NOTE, for anyone who does NOT use Area2D input for mouse above, this trick may be not workable.

  1. setup _input for Area2D to capture mouse click (not _input_event);
  2. setup other Node for _unhandled_input capture;
  3. do the trick;
    3.1 add an is_mouse_over flag for the Area2D;
    3.2 link mouse_entered message to set is_mouse_over true;
    3.3 link mouse_exited message to set is_mouse_over false;
    3.4 under Area2D _input, only handle the event(run your own code) and get_tree().set_input_as_handled() when is_mouse_over is true, or you don’t even handle the event under Area2D;

The idea behind it. _input is always fired before _unhandled_input in real code, so instead of using _input_event, for Area2D I use _input to get the event msg in advance; and only handle the event while the mouse is over this Area2D.

pros & cons. I think all input will be going through this Area2D first, so if you instance this node a lot, maybe will get a performance issue, which I did not test. the nice thing is, at least it works.

:bust_in_silhouette: Reply From: jgao

Been searching for a similar solution with no luck…

What I ended up doing is emitting a signal by _input_event and then “revert” or “override” the behaviour modified by_unhandled_input