TextureAtlasBuilder now respects insertion order (#11474)

# Objective

TextureAtlases are commonly used to drive animations described as a
consecutive range of indices. The current TextureAtlasBuilder uses the
AssetId of the image to determine the index of the texture in the
TextureAtlas. The AssetId of an Image Asset can change between runs.
The TextureAtlas exposes
[`get_texture_index`](https://docs.rs/bevy/latest/bevy/sprite/struct.TextureAtlas.html#method.get_texture_index)
to get the index from a given AssetId, but this needlessly complicates
the process of creating a simple TextureAtlas animation.
Fixes #2459

## Solution

- Use the (ordered) image_ids of the 'texture to place' vector to
retrieve the packed locations and compose the textures of the
TextureAtlas.
This commit is contained in:
Bude 2024-01-22 16:44:56 +01:00 committed by GitHub
parent f8191bebfb
commit b2e2f8d9e3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -84,6 +84,8 @@ impl TextureAtlasBuilder {
} }
/// Adds a texture to be copied to the texture atlas. /// 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) { pub fn add_texture(&mut self, image_id: AssetId<Image>, texture: &Image) {
self.textures_to_place self.textures_to_place
.push((image_id, texture.texture_descriptor.size)); .push((image_id, texture.texture_descriptor.size));
@ -150,6 +152,7 @@ impl TextureAtlasBuilder {
/// Consumes the builder, and returns the newly created texture handle and /// Consumes the builder, and returns the newly created texture handle and
/// the assciated atlas layout. /// the assciated atlas layout.
/// ///
/// Assigns indices to the textures based on the insertion order.
/// Internally it copies all rectangles from the textures and copies them /// Internally it copies all rectangles from the textures and copies them
/// into a new texture. /// into a new texture.
/// It is not useful to hold a strong handle to the texture afterwards else /// It is not useful to hold a strong handle to the texture afterwards else
@ -259,7 +262,10 @@ impl TextureAtlasBuilder {
let mut texture_rects = Vec::with_capacity(rect_placements.packed_locations().len()); let mut texture_rects = Vec::with_capacity(rect_placements.packed_locations().len());
let mut texture_ids = HashMap::default(); let mut texture_ids = HashMap::default();
for (image_id, (_, packed_location)) in rect_placements.packed_locations() { // 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();
let texture = textures.get(*image_id).unwrap(); let texture = textures.get(*image_id).unwrap();
let min = Vec2::new(packed_location.x() as f32, packed_location.y() as f32); let min = Vec2::new(packed_location.x() as f32, packed_location.y() as f32);
let max = min let max = min