Godot: Sub - viewports still don't handle _unhandled_input or CollisionObject._input_event()

Created on 7 Mar 2018  Â·  25Comments  Â·  Source: godotengine/godot

I noticed in PR https://github.com/godotengine/godot/pull/15712 the _input event is forwarded to explicitly created Viewports, but _unhandled_input and CollisionObject._input_event() still don't respond

Godot version:
3.0.stable.official

OS/device including version:
OSX 10.13.2 (17C88)

Issue description:
The only input events that propagate into sub-viewports are _input.

_unhandled_event and _input_event (for Area2D etc) do not get called.

Steps to reproduce:
Open the attached Godot project and run it.

The Red area is in the default Viewport and receives all click events.
The green area is a child of the explicit viewport and only receives _inputevents.

Minimal reproduction project:
ViewportInputBug.zip

bug confirmed core

Most helpful comment

It seems unhandled input was simply not being passed. I will add code so it gets passed, you will have to remove your hacks though.

All 25 comments

CC @Faless

PS. @JPTeasdale, can you try following the issue template for this and future bugs? It is hard to guess your version and OS otherwise :smiley: Also, it would be nice to have a simple project which reproduces the bug, in order to help hunting it.

Ahh, sorry about that. I thought since I included the link to the source
where _unhandled_input etc wasn't implemented it would be enough. I'll
hydrate the bug report when I get home.

On Thu, Mar 8, 2018 at 2:42 AM Bojidar Marinov notifications@github.com
wrote:

CC @Faless https://github.com/faless

PS. @JPTeasdale https://github.com/jpteasdale, can you try following
the issue template for this and future bugs? It is hard to guess your
version and OS otherwise 😃 Also, it would be nice to have a simple
project which reproduces the bug, in order to help hunting it.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/godotengine/godot/issues/17326#issuecomment-371443718,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABQzLzYOcPF7fiiaAqdMKTNrnYvTrL2Nks5tcQUGgaJpZM4Sf8tz
.

Was wondering why input wasn't working on subviewports. Has this fallen off the radar? Is the fix for _unhandled_input just a copy/paste of #15712?

Is the fix for _unhandled_input just a copy/paste of #15712?

Sadly no, it needs some more work to get object picking to work properly. I tried a fix at some point, but never got it right.

Has this fallen off the radar?

