Handling mouse events

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


Is there a way to filter mouse events?

I have a simple scene which has a Node2d (Root), with a sprite (Background) and camera2d (Camera) as children. The sprite is an image which is bigger than the viewport. I have a attached a script to the Node2d which is overriding _input(event)

When I drag around the scene (by handling InputEventScreenDrag) i move the camera so you can “look” around the entire background sprite. This works fine.

The issue I’m trying to resolve is that a whole lot of other input events fire (mousebutton, screentouch, etc) as well (obviously), but since they all come into the _input function separately how do i filter them?

For instance if a drag has happened, I don’t want this also to be seen as a tap (screentouch) as eventually i want this to do something else.

Also if I have add other child sprites to the root Node2d and “screentouch” one of those, how do I stop the events from firing on its siblings or parent as well?

I’ve just started playing with godot and gone through a lot of tutorials, but these mostly focus on keyboard entry. If I need to change the hierachy or the tree, or use different objects, or if its a code solution, any pointers, references, etc would be great.


How do You check for mouse input type?
Because maybe all you need is some if/elif/else structure to filter the events…

kozaluss | 2018-09-03 15:46

Thanks, but that doesnt work, the events come through as and when they happen, so the _input(event) function is called multiple times with a single event milliseconds apart, depending on how long you hold the buttons down for.

So if/else can redirect the event to a particular function, but you really need to know what the previous event(s) were that was passed to the function.
Since mousemove is also an event then _input(event) could be called 100’s of times between the mousedown and mouseup event, and then you would have to determine whether a drag event happened between those events to determine whether or not it was a click event. Since a mousedown and touch pressed and mouseup and touch released both fire on on a single click event, you cant handle both as you would essentially get two virtual clicks for every one physical click, so you would need to combine those events into a single event.

All of the above is programatically possible, but it seems like a lot of low level work, for a higher level tool. I was hoping that someone who knows godot better, would be able to point to some classes or implementation method, or node type, that was already built in that I’ve missed in the docs.

tyronewatt | 2018-09-03 15:59

That I do not know yet - I am a beginner also :slight_smile:

kozaluss | 2018-09-03 16:16

:bust_in_silhouette: Reply From: Zylann

When you use input callbacks, filtering event is done with ifs, like this:

if event is InputEventScreenDrag:
    # Do your drag

And you will always get only the drag event inside that if block. This is just how events work, at least when using _input.
If you did not use an if then you maybe got lucky because many events share the same properties, and you could have had errors by trying to access inexistent ones depending on which type of event the function received.

If you want nodes to interrupt events, I think you should not go with only _input because that one happens always for every node (when defined). It is better to use Control nodes instead, which are the building blocks for making GUIs and they handle input hierarchy automatically.
See how it works here: InputEvent — Godot Engine (3.0) documentation in English

When using _input_event(event) on Control nodes, you can make it so elements in front will receive events but not their background siblings.

In rare cases where nothing else works, you can use this to stop event propagation: SceneTree — Godot Engine (3.0) documentation in English