Skip to content

Commit 830ac83

Browse files
committed
Ui Texture Atlas
1 parent 7c27d92 commit 830ac83

File tree

2 files changed

+69
-7
lines changed

2 files changed

+69
-7
lines changed

crates/bevy_ui/src/render/mod.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use bevy_render::{
2323
view::{ComputedVisibility, ExtractedView, ViewUniforms},
2424
Extract, RenderApp, RenderStage,
2525
};
26-
use bevy_sprite::{Rect, SpriteAssetEvents, TextureAtlas};
26+
use bevy_sprite::{Rect, SpriteAssetEvents, TextureAtlas, TextureSheet};
2727
use bevy_text::{DefaultTextPipeline, Text};
2828
use bevy_transform::components::GlobalTransform;
2929
use bevy_utils::FloatOrd;
@@ -176,20 +176,23 @@ pub struct ExtractedUiNodes {
176176
pub fn extract_uinodes(
177177
mut extracted_uinodes: ResMut<ExtractedUiNodes>,
178178
images: Extract<Res<Assets<Image>>>,
179+
texture_atlases: Extract<Res<Assets<TextureAtlas>>>,
179180
uinode_query: Extract<
180181
Query<(
181182
&Node,
182183
&GlobalTransform,
183184
&UiColor,
184185
&UiImage,
185186
&ComputedVisibility,
187+
Option<&TextureSheet>,
186188
Option<&CalculatedClip>,
187189
)>,
188190
>,
189191
) {
190192
extracted_uinodes.uinodes.clear();
191-
for (uinode, transform, color, image, visibility, clip) in uinode_query.iter() {
192-
if !visibility.is_visible() {
193+
for (uinode, transform, color, image, visibility, sheet, clip) in uinode_query.iter() {
194+
// Skip if the node is invisible or if its size is set to zero (e.g. when a parent is set to `Display::None`)
195+
if !visibility.is_visible() || uinode.size == Vec2::ZERO {
193196
continue;
194197
}
195198
let image = image.0.clone_weak();
@@ -201,15 +204,29 @@ pub fn extract_uinodes(
201204
if color.0.a() == 0.0 {
202205
continue;
203206
}
207+
let (atlas_size, rect_min) = sheet
208+
.and_then(|s| {
209+
texture_atlases
210+
.get(&s.texture_atlas)
211+
.map(|a| (a, s.texture_index))
212+
})
213+
.and_then(|(atlas, index)| {
214+
atlas
215+
.textures
216+
.get(index)
217+
.map(|rect| (Some(atlas.size), rect.min))
218+
})
219+
.unwrap_or((None, Vec2::ZERO));
220+
204221
extracted_uinodes.uinodes.push(ExtractedUiNode {
205222
transform: transform.compute_matrix(),
206223
color: color.0,
207224
rect: bevy_sprite::Rect {
208-
min: Vec2::ZERO,
209-
max: uinode.size,
225+
min: rect_min,
226+
max: rect_min + uinode.size,
210227
},
211228
image,
212-
atlas_size: None,
229+
atlas_size,
213230
clip: clip.map(|clip| clip.clip),
214231
});
215232
}

examples/ui/button.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ fn main() {
1010
.insert_resource(WinitSettings::desktop_app())
1111
.add_startup_system(setup)
1212
.add_system(button_system)
13+
.add_system(sheet_button_system)
1314
.run();
1415
}
1516

@@ -43,9 +44,35 @@ fn button_system(
4344
}
4445
}
4546

46-
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
47+
fn sheet_button_system(
48+
mut interaction_query: Query<
49+
(&Interaction, &mut TextureSheet),
50+
(Changed<Interaction>, With<Button>),
51+
>,
52+
) {
53+
for (interaction, mut sheet) in interaction_query.iter_mut() {
54+
match *interaction {
55+
Interaction::Clicked => {
56+
sheet.texture_index = 2;
57+
}
58+
Interaction::Hovered => {
59+
sheet.texture_index = 1;
60+
}
61+
Interaction::None => {
62+
sheet.texture_index = 0;
63+
}
64+
}
65+
}
66+
}
67+
68+
fn setup(
69+
mut commands: Commands,
70+
asset_server: Res<AssetServer>,
71+
mut texture_atlases: ResMut<Assets<TextureAtlas>>,
72+
) {
4773
// ui camera
4874
commands.spawn_bundle(Camera2dBundle::default());
75+
// Classic button
4976
commands
5077
.spawn_bundle(ButtonBundle {
5178
style: Style {
@@ -71,4 +98,22 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
7198
},
7299
));
73100
});
101+
// Texture sheet button
102+
let handle = asset_server.load("textures/array_texture.png");
103+
let texture_atlas = texture_atlases.add(TextureAtlas::from_grid(Vec2::splat(250.0), 1, 4));
104+
commands
105+
.spawn_bundle(ButtonBundle {
106+
style: Style {
107+
size: Size::new(Val::Px(150.0), Val::Px(65.0)),
108+
// center button
109+
margin: UiRect::all(Val::Auto),
110+
..default()
111+
},
112+
image: handle.into(),
113+
..default()
114+
})
115+
.insert(TextureSheet {
116+
texture_atlas,
117+
texture_index: 0,
118+
});
74119
}

0 commit comments

Comments
 (0)