Signals for Unhandled Input

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

I’m adding some hybrid Drag/Drop/Select functionality. I want to reuse this in a few places, so I’ve tried to wrap it up into a separate class, a DragDropHandler, which I can then include through composition on different nodes needed. This is a Godot Object, not a Node in it’s own right (making it a Node feels odd).

The handler listens for input_event signals on the given object, and will then move the object around, handle selection, deselection etc. This is all encapsulated nicely.

When you drag too fast, the cursor will leave the object being dragged, and input events will no longer be received. If this code was wrapped inside a node I could use the _unhandled_input(…) callback and accommodate those inputs, but as it’s just a class listening to signals on the objects being dragged, I can’t do that.

I’m a bit new to Godot, so I’d welcome any suggestions. So far my ideas…

  1. My ideal method would be a signal that can be listened to for unhandled input (I can’t find one if there is).
  2. I can inject another Area2D (+ collision objects etc) into the viewport whilst a drag is in progress to intercept events until the mouse is released, but feels a bit hacky to me.
  3. I could impose the requirement that all Nodes using the DragDropHandler have some code to override _unhandled_input(…) and pass the event on. That feels super ugly though - the whole point of having the handler is to keep the Drag/Drop code out of the Nodes.

Is there a nice/better way of doing this?

Hmmm… I didn’t do any drag & drop handling yet in godot.
This is Godot 3.x, right?

_gui_input(event) in a Control will catch only the messages that have coordinates in the control.
(The event will also have control-local position coordinates)
This is what you are probably using at the moment.

_input(event) in a control should get all messages (i.e. mouse and touch).
Event positions will be global here but can be made local-relative with make_input_local(event) if required. (So it is easier to check if the event occured inside the controls rect)

You can watch if a MouseButton pressed=true event occurs in _gui_input().
Then set a boolean in the nodes script and watch _input() for mouse coords until _input receives MouseButton pressed=false event. (= drop).

wombatstampede | 2019-03-13 11:22

Yes, It’s Godot 3 - I have updated the tags thanks.

I’m trying to not override the _input etc methods, as this is class is a mixin rather than a node itself. If I have to start putting a large amount of plumbing in every Node that I want to have this functionality it will get quite ugly.

AndySavage | 2019-03-13 16:43

I think I’m just going to suck it up and make this as a Node instead, then you can add Drag/Drop functionality by adding this node as a child of an existing. I guess that’s similar to how you would add an Area2D for input signals anyway. Maybe this is the “Godot way”.

AndySavage | 2019-03-13 18:50