Fix ui picking outside the viewport (#19744)
# Objective
Fixes #19692
## Solution
- Skip pointers outside the viewport.
## Testing
Tested with the following example:
<details>
<summary>Click to expand code</summary>
```rust
use bevy::{
prelude::*, render:📷:Viewport, window::SystemCursorIcon, winit::cursor::CursorIcon,
};
fn main() -> AppExit {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.insert_resource(ClearColor(Color::BLACK))
.run()
}
fn setup(mut commands: Commands, window: Single<&Window>) {
//
commands.spawn((
Camera2d,
Camera {
clear_color: ClearColorConfig::Custom(Color::WHITE),
viewport: Some(Viewport {
physical_position: UVec2::new(
window.physical_width() / 4,
window.physical_height() / 4,
),
physical_size: UVec2::new(
window.physical_width() / 2,
window.physical_height() / 2,
),
..default()
}),
..default()
},
));
commands
.spawn((
Node {
top: Val::Px(100.0),
left: Val::Px(100.0),
width: Val::Px(200.0),
height: Val::Px(200.0),
..default()
},
BackgroundColor(Color::srgb(1.0, 0.0, 0.0)),
))
.observe(|trigger: On<Pointer<Drag>>, mut node: Query<&mut Node>| {
let mut node = node.get_mut(trigger.target()).unwrap();
node.left = Val::Px(px(node.left) + trigger.delta.x);
node.top = Val::Px(px(node.top) + trigger.delta.y);
})
.observe(
|_: On<Pointer<DragStart>>,
window: Single<Entity, With<Window>>,
mut commands: Commands| {
commands
.entity(*window)
.insert(CursorIcon::from(SystemCursorIcon::Grabbing));
},
)
.observe(
|_: On<Pointer<DragEnd>>,
window: Single<Entity, With<Window>>,
mut commands: Commands| {
commands.entity(*window).remove::<CursorIcon>();
},
);
}
fn px(val: Val) -> f32 {
match val {
Val::Px(px) => px,
_ => 0.0,
}
}
```
</details>
## Additional information
This is at least also broken on the sprite picking backend. I guess the
fix for other backends are also trivial if this is correct.
(Sprite picking: #19747)