-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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
Fix action state when multiple events are assigned #80859
Fix action state when multiple events are assigned #80859
Conversation
e84cf58
to
c9773c6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can test with a keyboard, with 2 keys assigned to the same action (e.g. the default |
Seems so, although it's weird that it says that it worked in Godot 3 🤔 |
c9773c6
to
0d1aa91
Compare
Ok I pushed some changes to also fix action strength. I can't exactly reproduce the original issue (i.e. "controls randomly not working"), so it needs to be tested by affected users. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't replicate #45628, so it is difficult for me to verify, if the new changes fix that issue.
action.strength = p_event->get_action_strength(E.key); | ||
action.raw_strength = p_event->get_action_raw_strength(E.key); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This implementation changes the action.strength on every event, which might lead to alternating values, if two axis inputs are mapped to the same action and both axis are moved.
The comment #45628 (comment) suggests to use as strength the maximum strength of all related actions. Perhaps that would be a better solution?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But then what happens on release? It should assign max strength of still pressed actions, but they are not tracked. This means that if you use analog and then press a key, your analog strength will be ignored until it's released.
Maybe it's fine, idk.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should assign max strength of still pressed actions, but they are not tracked
Perhaps we could track it with the following, but I haven thought it through yet.
diff --git a/core/input/input_map.h b/core/input/input_map.h
index b4d5beacb3..b59e898730 100644
--- a/core/input/input_map.h
+++ b/core/input/input_map.h
@@ -48,10 +48,17 @@ public:
*/
static int ALL_DEVICES;
+ struct EventWithStrength {
+ Ref<InputEvent> event;
+ int pressed = 0;
+ float strength = 0.0f;
+ float raw_strength = 0.0f;
+ };
+
struct Action {
int id;
float deadzone;
- List<Ref<InputEvent>> inputs;
+ List<EventWithStrength> inputs;
};
private:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be addressed later if someone opens an issue. Let's see if the current behavior is ok for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good to me.
0d1aa91
to
f1d00ab
Compare
Stumbled upon this PR while investigating some related behaviour, so I tested this under Linux: When idle, the (my) DS4's analogue sticks often send out a stream of events with very low values (|n| < 0.1), alternating between two ±0.01 values (eg. 0.06, 0.07 in quick succession). So if a stick axis is mapped to an action, and that action is triggered through a different input than the stick, the action will tend to be "released" after a short amount of time. I also noticed that, with this PR, if the action is triggered via the stick, it will not always release immediately when the stick is released. The associated input events will be fired, but Also, unrelated to stick axes (I disconnected the DS4 just to be sure!), it appears that the "inputs held" counter doesn't reset to zero when the window loses focus. If I hold down two keys to trigger an action, and move focus to another window, FWIW, this was my test project: is-action-pressed.zip |
Have you tried to set the deadzone to
That issue is tracked in #36223. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good
To me this was always the right approach to solve the original issue btw. |
The deadzone specified in the input map is the default
I'm using Linux, but that issue appears to be specific to MacOS? 😕 It seems to be that with this patch the "held keys" is reduced by one on each focus loss, so if an action does get "stuck" in this way, one can release it by repeatedly focus-defocusing the window. |
f1d00ab
to
ad1abca
Compare
Fixed. |
Thanks! I actually merged this by mistake xD |
Haa ok, I understand now. So the deadzone doesn't apply if the button is not pressed by the user ? (like these random events) ? I don't really see why we don't just apply this deadzone to any events, it should fix the original issue of really small and random events, no ? |
The deadzone is always used. It determines whether action is pressed or not. |
Fixes #45628
This PR simply changes
Action.pressed
(internal struct) from bool to int and increments it when action is pressed and decrements when it's released.Input.is_action_pressed()
and related actions return true when at least one even is pressed.There is some weirdness when releasing actions with modifier keys. They can be released without being pressed. I added a small workaround, but the changes need some testing in general.