diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a89d5dd..f7dc4155 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # UNRELEASED +- Fixed: sprite picking depth is now consistent with other picking backends. - Fixed: entities with identical depth could be dropped due to the use of a BTreeMap to sort entities by depth. This has been changed to use a sorted Vec, to allow entities with the same depth to coexist. diff --git a/backends/bevy_picking_sprite/src/lib.rs b/backends/bevy_picking_sprite/src/lib.rs index 3edb2085..be45c907 100644 --- a/backends/bevy_picking_sprite/src/lib.rs +++ b/backends/bevy_picking_sprite/src/lib.rs @@ -35,7 +35,7 @@ impl Plugin for SpriteBackend { /// Checks if any sprite entities are under each pointer pub fn sprite_picking( pointers: Query<(&PointerId, &PointerLocation)>, - cameras: Query<(Entity, &Camera, &GlobalTransform)>, + cameras: Query<(Entity, &Camera, &GlobalTransform, &OrthographicProjection)>, primary_window: Query>, images: Res>, texture_atlas: Res>, @@ -63,10 +63,10 @@ pub fn sprite_picking( pointer_location.location().map(|loc| (pointer, loc)) }) { let mut blocked = false; - let Some((cam_entity, camera, cam_transform)) = cameras + let Some((cam_entity, camera, cam_transform, cam_ortho)) = cameras .iter() - .filter(|(_, camera, _)| camera.is_active) - .find(|(_, camera, _)| { + .filter(|(_, camera, _, _)| camera.is_active) + .find(|(_, camera, _, _)| { camera .target .normalize(Some(primary_window.single())) @@ -123,10 +123,10 @@ pub fn sprite_picking( blocked = is_cursor_in_sprite && pickable.map(|p| p.should_block_lower) != Some(false); - is_cursor_in_sprite.then_some(( - entity, - HitData::new(cam_entity, sprite_transform.translation().z, None, None), - )) + // HitData requires a depth as calculated from the camera's near clipping plane + let depth = -cam_ortho.near - sprite_transform.translation().z; + + is_cursor_in_sprite.then_some((entity, HitData::new(cam_entity, depth, None, None))) }) .collect(); diff --git a/crates/bevy_picking_core/src/backend.rs b/crates/bevy_picking_core/src/backend.rs index 618e7ca0..69c5f7e4 100644 --- a/crates/bevy_picking_core/src/backend.rs +++ b/crates/bevy_picking_core/src/backend.rs @@ -85,16 +85,16 @@ impl PointerHits { } } -/// Holds data from a successful pointer hit test. -/// -/// `depth` only needs to be self-consistent with other [`PointerHits`]s using the same -/// [`RenderTarget`](bevy_render::camera::RenderTarget). +/// Holds data from a successful pointer hit test. See [`HitData::depth`] for important details. #[derive(Clone, Debug, PartialEq, Reflect)] pub struct HitData { /// The camera entity used to detect this hit. Useful when you need to find the ray that was /// casted for this hit when using a raycasting backend. pub camera: Entity, - /// The distance from the pointer to the entity into the screen, or depth. + /// `depth` only needs to be self-consistent with other [`PointerHits`]s using the same + /// [`RenderTarget`](bevy_render::camera::RenderTarget). However, it is recommended to use the + /// distance from the pointer to the hit, measured from the near plane of the camera, to the + /// point, in world space. pub depth: f32, /// The position of the intersection in the world, if the data is available from the backend. pub position: Option,