Fixing sprite pixel space point computation for sprites with zero custom_size (#19907)

# Objective

Current implementation of `Sprite::compute_pixel_space_point` always
returns the sprite centre as an `Ok` point when the `custom_size` is set
to `Vec2::ZERO`. This leads to unexpected behaviour. For example, it
causes these sprites to block all interactions with other sprites in the
picking backend (under default settings). This small PR:

- Fixes sprite pixel space point computation for sprites with zero
custom_size
- Resolves issue #19880.

## Solution

We handle the zero custom_size case explicitly and return
`Err(point_relative_to_sprite_center)` instead of
`Ok(point_relative_to_texture)`.

## Testing

Implemented a new test for zero custom_size sprites within the
`bevy_sprite::sprite` module. Also verified that the example from issue
#19880 is behaving as expected.

No further testing is required.

- How can other people (reviewers) test your changes? Is there anything
specific they need to know?

Can run the simple application example from the linked issue. Or
evaluate the implemented test.

---------

Co-authored-by: James Lucas <jalucas@nvidia.com>
This commit is contained in:
James Lucas 2025-07-03 18:43:32 +01:00 committed by GitHub
parent 870490808d
commit 0f1eebed38
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -124,12 +124,15 @@ impl Sprite {
point_relative_to_sprite_center.y *= -1.0;
}
if sprite_size.x == 0.0 || sprite_size.y == 0.0 {
return Err(point_relative_to_sprite_center);
}
let sprite_to_texture_ratio = {
let texture_size = texture_rect.size();
let div_or_zero = |a, b| if b == 0.0 { 0.0 } else { a / b };
Vec2::new(
div_or_zero(texture_size.x, sprite_size.x),
div_or_zero(texture_size.y, sprite_size.y),
texture_size.x / sprite_size.x,
texture_size.y / sprite_size.y,
)
};
@ -555,4 +558,34 @@ mod tests {
// The pixel is outside the texture atlas, but is still a valid pixel in the image.
assert_eq!(compute(Vec2::new(0.0, 35.0)), Err(Vec2::new(2.5, -1.0)));
}
#[test]
fn compute_pixel_space_point_for_sprite_with_zero_custom_size() {
let mut image_assets = Assets::<Image>::default();
let texture_atlas_assets = Assets::<TextureAtlasLayout>::default();
let image = image_assets.add(make_image(UVec2::new(5, 10)));
let sprite = Sprite {
image,
custom_size: Some(Vec2::new(0.0, 0.0)),
..Default::default()
};
let compute = |point| {
sprite.compute_pixel_space_point(
point,
Anchor::default(),
&image_assets,
&texture_atlas_assets,
)
};
assert_eq!(compute(Vec2::new(30.0, 15.0)), Err(Vec2::new(30.0, -15.0)));
assert_eq!(
compute(Vec2::new(-10.0, -15.0)),
Err(Vec2::new(-10.0, 15.0))
);
// The pixel is outside the texture atlas, but is still a valid pixel in the image.
assert_eq!(compute(Vec2::new(0.0, 35.0)), Err(Vec2::new(0.0, -35.0)));
}
}