Fix bevy_picking sprite backend panic in out of bounds atlas index (#15202)

# Objective

- Fix panic when atlas index is out of bounds
- Took the chance to clean it up a bit

## Solution

- Use texture dimensions like rendering pipeline. Dropped atlas layouts
and indexes out of bounds are shown as a sprite.

## Testing

Used sprite_picking example, drop layout and/or use indexes out of
bounds.
This commit is contained in:
s-puig 2024-09-30 19:03:31 +02:00 committed by GitHub
parent 0d751e8809
commit 4a1645bb8a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -29,18 +29,15 @@ pub fn sprite_picking(
primary_window: Query<Entity, With<PrimaryWindow>>,
images: Res<Assets<Image>>,
texture_atlas_layout: Res<Assets<TextureAtlasLayout>>,
sprite_query: Query<
(
Entity,
Option<&Sprite>,
Option<&TextureAtlas>,
Option<&Handle<Image>>,
&GlobalTransform,
Option<&Pickable>,
&ViewVisibility,
),
Or<(With<Sprite>, With<TextureAtlas>)>,
>,
sprite_query: Query<(
Entity,
&Sprite,
Option<&TextureAtlas>,
&Handle<Image>,
&GlobalTransform,
Option<&Pickable>,
&ViewVisibility,
)>,
mut output: EventWriter<PointerHits>,
) {
let mut sorted_sprites: Vec<_> = sprite_query
@ -87,24 +84,18 @@ pub fn sprite_picking(
}
// Hit box in sprite coordinate system
let (extents, anchor) = if let Some((sprite, atlas)) = sprite.zip(atlas) {
let extents = sprite.custom_size.or_else(|| {
texture_atlas_layout
.get(&atlas.layout)
.map(|f| f.textures[atlas.index].size().as_vec2())
})?;
let anchor = sprite.anchor.as_vec();
(extents, anchor)
} else if let Some((sprite, image)) = sprite.zip(image) {
let extents = sprite
.custom_size
.or_else(|| images.get(image).map(|f| f.size().as_vec2()))?;
let anchor = sprite.anchor.as_vec();
(extents, anchor)
} else {
return None;
let extents = match (sprite.custom_size, atlas) {
(Some(custom_size), _) => custom_size,
(None, None) => images.get(image)?.size().as_vec2(),
(None, Some(atlas)) => texture_atlas_layout
.get(&atlas.layout)
.and_then(|layout| layout.textures.get(atlas.index))
// Dropped atlas layouts and indexes out of bounds are rendered as a sprite
.map_or(images.get(image)?.size().as_vec2(), |rect| {
rect.size().as_vec2()
}),
};
let anchor = sprite.anchor.as_vec();
let center = -anchor * extents;
let rect = Rect::from_center_half_size(center, extents / 2.0);