Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow TextureAtlasBuilder in AssetLoader #11548

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 26 additions & 25 deletions crates/bevy_sprite/src/texture_atlas_builder.rs
Original file line number Diff line number Diff line change
@@ -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::{
Expand Down Expand Up @@ -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<Image>, Extent3d)>,
textures_to_place: Vec<(Option<AssetId<Image>>, &'a Image)>,
/// The initial atlas size in pixels.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doc comment should be updated

initial_size: Vec2,
/// The absolute maximum size of the texture atlas in pixels.
Expand All @@ -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(),
Expand All @@ -58,7 +57,7 @@ impl Default for TextureAtlasBuilder {

pub type TextureAtlasBuilderResult<T> = Result<T, TextureAtlasBuilderError>;

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;
Expand Down Expand Up @@ -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<Image>, texture: &Image) {
self.textures_to_place
.push((image_id, texture.texture_descriptor.size));
pub fn add_texture(&mut self, image_id: Option<AssetId<Image>>, 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.
Expand Down Expand Up @@ -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
Expand All @@ -172,7 +170,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 {
Expand All @@ -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<Image>,
) -> Result<(TextureAtlasLayout, Handle<Image>), 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;
Expand All @@ -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::<AssetId<Image>>::new();
let mut rects_to_place = GroupedRectsToPlace::<usize>::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,
),
);
}

Expand Down Expand Up @@ -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!(
Expand All @@ -291,7 +292,7 @@ impl TextureAtlasBuilder {
textures: texture_rects,
texture_handles: Some(texture_ids),
},
textures.add(atlas_texture),
atlas_texture,
))
}
}
5 changes: 3 additions & 2 deletions examples/2d/texture_atlas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Loading