From 62e77db07ca0783558d52b5dd4925609b2e80165 Mon Sep 17 00:00:00 2001 From: kdecay Date: Fri, 31 Dec 2021 03:59:03 +0100 Subject: [PATCH 01/15] Added and updated bevy_math documentation. Added an example for 100% example coverage. --- crates/bevy_math/src/face_toward.rs | 47 ++++++++++++++++++- crates/bevy_math/src/geometry.rs | 72 ++++++++++++++++++++++++++++- crates/bevy_math/src/lib.rs | 19 ++++++++ 3 files changed, 134 insertions(+), 4 deletions(-) diff --git a/crates/bevy_math/src/face_toward.rs b/crates/bevy_math/src/face_toward.rs index f873964b18afc..695a02edf7bca 100644 --- a/crates/bevy_math/src/face_toward.rs +++ b/crates/bevy_math/src/face_toward.rs @@ -1,8 +1,51 @@ use crate::{Mat4, Vec3}; -/// Generates a translation / rotation matrix that faces a given target +/// Implements a function to generate a translation / rotation matrix that faces a given target. +/// +/// # Example +/// +/// ```rust +/// # use bevy_math::{FaceToward, Vec3, Vec4}; +/// # #[allow(dead_code)] +/// struct Matrix { +/// x_axis: Vec4, +/// y_axis: Vec4, +/// z_axis: Vec4, +/// w_axis: Vec4, +/// } +/// +/// impl FaceToward for Matrix { +/// fn face_toward(eye: Vec3, center: Vec3, up: Vec3) -> Self { +/// let forward = (eye - center).normalize(); +/// let right = up.cross(forward).normalize(); +/// let up = forward.cross(right); +/// +/// Matrix { +/// x_axis: right.extend(0.0), +/// y_axis: up.extend(0.0), +/// z_axis: forward.extend(0.0), +/// w_axis: eye.extend(1.0), +/// } +/// } +/// } +/// +/// fn main() { +/// let matrix = Matrix::face_toward( +/// Vec3::new(50.0, 60.0, 0.0), +/// Vec3::new(0.0, 0.0, 0.0), +/// Vec3::new(0.0, 1.0, 0.0), +/// ); +/// +/// assert_eq!(matrix.x_axis, Vec4::new(0.0, 0.0, -1.0, -0.0)); +/// assert_eq!(matrix.y_axis, Vec4::new(-0.7682213, 0.6401844, 0.0, 0.0)); +/// assert_eq!(matrix.z_axis, Vec4::new(0.6401844, 0.7682213, 0.0, 0.0)); +/// assert_eq!(matrix.w_axis, Vec4::new(50.0, 60.0, 0.0, 1.0)); +/// } +/// ``` pub trait FaceToward { - /// Generates a translation / rotation matrix that faces a given target + /// Generates a translation / rotation matrix that faces a given target. + /// + /// For an example on how to use this function see [`FaceToward`]. fn face_toward(eye: Vec3, center: Vec3, up: Vec3) -> Self; } diff --git a/crates/bevy_math/src/geometry.rs b/crates/bevy_math/src/geometry.rs index 0a449e5d026f9..a0f0994082bb8 100644 --- a/crates/bevy_math/src/geometry.rs +++ b/crates/bevy_math/src/geometry.rs @@ -2,15 +2,45 @@ use bevy_reflect::Reflect; use glam::Vec2; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; -/// A two dimensional "size" as defined by a width and height +/// A 2-dimensional area defined by a width and height. +/// +/// It is commonly used to define the size of a text or UI element. +/// +/// # Example +/// +/// ```rust +/// # use bevy_math::Size; +/// # +/// let size = Size:: { +/// width: 1.0, +/// height: 2.0, +/// }; +/// +/// assert_eq!(size.width, 1.0); +/// assert_eq!(size.height, 2.0); +/// ``` #[derive(Copy, Clone, PartialEq, Debug, Reflect)] #[reflect(PartialEq)] pub struct Size { + /// The width of the 2-dimensional area. pub width: T, + /// The height of the 2-dimensional area. pub height: T, } impl Size { + /// Creates a new [`Size`] from a width and a height. + /// + /// # Example + /// + /// ```rust + /// # use bevy_math::Size; + /// # + /// let size = Size::new(1.0, 2.0); + /// + /// assert_eq!(size.width, 1.0); + /// assert_eq!(size.height, 2.0); + /// ``` pub fn new(width: T, height: T) -> Self { Size { width, height } } @@ -25,17 +55,55 @@ impl Default for Size { } } -/// A rect, as defined by its "side" locations +/// A rectangle defined by its side locations. +/// +/// It is commonly used to define positions, margins, paddings and borders. +/// +/// # Example +/// +/// ```rust +/// # use bevy_math::Rect; +/// # +/// let rect = Rect:: { +/// left: 1.0, +/// right: 2.0, +/// top: 3.0, +/// bottom: 4.0, +/// }; +/// +/// assert_eq!(rect.left, 1.0); +/// assert_eq!(rect.right, 2.0); +/// assert_eq!(rect.top, 3.0); +/// assert_eq!(rect.bottom, 4.0); +/// ``` #[derive(Copy, Clone, PartialEq, Debug, Reflect)] #[reflect(PartialEq)] pub struct Rect { + /// The left side of the rectangle. pub left: T, + /// The right side of the rectangle. pub right: T, + /// The top side of the rectangle. pub top: T, + /// The bottom side of the rectangle. pub bottom: T, } impl Rect { + /// Creates a new [`Rect`] from a single value. + /// + /// # Example + /// + /// ```rust + /// # use bevy_math::Rect; + /// # + /// let rect = Rect::::all(1.0); + /// + /// assert_eq!(rect.left, 1.0); + /// assert_eq!(rect.right, 1.0); + /// assert_eq!(rect.top, 1.0); + /// assert_eq!(rect.bottom, 1.0); + /// ``` pub fn all(value: T) -> Self where T: Clone, diff --git a/crates/bevy_math/src/lib.rs b/crates/bevy_math/src/lib.rs index 9a8ae797ed04b..641de659ef6f0 100644 --- a/crates/bevy_math/src/lib.rs +++ b/crates/bevy_math/src/lib.rs @@ -1,3 +1,15 @@ +#![warn(missing_docs)] + +//! Provides math types and functionalities for the bevy game engine. +//! +//! The commonly used types are vectors, rectangles and sizes. +//! +//! # Example +//! +//! ```rust +//! use bevy_math::prelude::*; +//! ``` + mod face_toward; mod geometry; @@ -5,6 +17,13 @@ pub use face_toward::*; pub use geometry::*; pub use glam::*; +/// The bevy_math prelude. +/// +/// # Example +/// +/// ```rust +/// use bevy_math::prelude::*; +/// ``` pub mod prelude { #[doc(hidden)] pub use crate::{ From 91720c8e6512eb497d7fb61d4a012a5836d0d6d7 Mon Sep 17 00:00:00 2001 From: kdecay Date: Fri, 31 Dec 2021 05:44:49 +0100 Subject: [PATCH 02/15] Added a better description and small fixes. --- crates/bevy_math/src/face_toward.rs | 2 +- crates/bevy_math/src/geometry.rs | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/crates/bevy_math/src/face_toward.rs b/crates/bevy_math/src/face_toward.rs index 695a02edf7bca..7dbc8bbeb500e 100644 --- a/crates/bevy_math/src/face_toward.rs +++ b/crates/bevy_math/src/face_toward.rs @@ -1,6 +1,6 @@ use crate::{Mat4, Vec3}; -/// Implements a function to generate a translation / rotation matrix that faces a given target. +/// Implements a function that generates a translation / rotation matrix that faces a given target. /// /// # Example /// diff --git a/crates/bevy_math/src/geometry.rs b/crates/bevy_math/src/geometry.rs index a0f0994082bb8..28e5783b05d49 100644 --- a/crates/bevy_math/src/geometry.rs +++ b/crates/bevy_math/src/geometry.rs @@ -59,8 +59,16 @@ impl Default for Size { /// /// It is commonly used to define positions, margins, paddings and borders. /// +/// The values supplied define the distances from the nominal center of the +/// rectangle to the edge. If any of the values supplied are negative the +/// nominal center wouldn't be inside of the rectangle. +/// /// # Example /// +/// In the following example the rectangle has a left value of 1.0 and a right +/// value of 2.0, which means that the width of the rectangle is 3.0. The actual +/// center of this rectangle is offset by 0.5 to the right of the nominal center. +/// /// ```rust /// # use bevy_math::Rect; /// # @@ -90,7 +98,7 @@ pub struct Rect { } impl Rect { - /// Creates a new [`Rect`] from a single value. + /// Creates a new [`Rect`] where all sides are equidistant from the center. /// /// # Example /// @@ -104,15 +112,15 @@ impl Rect { /// assert_eq!(rect.top, 1.0); /// assert_eq!(rect.bottom, 1.0); /// ``` - pub fn all(value: T) -> Self + pub fn all(distance_from_center: T) -> Self where T: Clone, { Rect { - left: value.clone(), - right: value.clone(), - top: value.clone(), - bottom: value, + left: distance_from_center.clone(), + right: distance_from_center.clone(), + top: distance_from_center.clone(), + bottom: distance_from_center, } } } From a51d3b206d3d777cba9bd4d34bce1a43bdb620c7 Mon Sep 17 00:00:00 2001 From: kdecay Date: Mon, 10 Jan 2022 03:11:18 +0100 Subject: [PATCH 03/15] Clean up bevy_math and rename Rect to UiRect. --- crates/bevy_math/src/face_toward.rs | 84 ------ crates/bevy_math/src/geometry.rs | 260 ------------------ crates/bevy_math/src/lib.rs | 23 +- crates/bevy_render/src/texture/image.rs | 6 +- crates/bevy_text/src/glyph_brush.rs | 6 +- crates/bevy_text/src/pipeline.rs | 10 +- crates/bevy_text/src/text.rs | 4 +- crates/bevy_text/src/text2d.rs | 16 +- crates/bevy_ui/src/flex/convert.rs | 5 +- crates/bevy_ui/src/geometry.rs | 333 +++++++++++++++++++++++ crates/bevy_ui/src/lib.rs | 7 +- crates/bevy_ui/src/ui_node.rs | 16 +- crates/bevy_ui/src/widget/image.rs | 3 +- crates/bevy_ui/src/widget/text.rs | 10 +- examples/ecs/state.rs | 2 +- examples/game/alien_cake_addict.rs | 4 +- examples/game/breakout.rs | 2 +- examples/tools/bevymark.rs | 2 +- examples/ui/button.rs | 2 +- examples/ui/font_atlas_debug.rs | 2 +- examples/ui/text.rs | 2 +- examples/ui/text_debug.rs | 8 +- examples/ui/ui.rs | 20 +- examples/window/scale_factor_override.rs | 2 +- 24 files changed, 401 insertions(+), 428 deletions(-) delete mode 100644 crates/bevy_math/src/face_toward.rs delete mode 100644 crates/bevy_math/src/geometry.rs create mode 100644 crates/bevy_ui/src/geometry.rs diff --git a/crates/bevy_math/src/face_toward.rs b/crates/bevy_math/src/face_toward.rs deleted file mode 100644 index 7dbc8bbeb500e..0000000000000 --- a/crates/bevy_math/src/face_toward.rs +++ /dev/null @@ -1,84 +0,0 @@ -use crate::{Mat4, Vec3}; - -/// Implements a function that generates a translation / rotation matrix that faces a given target. -/// -/// # Example -/// -/// ```rust -/// # use bevy_math::{FaceToward, Vec3, Vec4}; -/// # #[allow(dead_code)] -/// struct Matrix { -/// x_axis: Vec4, -/// y_axis: Vec4, -/// z_axis: Vec4, -/// w_axis: Vec4, -/// } -/// -/// impl FaceToward for Matrix { -/// fn face_toward(eye: Vec3, center: Vec3, up: Vec3) -> Self { -/// let forward = (eye - center).normalize(); -/// let right = up.cross(forward).normalize(); -/// let up = forward.cross(right); -/// -/// Matrix { -/// x_axis: right.extend(0.0), -/// y_axis: up.extend(0.0), -/// z_axis: forward.extend(0.0), -/// w_axis: eye.extend(1.0), -/// } -/// } -/// } -/// -/// fn main() { -/// let matrix = Matrix::face_toward( -/// Vec3::new(50.0, 60.0, 0.0), -/// Vec3::new(0.0, 0.0, 0.0), -/// Vec3::new(0.0, 1.0, 0.0), -/// ); -/// -/// assert_eq!(matrix.x_axis, Vec4::new(0.0, 0.0, -1.0, -0.0)); -/// assert_eq!(matrix.y_axis, Vec4::new(-0.7682213, 0.6401844, 0.0, 0.0)); -/// assert_eq!(matrix.z_axis, Vec4::new(0.6401844, 0.7682213, 0.0, 0.0)); -/// assert_eq!(matrix.w_axis, Vec4::new(50.0, 60.0, 0.0, 1.0)); -/// } -/// ``` -pub trait FaceToward { - /// Generates a translation / rotation matrix that faces a given target. - /// - /// For an example on how to use this function see [`FaceToward`]. - fn face_toward(eye: Vec3, center: Vec3, up: Vec3) -> Self; -} - -impl FaceToward for Mat4 { - fn face_toward(eye: Vec3, center: Vec3, up: Vec3) -> Self { - let forward = (eye - center).normalize(); - let right = up.cross(forward).normalize(); - let up = forward.cross(right); - Mat4::from_cols( - right.extend(0.0), - up.extend(0.0), - forward.extend(0.0), - eye.extend(1.0), - ) - } -} - -#[cfg(test)] -mod test { - #[test] - fn face_toward_mat4() { - use crate::{FaceToward, Mat4, Vec3, Vec4}; - - // Completely arbitrary arguments - let matrix = Mat4::face_toward( - Vec3::new(50.0, 60.0, 0.0), - Vec3::new(0.0, 0.0, 0.0), - Vec3::new(0.0, 1.0, 0.0), - ); - - assert_eq!(matrix.x_axis, Vec4::new(0.0, 0.0, -1.0, -0.0)); - assert_eq!(matrix.y_axis, Vec4::new(-0.7682213, 0.6401844, 0.0, 0.0)); - assert_eq!(matrix.z_axis, Vec4::new(0.6401844, 0.7682213, 0.0, 0.0)); - assert_eq!(matrix.w_axis, Vec4::new(50.0, 60.0, 0.0, 1.0)); - } -} diff --git a/crates/bevy_math/src/geometry.rs b/crates/bevy_math/src/geometry.rs deleted file mode 100644 index 28e5783b05d49..0000000000000 --- a/crates/bevy_math/src/geometry.rs +++ /dev/null @@ -1,260 +0,0 @@ -use bevy_reflect::Reflect; -use glam::Vec2; -use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; - -/// A 2-dimensional area defined by a width and height. -/// -/// It is commonly used to define the size of a text or UI element. -/// -/// # Example -/// -/// ```rust -/// # use bevy_math::Size; -/// # -/// let size = Size:: { -/// width: 1.0, -/// height: 2.0, -/// }; -/// -/// assert_eq!(size.width, 1.0); -/// assert_eq!(size.height, 2.0); -/// ``` -#[derive(Copy, Clone, PartialEq, Debug, Reflect)] -#[reflect(PartialEq)] -pub struct Size { - /// The width of the 2-dimensional area. - pub width: T, - /// The height of the 2-dimensional area. - pub height: T, -} - -impl Size { - /// Creates a new [`Size`] from a width and a height. - /// - /// # Example - /// - /// ```rust - /// # use bevy_math::Size; - /// # - /// let size = Size::new(1.0, 2.0); - /// - /// assert_eq!(size.width, 1.0); - /// assert_eq!(size.height, 2.0); - /// ``` - pub fn new(width: T, height: T) -> Self { - Size { width, height } - } -} - -impl Default for Size { - fn default() -> Self { - Self { - width: Default::default(), - height: Default::default(), - } - } -} - -/// A rectangle defined by its side locations. -/// -/// It is commonly used to define positions, margins, paddings and borders. -/// -/// The values supplied define the distances from the nominal center of the -/// rectangle to the edge. If any of the values supplied are negative the -/// nominal center wouldn't be inside of the rectangle. -/// -/// # Example -/// -/// In the following example the rectangle has a left value of 1.0 and a right -/// value of 2.0, which means that the width of the rectangle is 3.0. The actual -/// center of this rectangle is offset by 0.5 to the right of the nominal center. -/// -/// ```rust -/// # use bevy_math::Rect; -/// # -/// let rect = Rect:: { -/// left: 1.0, -/// right: 2.0, -/// top: 3.0, -/// bottom: 4.0, -/// }; -/// -/// assert_eq!(rect.left, 1.0); -/// assert_eq!(rect.right, 2.0); -/// assert_eq!(rect.top, 3.0); -/// assert_eq!(rect.bottom, 4.0); -/// ``` -#[derive(Copy, Clone, PartialEq, Debug, Reflect)] -#[reflect(PartialEq)] -pub struct Rect { - /// The left side of the rectangle. - pub left: T, - /// The right side of the rectangle. - pub right: T, - /// The top side of the rectangle. - pub top: T, - /// The bottom side of the rectangle. - pub bottom: T, -} - -impl Rect { - /// Creates a new [`Rect`] where all sides are equidistant from the center. - /// - /// # Example - /// - /// ```rust - /// # use bevy_math::Rect; - /// # - /// let rect = Rect::::all(1.0); - /// - /// assert_eq!(rect.left, 1.0); - /// assert_eq!(rect.right, 1.0); - /// assert_eq!(rect.top, 1.0); - /// assert_eq!(rect.bottom, 1.0); - /// ``` - pub fn all(distance_from_center: T) -> Self - where - T: Clone, - { - Rect { - left: distance_from_center.clone(), - right: distance_from_center.clone(), - top: distance_from_center.clone(), - bottom: distance_from_center, - } - } -} - -impl Default for Rect { - fn default() -> Self { - Self { - left: Default::default(), - right: Default::default(), - top: Default::default(), - bottom: Default::default(), - } - } -} - -impl Add for Size -where - T: Add, -{ - type Output = Size; - - fn add(self, rhs: Vec2) -> Self::Output { - Self { - width: self.width + rhs.x, - height: self.height + rhs.y, - } - } -} - -impl AddAssign for Size -where - T: AddAssign, -{ - fn add_assign(&mut self, rhs: Vec2) { - self.width += rhs.x; - self.height += rhs.y; - } -} - -impl Sub for Size -where - T: Sub, -{ - type Output = Size; - - fn sub(self, rhs: Vec2) -> Self::Output { - Self { - width: self.width - rhs.x, - height: self.height - rhs.y, - } - } -} - -impl SubAssign for Size -where - T: SubAssign, -{ - fn sub_assign(&mut self, rhs: Vec2) { - self.width -= rhs.x; - self.height -= rhs.y; - } -} - -impl Mul for Size -where - T: Mul, -{ - type Output = Size; - - fn mul(self, rhs: f32) -> Self::Output { - Self::Output { - width: self.width * rhs, - height: self.height * rhs, - } - } -} - -impl MulAssign for Size -where - T: MulAssign, -{ - fn mul_assign(&mut self, rhs: f32) { - self.width *= rhs; - self.height *= rhs; - } -} - -impl Div for Size -where - T: Div, -{ - type Output = Size; - - fn div(self, rhs: f32) -> Self::Output { - Self::Output { - width: self.width / rhs, - height: self.height / rhs, - } - } -} - -impl DivAssign for Size -where - T: DivAssign, -{ - fn div_assign(&mut self, rhs: f32) { - self.width /= rhs; - self.height /= rhs; - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn size_ops() { - type SizeF = Size; - - assert_eq!( - SizeF::new(10., 10.) + Vec2::new(10., 10.), - SizeF::new(20., 20.) - ); - assert_eq!( - SizeF::new(20., 20.) - Vec2::new(10., 10.), - SizeF::new(10., 10.) - ); - assert_eq!(SizeF::new(10., 10.) * 2., SizeF::new(20., 20.)); - assert_eq!(SizeF::new(20., 20.) / 2., SizeF::new(10., 10.)); - - let mut size = SizeF::new(10., 10.); - - size += Vec2::new(10., 10.); - - assert_eq!(size, SizeF::new(20., 20.)); - } -} diff --git a/crates/bevy_math/src/lib.rs b/crates/bevy_math/src/lib.rs index 641de659ef6f0..ca7d41c3f7fe0 100644 --- a/crates/bevy_math/src/lib.rs +++ b/crates/bevy_math/src/lib.rs @@ -2,32 +2,15 @@ //! Provides math types and functionalities for the bevy game engine. //! -//! The commonly used types are vectors, rectangles and sizes. -//! -//! # Example -//! -//! ```rust -//! use bevy_math::prelude::*; -//! ``` - -mod face_toward; -mod geometry; +//! The commonly used types are vectors and matrices. -pub use face_toward::*; -pub use geometry::*; pub use glam::*; /// The bevy_math prelude. -/// -/// # Example -/// -/// ```rust -/// use bevy_math::prelude::*; -/// ``` pub mod prelude { #[doc(hidden)] pub use crate::{ - BVec2, BVec3, BVec4, EulerRot, FaceToward, IVec2, IVec3, IVec4, Mat3, Mat4, Quat, Rect, - Size, UVec2, UVec3, UVec4, Vec2, Vec3, Vec4, + BVec2, BVec3, BVec4, EulerRot, IVec2, IVec3, IVec4, Mat3, Mat4, Quat, UVec2, UVec3, UVec4, + Vec2, Vec3, Vec4, }; } diff --git a/crates/bevy_render/src/texture/image.rs b/crates/bevy_render/src/texture/image.rs index 29063905ae82c..d2abbe87ab614 100644 --- a/crates/bevy_render/src/texture/image.rs +++ b/crates/bevy_render/src/texture/image.rs @@ -7,7 +7,7 @@ use crate::{ }; use bevy_asset::HandleUntyped; use bevy_ecs::system::{lifetimeless::SRes, SystemParamItem}; -use bevy_math::Size; +use bevy_math::Vec2; use bevy_reflect::TypeUuid; use thiserror::Error; use wgpu::{ @@ -380,7 +380,7 @@ pub struct GpuImage { pub texture: Texture, pub texture_view: TextureView, pub sampler: Sampler, - pub size: Size, + pub size: Vec2, } impl RenderAsset for Image { @@ -428,7 +428,7 @@ impl RenderAsset for Image { ); let texture_view = texture.create_view(&TextureViewDescriptor::default()); - let size = Size::new( + let size = Vec2::new( image.texture_descriptor.size.width as f32, image.texture_descriptor.size.height as f32, ); diff --git a/crates/bevy_text/src/glyph_brush.rs b/crates/bevy_text/src/glyph_brush.rs index fc9d5fffc76c5..e7c26e851d4de 100644 --- a/crates/bevy_text/src/glyph_brush.rs +++ b/crates/bevy_text/src/glyph_brush.rs @@ -1,6 +1,6 @@ use ab_glyph::{Font as _, FontArc, Glyph, ScaleFont as _}; use bevy_asset::{Assets, Handle}; -use bevy_math::{Size, Vec2}; +use bevy_math::Vec2; use bevy_render::texture::Image; use bevy_sprite::TextureAtlas; use glyph_brush_layout::{ @@ -29,11 +29,11 @@ impl GlyphBrush { pub fn compute_glyphs( &self, sections: &[S], - bounds: Size, + bounds: Vec2, text_alignment: TextAlignment, ) -> Result, TextError> { let geom = SectionGeometry { - bounds: (bounds.width, bounds.height), + bounds: (bounds.x, bounds.y), ..Default::default() }; let section_glyphs = Layout::default() diff --git a/crates/bevy_text/src/pipeline.rs b/crates/bevy_text/src/pipeline.rs index 4a13ecffdf1b0..fdefd97175930 100644 --- a/crates/bevy_text/src/pipeline.rs +++ b/crates/bevy_text/src/pipeline.rs @@ -2,7 +2,7 @@ use std::hash::Hash; use ab_glyph::{PxScale, ScaleFont}; use bevy_asset::{Assets, Handle, HandleId}; -use bevy_math::Size; +use bevy_math::Vec2; use bevy_render::texture::Image; use bevy_sprite::TextureAtlas; use bevy_utils::HashMap; @@ -32,7 +32,7 @@ impl Default for TextPipeline { pub struct TextLayoutInfo { pub glyphs: Vec, - pub size: Size, + pub size: Vec2, } impl TextPipeline { @@ -56,7 +56,7 @@ impl TextPipeline { sections: &[TextSection], scale_factor: f64, text_alignment: TextAlignment, - bounds: Size, + bounds: Vec2, font_atlas_set_storage: &mut Assets, texture_atlases: &mut Assets, textures: &mut Assets, @@ -92,7 +92,7 @@ impl TextPipeline { id, TextLayoutInfo { glyphs: Vec::new(), - size: Size::new(0., 0.), + size: Vec2::new(0., 0.), }, ); return Ok(()); @@ -112,7 +112,7 @@ impl TextPipeline { max_y = max_y.max(glyph.position.y - scaled_font.descent()); } - let size = Size::new(max_x - min_x, max_y - min_y); + let size = Vec2::new(max_x - min_x, max_y - min_y); let glyphs = self.brush.process_glyphs( section_glyphs, diff --git a/crates/bevy_text/src/text.rs b/crates/bevy_text/src/text.rs index 2f2b37ab9a19e..0b1b22eebdd08 100644 --- a/crates/bevy_text/src/text.rs +++ b/crates/bevy_text/src/text.rs @@ -1,6 +1,6 @@ use bevy_asset::Handle; use bevy_ecs::{prelude::Component, reflect::ReflectComponent}; -use bevy_math::Size; +use bevy_math::Vec2; use bevy_reflect::{FromReflect, Reflect, ReflectDeserialize}; use bevy_render::color::Color; use serde::{Deserialize, Serialize}; @@ -154,5 +154,5 @@ impl Default for TextStyle { #[derive(Component, Default, Copy, Clone, Debug, Reflect)] #[reflect(Component)] pub struct Text2dSize { - pub size: Size, + pub size: Vec2, } diff --git a/crates/bevy_text/src/text2d.rs b/crates/bevy_text/src/text2d.rs index bee204e755fa3..1e33f27fb604d 100644 --- a/crates/bevy_text/src/text2d.rs +++ b/crates/bevy_text/src/text2d.rs @@ -5,7 +5,7 @@ use bevy_ecs::{ query::{Changed, QueryState, With}, system::{Local, Query, QuerySet, Res, ResMut}, }; -use bevy_math::{Size, Vec3}; +use bevy_math::{Mat4, Vec2, Vec3}; use bevy_render::{texture::Image, view::Visibility, RenderWorld}; use bevy_sprite::{ExtractedSprite, ExtractedSprites, TextureAtlas}; use bevy_transform::prelude::{GlobalTransform, Transform}; @@ -34,7 +34,7 @@ impl Default for Text2dBundle { transform: Default::default(), global_transform: Default::default(), text_2d_size: Text2dSize { - size: Size::default(), + size: Vec2::default(), }, visibility: Default::default(), } @@ -60,7 +60,7 @@ pub fn extract_text2d_sprite( if !visibility.is_visible { continue; } - let (width, height) = (calculated_size.size.width, calculated_size.size.height); + let (width, height) = (calculated_size.size.x, calculated_size.size.y); if let Some(text_layout) = text_pipeline.get_glyphs(&entity) { let text_glyphs = &text_layout.glyphs; @@ -155,7 +155,7 @@ pub fn text2d_system( &text.sections, scale_factor, text.alignment, - Size::new(f32::MAX, f32::MAX), + Vec2::new(f32::MAX, f32::MAX), &mut *font_atlas_set_storage, &mut *texture_atlases, &mut *textures, @@ -172,10 +172,10 @@ pub fn text2d_system( let text_layout_info = text_pipeline.get_glyphs(&entity).expect( "Failed to get glyphs from the pipeline that have just been computed", ); - calculated_size.size = Size { - width: scale_value(text_layout_info.size.width, 1. / scale_factor), - height: scale_value(text_layout_info.size.height, 1. / scale_factor), - }; + calculated_size.size = Vec2::new( + scale_value(text_layout_info.size.x, 1. / scale_factor), + scale_value(text_layout_info.size.y, 1. / scale_factor), + ); } } } diff --git a/crates/bevy_ui/src/flex/convert.rs b/crates/bevy_ui/src/flex/convert.rs index 10e6839134349..3c73b1f566714 100644 --- a/crates/bevy_ui/src/flex/convert.rs +++ b/crates/bevy_ui/src/flex/convert.rs @@ -1,12 +1,11 @@ use crate::{ AlignContent, AlignItems, AlignSelf, Direction, Display, FlexDirection, FlexWrap, - JustifyContent, PositionType, Style, Val, + JustifyContent, PositionType, Size, Style, UiRect, Val, }; -use bevy_math::{Rect, Size}; pub fn from_rect( scale_factor: f64, - rect: Rect, + rect: UiRect, ) -> stretch::geometry::Rect { stretch::geometry::Rect { start: from_val(scale_factor, rect.left), diff --git a/crates/bevy_ui/src/geometry.rs b/crates/bevy_ui/src/geometry.rs new file mode 100644 index 0000000000000..32228f26092ed --- /dev/null +++ b/crates/bevy_ui/src/geometry.rs @@ -0,0 +1,333 @@ +use bevy_math::Vec2; +use bevy_reflect::Reflect; +use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; + +/// A 2-dimensional area defined by a width and height. +/// +/// It is commonly used to define the size of a text or UI element. +/// +/// # Example +/// +/// In this example an UI size gets created. It has a width of 100px and a height of 200px. +/// +/// ```rust +/// # use bevy_ui::{Size, Val}; +/// # +/// let size = Size { +/// width: Val::Px(100.0), +/// height: Val::Px(200.0), +/// }; +/// +/// assert_eq!(size.width, Val::Px(100.0)); +/// assert_eq!(size.height, Val::Px(200.0)); +/// ``` +#[derive(Copy, Clone, PartialEq, Debug, Reflect)] +#[reflect(PartialEq)] +pub struct Size { + /// The width of the 2-dimensional area. + pub width: T, + /// The height of the 2-dimensional area. + pub height: T, +} + +impl Size { + /// Creates a new [`Size`] from a width and a height. + /// + /// # Example + /// + /// In this example an UI size gets created. It has a width of 100px and a height of 200px. + /// + /// ```rust + /// # use bevy_ui::{Size, Val}; + /// # + /// let size = Size::new(Val::Px(100.0), Val::Px(200.0)); + /// + /// assert_eq!(size.width, Val::Px(100.0)); + /// assert_eq!(size.height, Val::Px(200.0)); + /// ``` + pub fn new(width: T, height: T) -> Self { + Size { width, height } + } +} + +impl Default for Size { + fn default() -> Self { + Self { + width: Default::default(), + height: Default::default(), + } + } +} + +/// A type which is commonly used to define positions, margins, paddings and borders. +/// +/// # Examples +/// +/// ## Position +/// +/// A position is used to determine where to place an UI element. +/// +/// In this example an UI position gets created. It has a left value of 100px and a top value of 50px. +/// If positioned absolutely this would correspond to an UI element which is positioned 100px to the right +/// from the left side of the window and 50px down from the top side of the window. +/// +/// ```rust +/// # use bevy_ui::{UiRect, Val}; +/// # +/// let position = UiRect { +/// left: Val::Px(100.0), +/// top: Val::Px(50.0), +/// ..Default::default() +/// }; +/// +/// assert_eq!(position.left, Val::Px(100.0)); +/// assert_eq!(position.top, Val::Px(50.0)); +/// assert_eq!(position.right, Val::Undefined); +/// assert_eq!(position.bottom, Val::Undefined); +/// ``` +/// +/// ## Margin +/// +/// A margin is used to create space around UI elements, outside of any defined borders. +/// +/// In this example an UI margin gets created. It has a left value of 10px, a top value of 20px, +/// a right value of 30px and a bottom value of 40px. This would add a margin of 10px on the left, +/// 20px on the top, 30px on the right and 40px on the bottom of the UI element. +/// +/// ```rust +/// # use bevy_ui::{UiRect, Val}; +/// # +/// let margin = UiRect { +/// left: Val::Px(10.0), +/// top: Val::Px(20.0), +/// right: Val::Px(30.0), +/// bottom: Val::Px(40.0), +/// }; +/// +/// assert_eq!(margin.left, Val::Px(10.0)); +/// assert_eq!(margin.top, Val::Px(20.0)); +/// assert_eq!(margin.right, Val::Px(30.0)); +/// assert_eq!(margin.bottom, Val::Px(40.0)); +/// ``` +/// +/// ## Padding +/// +/// A padding is used to create space around UI elements, inside of any defined borders. +/// +/// In this example an UI padding gets created. It has a left value of 10px, a top value of 20px, +/// a right value of 30px and a bottom value of 40px. This would add a padding of 10px on the left, +/// 20px on the top, 30px on the right and 40px on the bottom of the UI element. +/// +/// ```rust +/// # use bevy_ui::{UiRect, Val}; +/// # +/// let padding = UiRect { +/// left: Val::Px(10.0), +/// top: Val::Px(20.0), +/// right: Val::Px(30.0), +/// bottom: Val::Px(40.0), +/// }; +/// +/// assert_eq!(padding.left, Val::Px(10.0)); +/// assert_eq!(padding.top, Val::Px(20.0)); +/// assert_eq!(padding.right, Val::Px(30.0)); +/// assert_eq!(padding.bottom, Val::Px(40.0)); +/// ``` +/// +/// ## Borders +/// +/// A border is used to define the width of the border of an UI element. +/// +/// In this example an UI border gets created. It has a left value of 10px, a top value of 20px, +/// a right value of 30px and a bottom value of 40px. This would create a border around an UI element +/// that has a width of 10px on the left, 20px on the top, 30px on the right and 40px on the bottom. +/// +/// ```rust +/// # use bevy_ui::{UiRect, Val}; +/// # +/// let border = UiRect { +/// left: Val::Px(10.0), +/// top: Val::Px(20.0), +/// right: Val::Px(30.0), +/// bottom: Val::Px(40.0), +/// }; +/// +/// assert_eq!(border.left, Val::Px(10.0)); +/// assert_eq!(border.top, Val::Px(20.0)); +/// assert_eq!(border.right, Val::Px(30.0)); +/// assert_eq!(border.bottom, Val::Px(40.0)); +/// ``` +#[derive(Copy, Clone, PartialEq, Debug, Reflect)] +#[reflect(PartialEq)] +pub struct UiRect { + /// The left value of the [`UiRect`]. + pub left: T, + /// The right value of the [`UiRect`]. + pub right: T, + /// The top value of the [`UiRect`]. + pub top: T, + /// The bottom value of the [`UiRect`]. + pub bottom: T, +} + +impl UiRect { + /// Creates a new [`UiRect`] where all sides have the same value. + /// + /// # Example + /// + /// ```rust + /// # use bevy_ui::{UiRect, Val}; + /// # + /// let ui_rect = UiRect::all(Val::Px(10.0)); + /// + /// assert_eq!(ui_rect.left, Val::Px(10.0)); + /// assert_eq!(ui_rect.top, Val::Px(10.0)); + /// assert_eq!(ui_rect.right, Val::Px(10.0)); + /// assert_eq!(ui_rect.bottom, Val::Px(10.0)); + /// ``` + pub fn all(value: T) -> Self + where + T: Clone, + { + UiRect { + left: value.clone(), + right: value.clone(), + top: value.clone(), + bottom: value, + } + } +} + +impl Default for UiRect { + fn default() -> Self { + Self { + left: Default::default(), + right: Default::default(), + top: Default::default(), + bottom: Default::default(), + } + } +} + +impl Add for Size +where + T: Add, +{ + type Output = Size; + + fn add(self, rhs: Vec2) -> Self::Output { + Self { + width: self.width + rhs.x, + height: self.height + rhs.y, + } + } +} + +impl AddAssign for Size +where + T: AddAssign, +{ + fn add_assign(&mut self, rhs: Vec2) { + self.width += rhs.x; + self.height += rhs.y; + } +} + +impl Sub for Size +where + T: Sub, +{ + type Output = Size; + + fn sub(self, rhs: Vec2) -> Self::Output { + Self { + width: self.width - rhs.x, + height: self.height - rhs.y, + } + } +} + +impl SubAssign for Size +where + T: SubAssign, +{ + fn sub_assign(&mut self, rhs: Vec2) { + self.width -= rhs.x; + self.height -= rhs.y; + } +} + +impl Mul for Size +where + T: Mul, +{ + type Output = Size; + + fn mul(self, rhs: f32) -> Self::Output { + Self::Output { + width: self.width * rhs, + height: self.height * rhs, + } + } +} + +impl MulAssign for Size +where + T: MulAssign, +{ + fn mul_assign(&mut self, rhs: f32) { + self.width *= rhs; + self.height *= rhs; + } +} + +impl Div for Size +where + T: Div, +{ + type Output = Size; + + fn div(self, rhs: f32) -> Self::Output { + Self::Output { + width: self.width / rhs, + height: self.height / rhs, + } + } +} + +impl DivAssign for Size +where + T: DivAssign, +{ + fn div_assign(&mut self, rhs: f32) { + self.width /= rhs; + self.height /= rhs; + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn size_ops() { + type SizeF = Size; + + assert_eq!( + SizeF::new(10., 10.) + Vec2::new(10., 10.), + SizeF::new(20., 20.) + ); + assert_eq!( + SizeF::new(20., 20.) - Vec2::new(10., 10.), + SizeF::new(10., 10.) + ); + assert_eq!(SizeF::new(10., 10.) * 2., SizeF::new(20., 20.)); + assert_eq!(SizeF::new(20., 20.) / 2., SizeF::new(10., 10.)); + + let mut size = SizeF::new(10., 10.); + + size += Vec2::new(10., 10.); + + assert_eq!(size, SizeF::new(20., 20.)); + } +} diff --git a/crates/bevy_ui/src/lib.rs b/crates/bevy_ui/src/lib.rs index 2f89f6df9ca85..113a0289cc230 100644 --- a/crates/bevy_ui/src/lib.rs +++ b/crates/bevy_ui/src/lib.rs @@ -4,6 +4,7 @@ //! This UI is laid out with the Flexbox paradigm (see ) except the vertical axis is inverted mod flex; mod focus; +mod geometry; mod margins; mod render; mod ui_node; @@ -14,6 +15,7 @@ pub mod widget; pub use flex::*; pub use focus::*; +pub use geometry::*; pub use margins::*; pub use render::*; pub use ui_node::*; @@ -21,13 +23,12 @@ pub use ui_node::*; #[doc(hidden)] pub mod prelude { #[doc(hidden)] - pub use crate::{entity::*, ui_node::*, widget::Button, Interaction, Margins}; + pub use crate::{entity::*, geometry::*, ui_node::*, widget::Button, Interaction, Margins}; } use bevy_app::prelude::*; use bevy_ecs::schedule::{ParallelSystemDescriptorCoercion, SystemLabel}; use bevy_input::InputSystem; -use bevy_math::{Rect, Size}; use bevy_transform::TransformSystem; use update::{ui_z_system, update_clipping_system}; @@ -65,7 +66,7 @@ impl Plugin for UiPlugin { .register_type::() .register_type::>() .register_type::>() - .register_type::>() + .register_type::>() .register_type::