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