Skip to content

Commit a97e8d0

Browse files
committed
Ui texture sheet
1 parent 8388f0b commit a97e8d0

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::{ExtractedView, ViewUniforms, Visibility},
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,36 +176,53 @@ 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
&Visibility,
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();
196199
// Skip loading images
197200
if !images.contains(&image) {
198201
continue;
199202
}
203+
let (atlas_size, rect_min) = sheet
204+
.and_then(|s| {
205+
texture_atlases
206+
.get(&s.texture_atlas)
207+
.map(|a| (a, s.texture_index))
208+
})
209+
.and_then(|(atlas, index)| {
210+
atlas
211+
.textures
212+
.get(index)
213+
.map(|rect| (Some(atlas.size), rect.min))
214+
})
215+
.unwrap_or((None, Vec2::ZERO));
216+
200217
extracted_uinodes.uinodes.push(ExtractedUiNode {
201218
transform: transform.compute_matrix(),
202219
color: color.0,
203220
rect: bevy_sprite::Rect {
204-
min: Vec2::ZERO,
205-
max: uinode.size,
221+
min: rect_min,
222+
max: rect_min + uinode.size,
206223
},
207224
image,
208-
atlas_size: None,
225+
atlas_size,
209226
clip: clip.map(|clip| clip.clip),
210227
});
211228
}

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 {
@@ -75,4 +102,22 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
75102
..default()
76103
});
77104
});
105+
// Texture sheet button
106+
let handle = asset_server.load("textures/array_texture.png");
107+
let texture_atlas = texture_atlases.add(TextureAtlas::from_grid(Vec2::splat(250.0), 1, 4));
108+
commands
109+
.spawn_bundle(ButtonBundle {
110+
style: Style {
111+
size: Size::new(Val::Px(150.0), Val::Px(65.0)),
112+
// center button
113+
margin: UiRect::all(Val::Auto),
114+
..default()
115+
},
116+
image: handle.into(),
117+
..default()
118+
})
119+
.insert(TextureSheet {
120+
texture_atlas,
121+
texture_index: 0,
122+
});
78123
}

0 commit comments

Comments
 (0)