Add TextureAtlasSources::uv_rect to get Rect in UV coords (#18178)

# Objective

I'm building a bloxel game in which I (currently) use a texture atlas to
render the blocks the world is made of. While I was coding it, I was
using the `TextureAtlas...` types to build the terrain's texture atlas
at runtime as shown in the
[example](https://github.com/bevyengine/bevy/blob/latest/examples/2d/texture_atlas.rs).
But when I was using it to build a 3D mesh out of the blocks, I found
that there was no easy way get the texture rect in UV coordinates, only
in pixels via `texture_rect()`. I had to resort to writing code like
this:

```rs
let size = layout.size.as_vec2();
if let Some(rect) = sources.texture_rect(layout, texture) {
    let rect = rect.as_rect();
    let uvs = Rect::from_corners(rect.min / size, rect.max / size);
    // use the UVs here, such as to build vertex buffer
}
```

That is, until I wrote a helper function that's practically identical to
the one in this PR.

## Solution

Add a `uv_rect` function to `TextureAtlasSources` that will return a
`Rect` with coordinates in the range of 0.0 to 1.0 – that is, UV
coordinates – which can then be used directly to build `Vec2` UV values
to put into a buffer and send to the GPU.

I'm a little unsure about the wording of the `texture_rect`
documentation but I kept it intact and based mine on it. If you think
this could be improved and have some advice, I'd love to include that in
this PR.

## Testing

I've not done any testing with the updated bevy branch, other than
seeing that the original helper function (identical in functionality)
worked in my currently very small project, and making sure `cargo build`
doesn't error, but I'm new to making changes to Bevy so unsure if this
is sufficient.

## Showcase


![image](https://github.com/user-attachments/assets/a6d25608-e4ea-4cfd-ba1f-911dc4430138)
This commit is contained in:
copygirl 2025-03-07 02:59:45 +01:00 committed by GitHub
parent cca5813472
commit 6cd98b38b9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,6 +1,6 @@
use bevy_app::prelude::*;
use bevy_asset::{Asset, AssetApp as _, AssetId, Assets, Handle};
use bevy_math::{URect, UVec2};
use bevy_math::{Rect, URect, UVec2};
use bevy_platform_support::collections::HashMap;
#[cfg(feature = "bevy_reflect")]
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
@ -51,7 +51,7 @@ impl TextureAtlasSources {
})
}
/// Retrieves the texture *section* rectangle of the given `texture` handle.
/// Retrieves the texture *section* rectangle of the given `texture` handle in pixels.
pub fn texture_rect(
&self,
layout: &TextureAtlasLayout,
@ -59,6 +59,20 @@ impl TextureAtlasSources {
) -> Option<URect> {
layout.textures.get(self.texture_index(texture)?).cloned()
}
/// Retrieves the texture *section* rectangle of the given `texture` handle in UV coordinates.
/// These are within the range [0..1], as a fraction of the entire texture atlas' size.
pub fn uv_rect(
&self,
layout: &TextureAtlasLayout,
texture: impl Into<AssetId<Image>>,
) -> Option<Rect> {
self.texture_rect(layout, texture).map(|rect| {
let rect = rect.as_rect();
let size = layout.size.as_vec2();
Rect::from_corners(rect.min / size, rect.max / size)
})
}
}
/// Stores a map used to lookup the position of a texture in a [`TextureAtlas`].