3D camera _input conflicting with 2D button click

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

Hi,

Enjoying godot 3 but I have a small problem.

I use the mouse with pressed button to control the camera in a 3D scene.

func _input(event):
    if event is InputEventMouseButton:
        if event.button_index == BUTTON_LEFT:
            if (Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED):
                Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
                pantilt = false
            else:
                Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
                pantilt = true

But I also have an onscreen GUI composed of Buttons with associated functions like:

func _on_ButtonMap_pressed():
       worldmap.visible = not worldmap.visible

It works except that pressing the 2D button does the _on_ButtonMap_pressed func as expected but ALSO triggers the _input event on the 3D scene script, which captures the mouse and then frees it. This causes the mouse to reset to the centre of the screen each time the button is pressed.

In the Button inspector, mouse->filter is set to stop. The camera script is a per scene instance and the GUI script is a global autoload, which I think might mean the camera script always receives the events before the Button does?

Any ideas on how to stop this behaviour?

Here is how input event works.

InputEvent — Godot Engine (3.0) documentation in English

volzhs | 2018-02-20 07:26

yeah, I think the behaviour is because the buttons are in a singleton that is autoloaded.

set_input_as_handled() doesn’t consume the event before it gets to the 3D camera _input so I think that means the local camera node is processed before the singleton?

(Singletons (AutoLoad) — Godot Engine (3.0) documentation in English)

dodgyville | 2018-02-20 23:27

:bust_in_silhouette: Reply From: dodgyville

The solution was to place my mouse event code under:

func _unhandled_input(event):

instead of:

func _input(event):

_input is processed before controls and _unhandled_input is done afterwards which is the behaviour I needed.