From 43d7184b353259b4a9a45d51c703fcb149148747 Mon Sep 17 00:00:00 2001 From: ickshonpe Date: Mon, 17 Apr 2023 16:58:34 +0100 Subject: [PATCH] Fix the UV calculations for clipped and flipped ImageNodes (#8195) # Objective Instead of flipping the entire image, `prepare_ui_nodes` only flips the unclipped area. overflow_flipped_bug ## Solution Whenever flip_x or flip_y is set swap the image rect coordinates and invert the clipping coords along the flipped axes before the UVs are calculated. overflow_fixed -- ## Changelog * Modified `prepare_uinodes` so that the UVs for clipped and flipped image nodes are calculated correctly. --- crates/bevy_ui/src/render/mod.rs | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index 7845ffd0c9893..eb821a32f9683 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -414,7 +414,8 @@ pub fn prepare_uinodes( current_batch_handle = extracted_uinode.image.clone_weak(); } - let uinode_rect = extracted_uinode.rect; + let mut uinode_rect = extracted_uinode.rect; + let rect_size = uinode_rect.size().extend(1.0); // Specify the corners of the node @@ -423,7 +424,7 @@ pub fn prepare_uinodes( // Calculate the effect of clipping // Note: this won't work with rotation/scaling, but that's much more complex (may need more that 2 quads) - let positions_diff = if let Some(clip) = extracted_uinode.clip { + let mut positions_diff = if let Some(clip) = extracted_uinode.clip { [ Vec2::new( f32::max(clip.min.x - positions[0].x, 0.), @@ -473,7 +474,21 @@ pub fn prepare_uinodes( [Vec2::ZERO, Vec2::X, Vec2::ONE, Vec2::Y] } else { let atlas_extent = extracted_uinode.atlas_size.unwrap_or(uinode_rect.max); - let mut uvs = [ + if extracted_uinode.flip_x { + std::mem::swap(&mut uinode_rect.max.x, &mut uinode_rect.min.x); + positions_diff[0].x *= -1.; + positions_diff[1].x *= -1.; + positions_diff[2].x *= -1.; + positions_diff[3].x *= -1.; + } + if extracted_uinode.flip_y { + std::mem::swap(&mut uinode_rect.max.y, &mut uinode_rect.min.y); + positions_diff[0].y *= -1.; + positions_diff[1].y *= -1.; + positions_diff[2].y *= -1.; + positions_diff[3].y *= -1.; + } + [ Vec2::new( uinode_rect.min.x + positions_diff[0].x, uinode_rect.min.y + positions_diff[0].y, @@ -491,15 +506,7 @@ pub fn prepare_uinodes( uinode_rect.max.y + positions_diff[3].y, ), ] - .map(|pos| pos / atlas_extent); - - if extracted_uinode.flip_x { - uvs = [uvs[1], uvs[0], uvs[3], uvs[2]]; - } - if extracted_uinode.flip_y { - uvs = [uvs[3], uvs[2], uvs[1], uvs[0]]; - } - uvs + .map(|pos| pos / atlas_extent) }; let color = extracted_uinode.color.as_linear_rgba_f32();