Use FloatOrd for sprite Z comparison and ignore sprites with NaN (#15267)

# Objective

Fixes #15258

## Solution

If my understanding is correct, sprites with NaN anywhere in their
transform won't even get onto the screen, so should not generate pick
events. This PR filters sprites with NaN in their transforms before
sorting by depth, then uses `FloatOrd` to simplify the comparison. Since
we're guaranteed to not have NaN values, it's technically unnecessary,
and we could instead sort with `a.partial_cmp(&b).unwrap()`, or even
`unwrap_unchecked()`.

## Testing

I ran the picking example to ensure Z sorting was working as intended.
This commit is contained in:
JoshValjosh 2024-09-17 17:27:53 -06:00 committed by GitHub
parent e0d38a4a3b
commit 8d78c37ce9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -2,13 +2,13 @@
//! sprites with arbitrary transforms. Picking is done based on sprite bounds, not visible pixels.
//! This means a partially transparent sprite is pickable even in its transparent areas.
use std::cmp::Ordering;
use std::cmp::Reverse;
use crate::{Sprite, TextureAtlas, TextureAtlasLayout};
use bevy_app::prelude::*;
use bevy_asset::prelude::*;
use bevy_ecs::prelude::*;
use bevy_math::{prelude::*, FloatExt};
use bevy_math::{prelude::*, FloatExt, FloatOrd};
use bevy_picking::backend::prelude::*;
use bevy_render::prelude::*;
use bevy_transform::prelude::*;
@ -43,12 +43,11 @@ pub fn sprite_picking(
>,
mut output: EventWriter<PointerHits>,
) {
let mut sorted_sprites: Vec<_> = sprite_query.iter().collect();
sorted_sprites.sort_by(|a, b| {
(b.4.translation().z)
.partial_cmp(&a.4.translation().z)
.unwrap_or(Ordering::Equal)
});
let mut sorted_sprites: Vec<_> = sprite_query
.iter()
.filter(|x| !x.4.affine().is_nan())
.collect();
sorted_sprites.sort_by_key(|x| Reverse(FloatOrd(x.4.translation().z)));
let primary_window = primary_window.get_single().ok();