Fix UI texture atlas with offset (#13620)
# Objective - Fixes #11219 ## Solution - Scaling calculations use texture dimensions instead of layout dimensions. ## Testing - Did you test these changes? If so, how? All UI examples look fine. - How can other people (reviewers) test your changes? Is there anything specific they need to know? Example in #11219 ## Migration Guide ```diff let ui_node = ExtractedUiNode { stack_index, transform, color, rect, image, - atlas_size: Some(atlas_size * scale_factor), + atlas_scaling: Some(Vec2::splat(scale_factor)), clip, flip_x, flip_y, camera_entity, border, border_radius, node_type, }, ``` ```diff let computed_slices = ComputedTextureSlices { slices, - image_size, } ```
This commit is contained in:
parent
d722fef23d
commit
ba09f35474
@ -163,7 +163,7 @@ pub struct ExtractedUiNode {
|
||||
pub color: LinearRgba,
|
||||
pub rect: Rect,
|
||||
pub image: AssetId<Image>,
|
||||
pub atlas_size: Option<Vec2>,
|
||||
pub atlas_scaling: Option<Vec2>,
|
||||
pub clip: Option<Rect>,
|
||||
pub flip_x: bool,
|
||||
pub flip_y: bool,
|
||||
@ -278,7 +278,7 @@ pub fn extract_uinode_background_colors(
|
||||
},
|
||||
clip: clip.map(|clip| clip.clip),
|
||||
image: AssetId::default(),
|
||||
atlas_size: None,
|
||||
atlas_scaling: None,
|
||||
flip_x: false,
|
||||
flip_y: false,
|
||||
camera_entity,
|
||||
@ -351,19 +351,17 @@ pub fn extract_uinode_images(
|
||||
continue;
|
||||
}
|
||||
|
||||
let (rect, atlas_size) = match atlas {
|
||||
let (rect, atlas_scaling) = match atlas {
|
||||
Some(atlas) => {
|
||||
let Some(layout) = texture_atlases.get(&atlas.layout) else {
|
||||
// Atlas not present in assets resource (should this warn the user?)
|
||||
continue;
|
||||
};
|
||||
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;
|
||||
atlas_rect.max *= scale;
|
||||
atlas_size *= scale;
|
||||
(atlas_rect, Some(atlas_size))
|
||||
let atlas_scaling = uinode.size() / atlas_rect.size();
|
||||
atlas_rect.min *= atlas_scaling;
|
||||
atlas_rect.max *= atlas_scaling;
|
||||
(atlas_rect, Some(atlas_scaling))
|
||||
}
|
||||
None => (
|
||||
Rect {
|
||||
@ -420,7 +418,7 @@ pub fn extract_uinode_images(
|
||||
rect,
|
||||
clip: clip.map(|clip| clip.clip),
|
||||
image: image.texture.id(),
|
||||
atlas_size,
|
||||
atlas_scaling,
|
||||
flip_x: image.flip_x,
|
||||
flip_y: image.flip_y,
|
||||
camera_entity,
|
||||
@ -598,7 +596,7 @@ pub fn extract_uinode_borders(
|
||||
..Default::default()
|
||||
},
|
||||
image,
|
||||
atlas_size: None,
|
||||
atlas_scaling: None,
|
||||
clip: clip.map(|clip| clip.clip),
|
||||
flip_x: false,
|
||||
flip_y: false,
|
||||
@ -691,7 +689,7 @@ pub fn extract_uinode_outlines(
|
||||
..Default::default()
|
||||
},
|
||||
image,
|
||||
atlas_size: None,
|
||||
atlas_scaling: None,
|
||||
clip: maybe_clip.map(|clip| clip.clip),
|
||||
flip_x: false,
|
||||
flip_y: false,
|
||||
@ -873,7 +871,7 @@ pub fn extract_uinode_text(
|
||||
color,
|
||||
rect,
|
||||
image: atlas_info.texture.id(),
|
||||
atlas_size: Some(atlas.size.as_vec2() * inverse_scale_factor),
|
||||
atlas_scaling: Some(Vec2::splat(inverse_scale_factor)),
|
||||
clip: clip.map(|clip| clip.clip),
|
||||
flip_x: false,
|
||||
flip_y: false,
|
||||
@ -1175,7 +1173,14 @@ pub fn prepare_uinodes(
|
||||
let uvs = if flags == shader_flags::UNTEXTURED {
|
||||
[Vec2::ZERO, Vec2::X, Vec2::ONE, Vec2::Y]
|
||||
} else {
|
||||
let atlas_extent = extracted_uinode.atlas_size.unwrap_or(uinode_rect.max);
|
||||
let image = gpu_images
|
||||
.get(extracted_uinode.image)
|
||||
.expect("Image was checked during batching and should still exist");
|
||||
// Rescale atlases. This is done here because we need texture data that might not be available in Extract.
|
||||
let atlas_extent = extracted_uinode
|
||||
.atlas_scaling
|
||||
.map(|scaling| image.size.as_vec2() * scaling)
|
||||
.unwrap_or(uinode_rect.max);
|
||||
if extracted_uinode.flip_x {
|
||||
std::mem::swap(&mut uinode_rect.max.x, &mut uinode_rect.min.x);
|
||||
positions_diff[0].x *= -1.;
|
||||
|
@ -18,7 +18,6 @@ use crate::{CalculatedClip, ExtractedUiNode, Node, NodeType, UiImage};
|
||||
#[derive(Debug, Clone, Component)]
|
||||
pub struct ComputedTextureSlices {
|
||||
slices: Vec<TextureSlice>,
|
||||
image_size: Vec2,
|
||||
}
|
||||
|
||||
impl ComputedTextureSlices {
|
||||
@ -56,7 +55,6 @@ impl ComputedTextureSlices {
|
||||
let mut rect = slice.texture_rect;
|
||||
rect.min *= scale;
|
||||
rect.max *= scale;
|
||||
let atlas_size = Some(self.image_size * scale);
|
||||
ExtractedUiNode {
|
||||
stack_index: node.stack_index,
|
||||
color: image.color.into(),
|
||||
@ -65,7 +63,7 @@ impl ComputedTextureSlices {
|
||||
flip_x,
|
||||
flip_y,
|
||||
image: image.texture.id(),
|
||||
atlas_size,
|
||||
atlas_scaling: Some(scale),
|
||||
clip: clip.map(|clip| clip.clip),
|
||||
camera_entity,
|
||||
border: [0.; 4],
|
||||
@ -99,13 +97,10 @@ fn compute_texture_slices(
|
||||
atlas: Option<&TextureAtlas>,
|
||||
atlas_layouts: &Assets<TextureAtlasLayout>,
|
||||
) -> Option<ComputedTextureSlices> {
|
||||
let (image_size, texture_rect) = match atlas {
|
||||
let texture_rect = match atlas {
|
||||
Some(a) => {
|
||||
let layout = atlas_layouts.get(&a.layout)?;
|
||||
(
|
||||
layout.size.as_vec2(),
|
||||
layout.textures.get(a.index)?.as_rect(),
|
||||
)
|
||||
layout.textures.get(a.index)?.as_rect()
|
||||
}
|
||||
None => {
|
||||
let image = images.get(&image_handle.texture)?;
|
||||
@ -113,11 +108,10 @@ fn compute_texture_slices(
|
||||
image.texture_descriptor.size.width as f32,
|
||||
image.texture_descriptor.size.height as f32,
|
||||
);
|
||||
let rect = Rect {
|
||||
Rect {
|
||||
min: Vec2::ZERO,
|
||||
max: size,
|
||||
};
|
||||
(size, rect)
|
||||
}
|
||||
}
|
||||
};
|
||||
let slices = match scale_mode {
|
||||
@ -135,7 +129,7 @@ fn compute_texture_slices(
|
||||
slice.tiled(*stretch_value, (*tile_x, *tile_y))
|
||||
}
|
||||
};
|
||||
Some(ComputedTextureSlices { slices, image_size })
|
||||
Some(ComputedTextureSlices { slices })
|
||||
}
|
||||
|
||||
/// System reacting to added or modified [`Image`] handles, and recompute sprite slices
|
||||
|
@ -50,7 +50,8 @@ fn setup(
|
||||
mut texture_atlases: ResMut<Assets<TextureAtlasLayout>>,
|
||||
) {
|
||||
let texture_handle = asset_server.load("textures/fantasy_ui_borders/border_sheet.png");
|
||||
let atlas_layout = TextureAtlasLayout::from_grid(UVec2::new(50, 50), 6, 6, None, None);
|
||||
let atlas_layout =
|
||||
TextureAtlasLayout::from_grid(UVec2::new(50, 50), 6, 6, Some(UVec2::splat(2)), None);
|
||||
let atlas_layout_handle = texture_atlases.add(atlas_layout);
|
||||
|
||||
let slicer = TextureSlicer {
|
||||
|
Loading…
Reference in New Issue
Block a user