Skip to content

Commit

Permalink
use u32 types in TextureAtlasLayout and TextureAtlasBuilder
Browse files Browse the repository at this point in the history
  • Loading branch information
CptPotato committed Feb 25, 2024
1 parent 62ee077 commit ba5f0fe
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 55 deletions.
32 changes: 19 additions & 13 deletions crates/bevy_sprite/src/dynamic_texture_atlas_builder.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::TextureAtlasLayout;
use bevy_asset::{Assets, Handle};
use bevy_math::{IVec2, Rect, UVec2};
use bevy_math::{URect, UVec2};
use bevy_render::{
render_asset::{RenderAsset, RenderAssetUsages},
texture::{Image, TextureFormatPixelInfo},
Expand All @@ -13,7 +13,7 @@ use guillotiere::{size2, Allocation, AtlasAllocator};
/// e.g: in a font glyph [`TextureAtlasLayout`], only add the [`Image`] texture for letters to be rendered.
pub struct DynamicTextureAtlasBuilder {
atlas_allocator: AtlasAllocator,
padding: i32,
padding: u32,
}

impl DynamicTextureAtlasBuilder {
Expand All @@ -23,7 +23,7 @@ impl DynamicTextureAtlasBuilder {
///
/// * `size` - total size for the atlas
/// * `padding` - gap added between textures in the atlas, both in x axis and y axis
pub fn new(size: UVec2, padding: i32) -> Self {
pub fn new(size: UVec2, padding: u32) -> Self {
Self {
atlas_allocator: AtlasAllocator::new(to_size2(size)),
padding,
Expand All @@ -50,8 +50,8 @@ impl DynamicTextureAtlasBuilder {
atlas_texture_handle: &Handle<Image>,
) -> Option<usize> {
let allocation = self.atlas_allocator.allocate(size2(
texture.width() as i32 + self.padding,
texture.height() as i32 + self.padding,
(texture.width() + self.padding).try_into().unwrap(),
(texture.height() + self.padding).try_into().unwrap(),
));
if let Some(allocation) = allocation {
let atlas_texture = textures.get_mut(atlas_texture_handle).unwrap();
Expand All @@ -63,8 +63,8 @@ impl DynamicTextureAtlasBuilder {
);

self.place_texture(atlas_texture, allocation, texture);
let mut rect: Rect = to_rect(allocation.rectangle);
rect.max -= self.padding as f32;
let mut rect: URect = to_rect(allocation.rectangle);
rect.max = rect.max.saturating_sub(UVec2::splat(self.padding));
Some(atlas_layout.add_texture(rect))
} else {
None
Expand All @@ -78,8 +78,8 @@ impl DynamicTextureAtlasBuilder {
texture: &Image,
) {
let mut rect = allocation.rectangle;
rect.max.x -= self.padding;
rect.max.y -= self.padding;
rect.max.x -= self.padding as i32;
rect.max.y -= self.padding as i32;
let atlas_width = atlas_texture.width() as usize;
let rect_width = rect.width() as usize;
let format_size = atlas_texture.texture_descriptor.format.pixel_size();
Expand All @@ -95,10 +95,16 @@ impl DynamicTextureAtlasBuilder {
}
}

fn to_rect(rectangle: guillotiere::Rectangle) -> Rect {
Rect {
min: IVec2::new(rectangle.min.x, rectangle.min.y).as_vec2(),
max: IVec2::new(rectangle.max.x, rectangle.max.y).as_vec2(),
fn to_rect(rectangle: guillotiere::Rectangle) -> URect {
URect {
min: UVec2::new(
rectangle.min.x.try_into().unwrap(),
rectangle.min.y.try_into().unwrap(),
),
max: UVec2::new(
rectangle.max.x.try_into().unwrap(),
rectangle.max.y.try_into().unwrap(),
),
}
}

Expand Down
4 changes: 3 additions & 1 deletion crates/bevy_sprite/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,9 @@ pub fn calculate_bounds_2d(
// We default to the texture size for regular sprites
None => images.get(texture_handle).map(|image| image.size_f32()),
// We default to the drawn rect for atlas sprites
Some(atlas) => atlas.texture_rect(&atlases).map(|rect| rect.size()),
Some(atlas) => atlas
.texture_rect(&atlases)
.map(|rect| rect.size().as_vec2()),
}) {
let aabb = Aabb {
center: (-sprite.anchor.as_vec() * size).extend(0.0).into(),
Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_sprite/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,10 +366,10 @@ pub fn extract_sprites(
let rect = match (atlas_rect, sprite.rect) {
(None, None) => None,
(None, Some(sprite_rect)) => Some(sprite_rect),
(Some(atlas_rect), None) => Some(atlas_rect),
(Some(atlas_rect), None) => Some(atlas_rect.as_rect()),
(Some(atlas_rect), Some(mut sprite_rect)) => {
sprite_rect.min += atlas_rect.min;
sprite_rect.max += atlas_rect.min;
sprite_rect.min += atlas_rect.min.as_vec2();
sprite_rect.max += atlas_rect.min.as_vec2();

Some(sprite_rect)
}
Expand Down
17 changes: 8 additions & 9 deletions crates/bevy_sprite/src/texture_atlas.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use bevy_asset::{Asset, AssetId, Assets, Handle};
use bevy_ecs::component::Component;
use bevy_math::{Rect, UVec2};
use bevy_math::{URect, UVec2};
use bevy_reflect::Reflect;
use bevy_render::texture::Image;
use bevy_utils::HashMap;
Expand All @@ -21,7 +21,7 @@ pub struct TextureAtlasLayout {
// TODO: add support to Uniforms derive to write dimensions and sprites to the same buffer
pub size: UVec2,
/// The specific areas of the atlas where each texture can be found
pub textures: Vec<Rect>,
pub textures: Vec<URect>,
/// Maps from a specific image handle to the index in `textures` where they can be found.
///
/// This field is set by [`TextureAtlasBuilder`].
Expand Down Expand Up @@ -94,12 +94,11 @@ impl TextureAtlasLayout {
}

let cell = UVec2::new(x, y);

let rect_min = (tile_size + current_padding) * cell + offset;

sprites.push(Rect {
min: rect_min.as_vec2(),
max: (rect_min + tile_size).as_vec2(),
sprites.push(URect {
min: rect_min,
max: rect_min + tile_size,
});
}
}
Expand All @@ -121,7 +120,7 @@ impl TextureAtlasLayout {
/// * `rect` - The section of the texture to be added
///
/// [`TextureAtlas`]: crate::TextureAtlas
pub fn add_texture(&mut self, rect: Rect) -> usize {
pub fn add_texture(&mut self, rect: URect) -> usize {
self.textures.push(rect);
self.textures.len() - 1
}
Expand Down Expand Up @@ -149,8 +148,8 @@ impl TextureAtlasLayout {
}

impl TextureAtlas {
/// Retrieves the current texture [`Rect`] of the sprite sheet according to the section `index`
pub fn texture_rect(&self, texture_atlases: &Assets<TextureAtlasLayout>) -> Option<Rect> {
/// Retrieves the current texture [`URect`] of the sprite sheet according to the section `index`
pub fn texture_rect(&self, texture_atlases: &Assets<TextureAtlasLayout>) -> Option<URect> {
let atlas = texture_atlases.get(&self.layout)?;
atlas.textures.get(self.index).copied()
}
Expand Down
35 changes: 15 additions & 20 deletions crates/bevy_sprite/src/texture_atlas_builder.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use bevy_asset::AssetId;
use bevy_log::{debug, error, warn};
use bevy_math::{Rect, UVec2, Vec2};
use bevy_math::{URect, UVec2};
use bevy_render::{
render_asset::RenderAssetUsages,
render_resource::{Extent3d, TextureDimension, TextureFormat},
Expand Down Expand Up @@ -31,9 +31,9 @@ pub struct TextureAtlasBuilder<'a> {
/// Collection of texture's asset id (optional) and image data to be packed into an atlas
textures_to_place: Vec<(Option<AssetId<Image>>, &'a Image)>,
/// The initial atlas size in pixels.
initial_size: Vec2,
initial_size: UVec2,
/// The absolute maximum size of the texture atlas in pixels.
max_size: Vec2,
max_size: UVec2,
/// The texture format for the textures that will be loaded in the atlas.
format: TextureFormat,
/// Enable automatic format conversion for textures if they are not in the atlas format.
Expand All @@ -46,8 +46,8 @@ impl Default for TextureAtlasBuilder<'_> {
fn default() -> Self {
Self {
textures_to_place: Vec::new(),
initial_size: Vec2::new(256., 256.),
max_size: Vec2::new(2048., 2048.),
initial_size: UVec2::splat(256),
max_size: UVec2::splat(2048),
format: TextureFormat::Rgba8UnormSrgb,
auto_format_conversion: true,
padding: UVec2::ZERO,
Expand All @@ -59,13 +59,13 @@ pub type TextureAtlasBuilderResult<T> = Result<T, TextureAtlasBuilderError>;

impl<'a> TextureAtlasBuilder<'a> {
/// Sets the initial size of the atlas in pixels.
pub fn initial_size(mut self, size: Vec2) -> Self {
pub fn initial_size(mut self, size: UVec2) -> Self {
self.initial_size = size;
self
}

/// Sets the max size of the atlas in pixels.
pub fn max_size(mut self, size: Vec2) -> Self {
pub fn max_size(mut self, size: UVec2) -> Self {
self.max_size = size;
self
}
Expand Down Expand Up @@ -189,13 +189,11 @@ impl<'a> TextureAtlasBuilder<'a> {
/// 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) -> 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;
let max_height = self.max_size.y as u32;
let max_width = self.max_size.x;
let max_height = self.max_size.y;

let mut current_width = initial_width;
let mut current_height = initial_height;
let mut current_width = self.initial_size.x;
let mut current_height = self.initial_size.y;
let mut rect_placements = None;
let mut atlas_texture = Image::default();
let mut rects_to_place = GroupedRectsToPlace::<usize>::new();
Expand Down Expand Up @@ -265,16 +263,13 @@ impl<'a> TextureAtlasBuilder<'a> {
for (index, (image_id, texture)) in self.textures_to_place.iter().enumerate() {
let (_, packed_location) = rect_placements.packed_locations().get(&index).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,
);
let min = UVec2::new(packed_location.x(), packed_location.y());
let max =
min + UVec2::new(packed_location.width(), packed_location.height()) - self.padding;
if let Some(image_id) = image_id {
texture_ids.insert(*image_id, index);
}
texture_rects.push(Rect { min, max });
texture_rects.push(URect { min, max });
if texture.texture_descriptor.format != self.format && !self.auto_format_conversion {
warn!(
"Loading a texture of format '{:?}' in an atlas with format '{:?}'",
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_text/src/glyph_brush.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ impl GlyphBrush {

let texture_atlas = texture_atlases.get(&atlas_info.texture_atlas).unwrap();
let glyph_rect = texture_atlas.textures[atlas_info.glyph_index];
let size = Vec2::new(glyph_rect.width(), glyph_rect.height());
let size = glyph_rect.size().as_vec2();

let x = bounds.min.x + size.x / 2.0 - text_bounds.min.x;

Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_text/src/text2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ pub fn extract_text2d_sprite(
ExtractedSprite {
transform: transform * GlobalTransform::from_translation(position.extend(0.)),
color,
rect: Some(atlas.textures[atlas_info.glyph_index]),
rect: Some(atlas.textures[atlas_info.glyph_index].as_rect()),
custom_size: None,
image_handle_id: atlas_info.texture.id(),
flip_x: false,
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_ui/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ pub fn extract_uinodes(
// Atlas not present in assets resource (should this warn the user?)
continue;
};
let mut atlas_rect = layout.textures[atlas.index];
let mut atlas_rect = layout.textures[atlas.index].as_rect();
let mut atlas_size = layout.size.as_vec2();
let scale = uinode.size() / atlas_rect.size();
atlas_rect.min *= scale;
Expand Down Expand Up @@ -616,7 +616,7 @@ pub fn extract_text_uinodes(
}
let atlas = texture_atlases.get(&atlas_info.texture_atlas).unwrap();

let mut rect = atlas.textures[atlas_info.glyph_index];
let mut rect = atlas.textures[atlas_info.glyph_index].as_rect();
rect.min *= inverse_scale_factor;
rect.max *= inverse_scale_factor;
extracted_uinodes.uinodes.insert(
Expand Down
10 changes: 5 additions & 5 deletions crates/bevy_ui/src/widget/image.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{measurement::AvailableSpace, ContentSize, Measure, Node, UiImage, UiScale};
use bevy_asset::Assets;
use bevy_ecs::prelude::*;
use bevy_math::Vec2;
use bevy_math::{UVec2, Vec2};
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bevy_render::texture::Image;
use bevy_sprite::{TextureAtlas, TextureAtlasLayout};
Expand All @@ -16,12 +16,12 @@ pub struct UiImageSize {
/// The size of the image's texture
///
/// This field is updated automatically by [`update_image_content_size_system`]
size: Vec2,
size: UVec2,
}

impl UiImageSize {
/// The size of the image's texture
pub fn size(&self) -> Vec2 {
pub fn size(&self) -> UVec2 {
self.size
}
}
Expand Down Expand Up @@ -92,7 +92,7 @@ pub fn update_image_content_size_system(
for (mut content_size, image, mut image_size, atlas_image) in &mut query {
if let Some(size) = match atlas_image {
Some(atlas) => atlas.texture_rect(&atlases).map(|t| t.size()),
None => textures.get(&image.texture).map(|t| t.size_f32()),
None => textures.get(&image.texture).map(|t| t.size()),
} {
// Update only if size or scale factor has changed to avoid needless layout calculations
if size != image_size.size
Expand All @@ -102,7 +102,7 @@ pub fn update_image_content_size_system(
image_size.size = size;
content_size.set(ImageMeasure {
// multiply the image size by the scale factor to get the physical size
size: size * combined_scale_factor,
size: size.as_vec2() * combined_scale_factor,
});
}
}
Expand Down

0 comments on commit ba5f0fe

Please sign in to comment.