Fix TextureAtlasBuilder padding (#10031)

# Objective

- Fix TextureAtlasBuilder padding issue

TextureAtlasBuilder padding is reserved during add_texture() but can
still be changed afterwards. This means that changing padding after the
textures will be wrongly applied, either distorting the textures or
panicking if new padding is higher than texture+old padding.


## Solution

- Delay applying padding until finish()
This commit is contained in:
s-puig 2023-10-06 17:33:57 +02:00 committed by GitHub
parent 8b21ee45c0
commit a31ebdc1a6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -27,9 +27,8 @@ pub enum TextureAtlasBuilderError {
/// A builder which is used to create a texture atlas from many individual
/// sprites.
pub struct TextureAtlasBuilder {
/// The grouped rects which must be placed with a key value pair of a
/// texture handle to an index.
rects_to_place: GroupedRectsToPlace<AssetId<Image>>,
/// Collection of textures and their size to be packed into an atlas
textures_to_place: Vec<(AssetId<Image>, Extent3d)>,
/// The initial atlas size in pixels.
initial_size: Vec2,
/// The absolute maximum size of the texture atlas in pixels.
@ -45,7 +44,7 @@ pub struct TextureAtlasBuilder {
impl Default for TextureAtlasBuilder {
fn default() -> Self {
Self {
rects_to_place: GroupedRectsToPlace::new(),
textures_to_place: Vec::new(),
initial_size: Vec2::new(256., 256.),
max_size: Vec2::new(2048., 2048.),
format: TextureFormat::Rgba8UnormSrgb,
@ -84,15 +83,8 @@ impl TextureAtlasBuilder {
/// Adds a texture to be copied to the texture atlas.
pub fn add_texture(&mut self, image_id: AssetId<Image>, texture: &Image) {
self.rects_to_place.push_rect(
image_id,
None,
RectToInsert::new(
texture.texture_descriptor.size.width + self.padding.x,
texture.texture_descriptor.size.height + self.padding.y,
1,
),
);
self.textures_to_place
.push((image_id, texture.texture_descriptor.size));
}
/// Sets the amount of padding in pixels to add between the textures in the texture atlas.
@ -177,6 +169,16 @@ 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();
// Adds textures to rectangle group packer
for (image_id, size) in &self.textures_to_place {
rects_to_place.push_rect(
*image_id,
None,
RectToInsert::new(size.width + self.padding.x, size.height + self.padding.y, 1),
);
}
while rect_placements.is_none() {
if current_width > max_width || current_height > max_height {
@ -188,7 +190,7 @@ impl TextureAtlasBuilder {
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,
&rects_to_place,
&mut target_bins,
&volume_heuristic,
&contains_smallest_box,