godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Add a way to get source device type from `InputEventAction` #3836

Open cgbeutler opened 2 years ago

cgbeutler commented 2 years ago

Describe the project you are working on

Platformer game. I have a few spots where I want to filter the input actions based on the device.

Describe the problem or limitation you are having in your project

InputEventAction has a Device property for getting the device id that spawned it, but that device id is not unique. There is no way to tell if DeviceId 0 is a joypad, keyboard, mouse, etc.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Add a property for getting the type of device that spawned the action event. Then with that and the id, you have a unique key!

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

Maybe add an enum for the different device types that the device id has overlap on. Something like:

enum DeviceType { Unknown = 0, Keyboard = 1, Mouse = 2, Gesture = 4, Screen = 8, Joypad = 16, Midi = 32 }

Then add a new property to InputEventAction that can return that enum type.

if actEvent.DeviceType == DeviceType.Joypad and actEvent.Device == curr:
  ...

If this enhancement will not be used often, can it be worked around with a few lines of script?

It could default to unknown if the user creates an event manually but does not set the device type. (Thus ignoring it would be fine, if they don't need it.)

Is there a reason why this should be core and not an add-on in the asset library?

Unless I have missed something, there is currently no way to truly map an InputEventAction back to the source device. That seems like a core oversight to me...?

KoBeWi commented 2 years ago

Why do you need to know the device though?

cgbeutler commented 2 years ago

If you are looking to provide workarounds or alternatives, I have already implemented those and don't need help there.

I mostly request this feature because it would really simplify a lot of action-based work. Other InputEvents have a way to figure out the exact device because they are unique types based on those devices. This info is lost as an event is sliced down to an action event. It seems like an oversight that InputEventAction is the only one that can't determine an exact device of origin. I could see maybe allowing InputEventAction to just be given an 'internal event' type field that can hold the upstream event that was turned into the action event. Then I could at least get that event and do a lookup that way.

In case you weren't asking as a way to help, but actually couldn't see why this would be nice to have, here are a few examples of where it would help me: I would like to define a reduced/minimal set of actions marked with "any joypad" so that an unbounded number of players could join. Inputs could then be filtered on controller type/number. Currently, you would have to use a more roundabout workaround using action lookups on other events or looking up actions in a non-event way. I also have some "big brother/little brother" systems in place. This proposal would make is super easily filter inputs on the start menu, allowing the big bro device to control it, but nothing else. The reduced set action binding would also allow something like watching for the "ui_accept" event from any device, then lookup who hit it, marking that player as 'ready'.

And, again, I get that there are workarounds, I just feel like this is a glaring whole in the Action system that makes it a lot less useful and forces you to other forms of input handling.

KoBeWi commented 2 years ago

If you are looking to provide workarounds or alternatives, I have already implemented those and don't need help there.

No, you just said that the feature is lacking without providing any use-case.

The most common way to support inputs for many players is prefixing your actions with e.g. p1_, p2_ etc. and for each set of actions use a different device id. The worst part is setup, after that it's not different than manually checking device - just use a different action name based on player.

3555 is probably related.

laurentsenta commented 1 week ago

Found this issue looking for the same feature,

My use case:

Since input.device is 0 for all my inputs, I believe my only option here is to write a huge if type of input is ... then ... elif type is ....

That's a workaround, but it breaks a bunch of expectations: