From c8763f64acd5114247bf5ad36e05b60e277b351b Mon Sep 17 00:00:00 2001 From: felix de Maneville Date: Sat, 25 Mar 2023 11:43:54 +0100 Subject: [PATCH] Ui texture Atlas --- crates/bevy_ui/src/render/mod.rs | 30 ++++++++++++++---- examples/ui/button.rs | 53 ++++++++++++++++++++++++++++++-- 2 files changed, 75 insertions(+), 8 deletions(-) diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index 42d697e050aa9..c62526474a02f 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -29,7 +29,7 @@ use bevy_render::{ }; use bevy_sprite::SpriteAssetEvents; #[cfg(feature = "bevy_text")] -use bevy_sprite::TextureAtlasLayout; +use bevy_sprite::{TextureAtlas, TextureAtlasLayout}; #[cfg(feature = "bevy_text")] use bevy_text::{PositionedGlyph, Text, TextLayoutInfo}; use bevy_transform::components::GlobalTransform; @@ -165,6 +165,7 @@ pub fn extract_uinodes( mut extracted_uinodes: ResMut, images: Extract>>, ui_stack: Extract>, + atlas_layouts: Extract>>, uinode_query: Extract< Query<( &Node, @@ -172,13 +173,14 @@ pub fn extract_uinodes( &BackgroundColor, Option<&UiImage>, &ComputedVisibility, + Option<&TextureAtlas>, Option<&CalculatedClip>, )>, >, ) { extracted_uinodes.uinodes.clear(); for (stack_index, entity) in ui_stack.uinodes.iter().enumerate() { - if let Ok((uinode, transform, color, maybe_image, visibility, clip)) = + if let Ok((uinode, transform, color, maybe_image, visibility, atlas, clip)) = uinode_query.get(*entity) { // Skip invisible and completely transparent nodes @@ -195,17 +197,33 @@ pub fn extract_uinodes( } else { (DEFAULT_IMAGE_HANDLE.typed().clone_weak(), false, false) }; - + // Skip loading images + if !images.contains(&image) { + continue; + } + // Skip completely transparent nodes + if color.0.a() == 0.0 { + continue; + } + let (atlas_size, rect_min) = atlas + .and_then(|a| atlas_layouts.get(&a.layout).map(|l| (l, a.index))) + .and_then(|(atlas, index)| { + atlas + .textures + .get(index) + .map(|rect| (Some(atlas.size), rect.min)) + }) + .unwrap_or((None, Vec2::ZERO)); extracted_uinodes.uinodes.push(ExtractedUiNode { stack_index, transform: transform.compute_matrix(), color: color.0, rect: Rect { - min: Vec2::ZERO, - max: uinode.calculated_size, + min: rect_min, + max: rect_min + uinode.calculated_size, }, image, - atlas_size: None, + atlas_size, clip: clip.map(|clip| clip.clip), flip_x, flip_y, diff --git a/examples/ui/button.rs b/examples/ui/button.rs index d91be809964d2..8df3947026cc6 100644 --- a/examples/ui/button.rs +++ b/examples/ui/button.rs @@ -9,7 +9,7 @@ fn main() { // Only run the app when there is user input. This will significantly reduce CPU/GPU use. .insert_resource(WinitSettings::desktop_app()) .add_systems(Startup, setup) - .add_systems(Update, button_system) + .add_systems(Update, (button_system, sheet_button_system)) .run(); } @@ -43,7 +43,40 @@ fn button_system( } } -fn setup(mut commands: Commands, asset_server: Res) { +fn sheet_button_system( + mut interaction_query: Query< + (&Interaction, &mut TextureAtlas), + (Changed, With