From c9315fbfd52b3ae8e927fa8a337958b50cca226b Mon Sep 17 00:00:00 2001 From: KDecay Date: Wed, 20 Jul 2022 15:42:18 +0000 Subject: [PATCH] Document `Size` and `UiRect` (#5381) # Objective - Migrate changes from #3503. ## Solution - Document `Size` and `UiRect`. - I also removed the type alias from the `size_ops` test since it's unnecessary. ## Follow Up After this change is merged I'd follow up with removing the generics from `Size` and `UiRect` since `Val` should be extensible enough. This was also discussed and decided on in #3503. let me know if this is not needed or wanted anymore! --- crates/bevy_ui/src/geometry.rs | 200 +++++++++++++++++++++++++++++++-- 1 file changed, 188 insertions(+), 12 deletions(-) diff --git a/crates/bevy_ui/src/geometry.rs b/crates/bevy_ui/src/geometry.rs index 2ce50140a4eaa7..e60dd3089f62bf 100644 --- a/crates/bevy_ui/src/geometry.rs +++ b/crates/bevy_ui/src/geometry.rs @@ -2,17 +2,179 @@ use bevy_math::Vec2; use bevy_reflect::Reflect; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; -/// A rect, as defined by its "side" locations +/// A type which is commonly used to define positions, margins, paddings and borders. +/// +/// # Examples +/// +/// ## Position +/// +/// A position is used to determine where to place a UI element. +/// +/// ``` +/// # use bevy_ui::{UiRect, Val}; +/// # use bevy_utils::default; +/// # +/// let position = UiRect { +/// left: Val::Px(100.0), +/// top: Val::Px(50.0), +/// ..default() +/// }; +/// ``` +/// +/// If you define opposite sides of the position, the size of the UI element will automatically be calculated +/// if not explicitly specified. This means that if you have a [`Size`] that uses [`Val::Undefined`](crate::Val::Undefined) +/// as a width and height, the size would be determined by the window size and the values specified in the position. +/// +/// ``` +/// # use bevy_ui::{UiRect, Val}; +/// # +/// let position = UiRect { +/// left: Val::Px(100.0), +/// right: Val::Px(200.0), +/// top: Val::Px(300.0), +/// bottom: Val::Px(400.0), +/// }; +/// ``` +/// +/// To determine the width of the UI element you have to take the width of the window and subtract it by the +/// left and right values of the position. To determine the height of the UI element you have to take the height +/// of the window and subtract it by the top and bottom values of the position. If we had a window with a width +/// and height of 1000px, the UI element declared above would have a width of 700px and a height of 300px. +/// +/// ``` +/// // Size of the window +/// let window_width = 1000.0; +/// let window_height = 1000.0; +/// +/// // Values of the position +/// let left = 100.0; +/// let right = 200.0; +/// let top = 300.0; +/// let bottom = 400.0; +/// +/// // Calculation to get the size of the UI element +/// let ui_element_width = window_width - left - right; +/// let ui_element_height = window_height - top - bottom; +/// +/// assert_eq!(ui_element_width, 700.0); +/// assert_eq!(ui_element_height, 300.0); +/// ``` +/// +/// If you define a [`Size`] and also all four sides of the position, the top and left values of the position +/// are used to determine where to place the UI element. The size will not be calculated using the bottom and +/// right values of the position because the size of the UI element is already explicitly specified. +/// +/// ``` +/// # use bevy_ui::{UiRect, Size, Val, Style}; +/// # use bevy_utils::default; +/// # +/// let style = Style { +/// position: UiRect { // Defining all four sides +/// left: Val::Px(100.0), +/// right: Val::Px(200.0), +/// top: Val::Px(300.0), +/// bottom: Val::Px(400.0), +/// }, +/// size: Size::new(Val::Percent(100.0), Val::Percent(50.0)), // but also explicitly specifying a size +/// ..default() +/// }; +/// ``` +/// +/// ## Margin +/// +/// A margin is used to create space around UI elements, outside of any defined borders. +/// +/// ``` +/// # use bevy_ui::{UiRect, Val}; +/// # +/// let margin = UiRect::all(Val::Auto); // Centers the UI element +/// ``` +/// +/// ## Padding +/// +/// A padding is used to create space around UI elements, inside of any defined borders. +/// +/// ``` +/// # use bevy_ui::{UiRect, Val}; +/// # +/// let padding = UiRect { +/// left: Val::Px(10.0), +/// right: Val::Px(20.0), +/// top: Val::Px(30.0), +/// bottom: Val::Px(40.0), +/// }; +/// ``` +/// +/// ## Borders +/// +/// A border is used to define the width of the border of a UI element. +/// +/// ``` +/// # use bevy_ui::{UiRect, Val}; +/// # +/// let border = UiRect { +/// left: Val::Px(10.0), +/// right: Val::Px(20.0), +/// top: Val::Px(30.0), +/// bottom: Val::Px(40.0), +/// }; +/// ``` #[derive(Copy, Clone, PartialEq, Debug, Reflect)] #[reflect(PartialEq)] pub struct UiRect { + /// The value corresponding to the left side of the UI rect. pub left: T, + /// The value corresponding to the right side of the UI rect. pub right: T, + /// The value corresponding to the top side of the UI rect. pub top: T, + /// The value corresponding to the bottom side of the UI rect. pub bottom: T, } impl UiRect { + /// Creates a new [`UiRect`] from the values specified. + /// + /// # Example + /// + /// ``` + /// # use bevy_ui::{UiRect, Val}; + /// # + /// let ui_rect = UiRect::new( + /// Val::Px(10.0), + /// Val::Px(20.0), + /// Val::Px(30.0), + /// Val::Px(40.0), + /// ); + /// + /// assert_eq!(ui_rect.left, Val::Px(10.0)); + /// assert_eq!(ui_rect.right, Val::Px(20.0)); + /// assert_eq!(ui_rect.top, Val::Px(30.0)); + /// assert_eq!(ui_rect.bottom, Val::Px(40.0)); + /// ``` + pub fn new(left: T, right: T, top: T, bottom: T) -> Self { + UiRect { + left, + right, + top, + bottom, + } + } + + /// Creates a new [`UiRect`] where all sides have the same value. + /// + /// # Example + /// + /// ``` + /// # 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.right, Val::Px(10.0)); + /// assert_eq!(ui_rect.top, Val::Px(10.0)); + /// assert_eq!(ui_rect.bottom, Val::Px(10.0)); + /// ``` pub fn all(value: T) -> Self where T: Clone, @@ -37,15 +199,31 @@ impl Default for UiRect { } } -/// 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. #[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 + /// + /// ``` + /// # 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 } } @@ -162,23 +340,21 @@ mod tests { #[test] fn size_ops() { - type SizeF = Size; - assert_eq!( - SizeF::new(10., 10.) + Vec2::new(10., 10.), - SizeF::new(20., 20.) + Size::new(10., 10.) + Vec2::new(10., 10.), + Size::new(20., 20.) ); assert_eq!( - SizeF::new(20., 20.) - Vec2::new(10., 10.), - SizeF::new(10., 10.) + Size::new(20., 20.) - Vec2::new(10., 10.), + Size::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.)); + assert_eq!(Size::new(10., 10.) * 2., Size::new(20., 20.)); + assert_eq!(Size::new(20., 20.) / 2., Size::new(10., 10.)); - let mut size = SizeF::new(10., 10.); + let mut size = Size::new(10., 10.); size += Vec2::new(10., 10.); - assert_eq!(size, SizeF::new(20., 20.)); + assert_eq!(size, Size::new(20., 20.)); } }