pub fn finish(
        self,
        textures: &mut Assets<Image>,
    ) -> Result<TextureAtlas, 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;
        let max_height = self.max_size.y as u32;

        let mut current_width = initial_width;
        let mut current_height = initial_height;
        let mut rect_placements = None;
        let mut atlas_texture = Image::default();

        while rect_placements.is_none() {
            if current_width > max_width || current_height > max_height {
                break;
            }

            let last_attempt = current_height == max_height && current_width == max_width;

            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,
                &mut target_bins,
                &volume_heuristic,
                &contains_smallest_box,
            ) {
                Ok(rect_placements) => {
                    atlas_texture = Image::new(
                        Extent3d {
                            width: current_width,
                            height: current_height,
                            depth_or_array_layers: 1,
                        },
                        TextureDimension::D2,
                        vec![
                            0;
                            self.format.pixel_size() * (current_width * current_height) as usize
                        ],
                        self.format,
                    );
                    Some(rect_placements)
                }
                Err(rectangle_pack::RectanglePackError::NotEnoughBinSpace) => {
                    current_height = (current_height * 2).clamp(0, max_height);
                    current_width = (current_width * 2).clamp(0, max_width);
                    None
                }
            };

            if last_attempt {
                break;
            }
        }

        let rect_placements = rect_placements.ok_or(TextureAtlasBuilderError::NotEnoughSpace)?;

        let mut texture_rects = Vec::with_capacity(rect_placements.packed_locations().len());
        let mut texture_handles = HashMap::default();
        for (texture_handle, (_, packed_location)) in rect_placements.packed_locations().iter() {
            let texture = textures.get(texture_handle).unwrap();
            let min = Vec2::new(packed_location.x() as f32, packed_location.y() as f32);
            let max = min
                + Vec2::new(
                    packed_location.width() as f32,
                    packed_location.height() as f32,
                );
            texture_handles.insert(texture_handle.clone_weak(), texture_rects.len());
            texture_rects.push(Rect { min, max });
            if texture.texture_descriptor.format != self.format && !self.auto_format_conversion {
                warn!(
                    "Loading a texture of format '{:?}' in an atlas with format '{:?}'",
                    texture.texture_descriptor.format, self.format
                );
                return Err(TextureAtlasBuilderError::WrongFormat);
            }
            self.copy_converted_texture(&mut atlas_texture, texture, packed_location);
        }
        Ok(TextureAtlas {
            size: Vec2::new(
                atlas_texture.texture_descriptor.size.width as f32,
                atlas_texture.texture_descriptor.size.height as f32,
            ),
            texture: textures.add(atlas_texture),
            textures: texture_rects,
            texture_handles: Some(texture_handles),
        })
    }
/// Consumes the builder and returns a result with a new texture atlas.
///
/// Internally it copies all rectangles from the textures and copies them
/// into a new texture which the texture atlas will use. It is not useful to
/// hold a strong handle to the texture afterwards else it will exist twice
/// in memory.
///
/// # Errors
///
/// 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.
Consumes the builder and returns a result with a new texture atlas.
Internally it copies all rectangles from the textures and copies them
into a new texture which the texture atlas will use. It is not useful to
hold a strong handle to the texture afterwards else it will exist twice
in memory.
Consumes the builder and returns a result with a new texture atlas . Internally it copies all rectangles from the textures and copies them into a new texture which the texture atlas will use . It is not useful to hold a strong handle to the texture afterwards else it will exist twice in memory .
pub fn finish(
        self,
        textures: &mut Assets<Image>,
    ) -> Result<TextureAtlas, 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;
        let max_height = self.max_size.y as u32;
        let mut current_width = initial_width;
        let mut current_height = initial_height;
        let mut rect_placements = None;
        let mut atlas_texture = Image::default();
        while rect_placements.is_none() {
            if current_width > max_width || current_height > max_height {
                break;
            }
            let last_attempt = current_height == max_height && current_width == max_width;
            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,
                &mut target_bins,
                &volume_heuristic,
                &contains_smallest_box,
            ) {
                Ok(rect_placements) => {
                    atlas_texture = Image::new(
                        Extent3d {
                            width: current_width,
                            height: current_height,
                            depth_or_array_layers: 1,
                        },
                        TextureDimension::D2,
                        vec![
                            0;
                            self.format.pixel_size() * (current_width * current_height) as usize
                        ],
                        self.format,
                    );
                    Some(rect_placements)
                }
                Err(rectangle_pack::RectanglePackError::NotEnoughBinSpace) => {
                    current_height = (current_height * 2).clamp(0, max_height);
                    current_width = (current_width * 2).clamp(0, max_width);
                    None
                }
            };
            if last_attempt {
                break;
            }
        }
        let rect_placements = rect_placements.ok_or(TextureAtlasBuilderError::NotEnoughSpace)?;
        let mut texture_rects = Vec::with_capacity(rect_placements.packed_locations().len());
        let mut texture_handles = HashMap::default();
        for (texture_handle, (_, packed_location)) in rect_placements.packed_locations().iter() {
            let texture = textures.get(texture_handle).unwrap();
            let min = Vec2::new(packed_location.x() as f32, packed_location.y() as f32);
            let max = min
                + Vec2::new(
                    packed_location.width() as f32,
                    packed_location.height() as f32,
                );
            texture_handles.insert(texture_handle.clone_weak(), texture_rects.len());
            texture_rects.push(Rect { min, max });
            if texture.texture_descriptor.format != self.format && !self.auto_format_conversion {
                warn!(
                    "Loading a texture of format '{:?}' in an atlas with format '{:?}'",
                    texture.texture_descriptor.format, self.format
                );
                return Err(TextureAtlasBuilderError::WrongFormat);
            }
            self.copy_converted_texture(&mut atlas_texture, texture, packed_location);
        }
        Ok(TextureAtlas {
            size: Vec2::new(
                atlas_texture.texture_descriptor.size.width as f32,
                atlas_texture.texture_descriptor.size.height as f32,
            ),
            texture: textures.add(atlas_texture),
            textures: texture_rects,
            texture_handles: Some(texture_handles),
        })
    }
pub fn finish ( self , textures : & mut Assets < Image > , ) -> Result < TextureAtlas , 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 ; let max_height = self . max_size . y as u32 ; let mut current_width = initial_width ; let mut current_height = initial_height ; let mut rect_placements = None ; let mut atlas_texture = Image :: default ( ) ; while rect_placements . is_none ( ) { if current_width > max_width || current_height > max_height { break ; } let last_attempt = current_height == max_height && current_width == max_width ; 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 , & mut target_bins , & volume_heuristic , & contains_smallest_box , ) { Ok ( rect_placements ) => { atlas_texture = Image :: new ( Extent3d { width : current_width , height : current_height , depth_or_array_layers : 1 , } , TextureDimension :: D2 , vec ! [ 0 self format pixel_size ( ) ( current_width current_height ) as usize ] , self . format , ) ; Some ( rect_placements ) } Err ( rectangle_pack :: RectanglePackError :: NotEnoughBinSpace ) => { current_height = ( current_height * 2 ) . clamp ( 0 , max_height ) ; current_width = ( current_width * 2 ) . clamp ( 0 , max_width ) ; None } } ; if last_attempt { break ; } } let rect_placements = rect_placements . ok_or ( TextureAtlasBuilderError :: NotEnoughSpace ) ? ; let mut texture_rects = Vec :: with_capacity ( rect_placements . packed_locations ( ) . len ( ) ) ; let mut texture_handles = HashMap :: default ( ) ; for ( texture_handle , ( _ , packed_location ) ) in rect_placements . packed_locations ( ) . iter ( ) { let texture = textures . get ( texture_handle ) . unwrap ( ) ; let min = Vec2 :: new ( packed_location . x ( ) as f32 , packed_location . y ( ) as f32 ) ; let max = min + Vec2 :: new ( packed_location . width ( ) as f32 , packed_location . height ( ) as f32 , ) ; texture_handles . insert ( texture_handle . clone_weak ( ) , texture_rects . len ( ) ) ; texture_rects . push ( Rect { min , max } ) ; if texture . texture_descriptor . format != self . format && ! self . auto_format_conversion { warn ! ( " " texture texture_descriptor format self format ) ; return Err ( TextureAtlasBuilderError :: WrongFormat ) ; } self . copy_converted_texture ( & mut atlas_texture , texture , packed_location ) ; } Ok ( TextureAtlas { size : Vec2 :: new ( atlas_texture . texture_descriptor . size . width as f32 , atlas_texture . texture_descriptor . size . height as f32 , ) , texture : textures . add ( atlas_texture ) , textures : texture_rects , texture_handles : Some ( texture_handles ) , } ) }
Consumes the builder and returns a result with a new texture atlas.
Consumes the builder and returns a result with a new texture atlas .
self
textures
&mut Assets<Image>
self
textures
&mut Assets<Image>
errors
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.
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 .