diff --git a/crates/bevy_sprite/src/texture_atlas_builder.rs b/crates/bevy_sprite/src/texture_atlas_builder.rs index 116982719bff1..1499145975a9a 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 { - /// Collection of textures and their size to be packed into an atlas - textures_to_place: Vec<(AssetId, Extent3d)>, +pub struct TextureAtlasBuilder<'a> { + /// 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, /// 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; @@ -85,10 +84,10 @@ impl TextureAtlasBuilder { /// 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: 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,14 +148,12 @@ 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 /// 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 /// @@ -172,7 +169,8 @@ impl TextureAtlasBuilder { /// // 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 /// commands.spawn(SpriteSheetBundle { @@ -190,10 +188,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 +198,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 +262,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 +291,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();