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.
///
/// 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));
@ -150,6 +152,7 @@ impl TextureAtlasBuilder {
/// Consumes the builder, and returns the newly created texture handle and
/// 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
/// into a new texture.
/// 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_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 min = Vec2::new(packed_location.x() as f32, packed_location.y() as f32);
let max = min