Skip to content

Commit 5f12611

Browse files
committed
Flip UI image (#6292)
# Objective Fixes #3225, Allow for flippable UI Images ## Solution Add flip_x and flip_y fields to UiImage, and swap the UV coordinates accordingly in ui_prepare_nodes. ## Changelog * Changes UiImage to a struct with texture, flip_x, and flip_y fields. * Adds flip_x and flip_y fields to ExtractedUiNode. * Changes extract_uinodes to extract the flip_x and flip_y values from UiImage. * Changes prepare_uinodes to swap the UV coordinates as required. * Changes UiImage derefs to texture field accesses.
1 parent 3ac06b5 commit 5f12611

File tree

4 files changed

+48
-18
lines changed

4 files changed

+48
-18
lines changed

crates/bevy_ui/src/render/mod.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,8 @@ pub struct ExtractedUiNode {
192192
pub image: Handle<Image>,
193193
pub atlas_size: Option<Vec2>,
194194
pub clip: Option<Rect>,
195+
pub flip_x: bool,
196+
pub flip_y: bool,
195197
pub scale_factor: f32,
196198
}
197199

@@ -225,13 +227,11 @@ pub fn extract_uinodes(
225227
if !visibility.is_visible() {
226228
continue;
227229
}
228-
229-
let image = if let Some(image) = maybe_image {
230-
image.0.clone_weak()
230+
let (image, flip_x, flip_y) = if let Some(image) = maybe_image {
231+
(image.texture.clone_weak(), image.flip_x, image.flip_y)
231232
} else {
232-
DEFAULT_IMAGE_HANDLE.typed().clone_weak()
233+
(DEFAULT_IMAGE_HANDLE.typed().clone_weak(), false, false)
233234
};
234-
235235
// Skip loading images
236236
if !images.contains(&image) {
237237
continue;
@@ -252,6 +252,8 @@ pub fn extract_uinodes(
252252
image,
253253
atlas_size: None,
254254
clip: clip.map(|clip| clip.clip),
255+
flip_x,
256+
flip_y,
255257
scale_factor,
256258
});
257259
}
@@ -378,6 +380,8 @@ pub fn extract_text_uinodes(
378380
image: texture,
379381
atlas_size,
380382
clip: clip.map(|clip| clip.clip),
383+
flip_x: false,
384+
flip_y: false,
381385
scale_factor,
382386
});
383387
}
@@ -512,7 +516,7 @@ pub fn prepare_uinodes(
512516
}
513517

514518
let atlas_extent = extracted_uinode.atlas_size.unwrap_or(uinode_rect.max);
515-
let uvs = [
519+
let mut uvs = [
516520
Vec2::new(
517521
uinode_rect.min.x + positions_diff[0].x * extracted_uinode.scale_factor,
518522
uinode_rect.min.y + positions_diff[0].y * extracted_uinode.scale_factor,
@@ -532,6 +536,13 @@ pub fn prepare_uinodes(
532536
]
533537
.map(|pos| pos / atlas_extent);
534538

539+
if extracted_uinode.flip_x {
540+
uvs = [uvs[1], uvs[0], uvs[3], uvs[2]];
541+
}
542+
if extracted_uinode.flip_y {
543+
uvs = [uvs[3], uvs[2], uvs[1], uvs[0]];
544+
}
545+
535546
for i in QUAD_INDICES {
536547
ui_meta.vertices.push(UiVertex {
537548
position: positions_clipped[i].into(),

crates/bevy_ui/src/ui_node.rs

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use crate::{Size, UiRect};
22
use bevy_asset::Handle;
3-
use bevy_derive::{Deref, DerefMut};
43
use bevy_ecs::{prelude::Component, reflect::ReflectComponent};
54
use bevy_math::{Rect, Vec2};
65
use bevy_reflect::prelude::*;
@@ -452,19 +451,39 @@ impl From<Color> for BackgroundColor {
452451
}
453452

454453
/// The 2D texture displayed for this UI node
455-
#[derive(Component, Clone, Debug, Reflect, Deref, DerefMut)]
454+
#[derive(Component, Clone, Debug, Reflect)]
456455
#[reflect(Component, Default)]
457-
pub struct UiImage(pub Handle<Image>);
456+
pub struct UiImage {
457+
/// Handle to the texture
458+
pub texture: Handle<Image>,
459+
/// Whether the image should be flipped along its x-axis
460+
pub flip_x: bool,
461+
/// Whether the image should be flipped along its y-axis
462+
pub flip_y: bool,
463+
}
458464

459465
impl Default for UiImage {
460-
fn default() -> Self {
461-
Self(DEFAULT_IMAGE_HANDLE.typed())
466+
fn default() -> UiImage {
467+
UiImage {
468+
texture: DEFAULT_IMAGE_HANDLE.typed(),
469+
flip_x: false,
470+
flip_y: false,
471+
}
472+
}
473+
}
474+
475+
impl UiImage {
476+
pub fn new(texture: Handle<Image>) -> Self {
477+
Self {
478+
texture,
479+
..Default::default()
480+
}
462481
}
463482
}
464483

465484
impl From<Handle<Image>> for UiImage {
466-
fn from(handle: Handle<Image>) -> Self {
467-
Self(handle)
485+
fn from(texture: Handle<Image>) -> Self {
486+
Self::new(texture)
468487
}
469488
}
470489

crates/bevy_ui/src/widget/image.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub fn image_node_system(
2626
mut query: Query<(&mut CalculatedSize, &UiImage), (With<ImageMode>, Without<Text>)>,
2727
) {
2828
for (mut calculated_size, image) in &mut query {
29-
if let Some(texture) = textures.get(image) {
29+
if let Some(texture) = textures.get(&image.texture) {
3030
let size = Size {
3131
width: Val::Px(texture.texture_descriptor.size.width as f32),
3232
height: Val::Px(texture.texture_descriptor.size.height as f32),

examples/games/game_menu.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ mod splash {
9090
size: Size::new(Val::Px(200.0), Val::Auto),
9191
..default()
9292
},
93-
image: UiImage(icon),
93+
image: UiImage::new(icon),
9494
..default()
9595
},
9696
OnSplashScreen,
@@ -462,7 +462,7 @@ mod menu {
462462
let icon = asset_server.load("textures/Game Icons/right.png");
463463
parent.spawn(ImageBundle {
464464
style: button_icon_style.clone(),
465-
image: UiImage(icon),
465+
image: UiImage::new(icon),
466466
..default()
467467
});
468468
parent.spawn(TextBundle::from_section(
@@ -483,7 +483,7 @@ mod menu {
483483
let icon = asset_server.load("textures/Game Icons/wrench.png");
484484
parent.spawn(ImageBundle {
485485
style: button_icon_style.clone(),
486-
image: UiImage(icon),
486+
image: UiImage::new(icon),
487487
..default()
488488
});
489489
parent.spawn(TextBundle::from_section(
@@ -504,7 +504,7 @@ mod menu {
504504
let icon = asset_server.load("textures/Game Icons/exitRight.png");
505505
parent.spawn(ImageBundle {
506506
style: button_icon_style,
507-
image: UiImage(icon),
507+
image: UiImage::new(icon),
508508
..default()
509509
});
510510
parent.spawn(TextBundle::from_section("Quit", button_text_style));

0 commit comments

Comments
 (0)