bevy_picking/window.rs
1//! This module contains a basic backend that implements picking for window
2//! entities.
3//!
4//! Pointers can exist on windows, images, and gpu texture views. With
5//! [`update_window_hits`] enabled, when a pointer hovers over a window that
6//! window will be inserted as a pointer hit, listed behind all other pointer
7//! hits. This means that when the pointer isn't hovering any other entities,
8//! the picking events will be routed to the window.
9//!
10//! ## Implementation Notes
11//!
12//! - This backend does not provide `normal` in `HitData`.
13
14use bevy_camera::NormalizedRenderTarget;
15use bevy_ecs::prelude::*;
16
17use crate::{
18 backend::{ray::RayMap, HitData, PointerHits},
19 pointer::{Location, PointerLocation, PointerMap},
20};
21
22/// Generates pointer hit events for window entities.
23///
24/// A pointer is treated as hitting a window when it is located on that window. The order
25/// of the hit event is negative infinity, meaning it should appear behind all other entities.
26///
27/// The depth of the hit will be listed as zero.
28pub fn update_window_hits(
29 pointer_locations: Query<&PointerLocation>,
30 mut pointer_hits_writer: MessageWriter<PointerHits>,
31 ray_map: Res<RayMap>,
32 pointer_map: Res<PointerMap>,
33) {
34 for (&ray_id, _) in ray_map.iter() {
35 if let Some((position, window_entity)) =
36 pointer_map
37 .get_entity(ray_id.pointer)
38 .and_then(|pointer_e| {
39 if let Ok(PointerLocation {
40 location:
41 Some(Location {
42 target: NormalizedRenderTarget::Window(window_ref),
43 position,
44 ..
45 }),
46 }) = pointer_locations.get(pointer_e)
47 {
48 return Some((position, window_ref.entity()));
49 }
50 None
51 })
52 {
53 let hit_data = HitData::new(ray_id.camera, 0.0, Some(position.extend(0.0)), None);
54 pointer_hits_writer.write(PointerHits::new(
55 ray_id.pointer,
56 vec![(window_entity, hit_data)],
57 f32::NEG_INFINITY,
58 ));
59 }
60 }
61}