-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
Split PointerId into distinct id and PointerKind fields #17808
base: main
Are you sure you want to change the base?
Split PointerId into distinct id and PointerKind fields #17808
Conversation
id: 0, | ||
kind: PointerKind::Mouse, | ||
}; | ||
|
||
/// Returns true if the pointer is a touch input. | ||
pub fn is_touch(&self) -> bool { |
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 left these utility methods alone to ease migration, but I'm not convinced they're particularly valuable now.
pointer_id: PointerId::Mouse, | ||
pointer_id: PointerId { | ||
id: 0, | ||
kind: PointerKind::Virtual, |
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.
No more pretending to be a mouse!
/// controlled cursor. | ||
#[reflect(ignore)] | ||
Custom(Uuid), | ||
pub struct PointerId { |
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.
Given that PointerId is now a common "thing" maybe it should just be PointerId(u64)
and PointerKind
would just be stored adjacent to it in places where that is relevant (ex: as a separate Component)? To distinguish between two pointers, don't we only need to compare / hash the ID, not the kind?
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.
If it is not a common thing, then I think we should move back to a typed-wrapper to protect against comparing "unlike" ids across types.
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.
Right now (and before this PR), the IDs are only meaningfully used by touches. In theory you could encode information for Virtual / Custom types in the u64 / UUID, but I'm not sure what you would use that for.
In either case, in order for two PointerId to match, both the kind and the number associated with it must match. As a result, I don't think we should split these up, but I'm fine to go back to an enum design here. Which do you prefer?
- The current design, with split Id + kind.
enum PointerId
, onlyTouch
gets au64
.enum PointerId
, each kind has au64
.
I think I prefer solution 2, but went with solution 1 to ease migration.
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 also prefer solution (2). I think thats the move.
/// A pointer that is controlled by a mouse. | ||
/// | ||
/// Not a rodent; the device that you move around on a desk. | ||
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 think that PointerKind
is meant to describe the behaviour of the pointer, not the actual input device, but it seems a bit unclear. It would be nice to be able to support things like a "mouse" pointer that's controlled by a joystick or a mouse controlled first person pov with diegetic touch screen UI.
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.
Yeah, the intent is that things like UI libraries will match on this variant, and behave accordingly.
I don't currently have time for review, but I'd like us to consider that winit is shipping a pointer abstraction in it's next major release that does away with the distinction between mouse and touch entirely. |
We could just do a single u64 then 🤔 I'd prefer to reduce controversy and get this merged though; there's relatively important work (like removing |
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash, Reflect)] | ||
#[reflect(Default, Debug, Hash, PartialEq)] | ||
pub enum PointerKind { | ||
/// A pointer that is controlled by 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.
/// A pointer that is controlled by a mouse. | |
/// A pointer that behaves like a traditional mouse cursor. |
/// | ||
/// Not a rodent; the device that you move around on a desk. | ||
Mouse, | ||
/// A pointer that is controlled by a touch input. |
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 pointer that is controlled by a touch input. | |
/// A pointer that behaves like it is controlled by touch. |
Like an obvious thing I think we'd want to support here is touch input emulation with the mouse?
/// A stable identifier for a specific pointer. | ||
/// | ||
/// This is typically provided by winit, | ||
/// and is unique for each touch input or 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.
This feels misleading. The id here corresponds to a specific touch on the device and it's only guaranteed to be unique for the duration of that touch I think.
Maybe we shouldn't have the id here at all? The pointer entity which is spawned when the touch starts and despawned after it ends can be used to identify the touch within bevy. Then we just need to add a winit touch id -> pointer entity map somewhere that we can look up when we dispatch touch events. edit: Implemented in PR #17847 |
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 code looks correct to me, but given the comments of Cart in this PR and Aevyrie in ickshonpe's pr, I don't feel I have the requisite domain knowledge to properly weigh in on this.
Objective
As discussed in #17399, sending fake picking events (as you might want to do for clicking a focused element) is frustrating.
After discussing this with @aevyrie (notes here), part of the problem here is that our
PointerId
type is questionably designed. There are several small problems with it:Custom
variant has unclear semantics. When mocking inputs for tests, you almost always want to pretend to be a real mouse or touch (often at a level above this, sending raw input events). But when sending picking events for "click on the focused element", it's not clear what whether you should pretend to be a mouse, a custom input, or even a touch.Solution
PointerKind::Virtual
variant with clear semantics for this sort of software-driven pointer that doesn't correspond to real hardware.Future work
It would be nice to support multiple mice at some point in the future (I've had creative coding users asking me for this). Unfortunately, while this PR ensures that bevy_picking could easily accommodate it, winit still assumes a single mouse (and keyboard).
Unsurprisingly, patching winit is outside of the scope of this PR.
Testing
Existing tests pass. The picking examples seem to work fine, although I haven't tested them with touch inputs.
Migration Guide
PointerId
has been refactored for consistency. Check thekind
field to see thePointerKind
of the pointer, and read theid
field to recover the unique identifier.To construct a
PointerId::Mouse
, use thePointerId::MOUSE
constant. If you were usingPointerId::Custom
, either usePointerKind::Mouse
(if you were mocking inputs for tests) or usePointerKind::Virtual
if you were emulating a gamepad-controlled pointer or mocking pointer events to interact with various objects.