From 8d78c37ce9ed5efa1fe469863ee5fa7fedeb9835 Mon Sep 17 00:00:00 2001 From: JoshValjosh <48692273+jnhyatt@users.noreply.github.com> Date: Tue, 17 Sep 2024 17:27:53 -0600 Subject: [PATCH] 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. --- crates/bevy_sprite/src/picking_backend.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/crates/bevy_sprite/src/picking_backend.rs b/crates/bevy_sprite/src/picking_backend.rs index f47ca22a5a..15fd90b084 100644 --- a/crates/bevy_sprite/src/picking_backend.rs +++ b/crates/bevy_sprite/src/picking_backend.rs @@ -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, ) { - 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();