Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

event.actions for input actions matching in _Input() #497

Closed
TrickMe opened this issue Feb 20, 2020 · 8 comments
Closed

event.actions for input actions matching in _Input() #497

TrickMe opened this issue Feb 20, 2020 · 8 comments

Comments

@TrickMe
Copy link

TrickMe commented Feb 20, 2020

Describe the project you are working on:
Space grand strategy / X4 game

Describe the problem or limitation you are having in your project:
I have to use multiple 'if event.is_action("action_name")' statements instead of matching the event to actions in _unhandled_input(event).

Describe the feature / enhancement and how it helps to overcome the problem or limitation:
Using event.action is safer and more configurable than using event.scancode.
Matching an action is more convenient, easier to read and faster than using multiple if- or elif- statements.
Mostly it's about speed and low latency.

Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams:

match event.get_action():   or
match event.action:
    "MouseLeft":
        do_something
    "MouseRight":
        do_something
    "MouseMiddle":
        do_something

instead of:

if event.is_action("MouseLeft"):
    do_something
elif event.is_action("MouseRight"):
    do_something
elif event.is_action("MouseMiddle"):
    do_something

or:

match event.scancode:
    KEY_ESCAPE:
        do_something

If this enhancement will not be used often, can it be worked around with a few lines of script?:
Yes, with a lot of if- and elif- statements, one per assigned action.
I'm certain this feature could be used by pretty much any application that uses input.

Is there a reason why this should be core and not an add-on in the asset library?:
Input handling is pretty much a core task.

@groud
Copy link
Member

groud commented Feb 20, 2020

This could not work, a single event can correspond to several actions.
So the get_action() method you have here would become get_actions() and return a list, which would make things more complex than what they are today.

@TrickMe
Copy link
Author

TrickMe commented Feb 20, 2020

@groud good point
I assumed an event would be assigned to one action only.

Instead of the method
String get_action()
or property action:String
let's assume the method
Array get_actions()
or property actions:Array:

for action in event.get_actions():    or
for action in event.actions:
    match action:
        "MouseLeft":
            do_something
        "MouseRight":
            do_something
        "MouseMiddle":
            do_something

could be used.

In certainty of only one action being assigned to the event,

match event.get_actions()[0]:    or
match event.actions[0]:
    "MouseLeft":
        do_something
    "MouseRight":
        do_something
    "MouseMiddle":
        do_something

could be used to simplify and speed up matching.

I think it's not that complex and it would speed up input-action handling, especially with a growing number of actions, that an event could be assigned to.

@Xrayez
Copy link
Contributor

Xrayez commented Feb 22, 2020

There seems to be an existing proposal which could help what you're trying to achieve: godotengine/godot#15681.

@TrickMe
Copy link
Author

TrickMe commented Feb 22, 2020

@Xrayez there is a slight difference:
Input.is_action_pressed("action") and event.is_action_pressed("action") are very different in functionality.
Input.is_action_pressed("action") checks if a key is held down by querying the action that key is assigned to.
event.is_action("action") queries the action assigned to the input event.

godotengine/godot#15681 refers to extending Input.is_action_pressed("action") querying, if a specific key (action) is held down to Input.get_actions_pressed() querying ALL the keys (actions) currently being held down.

I want to propose to pass an array of assigned actions by event itself, instead of querying if event of _Input(event) is assigned to a specific action by using `event.is_action("action").
If the actions are passed by event, no querying would have to be done and the actions could be matched easily.

event.get_actions()
event.actions
do not have to pass the state pressed or released, which can be checked by using event.is_pressed() or event.pressed, which is already passed by event.

@TrickMe TrickMe changed the title event.get_action() for input action matching in _Input() event.actions for input actions matching in _Input() Feb 22, 2020
@dalexeev
Copy link
Member

This could not work, a single event can correspond to several actions.

I have a suggestion on how to fix this. But it breaks a little backward compatibility.

There is InputEventAction class with action property. But at the moment, events of this class are not automatically generated (however, they can be sent manually using the Input.parse_input_event() method).

If we make the InputInventActions automatically generated after the corresponding InputEvent*, the processing code will look something like this:

func _input(event):
    if not event is InputEventAction: return
    match e.action:
        "ui_left": ...
        "ui_right": ...
        "ui_up": ...
        "ui_down": ...

However, the old code using InputEvent.is_action() may not work correctly, because will handle two events instead of one.

@groud
Copy link
Member

groud commented Feb 26, 2020

Yeah, I had this idea before, but apparently this was apparently not done this way for performance reasons. Each event has to traverse the whole tree, so duplicating events wasn't really an option apparently. I am personally still unsure if this would be a real problem though.

@dalexeev
Copy link
Member

dalexeev commented Feb 26, 2020

I thought about it. In general, it is surprising that in Godot, every event is an object. But I did not think that this is a big problem, since now a high-level abstract interface is used for the input system.

In this case, is it possible to use a low-level interface? For example, implement the virtual method Node._input_action(action: String, pressed: bool).

@Calinou
Copy link
Member

Calinou commented Dec 25, 2021

Closing due to lack of support (see the lack of reactions on OP and lack of recent comments here). See also #1853.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants