Skip to content

Commit

Permalink
ChangeTextureAtlasBuilder into expected Builder conventions (#969)
Browse files Browse the repository at this point in the history
* Change`TextureAtlasBuilder` into expected Builder conventions
  • Loading branch information
joshuajbouw authored Dec 3, 2020
1 parent ff12f69 commit b8f8d46
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 22 deletions.
68 changes: 47 additions & 21 deletions crates/bevy_sprite/src/texture_atlas_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,51 @@ use rectangle_pack::{
};
use thiserror::Error;

#[derive(Debug, Error)]
pub enum TextureAtlasBuilderError {
#[error("could not pack textures into an atlas within the given bounds")]
NotEnoughSpace,
}

#[derive(Debug)]
/// A builder which is used to create a texture atlas from many individual
/// sprites.
pub struct TextureAtlasBuilder {
pub textures: Vec<Handle<Texture>>,
pub rects_to_place: GroupedRectsToPlace<Handle<Texture>>,
pub initial_size: Vec2,
pub max_size: Vec2,
/// The grouped rects which must be placed with a key value pair of a
/// texture handle to an index.
rects_to_place: GroupedRectsToPlace<Handle<Texture>>,
/// The initial atlas size in pixels.
initial_size: Vec2,
/// The absolute maximum size of the texture atlas in pixels.
max_size: Vec2,
}

impl Default for TextureAtlasBuilder {
fn default() -> Self {
Self::new(Vec2::new(256., 256.), Vec2::new(2048., 2048.))
Self {
rects_to_place: GroupedRectsToPlace::new(),
initial_size: Vec2::new(256., 256.),
max_size: Vec2::new(2048., 2048.),
}
}
}

#[derive(Debug, Error)]
pub enum RectanglePackError {
#[error("could not pack textures into an atlas within the given bounds")]
NotEnoughSpace,
}
pub type TextureAtlasBuilderResult<T> = Result<T, TextureAtlasBuilderError>;

impl TextureAtlasBuilder {
pub fn new(initial_size: Vec2, max_size: Vec2) -> Self {
Self {
textures: Default::default(),
rects_to_place: GroupedRectsToPlace::new(),
initial_size,
max_size,
}
/// Sets the initial size of the atlas in pixels.
pub fn initial_size(mut self, size: Vec2) -> Self {
self.initial_size = size;
self
}

/// Sets the max size of the atlas in pixels.
pub fn max_size(mut self, size: Vec2) -> Self {
self.max_size = size;
self
}

/// Adds a texture to be copied to the texture atlas.
pub fn add_texture(&mut self, texture_handle: Handle<Texture>, texture: &Texture) {
self.rects_to_place.push_rect(
texture_handle,
Expand All @@ -47,7 +62,7 @@ impl TextureAtlasBuilder {
)
}

fn place_texture(
fn copy_texture(
&mut self,
atlas_texture: &mut Texture,
texture: &Texture,
Expand All @@ -70,10 +85,21 @@ impl TextureAtlasBuilder {
}
}

/// 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.
pub fn finish(
mut self,
textures: &mut Assets<Texture>,
) -> Result<TextureAtlas, RectanglePackError> {
) -> 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;
Expand Down Expand Up @@ -120,7 +146,7 @@ impl TextureAtlasBuilder {
}
}

let rect_placements = rect_placements.ok_or(RectanglePackError::NotEnoughSpace)?;
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();
Expand All @@ -134,7 +160,7 @@ impl TextureAtlasBuilder {
);
texture_handles.insert(texture_handle.clone_weak(), texture_rects.len());
texture_rects.push(Rect { min, max });
self.place_texture(&mut atlas_texture, texture, packed_location);
self.copy_texture(&mut atlas_texture, texture, packed_location);
}
Ok(TextureAtlas {
size: atlas_texture.size.as_vec3().truncate(),
Expand Down
2 changes: 1 addition & 1 deletion examples/2d/texture_atlas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ fn load_atlas(
{
for handle in rpg_sprite_handles.handles.iter() {
let texture = textures.get(handle).unwrap();
texture_atlas_builder.add_texture(handle.clone_weak().typed::<Texture>(), &texture);
texture_atlas_builder.add_texture(handle.clone_weak().typed::<Texture>(), texture);
}

let texture_atlas = texture_atlas_builder.finish(&mut textures).unwrap();
Expand Down

0 comments on commit b8f8d46

Please sign in to comment.