Picking event ordering (#14862)
# Objective
Correctly order picking events. Resolves
https://github.com/bevyengine/bevy/issues/5984.
## Solution
Event ordering [very long standing
problem](https://github.com/aevyrie/bevy_mod_picking/issues/294) with
mod picking, stemming from two related issues. The first problem was
that `Pointer<T>` events of different types couldn't be ordered, but we
have already gotten around that in the upstream by switching to
observers. Since observers run in the order they are triggered, this
isn't an issue.
The second problem was that the underlying event streams that picking
uses to create it's pointer interaction events *also* lacked ordering,
and the systems that generated the points couldn't interleave events.
This PR fixes that by unifying the event streams and integrating the
various interaction systems.
The concrete changes are as follows:
+ `bevy_winit::WinitEvent` has been moved to `bevy_window::WindowEvent`.
This provides a unified (and more importantly, *ordered*) input stream
for both `bevy_window` and `bevy_input` events.
+ Replaces `InputMove` and `InputPress` with `PointerInput`, a new
unified input event which drives picking and interaction. This event is
built to have drop-in forward compatibility with [winit's upcoming
pointer abstraction](https://github.com/rust-windowing/winit/pull/3876).
I have added code to emulate it using the current winit input
abstractions, but this entire thing will be much more robust when it
lands.
+ Rolls `pointer_events` `send_click_and_drag_events` and
`send_drag_over_events` into a single system, which operates directly on
`PointerEvent` and triggers observers as output.
The PR also improves docs and takes the opportunity to
refactor/streamline the pointer event dispatch logic.
## Status & Testing
This PR is now feature complete and documented. While it is
theoretically possible to add unit tests for the ordering, building the
picking mocking for that will take a little while.
Feedback on the chosen ordering of events is within-scope.
## Migration Guide
For users switching from `bevy_mod_picking` to `bevy_picking`:
+ Instead of adding an `On<T>` component, use `.observe(|trigger:
Trigger<T>|)`. You may now apply multiple handlers to the same entity
using this command.
+ Pointer interaction events now have semi-deterministic ordering which
(more or less) aligns with the order of the raw input stream. Consult
the docs on `bevy_picking::event::pointer_events` for current
information. You may need to adjust your event handling logic
accordingly.
+ `PointerCancel` has been replaced with `Pointer<Cancled>`, which now
has the semantics of an OS touch pointer cancel event.
+ `InputMove` and `InputPress` have been merged into `PointerInput`. The
use remains exactly the same.
+ Picking interaction events are now only accessible through observers,
and no `EventReader`. This functionality may be re-implemented later.
For users of `bevy_winit`:
+ The event `bevy_winit::WinitEvent` has moved to
`bevy_window::WindowEvent`. If this was the only thing you depended on
`bevy_winit` for, you should switch your dependency to `bevy_window`.
+ `bevy_window` now depends on `bevy_input`. The dependencies of
`bevy_input` are a subset of the existing dependencies for `bevy_window`
so this should be non-breaking.
2024-09-04 19:41:06 +00:00
|
|
|
//! This crate provides 'picking' capabilities for the Bevy game engine. That means, in simple terms, figuring out
|
|
|
|
//! how to connect up a user's clicks or taps to the entities they are trying to interact with.
|
|
|
|
//!
|
|
|
|
//! ## Overview
|
|
|
|
//!
|
|
|
|
//! In the simplest case, this plugin allows you to click on things in the scene. However, it also
|
|
|
|
//! allows you to express more complex interactions, like detecting when a touch input drags a UI
|
|
|
|
//! element and drops it on a 3d mesh rendered to a different camera. The crate also provides a set of
|
|
|
|
//! interaction callbacks, allowing you to receive input directly on entities like here:
|
|
|
|
//!
|
|
|
|
//! ```rust
|
|
|
|
//! # use bevy_ecs::prelude::*;
|
|
|
|
//! # use bevy_picking::prelude::*;
|
|
|
|
//! # #[derive(Component)]
|
|
|
|
//! # struct MyComponent;
|
|
|
|
//! # let mut world = World::new();
|
|
|
|
//! world.spawn(MyComponent)
|
2024-10-09 15:39:29 +00:00
|
|
|
//! .observe(|mut trigger: Trigger<Pointer<Click>>| {
|
Picking event ordering (#14862)
# Objective
Correctly order picking events. Resolves
https://github.com/bevyengine/bevy/issues/5984.
## Solution
Event ordering [very long standing
problem](https://github.com/aevyrie/bevy_mod_picking/issues/294) with
mod picking, stemming from two related issues. The first problem was
that `Pointer<T>` events of different types couldn't be ordered, but we
have already gotten around that in the upstream by switching to
observers. Since observers run in the order they are triggered, this
isn't an issue.
The second problem was that the underlying event streams that picking
uses to create it's pointer interaction events *also* lacked ordering,
and the systems that generated the points couldn't interleave events.
This PR fixes that by unifying the event streams and integrating the
various interaction systems.
The concrete changes are as follows:
+ `bevy_winit::WinitEvent` has been moved to `bevy_window::WindowEvent`.
This provides a unified (and more importantly, *ordered*) input stream
for both `bevy_window` and `bevy_input` events.
+ Replaces `InputMove` and `InputPress` with `PointerInput`, a new
unified input event which drives picking and interaction. This event is
built to have drop-in forward compatibility with [winit's upcoming
pointer abstraction](https://github.com/rust-windowing/winit/pull/3876).
I have added code to emulate it using the current winit input
abstractions, but this entire thing will be much more robust when it
lands.
+ Rolls `pointer_events` `send_click_and_drag_events` and
`send_drag_over_events` into a single system, which operates directly on
`PointerEvent` and triggers observers as output.
The PR also improves docs and takes the opportunity to
refactor/streamline the pointer event dispatch logic.
## Status & Testing
This PR is now feature complete and documented. While it is
theoretically possible to add unit tests for the ordering, building the
picking mocking for that will take a little while.
Feedback on the chosen ordering of events is within-scope.
## Migration Guide
For users switching from `bevy_mod_picking` to `bevy_picking`:
+ Instead of adding an `On<T>` component, use `.observe(|trigger:
Trigger<T>|)`. You may now apply multiple handlers to the same entity
using this command.
+ Pointer interaction events now have semi-deterministic ordering which
(more or less) aligns with the order of the raw input stream. Consult
the docs on `bevy_picking::event::pointer_events` for current
information. You may need to adjust your event handling logic
accordingly.
+ `PointerCancel` has been replaced with `Pointer<Cancled>`, which now
has the semantics of an OS touch pointer cancel event.
+ `InputMove` and `InputPress` have been merged into `PointerInput`. The
use remains exactly the same.
+ Picking interaction events are now only accessible through observers,
and no `EventReader`. This functionality may be re-implemented later.
For users of `bevy_winit`:
+ The event `bevy_winit::WinitEvent` has moved to
`bevy_window::WindowEvent`. If this was the only thing you depended on
`bevy_winit` for, you should switch your dependency to `bevy_window`.
+ `bevy_window` now depends on `bevy_input`. The dependencies of
`bevy_input` are a subset of the existing dependencies for `bevy_window`
so this should be non-breaking.
2024-09-04 19:41:06 +00:00
|
|
|
//! // Get the underlying event type
|
|
|
|
//! let click_event: &Pointer<Click> = trigger.event();
|
|
|
|
//! // Stop the event from bubbling up the entity hierarchjy
|
|
|
|
//! trigger.propagate(false);
|
|
|
|
//! });
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! At its core, this crate provides a robust abstraction for computing picking state regardless of
|
|
|
|
//! pointing devices, or what you are hit testing against. It is designed to work with any input, including
|
|
|
|
//! mouse, touch, pens, or virtual pointers controlled by gamepads.
|
|
|
|
//!
|
|
|
|
//! ## Expressive Events
|
|
|
|
//!
|
|
|
|
//! The events in this module (see [`events`]) cannot be listened to with normal `EventReader`s.
|
|
|
|
//! Instead, they are dispatched to *ovservers* attached to specific entities. When events are generated, they
|
|
|
|
//! bubble up the entity hierarchy starting from their target, until they reach the root or bubbling is haulted
|
|
|
|
//! with a call to [`Trigger::propagate`](bevy_ecs::observer::Trigger::propagate).
|
|
|
|
//! See [`Observer`] for details.
|
|
|
|
//!
|
|
|
|
//! This allows you to run callbacks when any children of an entity are interacted with, and leads
|
|
|
|
//! to succinct, expressive code:
|
|
|
|
//!
|
|
|
|
//! ```
|
|
|
|
//! # use bevy_ecs::prelude::*;
|
|
|
|
//! # use bevy_transform::prelude::*;
|
|
|
|
//! # use bevy_picking::prelude::*;
|
|
|
|
//! # #[derive(Event)]
|
|
|
|
//! # struct Greeting;
|
|
|
|
//! fn setup(mut commands: Commands) {
|
|
|
|
//! commands.spawn(Transform::default())
|
|
|
|
//! // Spawn your entity here, e.g. a Mesh.
|
|
|
|
//! // When dragged, mutate the `Transform` component on the dragged target entity:
|
|
|
|
//! .observe(|trigger: Trigger<Pointer<Drag>>, mut transforms: Query<&mut Transform>| {
|
|
|
|
//! let mut transform = transforms.get_mut(trigger.entity()).unwrap();
|
|
|
|
//! let drag = trigger.event();
|
|
|
|
//! transform.rotate_local_y(drag.delta.x / 50.0);
|
|
|
|
//! })
|
|
|
|
//! .observe(|trigger: Trigger<Pointer<Click>>, mut commands: Commands| {
|
|
|
|
//! println!("Entity {:?} goes BOOM!", trigger.entity());
|
|
|
|
//! commands.entity(trigger.entity()).despawn();
|
|
|
|
//! })
|
|
|
|
//! .observe(|trigger: Trigger<Pointer<Over>>, mut events: EventWriter<Greeting>| {
|
|
|
|
//! events.send(Greeting);
|
|
|
|
//! });
|
|
|
|
//! }
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! ## Modularity
|
|
|
|
//!
|
|
|
|
//! #### Mix and Match Hit Testing Backends
|
|
|
|
//!
|
|
|
|
//! The plugin attempts to handle all the hard parts for you, all you need to do is tell it when a
|
|
|
|
//! pointer is hitting any entities. Multiple backends can be used at the same time! [Use this
|
|
|
|
//! simple API to write your own backend](crate::backend) in about 100 lines of code.
|
|
|
|
//!
|
|
|
|
//! #### Input Agnostic
|
|
|
|
//!
|
|
|
|
//! Picking provides a generic Pointer abstracton, which is useful for reacting to many different
|
|
|
|
//! types of input devices. Pointers can be controlled with anything, whether its the included mouse
|
|
|
|
//! or touch inputs, or a custom gamepad input system you write yourself to control a virtual pointer.
|
|
|
|
//!
|
|
|
|
//! ## Robustness
|
|
|
|
//!
|
|
|
|
//! In addition to these features, this plugin also correctly handles multitouch, multiple windows,
|
|
|
|
//! multiple cameras, viewports, and render layers. Using this as a library allows you to write a
|
|
|
|
//! picking backend that can interoperate with any other picking backend.
|
|
|
|
//!
|
|
|
|
//! # Getting Started
|
|
|
|
//!
|
|
|
|
//! TODO: This section will need to be re-written once more backends are introduced.
|
|
|
|
//!
|
|
|
|
//! #### Next Steps
|
|
|
|
//!
|
|
|
|
//! To learn more, take a look at the examples in the
|
|
|
|
//! [examples](https://github.com/bevyengine/bevy/tree/main/examples/picking). You
|
|
|
|
//! can read the next section to understand how the plugin works.
|
|
|
|
//!
|
|
|
|
//! # The Picking Pipeline
|
|
|
|
//!
|
|
|
|
//! This plugin is designed to be extremely modular. To do so, it works in well-defined stages that
|
|
|
|
//! form a pipeline, where events are used to pass data between each stage.
|
|
|
|
//!
|
|
|
|
//! #### Pointers ([`pointer`](mod@pointer))
|
|
|
|
//!
|
|
|
|
//! The first stage of the pipeline is to gather inputs and update pointers. This stage is
|
|
|
|
//! ultimately responsible for generating [`PointerInput`](pointer::PointerInput) events. The provided
|
|
|
|
//! crate does this automatically for mouse, touch, and pen inputs. If you wanted to implement your own
|
|
|
|
//! pointer, controlled by some other input, you can do that here. The ordering of events within the
|
|
|
|
//! [`PointerInput`](pointer::PointerInput) stream is meaningful for events with the same
|
|
|
|
//! [`PointerId`](pointer::PointerId), but not between different pointers.
|
|
|
|
//!
|
|
|
|
//! Because pointer positions and presses are driven by these events, you can use them to mock
|
|
|
|
//! inputs for testing.
|
|
|
|
//!
|
|
|
|
//! After inputs are generated, they are then collected to update the current
|
|
|
|
//! [`PointerLocation`](pointer::PointerLocation) for each pointer.
|
|
|
|
//!
|
|
|
|
//! #### Backend ([`backend`])
|
|
|
|
//!
|
|
|
|
//! A picking backend only has one job: reading [`PointerLocation`](pointer::PointerLocation) components,
|
|
|
|
//! and producing [`PointerHits`](backend::PointerHits). You can find all documentation and types needed to
|
|
|
|
//! implement a backend at [`backend`].
|
|
|
|
//!
|
|
|
|
//! You will eventually need to choose which picking backend(s) you want to use. This crate does not
|
|
|
|
//! supply any backends, and expects you to select some from the other bevy crates or the third-party
|
|
|
|
//! ecosystem. You can find all the provided backends in the [`backend`] module.
|
|
|
|
//!
|
|
|
|
//! It's important to understand that you can mix and match backends! For example, you might have a
|
|
|
|
//! backend for your UI, and one for the 3d scene, with each being specialized for their purpose.
|
|
|
|
//! This crate provides some backends out of the box, but you can even write your own. It's been
|
|
|
|
//! made as easy as possible intentionally; the `bevy_mod_raycast` backend is 50 lines of code.
|
|
|
|
//!
|
|
|
|
//! #### Focus ([`focus`])
|
|
|
|
//!
|
|
|
|
//! The next step is to use the data from the backends, combine and sort the results, and determine
|
|
|
|
//! what each cursor is hovering over, producing a [`HoverMap`](`crate::focus::HoverMap`). Note that
|
|
|
|
//! just because a pointer is over an entity, it is not necessarily *hovering* that entity. Although
|
|
|
|
//! multiple backends may be reporting that a pointer is hitting an entity, the focus system needs
|
|
|
|
//! to determine which entities are actually being hovered by this pointer based on the pick depth,
|
2024-10-07 17:09:57 +00:00
|
|
|
//! order of the backend, and the optional [`PickingBehavior`] component of the entity. In other words,
|
|
|
|
//! if one entity is in front of another, usually only the topmost one will be hovered.
|
Picking event ordering (#14862)
# Objective
Correctly order picking events. Resolves
https://github.com/bevyengine/bevy/issues/5984.
## Solution
Event ordering [very long standing
problem](https://github.com/aevyrie/bevy_mod_picking/issues/294) with
mod picking, stemming from two related issues. The first problem was
that `Pointer<T>` events of different types couldn't be ordered, but we
have already gotten around that in the upstream by switching to
observers. Since observers run in the order they are triggered, this
isn't an issue.
The second problem was that the underlying event streams that picking
uses to create it's pointer interaction events *also* lacked ordering,
and the systems that generated the points couldn't interleave events.
This PR fixes that by unifying the event streams and integrating the
various interaction systems.
The concrete changes are as follows:
+ `bevy_winit::WinitEvent` has been moved to `bevy_window::WindowEvent`.
This provides a unified (and more importantly, *ordered*) input stream
for both `bevy_window` and `bevy_input` events.
+ Replaces `InputMove` and `InputPress` with `PointerInput`, a new
unified input event which drives picking and interaction. This event is
built to have drop-in forward compatibility with [winit's upcoming
pointer abstraction](https://github.com/rust-windowing/winit/pull/3876).
I have added code to emulate it using the current winit input
abstractions, but this entire thing will be much more robust when it
lands.
+ Rolls `pointer_events` `send_click_and_drag_events` and
`send_drag_over_events` into a single system, which operates directly on
`PointerEvent` and triggers observers as output.
The PR also improves docs and takes the opportunity to
refactor/streamline the pointer event dispatch logic.
## Status & Testing
This PR is now feature complete and documented. While it is
theoretically possible to add unit tests for the ordering, building the
picking mocking for that will take a little while.
Feedback on the chosen ordering of events is within-scope.
## Migration Guide
For users switching from `bevy_mod_picking` to `bevy_picking`:
+ Instead of adding an `On<T>` component, use `.observe(|trigger:
Trigger<T>|)`. You may now apply multiple handlers to the same entity
using this command.
+ Pointer interaction events now have semi-deterministic ordering which
(more or less) aligns with the order of the raw input stream. Consult
the docs on `bevy_picking::event::pointer_events` for current
information. You may need to adjust your event handling logic
accordingly.
+ `PointerCancel` has been replaced with `Pointer<Cancled>`, which now
has the semantics of an OS touch pointer cancel event.
+ `InputMove` and `InputPress` have been merged into `PointerInput`. The
use remains exactly the same.
+ Picking interaction events are now only accessible through observers,
and no `EventReader`. This functionality may be re-implemented later.
For users of `bevy_winit`:
+ The event `bevy_winit::WinitEvent` has moved to
`bevy_window::WindowEvent`. If this was the only thing you depended on
`bevy_winit` for, you should switch your dependency to `bevy_window`.
+ `bevy_window` now depends on `bevy_input`. The dependencies of
`bevy_input` are a subset of the existing dependencies for `bevy_window`
so this should be non-breaking.
2024-09-04 19:41:06 +00:00
|
|
|
//!
|
|
|
|
//! #### Events ([`events`])
|
|
|
|
//!
|
|
|
|
//! In the final step, the high-level pointer events are generated, such as events that trigger when
|
|
|
|
//! a pointer hovers or clicks an entity. These simple events are then used to generate more complex
|
|
|
|
//! events for dragging and dropping.
|
|
|
|
//!
|
2024-10-20 01:03:27 +00:00
|
|
|
//! Because it is completely agnostic to the earlier stages of the pipeline, you can easily
|
Picking event ordering (#14862)
# Objective
Correctly order picking events. Resolves
https://github.com/bevyengine/bevy/issues/5984.
## Solution
Event ordering [very long standing
problem](https://github.com/aevyrie/bevy_mod_picking/issues/294) with
mod picking, stemming from two related issues. The first problem was
that `Pointer<T>` events of different types couldn't be ordered, but we
have already gotten around that in the upstream by switching to
observers. Since observers run in the order they are triggered, this
isn't an issue.
The second problem was that the underlying event streams that picking
uses to create it's pointer interaction events *also* lacked ordering,
and the systems that generated the points couldn't interleave events.
This PR fixes that by unifying the event streams and integrating the
various interaction systems.
The concrete changes are as follows:
+ `bevy_winit::WinitEvent` has been moved to `bevy_window::WindowEvent`.
This provides a unified (and more importantly, *ordered*) input stream
for both `bevy_window` and `bevy_input` events.
+ Replaces `InputMove` and `InputPress` with `PointerInput`, a new
unified input event which drives picking and interaction. This event is
built to have drop-in forward compatibility with [winit's upcoming
pointer abstraction](https://github.com/rust-windowing/winit/pull/3876).
I have added code to emulate it using the current winit input
abstractions, but this entire thing will be much more robust when it
lands.
+ Rolls `pointer_events` `send_click_and_drag_events` and
`send_drag_over_events` into a single system, which operates directly on
`PointerEvent` and triggers observers as output.
The PR also improves docs and takes the opportunity to
refactor/streamline the pointer event dispatch logic.
## Status & Testing
This PR is now feature complete and documented. While it is
theoretically possible to add unit tests for the ordering, building the
picking mocking for that will take a little while.
Feedback on the chosen ordering of events is within-scope.
## Migration Guide
For users switching from `bevy_mod_picking` to `bevy_picking`:
+ Instead of adding an `On<T>` component, use `.observe(|trigger:
Trigger<T>|)`. You may now apply multiple handlers to the same entity
using this command.
+ Pointer interaction events now have semi-deterministic ordering which
(more or less) aligns with the order of the raw input stream. Consult
the docs on `bevy_picking::event::pointer_events` for current
information. You may need to adjust your event handling logic
accordingly.
+ `PointerCancel` has been replaced with `Pointer<Cancled>`, which now
has the semantics of an OS touch pointer cancel event.
+ `InputMove` and `InputPress` have been merged into `PointerInput`. The
use remains exactly the same.
+ Picking interaction events are now only accessible through observers,
and no `EventReader`. This functionality may be re-implemented later.
For users of `bevy_winit`:
+ The event `bevy_winit::WinitEvent` has moved to
`bevy_window::WindowEvent`. If this was the only thing you depended on
`bevy_winit` for, you should switch your dependency to `bevy_window`.
+ `bevy_window` now depends on `bevy_input`. The dependencies of
`bevy_input` are a subset of the existing dependencies for `bevy_window`
so this should be non-breaking.
2024-09-04 19:41:06 +00:00
|
|
|
//! extend the plugin with arbitrary backends and input methods, yet still use all the high level
|
|
|
|
//! features.
|
2024-06-15 11:59:57 +00:00
|
|
|
|
|
|
|
#![deny(missing_docs)]
|
|
|
|
|
2024-09-27 00:59:59 +00:00
|
|
|
extern crate alloc;
|
|
|
|
|
2024-06-15 11:59:57 +00:00
|
|
|
pub mod backend;
|
2024-08-09 23:16:37 +00:00
|
|
|
pub mod events;
|
|
|
|
pub mod focus;
|
|
|
|
pub mod input;
|
Add mesh picking backend and `MeshRayCast` system parameter (#15800)
# Objective
Closes #15545.
`bevy_picking` supports UI and sprite picking, but not mesh picking.
Being able to pick meshes would be extremely useful for various games,
tools, and our own examples, as well as scene editors and inspectors.
So, we need a mesh picking backend!
Luckily,
[`bevy_mod_picking`](https://github.com/aevyrie/bevy_mod_picking) (which
`bevy_picking` is based on) by @aevyrie already has a [backend for
it](https://github.com/aevyrie/bevy_mod_picking/blob/74f0c3c0fbc8048632ba46fd8f14e26aaea9c76c/backends/bevy_picking_raycast/src/lib.rs)
using [`bevy_mod_raycast`](https://github.com/aevyrie/bevy_mod_raycast).
As a side product of adding mesh picking, we also get support for
performing ray casts on meshes!
## Solution
Upstream a large chunk of the immediate-mode ray casting functionality
from `bevy_mod_raycast`, and add a mesh picking backend based on
`bevy_mod_picking`. Huge thanks to @aevyrie who did all the hard work on
these incredible crates!
All meshes are pickable by default. Picking can be disabled for
individual entities by adding `PickingBehavior::IGNORE`, like normal.
Or, if you want mesh picking to be entirely opt-in, you can set
`MeshPickingBackendSettings::require_markers` to `true` and add a
`RayCastPickable` component to the desired camera and target entities.
You can also use the new `MeshRayCast` system parameter to cast rays
into the world manually:
```rust
fn ray_cast_system(mut ray_cast: MeshRayCast, foo_query: Query<(), With<Foo>>) {
let ray = Ray3d::new(Vec3::ZERO, Dir3::X);
// Only ray cast against entities with the `Foo` component.
let filter = |entity| foo_query.contains(entity);
// Never early-exit. Note that you can change behavior per-entity.
let early_exit_test = |_entity| false;
// Ignore the visibility of entities. This allows ray casting hidden entities.
let visibility = RayCastVisibility::Any;
let settings = RayCastSettings::default()
.with_filter(&filter)
.with_early_exit_test(&early_exit_test)
.with_visibility(visibility);
// Cast the ray with the settings, returning a list of intersections.
let hits = ray_cast.cast_ray(ray, &settings);
}
```
This is largely a direct port, but I did make several changes to match
our APIs better, remove things we don't need or that I think are
unnecessary, and do some general improvements to code quality and
documentation.
### Changes Relative to `bevy_mod_raycast` and `bevy_mod_picking`
- Every `Raycast` and "raycast" has been renamed to `RayCast` and "ray
cast" (similar reasoning as the "Naming" section in #15724)
- `Raycast` system param has been renamed to `MeshRayCast` to avoid
naming conflicts and to be explicit that it is not for colliders
- `RaycastBackend` has been renamed to `MeshPickingBackend`
- `RayCastVisibility` variants are now `Any`, `Visible`, and
`VisibleInView` instead of `Ignore`, `MustBeVisible`, and
`MustBeVisibleAndInView`
- `NoBackfaceCulling` has been renamed to `RayCastBackfaces`, to avoid
implying that it affects the rendering of backfaces for meshes (it
doesn't)
- `SimplifiedMesh` and `RayCastBackfaces` live near other ray casting
API types, not in their own 10 LoC module
- All intersection logic and types are in the same `intersections`
module, not split across several modules
- Some intersection types have been renamed to be clearer and more
consistent
- `IntersectionData` -> `RayMeshHit`
- `RayHit` -> `RayTriangleHit`
- General documentation and code quality improvements
### Removed / Not Ported
- Removed unused ray helpers and types, like `PrimitiveIntersection`
- Removed getters on intersection types, and made their properties
public
- There is no `2d` feature, and `Raycast::mesh_query` and
`Raycast::mesh2d_query` have been merged into `MeshRayCast::mesh_query`,
which handles both 2D and 3D
- I assume this existed previously because `Mesh2dHandle` used to be in
`bevy_sprite`. Now both the 2D and 3D mesh are in `bevy_render`.
- There is no `debug` feature or ray debug rendering
- There is no deferred API (`RaycastSource`)
- There is no `CursorRayPlugin` (the picking backend handles this)
### Note for Reviewers
In case it's helpful, the [first
commit](https://github.com/bevyengine/bevy/commit/281638ef10ebd25f783bee2533509fdf756f7ab4)
here is essentially a one-to-one port. The rest of the commits are
primarily refactoring and cleaning things up in the ways listed earlier,
as well as changes to the module structure.
It may also be useful to compare the original [picking
backend](https://github.com/aevyrie/bevy_mod_picking/blob/74f0c3c0fbc8048632ba46fd8f14e26aaea9c76c/backends/bevy_picking_raycast/src/lib.rs)
and [`bevy_mod_raycast`](https://github.com/aevyrie/bevy_mod_raycast) to
this PR. Feel free to mention if there are any changes that I should
revert or something I should not include in this PR.
## Testing
I tested mesh picking and relevant components in some examples, for both
2D and 3D meshes, and added a new `mesh_picking` example. I also
~~stole~~ ported over the [ray-mesh intersection
benchmark](https://github.com/aevyrie/bevy_mod_raycast/blob/dbc5ef32fe48997a1a7eeec7434d9dd8b829e52e/benches/ray_mesh_intersection.rs)
from `bevy_mod_raycast`.
---
## Showcase
Below is a version of the `2d_shapes` example modified to demonstrate 2D
mesh picking. This is not included in this PR.
https://github.com/user-attachments/assets/7742528c-8630-4c00-bacd-81576ac432bf
And below is the new `mesh_picking` example:
https://github.com/user-attachments/assets/b65c7a5a-fa3a-4c2d-8bbd-e7a2c772986e
There is also a really cool new `mesh_ray_cast` example ported over from
`bevy_mod_raycast`:
https://github.com/user-attachments/assets/3c5eb6c0-bd94-4fb0-bec6-8a85668a06c9
---------
Co-authored-by: Aevyrie <aevyrie@gmail.com>
Co-authored-by: Trent <2771466+tbillington@users.noreply.github.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
2024-10-13 17:24:19 +00:00
|
|
|
#[cfg(feature = "bevy_mesh")]
|
|
|
|
pub mod mesh_picking;
|
2024-06-15 11:59:57 +00:00
|
|
|
pub mod pointer;
|
|
|
|
|
2024-10-25 20:11:51 +00:00
|
|
|
use bevy_app::{prelude::*, PluginGroupBuilder};
|
2024-06-15 11:59:57 +00:00
|
|
|
use bevy_ecs::prelude::*;
|
|
|
|
use bevy_reflect::prelude::*;
|
|
|
|
|
2024-09-08 17:10:57 +00:00
|
|
|
/// The picking prelude.
|
|
|
|
///
|
|
|
|
/// This includes the most common types in this crate, re-exported for your convenience.
|
2024-08-15 14:43:55 +00:00
|
|
|
pub mod prelude {
|
Add mesh picking backend and `MeshRayCast` system parameter (#15800)
# Objective
Closes #15545.
`bevy_picking` supports UI and sprite picking, but not mesh picking.
Being able to pick meshes would be extremely useful for various games,
tools, and our own examples, as well as scene editors and inspectors.
So, we need a mesh picking backend!
Luckily,
[`bevy_mod_picking`](https://github.com/aevyrie/bevy_mod_picking) (which
`bevy_picking` is based on) by @aevyrie already has a [backend for
it](https://github.com/aevyrie/bevy_mod_picking/blob/74f0c3c0fbc8048632ba46fd8f14e26aaea9c76c/backends/bevy_picking_raycast/src/lib.rs)
using [`bevy_mod_raycast`](https://github.com/aevyrie/bevy_mod_raycast).
As a side product of adding mesh picking, we also get support for
performing ray casts on meshes!
## Solution
Upstream a large chunk of the immediate-mode ray casting functionality
from `bevy_mod_raycast`, and add a mesh picking backend based on
`bevy_mod_picking`. Huge thanks to @aevyrie who did all the hard work on
these incredible crates!
All meshes are pickable by default. Picking can be disabled for
individual entities by adding `PickingBehavior::IGNORE`, like normal.
Or, if you want mesh picking to be entirely opt-in, you can set
`MeshPickingBackendSettings::require_markers` to `true` and add a
`RayCastPickable` component to the desired camera and target entities.
You can also use the new `MeshRayCast` system parameter to cast rays
into the world manually:
```rust
fn ray_cast_system(mut ray_cast: MeshRayCast, foo_query: Query<(), With<Foo>>) {
let ray = Ray3d::new(Vec3::ZERO, Dir3::X);
// Only ray cast against entities with the `Foo` component.
let filter = |entity| foo_query.contains(entity);
// Never early-exit. Note that you can change behavior per-entity.
let early_exit_test = |_entity| false;
// Ignore the visibility of entities. This allows ray casting hidden entities.
let visibility = RayCastVisibility::Any;
let settings = RayCastSettings::default()
.with_filter(&filter)
.with_early_exit_test(&early_exit_test)
.with_visibility(visibility);
// Cast the ray with the settings, returning a list of intersections.
let hits = ray_cast.cast_ray(ray, &settings);
}
```
This is largely a direct port, but I did make several changes to match
our APIs better, remove things we don't need or that I think are
unnecessary, and do some general improvements to code quality and
documentation.
### Changes Relative to `bevy_mod_raycast` and `bevy_mod_picking`
- Every `Raycast` and "raycast" has been renamed to `RayCast` and "ray
cast" (similar reasoning as the "Naming" section in #15724)
- `Raycast` system param has been renamed to `MeshRayCast` to avoid
naming conflicts and to be explicit that it is not for colliders
- `RaycastBackend` has been renamed to `MeshPickingBackend`
- `RayCastVisibility` variants are now `Any`, `Visible`, and
`VisibleInView` instead of `Ignore`, `MustBeVisible`, and
`MustBeVisibleAndInView`
- `NoBackfaceCulling` has been renamed to `RayCastBackfaces`, to avoid
implying that it affects the rendering of backfaces for meshes (it
doesn't)
- `SimplifiedMesh` and `RayCastBackfaces` live near other ray casting
API types, not in their own 10 LoC module
- All intersection logic and types are in the same `intersections`
module, not split across several modules
- Some intersection types have been renamed to be clearer and more
consistent
- `IntersectionData` -> `RayMeshHit`
- `RayHit` -> `RayTriangleHit`
- General documentation and code quality improvements
### Removed / Not Ported
- Removed unused ray helpers and types, like `PrimitiveIntersection`
- Removed getters on intersection types, and made their properties
public
- There is no `2d` feature, and `Raycast::mesh_query` and
`Raycast::mesh2d_query` have been merged into `MeshRayCast::mesh_query`,
which handles both 2D and 3D
- I assume this existed previously because `Mesh2dHandle` used to be in
`bevy_sprite`. Now both the 2D and 3D mesh are in `bevy_render`.
- There is no `debug` feature or ray debug rendering
- There is no deferred API (`RaycastSource`)
- There is no `CursorRayPlugin` (the picking backend handles this)
### Note for Reviewers
In case it's helpful, the [first
commit](https://github.com/bevyengine/bevy/commit/281638ef10ebd25f783bee2533509fdf756f7ab4)
here is essentially a one-to-one port. The rest of the commits are
primarily refactoring and cleaning things up in the ways listed earlier,
as well as changes to the module structure.
It may also be useful to compare the original [picking
backend](https://github.com/aevyrie/bevy_mod_picking/blob/74f0c3c0fbc8048632ba46fd8f14e26aaea9c76c/backends/bevy_picking_raycast/src/lib.rs)
and [`bevy_mod_raycast`](https://github.com/aevyrie/bevy_mod_raycast) to
this PR. Feel free to mention if there are any changes that I should
revert or something I should not include in this PR.
## Testing
I tested mesh picking and relevant components in some examples, for both
2D and 3D meshes, and added a new `mesh_picking` example. I also
~~stole~~ ported over the [ray-mesh intersection
benchmark](https://github.com/aevyrie/bevy_mod_raycast/blob/dbc5ef32fe48997a1a7eeec7434d9dd8b829e52e/benches/ray_mesh_intersection.rs)
from `bevy_mod_raycast`.
---
## Showcase
Below is a version of the `2d_shapes` example modified to demonstrate 2D
mesh picking. This is not included in this PR.
https://github.com/user-attachments/assets/7742528c-8630-4c00-bacd-81576ac432bf
And below is the new `mesh_picking` example:
https://github.com/user-attachments/assets/b65c7a5a-fa3a-4c2d-8bbd-e7a2c772986e
There is also a really cool new `mesh_ray_cast` example ported over from
`bevy_mod_raycast`:
https://github.com/user-attachments/assets/3c5eb6c0-bd94-4fb0-bec6-8a85668a06c9
---------
Co-authored-by: Aevyrie <aevyrie@gmail.com>
Co-authored-by: Trent <2771466+tbillington@users.noreply.github.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
2024-10-13 17:24:19 +00:00
|
|
|
#[cfg(feature = "bevy_mesh")]
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub use crate::mesh_picking::{
|
|
|
|
ray_cast::{MeshRayCast, RayCastBackfaces, RayCastSettings, RayCastVisibility},
|
2024-10-25 20:11:51 +00:00
|
|
|
MeshPickingPlugin, MeshPickingSettings, RayCastPickable,
|
Add mesh picking backend and `MeshRayCast` system parameter (#15800)
# Objective
Closes #15545.
`bevy_picking` supports UI and sprite picking, but not mesh picking.
Being able to pick meshes would be extremely useful for various games,
tools, and our own examples, as well as scene editors and inspectors.
So, we need a mesh picking backend!
Luckily,
[`bevy_mod_picking`](https://github.com/aevyrie/bevy_mod_picking) (which
`bevy_picking` is based on) by @aevyrie already has a [backend for
it](https://github.com/aevyrie/bevy_mod_picking/blob/74f0c3c0fbc8048632ba46fd8f14e26aaea9c76c/backends/bevy_picking_raycast/src/lib.rs)
using [`bevy_mod_raycast`](https://github.com/aevyrie/bevy_mod_raycast).
As a side product of adding mesh picking, we also get support for
performing ray casts on meshes!
## Solution
Upstream a large chunk of the immediate-mode ray casting functionality
from `bevy_mod_raycast`, and add a mesh picking backend based on
`bevy_mod_picking`. Huge thanks to @aevyrie who did all the hard work on
these incredible crates!
All meshes are pickable by default. Picking can be disabled for
individual entities by adding `PickingBehavior::IGNORE`, like normal.
Or, if you want mesh picking to be entirely opt-in, you can set
`MeshPickingBackendSettings::require_markers` to `true` and add a
`RayCastPickable` component to the desired camera and target entities.
You can also use the new `MeshRayCast` system parameter to cast rays
into the world manually:
```rust
fn ray_cast_system(mut ray_cast: MeshRayCast, foo_query: Query<(), With<Foo>>) {
let ray = Ray3d::new(Vec3::ZERO, Dir3::X);
// Only ray cast against entities with the `Foo` component.
let filter = |entity| foo_query.contains(entity);
// Never early-exit. Note that you can change behavior per-entity.
let early_exit_test = |_entity| false;
// Ignore the visibility of entities. This allows ray casting hidden entities.
let visibility = RayCastVisibility::Any;
let settings = RayCastSettings::default()
.with_filter(&filter)
.with_early_exit_test(&early_exit_test)
.with_visibility(visibility);
// Cast the ray with the settings, returning a list of intersections.
let hits = ray_cast.cast_ray(ray, &settings);
}
```
This is largely a direct port, but I did make several changes to match
our APIs better, remove things we don't need or that I think are
unnecessary, and do some general improvements to code quality and
documentation.
### Changes Relative to `bevy_mod_raycast` and `bevy_mod_picking`
- Every `Raycast` and "raycast" has been renamed to `RayCast` and "ray
cast" (similar reasoning as the "Naming" section in #15724)
- `Raycast` system param has been renamed to `MeshRayCast` to avoid
naming conflicts and to be explicit that it is not for colliders
- `RaycastBackend` has been renamed to `MeshPickingBackend`
- `RayCastVisibility` variants are now `Any`, `Visible`, and
`VisibleInView` instead of `Ignore`, `MustBeVisible`, and
`MustBeVisibleAndInView`
- `NoBackfaceCulling` has been renamed to `RayCastBackfaces`, to avoid
implying that it affects the rendering of backfaces for meshes (it
doesn't)
- `SimplifiedMesh` and `RayCastBackfaces` live near other ray casting
API types, not in their own 10 LoC module
- All intersection logic and types are in the same `intersections`
module, not split across several modules
- Some intersection types have been renamed to be clearer and more
consistent
- `IntersectionData` -> `RayMeshHit`
- `RayHit` -> `RayTriangleHit`
- General documentation and code quality improvements
### Removed / Not Ported
- Removed unused ray helpers and types, like `PrimitiveIntersection`
- Removed getters on intersection types, and made their properties
public
- There is no `2d` feature, and `Raycast::mesh_query` and
`Raycast::mesh2d_query` have been merged into `MeshRayCast::mesh_query`,
which handles both 2D and 3D
- I assume this existed previously because `Mesh2dHandle` used to be in
`bevy_sprite`. Now both the 2D and 3D mesh are in `bevy_render`.
- There is no `debug` feature or ray debug rendering
- There is no deferred API (`RaycastSource`)
- There is no `CursorRayPlugin` (the picking backend handles this)
### Note for Reviewers
In case it's helpful, the [first
commit](https://github.com/bevyengine/bevy/commit/281638ef10ebd25f783bee2533509fdf756f7ab4)
here is essentially a one-to-one port. The rest of the commits are
primarily refactoring and cleaning things up in the ways listed earlier,
as well as changes to the module structure.
It may also be useful to compare the original [picking
backend](https://github.com/aevyrie/bevy_mod_picking/blob/74f0c3c0fbc8048632ba46fd8f14e26aaea9c76c/backends/bevy_picking_raycast/src/lib.rs)
and [`bevy_mod_raycast`](https://github.com/aevyrie/bevy_mod_raycast) to
this PR. Feel free to mention if there are any changes that I should
revert or something I should not include in this PR.
## Testing
I tested mesh picking and relevant components in some examples, for both
2D and 3D meshes, and added a new `mesh_picking` example. I also
~~stole~~ ported over the [ray-mesh intersection
benchmark](https://github.com/aevyrie/bevy_mod_raycast/blob/dbc5ef32fe48997a1a7eeec7434d9dd8b829e52e/benches/ray_mesh_intersection.rs)
from `bevy_mod_raycast`.
---
## Showcase
Below is a version of the `2d_shapes` example modified to demonstrate 2D
mesh picking. This is not included in this PR.
https://github.com/user-attachments/assets/7742528c-8630-4c00-bacd-81576ac432bf
And below is the new `mesh_picking` example:
https://github.com/user-attachments/assets/b65c7a5a-fa3a-4c2d-8bbd-e7a2c772986e
There is also a really cool new `mesh_ray_cast` example ported over from
`bevy_mod_raycast`:
https://github.com/user-attachments/assets/3c5eb6c0-bd94-4fb0-bec6-8a85668a06c9
---------
Co-authored-by: Aevyrie <aevyrie@gmail.com>
Co-authored-by: Trent <2771466+tbillington@users.noreply.github.com>
Co-authored-by: François Mockers <mockersf@gmail.com>
2024-10-13 17:24:19 +00:00
|
|
|
};
|
2024-08-15 14:43:55 +00:00
|
|
|
#[doc(hidden)]
|
|
|
|
pub use crate::{
|
Picking event ordering (#14862)
# Objective
Correctly order picking events. Resolves
https://github.com/bevyengine/bevy/issues/5984.
## Solution
Event ordering [very long standing
problem](https://github.com/aevyrie/bevy_mod_picking/issues/294) with
mod picking, stemming from two related issues. The first problem was
that `Pointer<T>` events of different types couldn't be ordered, but we
have already gotten around that in the upstream by switching to
observers. Since observers run in the order they are triggered, this
isn't an issue.
The second problem was that the underlying event streams that picking
uses to create it's pointer interaction events *also* lacked ordering,
and the systems that generated the points couldn't interleave events.
This PR fixes that by unifying the event streams and integrating the
various interaction systems.
The concrete changes are as follows:
+ `bevy_winit::WinitEvent` has been moved to `bevy_window::WindowEvent`.
This provides a unified (and more importantly, *ordered*) input stream
for both `bevy_window` and `bevy_input` events.
+ Replaces `InputMove` and `InputPress` with `PointerInput`, a new
unified input event which drives picking and interaction. This event is
built to have drop-in forward compatibility with [winit's upcoming
pointer abstraction](https://github.com/rust-windowing/winit/pull/3876).
I have added code to emulate it using the current winit input
abstractions, but this entire thing will be much more robust when it
lands.
+ Rolls `pointer_events` `send_click_and_drag_events` and
`send_drag_over_events` into a single system, which operates directly on
`PointerEvent` and triggers observers as output.
The PR also improves docs and takes the opportunity to
refactor/streamline the pointer event dispatch logic.
## Status & Testing
This PR is now feature complete and documented. While it is
theoretically possible to add unit tests for the ordering, building the
picking mocking for that will take a little while.
Feedback on the chosen ordering of events is within-scope.
## Migration Guide
For users switching from `bevy_mod_picking` to `bevy_picking`:
+ Instead of adding an `On<T>` component, use `.observe(|trigger:
Trigger<T>|)`. You may now apply multiple handlers to the same entity
using this command.
+ Pointer interaction events now have semi-deterministic ordering which
(more or less) aligns with the order of the raw input stream. Consult
the docs on `bevy_picking::event::pointer_events` for current
information. You may need to adjust your event handling logic
accordingly.
+ `PointerCancel` has been replaced with `Pointer<Cancled>`, which now
has the semantics of an OS touch pointer cancel event.
+ `InputMove` and `InputPress` have been merged into `PointerInput`. The
use remains exactly the same.
+ Picking interaction events are now only accessible through observers,
and no `EventReader`. This functionality may be re-implemented later.
For users of `bevy_winit`:
+ The event `bevy_winit::WinitEvent` has moved to
`bevy_window::WindowEvent`. If this was the only thing you depended on
`bevy_winit` for, you should switch your dependency to `bevy_window`.
+ `bevy_window` now depends on `bevy_input`. The dependencies of
`bevy_input` are a subset of the existing dependencies for `bevy_window`
so this should be non-breaking.
2024-09-04 19:41:06 +00:00
|
|
|
events::*, input::PointerInputPlugin, pointer::PointerButton, DefaultPickingPlugins,
|
2024-10-07 17:09:57 +00:00
|
|
|
InteractionPlugin, PickingBehavior, PickingPlugin,
|
2024-08-15 14:43:55 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2024-06-15 11:59:57 +00:00
|
|
|
/// An optional component that overrides default picking behavior for an entity, allowing you to
|
|
|
|
/// make an entity non-hoverable, or allow items below it to be hovered. See the documentation on
|
|
|
|
/// the fields for more details.
|
|
|
|
#[derive(Component, Debug, Clone, Reflect, PartialEq, Eq)]
|
2024-09-15 16:17:39 +00:00
|
|
|
#[reflect(Component, Default, Debug, PartialEq)]
|
2024-10-07 17:09:57 +00:00
|
|
|
pub struct PickingBehavior {
|
2024-06-15 11:59:57 +00:00
|
|
|
/// Should this entity block entities below it from being picked?
|
|
|
|
///
|
|
|
|
/// This is useful if you want picking to continue hitting entities below this one. Normally,
|
|
|
|
/// only the topmost entity under a pointer can be hovered, but this setting allows the pointer
|
|
|
|
/// to hover multiple entities, from nearest to farthest, stopping as soon as it hits an entity
|
|
|
|
/// that blocks lower entities.
|
|
|
|
///
|
|
|
|
/// Note that the word "lower" here refers to entities that have been reported as hit by any
|
|
|
|
/// picking backend, but are at a lower depth than the current one. This is different from the
|
|
|
|
/// concept of event bubbling, as it works irrespective of the entity hierarchy.
|
|
|
|
///
|
|
|
|
/// For example, if a pointer is over a UI element, as well as a 3d mesh, backends will report
|
|
|
|
/// hits for both of these entities. Additionally, the hits will be sorted by the camera order,
|
|
|
|
/// so if the UI is drawing on top of the 3d mesh, the UI will be "above" the mesh. When focus
|
|
|
|
/// is computed, the UI element will be checked first to see if it this field is set to block
|
|
|
|
/// lower entities. If it does (default), the focus system will stop there, and only the UI
|
|
|
|
/// element will be marked as hovered. However, if this field is set to `false`, both the UI
|
|
|
|
/// element *and* the mesh will be marked as hovered.
|
|
|
|
///
|
2024-10-07 17:09:57 +00:00
|
|
|
/// Entities without the [`PickingBehavior`] component will block by default.
|
2024-06-15 11:59:57 +00:00
|
|
|
pub should_block_lower: bool,
|
2024-08-09 23:16:37 +00:00
|
|
|
|
2024-06-15 11:59:57 +00:00
|
|
|
/// If this is set to `false` and `should_block_lower` is set to true, this entity will block
|
|
|
|
/// lower entities from being interacted and at the same time will itself not emit any events.
|
|
|
|
///
|
|
|
|
/// Note that the word "lower" here refers to entities that have been reported as hit by any
|
|
|
|
/// picking backend, but are at a lower depth than the current one. This is different from the
|
|
|
|
/// concept of event bubbling, as it works irrespective of the entity hierarchy.
|
|
|
|
///
|
|
|
|
/// For example, if a pointer is over a UI element, and this field is set to `false`, it will
|
|
|
|
/// not be marked as hovered, and consequently will not emit events nor will any picking
|
|
|
|
/// components mark it as hovered. This can be combined with the other field
|
|
|
|
/// [`Self::should_block_lower`], which is orthogonal to this one.
|
|
|
|
///
|
2024-10-07 17:09:57 +00:00
|
|
|
/// Entities without the [`PickingBehavior`] component are hoverable by default.
|
2024-06-15 11:59:57 +00:00
|
|
|
pub is_hoverable: bool,
|
|
|
|
}
|
|
|
|
|
2024-10-07 17:09:57 +00:00
|
|
|
impl PickingBehavior {
|
2024-06-15 11:59:57 +00:00
|
|
|
/// This entity will not block entities beneath it, nor will it emit events.
|
|
|
|
///
|
|
|
|
/// If a backend reports this entity as being hit, the picking plugin will completely ignore it.
|
|
|
|
pub const IGNORE: Self = Self {
|
|
|
|
should_block_lower: false,
|
|
|
|
is_hoverable: false,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2024-10-07 17:09:57 +00:00
|
|
|
impl Default for PickingBehavior {
|
2024-06-15 11:59:57 +00:00
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
should_block_lower: true,
|
|
|
|
is_hoverable: true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Groups the stages of the picking process under shared labels.
|
|
|
|
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
|
|
|
|
pub enum PickSet {
|
|
|
|
/// Produces pointer input events. In the [`First`] schedule.
|
|
|
|
Input,
|
|
|
|
/// Runs after input events are generated but before commands are flushed. In the [`First`]
|
|
|
|
/// schedule.
|
|
|
|
PostInput,
|
|
|
|
/// Receives and processes pointer input events. In the [`PreUpdate`] schedule.
|
|
|
|
ProcessInput,
|
|
|
|
/// Reads inputs and produces [`backend::PointerHits`]s. In the [`PreUpdate`] schedule.
|
|
|
|
Backend,
|
|
|
|
/// Reads [`backend::PointerHits`]s, and updates focus, selection, and highlighting states. In
|
|
|
|
/// the [`PreUpdate`] schedule.
|
|
|
|
Focus,
|
|
|
|
/// Runs after all the focus systems are done, before event listeners are triggered. In the
|
|
|
|
/// [`PreUpdate`] schedule.
|
|
|
|
PostFocus,
|
|
|
|
/// Runs after all other picking sets. In the [`PreUpdate`] schedule.
|
|
|
|
Last,
|
|
|
|
}
|
|
|
|
|
Picking event ordering (#14862)
# Objective
Correctly order picking events. Resolves
https://github.com/bevyengine/bevy/issues/5984.
## Solution
Event ordering [very long standing
problem](https://github.com/aevyrie/bevy_mod_picking/issues/294) with
mod picking, stemming from two related issues. The first problem was
that `Pointer<T>` events of different types couldn't be ordered, but we
have already gotten around that in the upstream by switching to
observers. Since observers run in the order they are triggered, this
isn't an issue.
The second problem was that the underlying event streams that picking
uses to create it's pointer interaction events *also* lacked ordering,
and the systems that generated the points couldn't interleave events.
This PR fixes that by unifying the event streams and integrating the
various interaction systems.
The concrete changes are as follows:
+ `bevy_winit::WinitEvent` has been moved to `bevy_window::WindowEvent`.
This provides a unified (and more importantly, *ordered*) input stream
for both `bevy_window` and `bevy_input` events.
+ Replaces `InputMove` and `InputPress` with `PointerInput`, a new
unified input event which drives picking and interaction. This event is
built to have drop-in forward compatibility with [winit's upcoming
pointer abstraction](https://github.com/rust-windowing/winit/pull/3876).
I have added code to emulate it using the current winit input
abstractions, but this entire thing will be much more robust when it
lands.
+ Rolls `pointer_events` `send_click_and_drag_events` and
`send_drag_over_events` into a single system, which operates directly on
`PointerEvent` and triggers observers as output.
The PR also improves docs and takes the opportunity to
refactor/streamline the pointer event dispatch logic.
## Status & Testing
This PR is now feature complete and documented. While it is
theoretically possible to add unit tests for the ordering, building the
picking mocking for that will take a little while.
Feedback on the chosen ordering of events is within-scope.
## Migration Guide
For users switching from `bevy_mod_picking` to `bevy_picking`:
+ Instead of adding an `On<T>` component, use `.observe(|trigger:
Trigger<T>|)`. You may now apply multiple handlers to the same entity
using this command.
+ Pointer interaction events now have semi-deterministic ordering which
(more or less) aligns with the order of the raw input stream. Consult
the docs on `bevy_picking::event::pointer_events` for current
information. You may need to adjust your event handling logic
accordingly.
+ `PointerCancel` has been replaced with `Pointer<Cancled>`, which now
has the semantics of an OS touch pointer cancel event.
+ `InputMove` and `InputPress` have been merged into `PointerInput`. The
use remains exactly the same.
+ Picking interaction events are now only accessible through observers,
and no `EventReader`. This functionality may be re-implemented later.
For users of `bevy_winit`:
+ The event `bevy_winit::WinitEvent` has moved to
`bevy_window::WindowEvent`. If this was the only thing you depended on
`bevy_winit` for, you should switch your dependency to `bevy_window`.
+ `bevy_window` now depends on `bevy_input`. The dependencies of
`bevy_input` are a subset of the existing dependencies for `bevy_window`
so this should be non-breaking.
2024-09-04 19:41:06 +00:00
|
|
|
/// One plugin that contains the [`PointerInputPlugin`](input::PointerInputPlugin), [`PickingPlugin`]
|
|
|
|
/// and the [`InteractionPlugin`], this is probably the plugin that will be most used.
|
|
|
|
///
|
2024-08-15 14:43:55 +00:00
|
|
|
/// Note: for any of these plugins to work, they require a picking backend to be active,
|
|
|
|
/// The picking backend is responsible to turn an input, into a [`crate::backend::PointerHits`]
|
|
|
|
/// that [`PickingPlugin`] and [`InteractionPlugin`] will refine into [`bevy_ecs::observer::Trigger`]s.
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct DefaultPickingPlugins;
|
|
|
|
|
2024-10-25 20:11:51 +00:00
|
|
|
impl PluginGroup for DefaultPickingPlugins {
|
|
|
|
fn build(self) -> PluginGroupBuilder {
|
2024-10-27 19:03:48 +00:00
|
|
|
PluginGroupBuilder::start::<Self>()
|
2024-10-25 20:11:51 +00:00
|
|
|
.add(input::PointerInputPlugin::default())
|
|
|
|
.add(PickingPlugin::default())
|
2024-10-27 19:03:48 +00:00
|
|
|
.add(InteractionPlugin)
|
2024-08-15 14:43:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-15 11:59:57 +00:00
|
|
|
/// This plugin sets up the core picking infrastructure. It receives input events, and provides the shared
|
|
|
|
/// types used by other picking plugins.
|
Picking event ordering (#14862)
# Objective
Correctly order picking events. Resolves
https://github.com/bevyengine/bevy/issues/5984.
## Solution
Event ordering [very long standing
problem](https://github.com/aevyrie/bevy_mod_picking/issues/294) with
mod picking, stemming from two related issues. The first problem was
that `Pointer<T>` events of different types couldn't be ordered, but we
have already gotten around that in the upstream by switching to
observers. Since observers run in the order they are triggered, this
isn't an issue.
The second problem was that the underlying event streams that picking
uses to create it's pointer interaction events *also* lacked ordering,
and the systems that generated the points couldn't interleave events.
This PR fixes that by unifying the event streams and integrating the
various interaction systems.
The concrete changes are as follows:
+ `bevy_winit::WinitEvent` has been moved to `bevy_window::WindowEvent`.
This provides a unified (and more importantly, *ordered*) input stream
for both `bevy_window` and `bevy_input` events.
+ Replaces `InputMove` and `InputPress` with `PointerInput`, a new
unified input event which drives picking and interaction. This event is
built to have drop-in forward compatibility with [winit's upcoming
pointer abstraction](https://github.com/rust-windowing/winit/pull/3876).
I have added code to emulate it using the current winit input
abstractions, but this entire thing will be much more robust when it
lands.
+ Rolls `pointer_events` `send_click_and_drag_events` and
`send_drag_over_events` into a single system, which operates directly on
`PointerEvent` and triggers observers as output.
The PR also improves docs and takes the opportunity to
refactor/streamline the pointer event dispatch logic.
## Status & Testing
This PR is now feature complete and documented. While it is
theoretically possible to add unit tests for the ordering, building the
picking mocking for that will take a little while.
Feedback on the chosen ordering of events is within-scope.
## Migration Guide
For users switching from `bevy_mod_picking` to `bevy_picking`:
+ Instead of adding an `On<T>` component, use `.observe(|trigger:
Trigger<T>|)`. You may now apply multiple handlers to the same entity
using this command.
+ Pointer interaction events now have semi-deterministic ordering which
(more or less) aligns with the order of the raw input stream. Consult
the docs on `bevy_picking::event::pointer_events` for current
information. You may need to adjust your event handling logic
accordingly.
+ `PointerCancel` has been replaced with `Pointer<Cancled>`, which now
has the semantics of an OS touch pointer cancel event.
+ `InputMove` and `InputPress` have been merged into `PointerInput`. The
use remains exactly the same.
+ Picking interaction events are now only accessible through observers,
and no `EventReader`. This functionality may be re-implemented later.
For users of `bevy_winit`:
+ The event `bevy_winit::WinitEvent` has moved to
`bevy_window::WindowEvent`. If this was the only thing you depended on
`bevy_winit` for, you should switch your dependency to `bevy_window`.
+ `bevy_window` now depends on `bevy_input`. The dependencies of
`bevy_input` are a subset of the existing dependencies for `bevy_window`
so this should be non-breaking.
2024-09-04 19:41:06 +00:00
|
|
|
///
|
|
|
|
/// This plugin contains several settings, and is added to the wrold as a resource after initialization. You
|
|
|
|
/// can configure picking settings at runtime through the resource.
|
|
|
|
#[derive(Copy, Clone, Debug, Resource, Reflect)]
|
2024-09-15 16:17:39 +00:00
|
|
|
#[reflect(Resource, Default, Debug)]
|
Picking event ordering (#14862)
# Objective
Correctly order picking events. Resolves
https://github.com/bevyengine/bevy/issues/5984.
## Solution
Event ordering [very long standing
problem](https://github.com/aevyrie/bevy_mod_picking/issues/294) with
mod picking, stemming from two related issues. The first problem was
that `Pointer<T>` events of different types couldn't be ordered, but we
have already gotten around that in the upstream by switching to
observers. Since observers run in the order they are triggered, this
isn't an issue.
The second problem was that the underlying event streams that picking
uses to create it's pointer interaction events *also* lacked ordering,
and the systems that generated the points couldn't interleave events.
This PR fixes that by unifying the event streams and integrating the
various interaction systems.
The concrete changes are as follows:
+ `bevy_winit::WinitEvent` has been moved to `bevy_window::WindowEvent`.
This provides a unified (and more importantly, *ordered*) input stream
for both `bevy_window` and `bevy_input` events.
+ Replaces `InputMove` and `InputPress` with `PointerInput`, a new
unified input event which drives picking and interaction. This event is
built to have drop-in forward compatibility with [winit's upcoming
pointer abstraction](https://github.com/rust-windowing/winit/pull/3876).
I have added code to emulate it using the current winit input
abstractions, but this entire thing will be much more robust when it
lands.
+ Rolls `pointer_events` `send_click_and_drag_events` and
`send_drag_over_events` into a single system, which operates directly on
`PointerEvent` and triggers observers as output.
The PR also improves docs and takes the opportunity to
refactor/streamline the pointer event dispatch logic.
## Status & Testing
This PR is now feature complete and documented. While it is
theoretically possible to add unit tests for the ordering, building the
picking mocking for that will take a little while.
Feedback on the chosen ordering of events is within-scope.
## Migration Guide
For users switching from `bevy_mod_picking` to `bevy_picking`:
+ Instead of adding an `On<T>` component, use `.observe(|trigger:
Trigger<T>|)`. You may now apply multiple handlers to the same entity
using this command.
+ Pointer interaction events now have semi-deterministic ordering which
(more or less) aligns with the order of the raw input stream. Consult
the docs on `bevy_picking::event::pointer_events` for current
information. You may need to adjust your event handling logic
accordingly.
+ `PointerCancel` has been replaced with `Pointer<Cancled>`, which now
has the semantics of an OS touch pointer cancel event.
+ `InputMove` and `InputPress` have been merged into `PointerInput`. The
use remains exactly the same.
+ Picking interaction events are now only accessible through observers,
and no `EventReader`. This functionality may be re-implemented later.
For users of `bevy_winit`:
+ The event `bevy_winit::WinitEvent` has moved to
`bevy_window::WindowEvent`. If this was the only thing you depended on
`bevy_winit` for, you should switch your dependency to `bevy_window`.
+ `bevy_window` now depends on `bevy_input`. The dependencies of
`bevy_input` are a subset of the existing dependencies for `bevy_window`
so this should be non-breaking.
2024-09-04 19:41:06 +00:00
|
|
|
pub struct PickingPlugin {
|
|
|
|
/// Enables and disables all picking features.
|
|
|
|
pub is_enabled: bool,
|
|
|
|
/// Enables and disables input collection.
|
|
|
|
pub is_input_enabled: bool,
|
|
|
|
/// Enables and disables updating interaction states of entities.
|
|
|
|
pub is_focus_enabled: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PickingPlugin {
|
|
|
|
/// Whether or not input collection systems should be running.
|
|
|
|
pub fn input_should_run(state: Res<Self>) -> bool {
|
|
|
|
state.is_input_enabled && state.is_enabled
|
|
|
|
}
|
|
|
|
/// Whether or not systems updating entities' [`PickingInteraction`](focus::PickingInteraction)
|
|
|
|
/// component should be running.
|
|
|
|
pub fn focus_should_run(state: Res<Self>) -> bool {
|
|
|
|
state.is_focus_enabled && state.is_enabled
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for PickingPlugin {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
is_enabled: true,
|
|
|
|
is_input_enabled: true,
|
|
|
|
is_focus_enabled: true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-06-15 11:59:57 +00:00
|
|
|
|
|
|
|
impl Plugin for PickingPlugin {
|
|
|
|
fn build(&self, app: &mut App) {
|
Picking event ordering (#14862)
# Objective
Correctly order picking events. Resolves
https://github.com/bevyengine/bevy/issues/5984.
## Solution
Event ordering [very long standing
problem](https://github.com/aevyrie/bevy_mod_picking/issues/294) with
mod picking, stemming from two related issues. The first problem was
that `Pointer<T>` events of different types couldn't be ordered, but we
have already gotten around that in the upstream by switching to
observers. Since observers run in the order they are triggered, this
isn't an issue.
The second problem was that the underlying event streams that picking
uses to create it's pointer interaction events *also* lacked ordering,
and the systems that generated the points couldn't interleave events.
This PR fixes that by unifying the event streams and integrating the
various interaction systems.
The concrete changes are as follows:
+ `bevy_winit::WinitEvent` has been moved to `bevy_window::WindowEvent`.
This provides a unified (and more importantly, *ordered*) input stream
for both `bevy_window` and `bevy_input` events.
+ Replaces `InputMove` and `InputPress` with `PointerInput`, a new
unified input event which drives picking and interaction. This event is
built to have drop-in forward compatibility with [winit's upcoming
pointer abstraction](https://github.com/rust-windowing/winit/pull/3876).
I have added code to emulate it using the current winit input
abstractions, but this entire thing will be much more robust when it
lands.
+ Rolls `pointer_events` `send_click_and_drag_events` and
`send_drag_over_events` into a single system, which operates directly on
`PointerEvent` and triggers observers as output.
The PR also improves docs and takes the opportunity to
refactor/streamline the pointer event dispatch logic.
## Status & Testing
This PR is now feature complete and documented. While it is
theoretically possible to add unit tests for the ordering, building the
picking mocking for that will take a little while.
Feedback on the chosen ordering of events is within-scope.
## Migration Guide
For users switching from `bevy_mod_picking` to `bevy_picking`:
+ Instead of adding an `On<T>` component, use `.observe(|trigger:
Trigger<T>|)`. You may now apply multiple handlers to the same entity
using this command.
+ Pointer interaction events now have semi-deterministic ordering which
(more or less) aligns with the order of the raw input stream. Consult
the docs on `bevy_picking::event::pointer_events` for current
information. You may need to adjust your event handling logic
accordingly.
+ `PointerCancel` has been replaced with `Pointer<Cancled>`, which now
has the semantics of an OS touch pointer cancel event.
+ `InputMove` and `InputPress` have been merged into `PointerInput`. The
use remains exactly the same.
+ Picking interaction events are now only accessible through observers,
and no `EventReader`. This functionality may be re-implemented later.
For users of `bevy_winit`:
+ The event `bevy_winit::WinitEvent` has moved to
`bevy_window::WindowEvent`. If this was the only thing you depended on
`bevy_winit` for, you should switch your dependency to `bevy_window`.
+ `bevy_window` now depends on `bevy_input`. The dependencies of
`bevy_input` are a subset of the existing dependencies for `bevy_window`
so this should be non-breaking.
2024-09-04 19:41:06 +00:00
|
|
|
app.insert_resource(*self)
|
2024-06-15 11:59:57 +00:00
|
|
|
.init_resource::<pointer::PointerMap>()
|
|
|
|
.init_resource::<backend::ray::RayMap>()
|
Picking event ordering (#14862)
# Objective
Correctly order picking events. Resolves
https://github.com/bevyengine/bevy/issues/5984.
## Solution
Event ordering [very long standing
problem](https://github.com/aevyrie/bevy_mod_picking/issues/294) with
mod picking, stemming from two related issues. The first problem was
that `Pointer<T>` events of different types couldn't be ordered, but we
have already gotten around that in the upstream by switching to
observers. Since observers run in the order they are triggered, this
isn't an issue.
The second problem was that the underlying event streams that picking
uses to create it's pointer interaction events *also* lacked ordering,
and the systems that generated the points couldn't interleave events.
This PR fixes that by unifying the event streams and integrating the
various interaction systems.
The concrete changes are as follows:
+ `bevy_winit::WinitEvent` has been moved to `bevy_window::WindowEvent`.
This provides a unified (and more importantly, *ordered*) input stream
for both `bevy_window` and `bevy_input` events.
+ Replaces `InputMove` and `InputPress` with `PointerInput`, a new
unified input event which drives picking and interaction. This event is
built to have drop-in forward compatibility with [winit's upcoming
pointer abstraction](https://github.com/rust-windowing/winit/pull/3876).
I have added code to emulate it using the current winit input
abstractions, but this entire thing will be much more robust when it
lands.
+ Rolls `pointer_events` `send_click_and_drag_events` and
`send_drag_over_events` into a single system, which operates directly on
`PointerEvent` and triggers observers as output.
The PR also improves docs and takes the opportunity to
refactor/streamline the pointer event dispatch logic.
## Status & Testing
This PR is now feature complete and documented. While it is
theoretically possible to add unit tests for the ordering, building the
picking mocking for that will take a little while.
Feedback on the chosen ordering of events is within-scope.
## Migration Guide
For users switching from `bevy_mod_picking` to `bevy_picking`:
+ Instead of adding an `On<T>` component, use `.observe(|trigger:
Trigger<T>|)`. You may now apply multiple handlers to the same entity
using this command.
+ Pointer interaction events now have semi-deterministic ordering which
(more or less) aligns with the order of the raw input stream. Consult
the docs on `bevy_picking::event::pointer_events` for current
information. You may need to adjust your event handling logic
accordingly.
+ `PointerCancel` has been replaced with `Pointer<Cancled>`, which now
has the semantics of an OS touch pointer cancel event.
+ `InputMove` and `InputPress` have been merged into `PointerInput`. The
use remains exactly the same.
+ Picking interaction events are now only accessible through observers,
and no `EventReader`. This functionality may be re-implemented later.
For users of `bevy_winit`:
+ The event `bevy_winit::WinitEvent` has moved to
`bevy_window::WindowEvent`. If this was the only thing you depended on
`bevy_winit` for, you should switch your dependency to `bevy_window`.
+ `bevy_window` now depends on `bevy_input`. The dependencies of
`bevy_input` are a subset of the existing dependencies for `bevy_window`
so this should be non-breaking.
2024-09-04 19:41:06 +00:00
|
|
|
.add_event::<pointer::PointerInput>()
|
2024-06-15 11:59:57 +00:00
|
|
|
.add_event::<backend::PointerHits>()
|
2024-08-26 18:01:32 +00:00
|
|
|
// Rather than try to mark all current and future backends as ambiguous with each other,
|
|
|
|
// we allow them to send their hits in any order. These are later sorted, so submission
|
|
|
|
// order doesn't matter. See `PointerHits` docs for caveats.
|
|
|
|
.allow_ambiguous_resource::<Events<backend::PointerHits>>()
|
2024-06-15 11:59:57 +00:00
|
|
|
.add_systems(
|
|
|
|
PreUpdate,
|
|
|
|
(
|
|
|
|
pointer::update_pointer_map,
|
Picking event ordering (#14862)
# Objective
Correctly order picking events. Resolves
https://github.com/bevyengine/bevy/issues/5984.
## Solution
Event ordering [very long standing
problem](https://github.com/aevyrie/bevy_mod_picking/issues/294) with
mod picking, stemming from two related issues. The first problem was
that `Pointer<T>` events of different types couldn't be ordered, but we
have already gotten around that in the upstream by switching to
observers. Since observers run in the order they are triggered, this
isn't an issue.
The second problem was that the underlying event streams that picking
uses to create it's pointer interaction events *also* lacked ordering,
and the systems that generated the points couldn't interleave events.
This PR fixes that by unifying the event streams and integrating the
various interaction systems.
The concrete changes are as follows:
+ `bevy_winit::WinitEvent` has been moved to `bevy_window::WindowEvent`.
This provides a unified (and more importantly, *ordered*) input stream
for both `bevy_window` and `bevy_input` events.
+ Replaces `InputMove` and `InputPress` with `PointerInput`, a new
unified input event which drives picking and interaction. This event is
built to have drop-in forward compatibility with [winit's upcoming
pointer abstraction](https://github.com/rust-windowing/winit/pull/3876).
I have added code to emulate it using the current winit input
abstractions, but this entire thing will be much more robust when it
lands.
+ Rolls `pointer_events` `send_click_and_drag_events` and
`send_drag_over_events` into a single system, which operates directly on
`PointerEvent` and triggers observers as output.
The PR also improves docs and takes the opportunity to
refactor/streamline the pointer event dispatch logic.
## Status & Testing
This PR is now feature complete and documented. While it is
theoretically possible to add unit tests for the ordering, building the
picking mocking for that will take a little while.
Feedback on the chosen ordering of events is within-scope.
## Migration Guide
For users switching from `bevy_mod_picking` to `bevy_picking`:
+ Instead of adding an `On<T>` component, use `.observe(|trigger:
Trigger<T>|)`. You may now apply multiple handlers to the same entity
using this command.
+ Pointer interaction events now have semi-deterministic ordering which
(more or less) aligns with the order of the raw input stream. Consult
the docs on `bevy_picking::event::pointer_events` for current
information. You may need to adjust your event handling logic
accordingly.
+ `PointerCancel` has been replaced with `Pointer<Cancled>`, which now
has the semantics of an OS touch pointer cancel event.
+ `InputMove` and `InputPress` have been merged into `PointerInput`. The
use remains exactly the same.
+ Picking interaction events are now only accessible through observers,
and no `EventReader`. This functionality may be re-implemented later.
For users of `bevy_winit`:
+ The event `bevy_winit::WinitEvent` has moved to
`bevy_window::WindowEvent`. If this was the only thing you depended on
`bevy_winit` for, you should switch your dependency to `bevy_window`.
+ `bevy_window` now depends on `bevy_input`. The dependencies of
`bevy_input` are a subset of the existing dependencies for `bevy_window`
so this should be non-breaking.
2024-09-04 19:41:06 +00:00
|
|
|
pointer::PointerInput::receive,
|
|
|
|
backend::ray::RayMap::repopulate.after(pointer::PointerInput::receive),
|
2024-06-15 11:59:57 +00:00
|
|
|
)
|
|
|
|
.in_set(PickSet::ProcessInput),
|
|
|
|
)
|
2024-08-15 14:43:55 +00:00
|
|
|
.configure_sets(
|
|
|
|
First,
|
|
|
|
(PickSet::Input, PickSet::PostInput)
|
|
|
|
.after(bevy_time::TimeSystem)
|
|
|
|
.after(bevy_ecs::event::EventUpdates)
|
|
|
|
.chain(),
|
|
|
|
)
|
2024-06-15 11:59:57 +00:00
|
|
|
.configure_sets(
|
|
|
|
PreUpdate,
|
|
|
|
(
|
Picking event ordering (#14862)
# Objective
Correctly order picking events. Resolves
https://github.com/bevyengine/bevy/issues/5984.
## Solution
Event ordering [very long standing
problem](https://github.com/aevyrie/bevy_mod_picking/issues/294) with
mod picking, stemming from two related issues. The first problem was
that `Pointer<T>` events of different types couldn't be ordered, but we
have already gotten around that in the upstream by switching to
observers. Since observers run in the order they are triggered, this
isn't an issue.
The second problem was that the underlying event streams that picking
uses to create it's pointer interaction events *also* lacked ordering,
and the systems that generated the points couldn't interleave events.
This PR fixes that by unifying the event streams and integrating the
various interaction systems.
The concrete changes are as follows:
+ `bevy_winit::WinitEvent` has been moved to `bevy_window::WindowEvent`.
This provides a unified (and more importantly, *ordered*) input stream
for both `bevy_window` and `bevy_input` events.
+ Replaces `InputMove` and `InputPress` with `PointerInput`, a new
unified input event which drives picking and interaction. This event is
built to have drop-in forward compatibility with [winit's upcoming
pointer abstraction](https://github.com/rust-windowing/winit/pull/3876).
I have added code to emulate it using the current winit input
abstractions, but this entire thing will be much more robust when it
lands.
+ Rolls `pointer_events` `send_click_and_drag_events` and
`send_drag_over_events` into a single system, which operates directly on
`PointerEvent` and triggers observers as output.
The PR also improves docs and takes the opportunity to
refactor/streamline the pointer event dispatch logic.
## Status & Testing
This PR is now feature complete and documented. While it is
theoretically possible to add unit tests for the ordering, building the
picking mocking for that will take a little while.
Feedback on the chosen ordering of events is within-scope.
## Migration Guide
For users switching from `bevy_mod_picking` to `bevy_picking`:
+ Instead of adding an `On<T>` component, use `.observe(|trigger:
Trigger<T>|)`. You may now apply multiple handlers to the same entity
using this command.
+ Pointer interaction events now have semi-deterministic ordering which
(more or less) aligns with the order of the raw input stream. Consult
the docs on `bevy_picking::event::pointer_events` for current
information. You may need to adjust your event handling logic
accordingly.
+ `PointerCancel` has been replaced with `Pointer<Cancled>`, which now
has the semantics of an OS touch pointer cancel event.
+ `InputMove` and `InputPress` have been merged into `PointerInput`. The
use remains exactly the same.
+ Picking interaction events are now only accessible through observers,
and no `EventReader`. This functionality may be re-implemented later.
For users of `bevy_winit`:
+ The event `bevy_winit::WinitEvent` has moved to
`bevy_window::WindowEvent`. If this was the only thing you depended on
`bevy_winit` for, you should switch your dependency to `bevy_window`.
+ `bevy_window` now depends on `bevy_input`. The dependencies of
`bevy_input` are a subset of the existing dependencies for `bevy_window`
so this should be non-breaking.
2024-09-04 19:41:06 +00:00
|
|
|
PickSet::ProcessInput.run_if(Self::input_should_run),
|
2024-06-15 11:59:57 +00:00
|
|
|
PickSet::Backend,
|
Picking event ordering (#14862)
# Objective
Correctly order picking events. Resolves
https://github.com/bevyengine/bevy/issues/5984.
## Solution
Event ordering [very long standing
problem](https://github.com/aevyrie/bevy_mod_picking/issues/294) with
mod picking, stemming from two related issues. The first problem was
that `Pointer<T>` events of different types couldn't be ordered, but we
have already gotten around that in the upstream by switching to
observers. Since observers run in the order they are triggered, this
isn't an issue.
The second problem was that the underlying event streams that picking
uses to create it's pointer interaction events *also* lacked ordering,
and the systems that generated the points couldn't interleave events.
This PR fixes that by unifying the event streams and integrating the
various interaction systems.
The concrete changes are as follows:
+ `bevy_winit::WinitEvent` has been moved to `bevy_window::WindowEvent`.
This provides a unified (and more importantly, *ordered*) input stream
for both `bevy_window` and `bevy_input` events.
+ Replaces `InputMove` and `InputPress` with `PointerInput`, a new
unified input event which drives picking and interaction. This event is
built to have drop-in forward compatibility with [winit's upcoming
pointer abstraction](https://github.com/rust-windowing/winit/pull/3876).
I have added code to emulate it using the current winit input
abstractions, but this entire thing will be much more robust when it
lands.
+ Rolls `pointer_events` `send_click_and_drag_events` and
`send_drag_over_events` into a single system, which operates directly on
`PointerEvent` and triggers observers as output.
The PR also improves docs and takes the opportunity to
refactor/streamline the pointer event dispatch logic.
## Status & Testing
This PR is now feature complete and documented. While it is
theoretically possible to add unit tests for the ordering, building the
picking mocking for that will take a little while.
Feedback on the chosen ordering of events is within-scope.
## Migration Guide
For users switching from `bevy_mod_picking` to `bevy_picking`:
+ Instead of adding an `On<T>` component, use `.observe(|trigger:
Trigger<T>|)`. You may now apply multiple handlers to the same entity
using this command.
+ Pointer interaction events now have semi-deterministic ordering which
(more or less) aligns with the order of the raw input stream. Consult
the docs on `bevy_picking::event::pointer_events` for current
information. You may need to adjust your event handling logic
accordingly.
+ `PointerCancel` has been replaced with `Pointer<Cancled>`, which now
has the semantics of an OS touch pointer cancel event.
+ `InputMove` and `InputPress` have been merged into `PointerInput`. The
use remains exactly the same.
+ Picking interaction events are now only accessible through observers,
and no `EventReader`. This functionality may be re-implemented later.
For users of `bevy_winit`:
+ The event `bevy_winit::WinitEvent` has moved to
`bevy_window::WindowEvent`. If this was the only thing you depended on
`bevy_winit` for, you should switch your dependency to `bevy_window`.
+ `bevy_window` now depends on `bevy_input`. The dependencies of
`bevy_input` are a subset of the existing dependencies for `bevy_window`
so this should be non-breaking.
2024-09-04 19:41:06 +00:00
|
|
|
PickSet::Focus.run_if(Self::focus_should_run),
|
2024-06-15 11:59:57 +00:00
|
|
|
PickSet::PostFocus,
|
|
|
|
PickSet::Last,
|
|
|
|
)
|
|
|
|
.chain(),
|
|
|
|
)
|
Picking event ordering (#14862)
# Objective
Correctly order picking events. Resolves
https://github.com/bevyengine/bevy/issues/5984.
## Solution
Event ordering [very long standing
problem](https://github.com/aevyrie/bevy_mod_picking/issues/294) with
mod picking, stemming from two related issues. The first problem was
that `Pointer<T>` events of different types couldn't be ordered, but we
have already gotten around that in the upstream by switching to
observers. Since observers run in the order they are triggered, this
isn't an issue.
The second problem was that the underlying event streams that picking
uses to create it's pointer interaction events *also* lacked ordering,
and the systems that generated the points couldn't interleave events.
This PR fixes that by unifying the event streams and integrating the
various interaction systems.
The concrete changes are as follows:
+ `bevy_winit::WinitEvent` has been moved to `bevy_window::WindowEvent`.
This provides a unified (and more importantly, *ordered*) input stream
for both `bevy_window` and `bevy_input` events.
+ Replaces `InputMove` and `InputPress` with `PointerInput`, a new
unified input event which drives picking and interaction. This event is
built to have drop-in forward compatibility with [winit's upcoming
pointer abstraction](https://github.com/rust-windowing/winit/pull/3876).
I have added code to emulate it using the current winit input
abstractions, but this entire thing will be much more robust when it
lands.
+ Rolls `pointer_events` `send_click_and_drag_events` and
`send_drag_over_events` into a single system, which operates directly on
`PointerEvent` and triggers observers as output.
The PR also improves docs and takes the opportunity to
refactor/streamline the pointer event dispatch logic.
## Status & Testing
This PR is now feature complete and documented. While it is
theoretically possible to add unit tests for the ordering, building the
picking mocking for that will take a little while.
Feedback on the chosen ordering of events is within-scope.
## Migration Guide
For users switching from `bevy_mod_picking` to `bevy_picking`:
+ Instead of adding an `On<T>` component, use `.observe(|trigger:
Trigger<T>|)`. You may now apply multiple handlers to the same entity
using this command.
+ Pointer interaction events now have semi-deterministic ordering which
(more or less) aligns with the order of the raw input stream. Consult
the docs on `bevy_picking::event::pointer_events` for current
information. You may need to adjust your event handling logic
accordingly.
+ `PointerCancel` has been replaced with `Pointer<Cancled>`, which now
has the semantics of an OS touch pointer cancel event.
+ `InputMove` and `InputPress` have been merged into `PointerInput`. The
use remains exactly the same.
+ Picking interaction events are now only accessible through observers,
and no `EventReader`. This functionality may be re-implemented later.
For users of `bevy_winit`:
+ The event `bevy_winit::WinitEvent` has moved to
`bevy_window::WindowEvent`. If this was the only thing you depended on
`bevy_winit` for, you should switch your dependency to `bevy_window`.
+ `bevy_window` now depends on `bevy_input`. The dependencies of
`bevy_input` are a subset of the existing dependencies for `bevy_window`
so this should be non-breaking.
2024-09-04 19:41:06 +00:00
|
|
|
.register_type::<Self>()
|
2024-10-07 17:09:57 +00:00
|
|
|
.register_type::<PickingBehavior>()
|
2024-06-15 11:59:57 +00:00
|
|
|
.register_type::<pointer::PointerId>()
|
|
|
|
.register_type::<pointer::PointerLocation>()
|
|
|
|
.register_type::<pointer::PointerPress>()
|
|
|
|
.register_type::<pointer::PointerInteraction>()
|
|
|
|
.register_type::<backend::ray::RayId>();
|
|
|
|
}
|
|
|
|
}
|
2024-08-09 23:16:37 +00:00
|
|
|
|
|
|
|
/// Generates [`Pointer`](events::Pointer) events and handles event bubbling.
|
2024-08-15 14:43:55 +00:00
|
|
|
#[derive(Default)]
|
2024-08-09 23:16:37 +00:00
|
|
|
pub struct InteractionPlugin;
|
|
|
|
|
|
|
|
impl Plugin for InteractionPlugin {
|
|
|
|
fn build(&self, app: &mut App) {
|
|
|
|
use events::*;
|
|
|
|
use focus::{update_focus, update_interactions};
|
|
|
|
|
|
|
|
app.init_resource::<focus::HoverMap>()
|
|
|
|
.init_resource::<focus::PreviousHoverMap>()
|
2024-10-27 19:05:31 +00:00
|
|
|
.add_event::<Pointer<Cancel>>()
|
|
|
|
.add_event::<Pointer<Click>>()
|
|
|
|
.add_event::<Pointer<Down>>()
|
|
|
|
.add_event::<Pointer<DragDrop>>()
|
|
|
|
.add_event::<Pointer<DragEnd>>()
|
|
|
|
.add_event::<Pointer<DragEnter>>()
|
|
|
|
.add_event::<Pointer<Drag>>()
|
|
|
|
.add_event::<Pointer<DragLeave>>()
|
|
|
|
.add_event::<Pointer<DragOver>>()
|
|
|
|
.add_event::<Pointer<DragStart>>()
|
|
|
|
.add_event::<Pointer<Move>>()
|
|
|
|
.add_event::<Pointer<Out>>()
|
|
|
|
.add_event::<Pointer<Over>>()
|
|
|
|
.add_event::<Pointer<Up>>()
|
2024-08-09 23:16:37 +00:00
|
|
|
.add_systems(
|
|
|
|
PreUpdate,
|
Picking event ordering (#14862)
# Objective
Correctly order picking events. Resolves
https://github.com/bevyengine/bevy/issues/5984.
## Solution
Event ordering [very long standing
problem](https://github.com/aevyrie/bevy_mod_picking/issues/294) with
mod picking, stemming from two related issues. The first problem was
that `Pointer<T>` events of different types couldn't be ordered, but we
have already gotten around that in the upstream by switching to
observers. Since observers run in the order they are triggered, this
isn't an issue.
The second problem was that the underlying event streams that picking
uses to create it's pointer interaction events *also* lacked ordering,
and the systems that generated the points couldn't interleave events.
This PR fixes that by unifying the event streams and integrating the
various interaction systems.
The concrete changes are as follows:
+ `bevy_winit::WinitEvent` has been moved to `bevy_window::WindowEvent`.
This provides a unified (and more importantly, *ordered*) input stream
for both `bevy_window` and `bevy_input` events.
+ Replaces `InputMove` and `InputPress` with `PointerInput`, a new
unified input event which drives picking and interaction. This event is
built to have drop-in forward compatibility with [winit's upcoming
pointer abstraction](https://github.com/rust-windowing/winit/pull/3876).
I have added code to emulate it using the current winit input
abstractions, but this entire thing will be much more robust when it
lands.
+ Rolls `pointer_events` `send_click_and_drag_events` and
`send_drag_over_events` into a single system, which operates directly on
`PointerEvent` and triggers observers as output.
The PR also improves docs and takes the opportunity to
refactor/streamline the pointer event dispatch logic.
## Status & Testing
This PR is now feature complete and documented. While it is
theoretically possible to add unit tests for the ordering, building the
picking mocking for that will take a little while.
Feedback on the chosen ordering of events is within-scope.
## Migration Guide
For users switching from `bevy_mod_picking` to `bevy_picking`:
+ Instead of adding an `On<T>` component, use `.observe(|trigger:
Trigger<T>|)`. You may now apply multiple handlers to the same entity
using this command.
+ Pointer interaction events now have semi-deterministic ordering which
(more or less) aligns with the order of the raw input stream. Consult
the docs on `bevy_picking::event::pointer_events` for current
information. You may need to adjust your event handling logic
accordingly.
+ `PointerCancel` has been replaced with `Pointer<Cancled>`, which now
has the semantics of an OS touch pointer cancel event.
+ `InputMove` and `InputPress` have been merged into `PointerInput`. The
use remains exactly the same.
+ Picking interaction events are now only accessible through observers,
and no `EventReader`. This functionality may be re-implemented later.
For users of `bevy_winit`:
+ The event `bevy_winit::WinitEvent` has moved to
`bevy_window::WindowEvent`. If this was the only thing you depended on
`bevy_winit` for, you should switch your dependency to `bevy_window`.
+ `bevy_window` now depends on `bevy_input`. The dependencies of
`bevy_input` are a subset of the existing dependencies for `bevy_window`
so this should be non-breaking.
2024-09-04 19:41:06 +00:00
|
|
|
(update_focus, pointer_events, update_interactions)
|
2024-08-09 23:16:37 +00:00
|
|
|
.chain()
|
|
|
|
.in_set(PickSet::Focus),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|