A bit :(

@Faless Ah I see, keyboard is easy enough to do manually so that's all right. I was just a bit surprised because the doc said ViewportContainer + Viewport handled input automatically.

As a workaround I've found doing this:

extends ViewportContainer

func _unhandled_input(event):
    $Viewport.unhandled_input(event)

seems to solve the issue (at least for CollisionObject._input_event())

So perhaps the fix can be copy pasted after all?

@Xrayez, unfortunately your workaround didn't work for me, as I'm trying to use Node._unhandled_input() under the Viewport (rather than CollisionObject._input_event() as you mentioned).

I'm just getting into Godot, and after about 3 months of fiddling around, the ViewportContainer and Viewport nodes are the correct solution to the functionality I'm trying to implement, but this flaw (that _unhandled_input() is not propagated correctly) is keeping it from being successful.

I've cloned the repository and I'm willing to try figuring this out and perhaps fixing it. This will be my first attempted contribution to an open source project. However I'm not familiar with any of the Godot Engine source, so we'll see how successful I am.

Yes, I can confirm that the suggested workaround doesn't work for the master branch. I had to move event handling code out of the viewport to mitigate the problem but it'd be nice if we can have a proper fix soon.

I made it works by copying #15712 and changing it to unhandled_input so that setting the viewport container mouse filter to ignore generate physics picking event with the correct position (which forwading event by the way of the script doesn't). I am sad that it is not the proper fix but it can help peoples desperate like me while waiting for the proper fix.

I'm curious what the "proper" fix is. I've looked at the code and understood about 20% of how events propagate through the stack, and unfortunately I'm just not familiar enough with the project. Can anyone explain how the problem is supposed to be solved?

Any news on this or any good way to work around this issue with the Viewports?

Okay, it seems that I made it work with this in my case:

extends ViewportContainer

func _input(event):
    $Viewport.unhandled_input(event)

And then set Disable Input and Object Picking to true on the Viewport itself

EDIT

Actually if seems that Disable Input can be false for my case but, I still need Object Picking as true

From what I have seen it only works when the ViewportContainer is at 0,0
(upper left corner)

On Thu, Sep 27, 2018, 4:39 PM Cristiano Santos notifications@github.com
wrote:

Okay, it seems that I made it work with this in my case:

extends ViewportContainer

func _input(event):
$Viewport.unhandled_input(event)

And then set Disable Input and Object Picking to true on the Viewport
itself

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/godotengine/godot/issues/17326#issuecomment-425275693,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AFFXbh6gjmgYVslgbZ_wgiOxwRSBCeRMks5ufWHFgaJpZM4Sf8tz
.

@NightGriffin yes, which is partly the reason why this is not trivial.
Only unhandled input over the viewport should be passed down.
Object picking should probably then block any further propagation to other ViewportContainers (eg, if one viewport is partly on top of another).
Input should be properly xformed to match the actual scale/pos of the viewport.

Here's a little improvement to @reyalpsirc's temporary solution to fix the issue @NightGriffin raises, until this is supported by the engine:

extends ViewportContainer

func _input(event):
    if event is InputEventMouse:
        event.position -= rect_global_position
    $Viewport.unhandled_input(event)

Looks like the event object is used by other nodes after the _input call returns, so modifying its position messes up other controls. Here's a better workaround for the issue:

extends ViewportContainer

func _input( event ):
    if event is InputEventMouse:
        var mouseEvent = event.duplicate()
        mouseEvent.position = get_global_transform().xform_inv(event.global_position)
        $ClassesViewport.unhandled_input(mouseEvent)
    else:
        $ClassesViewport.unhandled_input(event)

Note that this is a temporary workaround until a proper fix is implemented in the engine. It works for me, but may not for you. I wouldn't leave it in released code. Although I don't know the full design behind input handling in Godot, it seems weird to call unhandled_input from _input, but it does the job for now.

It seems unhandled input was simply not being passed. I will add code so it gets passed, you will have to remove your hacks though.

I"m seeing this issue in 3.1.1 maybe im doing something wrong?

@EstevanBR I opened a new issue here: #31802

@EstevanBR I can confirm it seems to be fixed in 3.2.0a2 available here.

I"m seeing this issue in 3.1.1 maybe im doing something wrong?

The issue is still present in 3.2.1

I tested it and it works for me. I also tried the original minimal reproduction project and it also works.

Did you set the mouse filter on the ViewportContainer control to ignore?

You are right, the events are now passed to viewport. I had a HUD control with mouse filter pass that consumes the events (the leftover of a workaroud that was connected with this issue).

I have slightly more complicated scene: I am viewing viewport as texture in TextureRect (to have filtering while upscaling viewport from lower resolution because Godot only supports the nearest neighbour upscaling which looks really terrible in my project) and I also have HUD control layer which I display on the root viewport (thus in native screen resolution - the similar way as Unreal engine displays controls). Then if I set all the controls nodes that can cover the screen (texturerect, viewportcontainer etc.) to ignore, the unhandled events are passed but with wrong screen position (when viewport size is different than the window size) thus I can not pick objects.

I have to first transform the position of events. Not sure if this is an intended feature or a bug. Until now I have not found better solution than set all the mouse filters of controls that covers the screen (HUD, ViewportContainer, ...) to pass. Simultaneously I sent events with transformed position from _input(event) in TextureRect to _unhandled_input() of the Viewport. The position of event has to be transformed when the viewport size is different from the window size.

Maybe I am missing something since this way seems to me quite complicated and I would expect it much more straightforward.

I still got this issue when using ParallaxBackgrounds. I wanted to use Area2D and mouse enter / exit signals in a Layer in ParallaxBackground and it also won't propagate mouse events correctly

This is still an issue. I had to use the workaround in https://github.com/godotengine/godot/issues/17326#issuecomment-431186323

Was this page helpful?
0 / 5 - 0 ratings