From 52768cbfc102d66d9c63f4eb0f14b1d819ee6b14 Mon Sep 17 00:00:00 2001 From: KirmesBude Date: Mon, 22 Jan 2024 17:28:29 +0100 Subject: [PATCH 1/3] Allow TextureAtlasBuilder in AssetLoader --- .../bevy_sprite/src/texture_atlas_builder.rs | 49 ++++++++++--------- examples/2d/texture_atlas.rs | 5 +- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/crates/bevy_sprite/src/texture_atlas_builder.rs b/crates/bevy_sprite/src/texture_atlas_builder.rs index 116982719bff1..8cd5c60dfb945 100644 --- a/crates/bevy_sprite/src/texture_atlas_builder.rs +++ b/crates/bevy_sprite/src/texture_atlas_builder.rs @@ -1,5 +1,4 @@ -use bevy_asset::Handle; -use bevy_asset::{AssetId, Assets}; +use bevy_asset::AssetId; use bevy_log::{debug, error, warn}; use bevy_math::{Rect, UVec2, Vec2}; use bevy_render::{ @@ -28,9 +27,9 @@ pub enum TextureAtlasBuilderError { #[must_use] /// A builder which is used to create a texture atlas from many individual /// sprites. -pub struct TextureAtlasBuilder { +pub struct TextureAtlasBuilder<'a> { /// Collection of textures and their size to be packed into an atlas - textures_to_place: Vec<(AssetId, Extent3d)>, + textures_to_place: Vec<(Option>, &'a Image)>, /// The initial atlas size in pixels. initial_size: Vec2, /// The absolute maximum size of the texture atlas in pixels. @@ -43,7 +42,7 @@ pub struct TextureAtlasBuilder { padding: UVec2, } -impl Default for TextureAtlasBuilder { +impl Default for TextureAtlasBuilder<'_> { fn default() -> Self { Self { textures_to_place: Vec::new(), @@ -58,7 +57,7 @@ impl Default for TextureAtlasBuilder { pub type TextureAtlasBuilderResult = Result; -impl TextureAtlasBuilder { +impl<'a> TextureAtlasBuilder<'a> { /// Sets the initial size of the atlas in pixels. pub fn initial_size(mut self, size: Vec2) -> Self { self.initial_size = size; @@ -86,9 +85,8 @@ impl TextureAtlasBuilder { /// Adds a texture to be copied to the texture atlas. /// /// The insertion order will reflect the index of the added texture in the finished texture atlas. - pub fn add_texture(&mut self, image_id: AssetId, texture: &Image) { - self.textures_to_place - .push((image_id, texture.texture_descriptor.size)); + pub fn add_texture(&mut self, image_id: Option>, texture: &'a Image) { + self.textures_to_place.push((image_id, texture)); } /// Sets the amount of padding in pixels to add between the textures in the texture atlas. @@ -149,8 +147,8 @@ impl TextureAtlasBuilder { } } - /// Consumes the builder, and returns the newly created texture handle and - /// the assciated atlas layout. + /// Consumes the builder, and returns the newly created texture atlas and + /// the associated atlas layout. /// /// Assigns indices to the textures based on the insertion order. /// Internally it copies all rectangles from the textures and copies them @@ -173,6 +171,7 @@ impl TextureAtlasBuilder { /// // ... /// // Build your texture and the atlas layout /// let (atlas_layout, texture) = builder.finish(&mut textures).unwrap(); + /// let texture = textures.add(texture); /// let layout = layouts.add(atlas_layout); /// // Spawn your sprite /// commands.spawn(SpriteSheetBundle { @@ -190,10 +189,7 @@ impl TextureAtlasBuilder { /// /// If there is not enough space in the atlas texture, an error will /// be returned. It is then recommended to make a larger sprite sheet. - pub fn finish( - self, - textures: &mut Assets, - ) -> Result<(TextureAtlasLayout, Handle), TextureAtlasBuilderError> { + pub fn finish(self) -> Result<(TextureAtlasLayout, Image), TextureAtlasBuilderError> { let initial_width = self.initial_size.x as u32; let initial_height = self.initial_size.y as u32; let max_width = self.max_size.x as u32; @@ -203,14 +199,18 @@ 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(); + let mut rects_to_place = GroupedRectsToPlace::::new(); // Adds textures to rectangle group packer - for (image_id, size) in &self.textures_to_place { + for (index, (_, texture)) in self.textures_to_place.iter().enumerate() { rects_to_place.push_rect( - *image_id, + index, None, - RectToInsert::new(size.width + self.padding.x, size.height + self.padding.y, 1), + RectToInsert::new( + texture.width() + self.padding.x, + texture.height() + self.padding.y, + 1, + ), ); } @@ -263,17 +263,18 @@ impl TextureAtlasBuilder { let mut texture_rects = Vec::with_capacity(rect_placements.packed_locations().len()); let mut texture_ids = HashMap::default(); // We iterate through the textures to place to respect the insertion order for the texture indices - for (image_id, _) in &self.textures_to_place { - let (_, packed_location) = rect_placements.packed_locations().get(image_id).unwrap(); + for (index, (image_id, texture)) in self.textures_to_place.iter().enumerate() { + let (_, packed_location) = rect_placements.packed_locations().get(&index).unwrap(); - let texture = textures.get(*image_id).unwrap(); let min = Vec2::new(packed_location.x() as f32, packed_location.y() as f32); let max = min + Vec2::new( (packed_location.width() - self.padding.x) as f32, (packed_location.height() - self.padding.y) as f32, ); - texture_ids.insert(*image_id, texture_rects.len()); + if let Some(image_id) = image_id { + texture_ids.insert(*image_id, index); + } texture_rects.push(Rect { min, max }); if texture.texture_descriptor.format != self.format && !self.auto_format_conversion { warn!( @@ -291,7 +292,7 @@ impl TextureAtlasBuilder { textures: texture_rects, texture_handles: Some(texture_ids), }, - textures.add(atlas_texture), + atlas_texture, )) } } diff --git a/examples/2d/texture_atlas.rs b/examples/2d/texture_atlas.rs index 9ee60c53ede35..ff4ce4b9cc457 100644 --- a/examples/2d/texture_atlas.rs +++ b/examples/2d/texture_atlas.rs @@ -220,10 +220,11 @@ fn create_texture_atlas( continue; }; - texture_atlas_builder.add_texture(id, texture); + texture_atlas_builder.add_texture(Some(id), texture); } - let (texture_atlas, texture) = texture_atlas_builder.finish(textures).unwrap(); + let (texture_atlas, texture) = texture_atlas_builder.finish().unwrap(); + let texture = textures.add(texture); // Update the sampling settings of the texture atlas let image = textures.get_mut(&texture).unwrap(); From 4c952b360b1c16770e1f1d6819181e5cf2c85d0f Mon Sep 17 00:00:00 2001 From: KirmesBude Date: Fri, 26 Jan 2024 21:05:52 +0100 Subject: [PATCH 2/3] Fix usage example in finish docs --- crates/bevy_sprite/src/texture_atlas_builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_sprite/src/texture_atlas_builder.rs b/crates/bevy_sprite/src/texture_atlas_builder.rs index 8cd5c60dfb945..63edd50d13434 100644 --- a/crates/bevy_sprite/src/texture_atlas_builder.rs +++ b/crates/bevy_sprite/src/texture_atlas_builder.rs @@ -170,7 +170,7 @@ impl<'a> TextureAtlasBuilder<'a> { /// // Customize it /// // ... /// // Build your texture and the atlas layout - /// let (atlas_layout, texture) = builder.finish(&mut textures).unwrap(); + /// let (atlas_layout, texture) = builder.finish().unwrap(); /// let texture = textures.add(texture); /// let layout = layouts.add(atlas_layout); /// // Spawn your sprite From ad23f37f16a6b369b6b4035851572a92a71cf169 Mon Sep 17 00:00:00 2001 From: KirmesBude Date: Sat, 27 Jan 2024 15:41:08 +0100 Subject: [PATCH 3/3] Fix documentation --- crates/bevy_sprite/src/texture_atlas_builder.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/bevy_sprite/src/texture_atlas_builder.rs b/crates/bevy_sprite/src/texture_atlas_builder.rs index 63edd50d13434..1499145975a9a 100644 --- a/crates/bevy_sprite/src/texture_atlas_builder.rs +++ b/crates/bevy_sprite/src/texture_atlas_builder.rs @@ -28,7 +28,7 @@ pub enum TextureAtlasBuilderError { /// A builder which is used to create a texture atlas from many individual /// sprites. pub struct TextureAtlasBuilder<'a> { - /// Collection of textures and their size to be packed into an atlas + /// Collection of texture's asset id (optional) and image data to be packed into an atlas textures_to_place: Vec<(Option>, &'a Image)>, /// The initial atlas size in pixels. initial_size: Vec2, @@ -84,6 +84,7 @@ impl<'a> TextureAtlasBuilder<'a> { /// Adds a texture to be copied to the texture atlas. /// + /// Optionally an asset id can be passed that can later be used with the texture layout to retrieve the index of this texture. /// The insertion order will reflect the index of the added texture in the finished texture atlas. pub fn add_texture(&mut self, image_id: Option>, texture: &'a Image) { self.textures_to_place.push((image_id, texture)); @@ -153,8 +154,6 @@ impl<'a> TextureAtlasBuilder<'a> { /// Assigns indices to the textures based on the insertion order. /// Internally it copies all rectangles from the textures and copies them /// into a new texture. - /// It is not useful to hold a strong handle to the texture afterwards else - /// it will exist twice in memory. /// /// # Usage ///