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
Better shortcut key support #1646
base: develop
Are you sure you want to change the base?
Conversation
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.
Added questions for things that weren't clear when I look through it them. But I believe I need a walkthrough from you @andrew-oc to understand better the work involved.
I also noticed some formatting inconsistencies for you to look at. Don't know if it's the GitHub "diff" viewer.
Packages/com.unity.inputsystem/InputSystem/Actions/InputAction.cs
Outdated
Show resolved
Hide resolved
Packages/com.unity.inputsystem/InputSystem/Actions/InputAction.cs
Outdated
Show resolved
Hide resolved
Packages/com.unity.inputsystem/InputSystem/Actions/InputAction.cs
Outdated
Show resolved
Hide resolved
Packages/com.unity.inputsystem/InputSystem/Actions/InputActionState.cs
Outdated
Show resolved
Hide resolved
Packages/com.unity.inputsystem/InputSystem/Actions/InputActionState.cs
Outdated
Show resolved
Hide resolved
Packages/com.unity.inputsystem/Documentation~/ActionBindings.md
Outdated
Show resolved
Hide resolved
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.
Overall, the work looks great and gives more control to developers. Great work 👍
Regarding the PR, I would like to suggest that we have more granularity in the commits OR smaller PRs to have a better understanding of the changes added. I
It was a bit hard for me to follow everything added in just one commit, and some parts are still clueless to me. But you can take this with "a grain of salt" as I'm still very new to the codebase.
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.
There are a couple of suggested changes and I'd like to discuss with design/product before landing on develop as the preference would be to expand further to see what could be done to handle the common case [CTRL/SHIFT/ALT]+KEY overriding KEY (without impacting WASD in two places).
var keyboard = InputSystem.AddDevice<Keyboard>(); | ||
|
||
var map1 = new InputActionMap("map1"); |
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.
Why are we removeing this WASD test case that we've seen from forums (ie the UI / game use case)
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 isn't really relevant anymore because the composites in that test don't by default handle input events, so they never get consumed. Those paths are tested by other tests though.
var map = new InputActionMap(); | ||
|
||
// action with bindings to Ctrl+Shift+C and C should appear twice in the 'C' group | ||
var action0 = map.AddAction("action1", binding: "<Keyboard>/c"); |
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.
action0 variable and action 1 name is a bit confusing for me to read can we be consistent. E.g rename variable to match strings
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.
Good call
* Added several APIs to allow application logic to control event handling/consumption. | ||
* CallbackContext.eventHandled can be used to check if a higher priority binding has already handled the current event | ||
* CallbackContext.HandleEvent() allows any 'performed' callback to set an input event as handled | ||
* InputAction.wasPerformedThisFrame(bool checkConflictingActions) allows polling code to determine if a higher priority binding has performed |
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'm not a fan of the bool here. I'd like to see that changing to an enum
InputAction.wasPerformedThisFrame(true) isn't very clear what that does
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.
Done. Introduced InputAction.EventHandledBehaviour enum.
@@ -2,6 +2,10 @@ | |||
|
|||
The following is a list of known limitations that the Input System currently has. | |||
|
|||
## Actions | |||
|
|||
* Input event consumption i.e. the ability to prevent a binding to "A" from triggering when a binding to "SHIFT+A" has already triggered, does not reliably work across multiple Input Action Assets, or multiple `InputActionMap` instances created through code. This is due to the way the runtime state for control grouping and priority is calculated in isolation for each Input Action Asset or standalone `InputActionMap`. |
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.
Is the limitation specific to multiple action maps created in code (i.e. multiple maps in an asset would work)
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.
Yes. Multiple action maps in the same input action asset work as intended. This also extends to singleton input actions created in code, as internally they get their own InputActionMap instances.
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.
Multiples maps in an asset would work. The limitation is only for maps that don't belong to an asset.
public unsafe bool WasPerformedThisFrame() | ||
/// <seealso cref="InputSettings.shortcutKeysConsumeInput"/> | ||
/// <seealso cref="InputBindingComposite.handleInputEvents"/> | ||
public unsafe bool WasPerformedThisFrame(bool checkConflictingActions) |
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.
As mentioned earlier I'd prefer this to be an enum for the parameter to make it clearer in usage
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.
Done
} | ||
controlGroupingAndComplexity[i * 2 + 1] = (ushort)complexity; | ||
controlGroupingAndComplexity[i].complexity = (ushort)complexity; |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
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.
Me too!
|
||
++currentGroup; | ||
} | ||
|
||
// add the action that the current binding belongs to to the relevant group | ||
if (controlGroupingAndComplexity[i].group >= m_ActionGroups.Length) |
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.
Wondering if we can move the resize outside the for loop so we only resize once
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.
Done. It means two loops over all the controls, but is probably still a win for larger input action assets, and the code is neater.
controlGroupingAndComplexity[i].group); | ||
#endif | ||
if (m_ActionGroups[controlGroupingAndComplexity[i].group].isCreated == false) | ||
grouping = new ActionGroup(5); |
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.
What's this 5 - perhaps we can make this a constant with a name
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.
Done
|
||
public ActionGroup(int capacity) | ||
{ | ||
actionIndicies = (int*)UnsafeUtility.Malloc(capacity, 8, Allocator.Persistent); |
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.
Could we add a named variable / static to make this 8 a bit clearer that its alignment (and why 8 chosen)
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.
Went one better. 8 was in fact an incorrect alignment!
public void AddActionIndex(int actionIndex) | ||
{ | ||
// return immediately if the actionIndex already exists in this group | ||
for (var i = 0; i < actionCount; i++) |
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.
Could call the contains function from below ?
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.
Done, thanks
This PR changes things so that WASD is never impacted anywhere. Event consumption is still off by default, so no inputs will go missing, while still allowing users to check for shortcut keys, but even if event consumption is turned on, Vector2 controls (and 1DAxis) don't handle events by default, so they still won't be impacted. The only time you'll see a WASD getting blocked (out of the box) is when event consumption is on and a modifier is used with W A S or D keys. |
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.
Thanks for the updates.
I still have a query about a resize call in a nested for loop and a bounds check.
@@ -4155,6 +4156,11 @@ public void Dispose() | |||
|
|||
actionIndicies = null; | |||
} | |||
|
|||
private static void* Allocate(int length) |
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 is a nice tidy up and using AlignOf
if (actionIndicies[i] == actionIndex) | ||
return; | ||
} | ||
if (Contains(actionIndex)) |
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.
Thanks
@@ -246,9 +249,10 @@ private void ComputeControlGroupingIfNecessary() | |||
|
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.
Wondering if this Resize could be moved out of the nested for loop, e.g. by. spinning round in advance to calculate max size.
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.
Also wondering if the actionCountInGroup index overflow the tempActionGroupIndexes above.
Perhaps splitting the loop could allow a sanity check (or perhaps a sanity check could be added without splitting the loop)
|
Description
Existing shortcut key support falls a bit a short of being useful:
Changes made
Notes
This PR does not change the default behaviour of code that has InputSettings.shortcutKeysConsumeInput turned off i.e. no bindings are blocked due to event consumption. However it is possible that due to the differences in how controls are sorted within the state monitor code that some bindings will now be triggered in a different order than before.
Future work
We can build two interesting features on top of this PR:
Checklist
Before review:
Changed
,Fixed
,Added
sections.([case %number%](https://issuetracker.unity3d.com/issues/...))
.Area_CanDoX
,Area_CanDoX_EvenIfYIsTheCase
,Area_WhenIDoX_AndYHappens_ThisIsTheResult
.