From 2e6f96f441ebb8901581bbe0a595b2b93e707d4d Mon Sep 17 00:00:00 2001 From: Ickshonpe Date: Tue, 18 Oct 2022 12:23:51 +0100 Subject: [PATCH 1/7] # Allow for flippable UI Images #3225 Adds the ImageFlip component. Adds an ImageFlip field called flip to UiImageBundle. Adds flip_x and flip_y fields to ExtractedUiNode. Changes extract_uinodes to extract the ImageFlip component values. Changes prepare_uinodes to swap the UV coords depending on the values of the ExtractedUiNode's flip_x and flip_y fields. --- crates/bevy_ui/src/entity.rs | 4 +++- crates/bevy_ui/src/render/mod.rs | 27 ++++++++++++++++++++++++--- crates/bevy_ui/src/ui_node.rs | 10 ++++++++++ 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/crates/bevy_ui/src/entity.rs b/crates/bevy_ui/src/entity.rs index abb73fae70ec2..9825e9d67bd26 100644 --- a/crates/bevy_ui/src/entity.rs +++ b/crates/bevy_ui/src/entity.rs @@ -2,7 +2,7 @@ use crate::{ widget::{Button, ImageMode}, - BackgroundColor, CalculatedSize, FocusPolicy, Interaction, Node, Style, UiImage, + BackgroundColor, CalculatedSize, FocusPolicy, Interaction, Node, Style, UiImage, FlipImage, }; use bevy_ecs::{ bundle::Bundle, @@ -81,6 +81,8 @@ pub struct ImageBundle { pub background_color: BackgroundColor, /// The image of the node pub image: UiImage, + /// Whether the image should be flipped along its x and y axes. + pub flip_image: FlipImage, /// Whether this node should block interaction with lower nodes pub focus_policy: FocusPolicy, /// The transform of the node diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index 835d0fbc97202..b0e12d8520ad3 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -5,7 +5,7 @@ use bevy_core_pipeline::{core_2d::Camera2d, core_3d::Camera3d}; pub use pipeline::*; pub use render_pass::*; -use crate::{prelude::UiCameraConfig, BackgroundColor, CalculatedClip, Node, UiImage}; +use crate::{prelude::UiCameraConfig, BackgroundColor, CalculatedClip, Node, UiImage, FlipImage}; use bevy_app::prelude::*; use bevy_asset::{load_internal_asset, AssetEvent, Assets, Handle, HandleUntyped}; use bevy_ecs::prelude::*; @@ -166,6 +166,8 @@ pub struct ExtractedUiNode { pub image: Handle, pub atlas_size: Option, pub clip: Option, + pub flip_x: bool, + pub flip_y: bool, } #[derive(Resource, Default)] @@ -183,12 +185,13 @@ pub fn extract_uinodes( &BackgroundColor, &UiImage, &ComputedVisibility, + Option<&FlipImage>, Option<&CalculatedClip>, )>, >, ) { extracted_uinodes.uinodes.clear(); - for (uinode, transform, color, image, visibility, clip) in uinode_query.iter() { + for (uinode, transform, color, image, visibility, flip_image, clip) in uinode_query.iter() { if !visibility.is_visible() { continue; } @@ -201,6 +204,12 @@ pub fn extract_uinodes( if color.0.a() == 0.0 { continue; } + let (flip_x, flip_y) = + if let Some(flip) = flip_image { + (flip.x_axis, flip.y_axis) + } else { + (false, false) + }; extracted_uinodes.uinodes.push(ExtractedUiNode { transform: transform.compute_matrix(), background_color: color.0, @@ -211,6 +220,8 @@ pub fn extract_uinodes( image, atlas_size: None, clip: clip.map(|clip| clip.clip), + flip_x, + flip_y, }); } } @@ -330,6 +341,8 @@ pub fn extract_text_uinodes( image: texture, atlas_size, clip: clip.map(|clip| clip.clip), + flip_x: false, + flip_y: false, }); } } @@ -462,7 +475,7 @@ pub fn prepare_uinodes( } let atlas_extent = extracted_uinode.atlas_size.unwrap_or(uinode_rect.max); - let uvs = [ + let mut uvs = [ Vec2::new( uinode_rect.min.x + positions_diff[3].x, uinode_rect.min.y - positions_diff[3].y, @@ -482,6 +495,14 @@ pub fn prepare_uinodes( ] .map(|pos| pos / atlas_extent); + if extracted_uinode.flip_x { + uvs = [uvs[1], uvs[0], uvs[3], uvs[2]]; + } + if extracted_uinode.flip_y { + uvs = [uvs[3], uvs[2], uvs[1], uvs[0]]; + } + + for i in QUAD_INDICES { ui_meta.vertices.push(UiVertex { position: positions_clipped[i].into(), diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index 332567274b8ce..9b3fb205d2bcc 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -409,6 +409,16 @@ impl Default for UiImage { } } +/// Controls whether image is flipped along the x and y axes. +#[derive(Component, Clone, Debug, Default, Reflect)] +#[reflect(Component, Default)] +pub struct FlipImage { + /// Flip the image along the x-axis + pub x_axis: bool, + /// Flip the image along the y-axis + pub y_axis: bool, +} + impl From> for UiImage { fn from(handle: Handle) -> Self { Self(handle) From 572a47182b508257702d9004b0c33fdb668a75e3 Mon Sep 17 00:00:00 2001 From: Ickshonpe Date: Tue, 18 Oct 2022 13:39:13 +0100 Subject: [PATCH 2/7] corrected formatting with cargo fmt --- crates/bevy_ui/src/entity.rs | 2 +- crates/bevy_ui/src/render/mod.rs | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/crates/bevy_ui/src/entity.rs b/crates/bevy_ui/src/entity.rs index 9825e9d67bd26..8f9e605fb6736 100644 --- a/crates/bevy_ui/src/entity.rs +++ b/crates/bevy_ui/src/entity.rs @@ -2,7 +2,7 @@ use crate::{ widget::{Button, ImageMode}, - BackgroundColor, CalculatedSize, FocusPolicy, Interaction, Node, Style, UiImage, FlipImage, + BackgroundColor, CalculatedSize, FlipImage, FocusPolicy, Interaction, Node, Style, UiImage, }; use bevy_ecs::{ bundle::Bundle, diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index b0e12d8520ad3..740f522780bb0 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -5,7 +5,7 @@ use bevy_core_pipeline::{core_2d::Camera2d, core_3d::Camera3d}; pub use pipeline::*; pub use render_pass::*; -use crate::{prelude::UiCameraConfig, BackgroundColor, CalculatedClip, Node, UiImage, FlipImage}; +use crate::{prelude::UiCameraConfig, BackgroundColor, CalculatedClip, FlipImage, Node, UiImage}; use bevy_app::prelude::*; use bevy_asset::{load_internal_asset, AssetEvent, Assets, Handle, HandleUntyped}; use bevy_ecs::prelude::*; @@ -191,7 +191,7 @@ pub fn extract_uinodes( >, ) { extracted_uinodes.uinodes.clear(); - for (uinode, transform, color, image, visibility, flip_image, clip) in uinode_query.iter() { + for (uinode, transform, color, image, visibility, flip_image, clip) in uinode_query.iter() { if !visibility.is_visible() { continue; } @@ -204,12 +204,11 @@ pub fn extract_uinodes( if color.0.a() == 0.0 { continue; } - let (flip_x, flip_y) = - if let Some(flip) = flip_image { - (flip.x_axis, flip.y_axis) - } else { - (false, false) - }; + let (flip_x, flip_y) = if let Some(flip) = flip_image { + (flip.x_axis, flip.y_axis) + } else { + (false, false) + }; extracted_uinodes.uinodes.push(ExtractedUiNode { transform: transform.compute_matrix(), background_color: color.0, @@ -502,7 +501,6 @@ pub fn prepare_uinodes( uvs = [uvs[3], uvs[2], uvs[1], uvs[0]]; } - for i in QUAD_INDICES { ui_meta.vertices.push(UiVertex { position: positions_clipped[i].into(), From 146a4813434a8dcbd3b14f0e75b8886b1e8d1a4e Mon Sep 17 00:00:00 2001 From: Ickshonpe Date: Tue, 18 Oct 2022 13:45:25 +0100 Subject: [PATCH 3/7] register_type FlipImage --- crates/bevy_ui/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bevy_ui/src/lib.rs b/crates/bevy_ui/src/lib.rs index 6e47967359214..92876c363d21b 100644 --- a/crates/bevy_ui/src/lib.rs +++ b/crates/bevy_ui/src/lib.rs @@ -92,6 +92,7 @@ impl Plugin for UiPlugin { .register_type::