-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Added PressedButtons
to PickingInteraction::Pressed
.
#16004
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
base: main
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.
I like this. It makes PickingInteraction
much more useful. The use of bitflag packing to reduce memory bloat is clever too.
This will be useful as part of #15597, and I'd like to get this merged first. |
Many computer mice have a "Back" and a "Forward" button, but I don't know if those affect focus. |
/// Middle mouse button is pressed. | ||
const MIDDLE = 4; | ||
/// Touch input is pressed. | ||
const TOUCH = 8; |
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 sure this is correct. Touch inputs are probably akin to a primary press, and some touch devices, like pens, can have a primary secondary, tertiary press, just like a mouse.
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've had something like that before: my Note 9 has a pen and it supports hovering over something with the pen in the air and clicking a side-button to perform a secondary action.
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.
A stylus is not a touch pointer. Winit does not currently support stylus input, so neither do we.
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 definitely works, I've tested it. It's treated like a touch input. This was on a MS surface with a surface pen.
Regardless, if you are matching on whether a button was pressed, why would you not want it to be considered pressed if it was touched by a different pointing device?
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 why I specifically used the wording "primary/secondary". A primary press can come from many types of devices.
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.
The PR just maps the input from picking in a form that makes the most sense to me. Definitely would like to see more detailed information and more buttons, but that has to come from picking first.
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.
Renamed to left
and right
.
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.
Tying an interaction struct to hardware is asking for people to just default to the mouse, and suddenly a bunch of software doesn't work with other pointing devices for no good reason.
I would take a look at the JS pointer event APIs - they were designed to be hardware agnostic for this reason: https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events#determining_button_states
I would strongly prefer we follow this model, and make the easy path one that is device agnostic. E.g. under the hood, this struct might be a huge bitflag that encodes which device buttons are down, but the easiest-to-access methods are things like is_primary_pressed
, which return true if the primary button of any pointing device is down.
I'd also like to ask whether this structure should even exist anymore. It was originally added to match Interaction
in bevy_ui. However, with observers, we can do the same thing with less memory and cpu, because we don't need to update the state of every interactive entity even if no one is interested in reading it. That might mean refactoring the pointer events a bit to coalesce button
information.
Yeah, this is increasingly my opinion. It's nice for the "change widget style based on interaction", but that's the only use case where it's nicer than observers. |
Which I am more than happy to do if we get specs for the events we need. Enter/Leave is already on the radar. |
We definitely have a need to coalesce multiple events to determine state. You can't, for example, use I think this PR would be okay to merge with some modifications to make it match the pointer API I linked. It currently mixes the concept of abstract pointer buttons and device button.
|
} else { | ||
match id { | ||
PointerId::Mouse => PickingInteraction::Pressed((*pointer_press).into()), | ||
PointerId::Touch(_) => PickingInteraction::Pressed(PressedButtons::TOUCH), |
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.
See here for the mapping from Touch
. I think that this is the right approach for the current PR.
Do you think it is fine to just reserve
According to this spec the current implementation is a upgrade on touch input since usually we treat touch as left click, but with this implementation you can potentially treat them differently. |
Objective
Fixes #15983.
PickingInteraction
is preferable to events in some use cases for code organization. This PR adds the keys pressed toPickingInteraction::Pressed
, allowing the user to ignore certain keys like the RMB in such use cases.Solution
PressedButtons
toPickingInteraction::Pressed
.Testing
PickingInteraction
s.PickingInteraction
.Migration Guide
PickingInteraction::Pressed
now has a field, code matching against it should usematches!(interaction, PickingInteraction::Pressed(..))
instead.