From a31ebdc1a68c1782a18d2224133d10e889800485 Mon Sep 17 00:00:00 2001 From: s-puig <39652109+s-puig@users.noreply.github.com> Date: Fri, 6 Oct 2023 17:33:57 +0200 Subject: [PATCH] Fix TextureAtlasBuilder padding (#10031) # Objective - Fix TextureAtlasBuilder padding issue TextureAtlasBuilder padding is reserved during add_texture() but can still be changed afterwards. This means that changing padding after the textures will be wrongly applied, either distorting the textures or panicking if new padding is higher than texture+old padding. ## Solution - Delay applying padding until finish() --- .../bevy_sprite/src/texture_atlas_builder.rs | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/crates/bevy_sprite/src/texture_atlas_builder.rs b/crates/bevy_sprite/src/texture_atlas_builder.rs index 82ef8bd695..a4d55016af 100644 --- a/crates/bevy_sprite/src/texture_atlas_builder.rs +++ b/crates/bevy_sprite/src/texture_atlas_builder.rs @@ -27,9 +27,8 @@ pub enum TextureAtlasBuilderError { /// A builder which is used to create a texture atlas from many individual /// sprites. pub struct TextureAtlasBuilder { - /// The grouped rects which must be placed with a key value pair of a - /// texture handle to an index. - rects_to_place: GroupedRectsToPlace>, + /// Collection of textures and their size to be packed into an atlas + textures_to_place: Vec<(AssetId, Extent3d)>, /// The initial atlas size in pixels. initial_size: Vec2, /// The absolute maximum size of the texture atlas in pixels. @@ -45,7 +44,7 @@ pub struct TextureAtlasBuilder { impl Default for TextureAtlasBuilder { fn default() -> Self { Self { - rects_to_place: GroupedRectsToPlace::new(), + textures_to_place: Vec::new(), initial_size: Vec2::new(256., 256.), max_size: Vec2::new(2048., 2048.), format: TextureFormat::Rgba8UnormSrgb, @@ -84,15 +83,8 @@ impl TextureAtlasBuilder { /// Adds a texture to be copied to the texture atlas. pub fn add_texture(&mut self, image_id: AssetId, texture: &Image) { - self.rects_to_place.push_rect( - image_id, - None, - RectToInsert::new( - texture.texture_descriptor.size.width + self.padding.x, - texture.texture_descriptor.size.height + self.padding.y, - 1, - ), - ); + self.textures_to_place + .push((image_id, texture.texture_descriptor.size)); } /// Sets the amount of padding in pixels to add between the textures in the texture atlas. @@ -177,6 +169,16 @@ impl TextureAtlasBuilder { let mut current_height = initial_height; let mut rect_placements = None; let mut atlas_texture = Image::default(); + let mut rects_to_place = GroupedRectsToPlace::>::new(); + + // Adds textures to rectangle group packer + for (image_id, size) in &self.textures_to_place { + rects_to_place.push_rect( + *image_id, + None, + RectToInsert::new(size.width + self.padding.x, size.height + self.padding.y, 1), + ); + } while rect_placements.is_none() { if current_width > max_width || current_height > max_height { @@ -188,7 +190,7 @@ impl TextureAtlasBuilder { let mut target_bins = std::collections::BTreeMap::new(); target_bins.insert(0, TargetBin::new(current_width, current_height, 1)); rect_placements = match pack_rects( - &self.rects_to_place, + &rects_to_place, &mut target_bins, &volume_heuristic, &contains_smallest_box,