diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index ef5466e86c92d0..ecd97e6d6bf869 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -23,7 +23,7 @@ use bevy_render::{ view::{ExtractedView, ViewUniforms, Visibility}, RenderApp, RenderStage, RenderWorld, }; -use bevy_sprite::{Rect, SpriteAssetEvents, TextureAtlas}; +use bevy_sprite::{Rect, SpriteAssetEvents, SpriteSheet, TextureAtlas}; use bevy_text::{DefaultTextPipeline, Text}; use bevy_transform::components::GlobalTransform; use bevy_utils::FloatOrd; @@ -183,31 +183,29 @@ pub fn extract_uinodes( &UiColor, &UiImage, &Visibility, + Option<&SpriteSheet>, Option<&CalculatedClip>, )>, ) { let mut extracted_uinodes = render_world.resource_mut::(); extracted_uinodes.uinodes.clear(); - for (uinode, transform, color, image, visibility, clip) in uinode_query.iter() { + for (uinode, transform, color, image, visibility, sheet, clip) in uinode_query.iter() { // Skip if the node is invisible or if its size is set to zero (e.g. when a parent is set to `Display::None`) if !visibility.is_visible || uinode.size == Vec2::ZERO { continue; } - let (image, atlas_size, rect_min) = match image { - UiImage::Image(handle) => (handle.clone_weak(), None, Vec2::ZERO), - UiImage::TextureAtlas { handle, index } => { - if let Some(atlas) = texture_atlases.get(handle) { - let rect = atlas.textures.get(*index).copied().unwrap_or_else(|| { - panic!("TextureAtlas {:?} as no texture at index {}", atlas, index) - }); - (atlas.texture.clone_weak(), Some(atlas.size), rect.min) - } else { - // Skip loading images - continue; - } - } - }; + let image = image.0.clone_weak(); + let sheet: Option<&SpriteSheet> = sheet; + let (atlas_size, rect_min) = sheet + .and_then(|s| texture_atlases.get(&s.texture_atlas).map(|a| (a, s.index))) + .and_then(|(atlas, index)| { + atlas + .textures + .get(index) + .map(|rect| (Some(atlas.size), rect.min)) + }) + .unwrap_or((None, Vec2::ZERO)); // Skip loading images if !images.contains(&image) { continue; diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index 024afbcde6561c..e32adef6d3eab3 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -1,5 +1,6 @@ use crate::{Size, UiRect}; use bevy_asset::Handle; +use bevy_derive::{Deref, DerefMut}; use bevy_ecs::{prelude::Component, reflect::ReflectComponent}; use bevy_math::Vec2; use bevy_reflect::prelude::*; @@ -7,7 +8,6 @@ use bevy_render::{ color::Color, texture::{Image, DEFAULT_IMAGE_HANDLE}, }; -use bevy_sprite::TextureAtlas; use serde::{Deserialize, Serialize}; use std::ops::{Add, AddAssign}; @@ -368,30 +368,20 @@ impl From for UiColor { } } -/// The image of the node. -#[derive(Component, Clone, Debug, Reflect)] +/// The base texture of the node. +#[derive(Component, Clone, Debug, Reflect, Deref, DerefMut)] #[reflect(Component, Default)] -pub enum UiImage { - /// Single texture - Image(Handle), - /// Texture atlas. - TextureAtlas { - /// Texture atlas handle - handle: Handle, - /// Texture atlas index - index: usize, - }, -} +pub struct UiImage(pub Handle); impl Default for UiImage { fn default() -> Self { - Self::Image(DEFAULT_IMAGE_HANDLE.typed()) + Self(DEFAULT_IMAGE_HANDLE.typed()) } } impl From> for UiImage { fn from(handle: Handle) -> Self { - Self::Image(handle) + Self(handle) } } diff --git a/crates/bevy_ui/src/widget/image.rs b/crates/bevy_ui/src/widget/image.rs index afebf32ea6a935..87bfe6471f2d65 100644 --- a/crates/bevy_ui/src/widget/image.rs +++ b/crates/bevy_ui/src/widget/image.rs @@ -9,7 +9,6 @@ use bevy_ecs::{ }; use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize}; use bevy_render::texture::Image; -use bevy_sprite::TextureAtlas; use serde::{Deserialize, Serialize}; /// Describes how to resize the Image node @@ -29,29 +28,18 @@ impl Default for ImageMode { /// Updates calculated size of the node based on the image provided pub fn image_node_system( textures: Res>, - texture_atlases: Res>, mut query: Query<(&mut CalculatedSize, &UiImage), With>, ) { for (mut calculated_size, image) in query.iter_mut() { - let size = match image { - UiImage::Image(handle) => match textures.get(handle) { - None => continue, - Some(texture) => Size { - width: texture.texture_descriptor.size.width as f32, - height: texture.texture_descriptor.size.height as f32, - }, - }, - UiImage::TextureAtlas { handle, index } => match texture_atlases.get(handle) { - None => continue, - Some(atlas) => { - let rect = atlas.textures[*index]; - Size::new(rect.width(), rect.height()) - } - }, + if let Some(texture) = textures.get(image) { + let size = Size { + width: texture.texture_descriptor.size.width as f32, + height: texture.texture_descriptor.size.height as f32, + }; + // Update only if size has changed to avoid needless layout calculations + if size != calculated_size.size { + calculated_size.size = size; + } }; - // Update only if size has changed to avoid needless layout calculations - if size != calculated_size.size { - calculated_size.size = size; - } } } diff --git a/examples/games/game_menu.rs b/examples/games/game_menu.rs index 7216ac5e0c1b54..f6c88c632a806e 100644 --- a/examples/games/game_menu.rs +++ b/examples/games/game_menu.rs @@ -90,7 +90,7 @@ mod splash { size: Size::new(Val::Px(200.0), Val::Auto), ..default() }, - image: UiImage::Image(icon), + image: UiImage(icon), ..default() }) .insert(OnSplashScreen); @@ -464,7 +464,7 @@ mod menu { let icon = asset_server.load("textures/Game Icons/right.png"); parent.spawn_bundle(ImageBundle { style: button_icon_style.clone(), - image: UiImage::Image(icon), + image: UiImage(icon), ..default() }); parent.spawn_bundle(TextBundle { @@ -487,7 +487,7 @@ mod menu { let icon = asset_server.load("textures/Game Icons/wrench.png"); parent.spawn_bundle(ImageBundle { style: button_icon_style.clone(), - image: UiImage::Image(icon), + image: UiImage(icon), ..default() }); parent.spawn_bundle(TextBundle { @@ -510,7 +510,7 @@ mod menu { let icon = asset_server.load("textures/Game Icons/exitRight.png"); parent.spawn_bundle(ImageBundle { style: button_icon_style, - image: UiImage::Image(icon), + image: UiImage(icon), ..default() }); parent.spawn_bundle(TextBundle { diff --git a/examples/ui/button.rs b/examples/ui/button.rs index 187d08e3200d60..06016a7d396f08 100644 --- a/examples/ui/button.rs +++ b/examples/ui/button.rs @@ -2,7 +2,6 @@ //! interaction state. use bevy::{prelude::*, winit::WinitSettings}; -use std::ops::DerefMut; fn main() { App::new() @@ -47,22 +46,20 @@ fn button_system( fn sheet_button_system( mut interaction_query: Query< - (&Interaction, &mut UiImage), + (&Interaction, &mut SpriteSheet), (Changed, With