Added Val::ZERO Constant (#9566)

# Objective

- Fixes #9533

## Solution

* Added `Val::ZERO` as a constant which is defined as `Val::Px(0.)`.
* Added manual `PartialEq` implementation for `Val` which allows any
zero value to equal any other zero value. E.g., `Val::Px(0.) ==
Val::Percent(0.)` etc. This is technically a breaking change, as
`Val::Px(0.) == Val::Percent(0.)` now equals `true` instead of `false`
(as an example)
* Replaced instances of `Val::Px(0.)`, `Val::Percent(0.)`, etc. with
`Val::ZERO`
* Fixed `bevy_ui::layout::convert::tests::test_convert_from` test to
account for Taffy not equating `Points(0.)` and `Percent(0.)`. These
tests now use `assert_eq!(...)` instead of `assert!(matches!(...))`
which gives easier to diagnose error messages.
This commit is contained in:
Zachary Harrold 2023-08-27 00:00:53 +10:00 committed by GitHub
parent 349dd8bd45
commit 90b3ac7f3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 161 additions and 140 deletions

View File

@ -60,10 +60,17 @@ pub struct UiRect {
impl UiRect {
pub const DEFAULT: Self = Self {
left: Val::Px(0.),
right: Val::Px(0.),
top: Val::Px(0.),
bottom: Val::Px(0.),
left: Val::ZERO,
right: Val::ZERO,
top: Val::ZERO,
bottom: Val::ZERO,
};
pub const ZERO: Self = Self {
left: Val::ZERO,
right: Val::ZERO,
top: Val::ZERO,
bottom: Val::ZERO,
};
/// Creates a new [`UiRect`] from the values specified.
@ -166,7 +173,7 @@ impl UiRect {
}
/// Creates a new [`UiRect`] where `left` and `right` take the given value,
/// and `top` and `bottom` set to zero `Val::Px(0.)`.
/// and `top` and `bottom` set to zero `Val::ZERO`.
///
/// # Example
///
@ -177,8 +184,8 @@ impl UiRect {
///
/// 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(0.));
/// assert_eq!(ui_rect.bottom, Val::Px(0.));
/// assert_eq!(ui_rect.top, Val::ZERO);
/// assert_eq!(ui_rect.bottom, Val::ZERO);
/// ```
pub fn horizontal(value: Val) -> Self {
UiRect {
@ -189,7 +196,7 @@ impl UiRect {
}
/// Creates a new [`UiRect`] where `top` and `bottom` take the given value,
/// and `left` and `right` are set to `Val::Px(0.)`.
/// and `left` and `right` are set to `Val::ZERO`.
///
/// # Example
///
@ -198,8 +205,8 @@ impl UiRect {
/// #
/// let ui_rect = UiRect::vertical(Val::Px(10.0));
///
/// assert_eq!(ui_rect.left, Val::Px(0.));
/// assert_eq!(ui_rect.right, Val::Px(0.));
/// assert_eq!(ui_rect.left, Val::ZERO);
/// assert_eq!(ui_rect.right, Val::ZERO);
/// assert_eq!(ui_rect.top, Val::Px(10.0));
/// assert_eq!(ui_rect.bottom, Val::Px(10.0));
/// ```
@ -235,7 +242,7 @@ impl UiRect {
}
/// Creates a new [`UiRect`] where `left` takes the given value, and
/// the other fields are set to `Val::Px(0.)`.
/// the other fields are set to `Val::ZERO`.
///
/// # Example
///
@ -245,9 +252,9 @@ impl UiRect {
/// let ui_rect = UiRect::left(Val::Px(10.0));
///
/// assert_eq!(ui_rect.left, Val::Px(10.0));
/// assert_eq!(ui_rect.right, Val::Px(0.));
/// assert_eq!(ui_rect.top, Val::Px(0.));
/// assert_eq!(ui_rect.bottom, Val::Px(0.));
/// assert_eq!(ui_rect.right, Val::ZERO);
/// assert_eq!(ui_rect.top, Val::ZERO);
/// assert_eq!(ui_rect.bottom, Val::ZERO);
/// ```
pub fn left(value: Val) -> Self {
UiRect {
@ -257,7 +264,7 @@ impl UiRect {
}
/// Creates a new [`UiRect`] where `right` takes the given value,
/// and the other fields are set to `Val::Px(0.)`.
/// and the other fields are set to `Val::ZERO`.
///
/// # Example
///
@ -266,10 +273,10 @@ impl UiRect {
/// #
/// let ui_rect = UiRect::right(Val::Px(10.0));
///
/// assert_eq!(ui_rect.left, Val::Px(0.));
/// assert_eq!(ui_rect.left, Val::ZERO);
/// assert_eq!(ui_rect.right, Val::Px(10.0));
/// assert_eq!(ui_rect.top, Val::Px(0.));
/// assert_eq!(ui_rect.bottom, Val::Px(0.));
/// assert_eq!(ui_rect.top, Val::ZERO);
/// assert_eq!(ui_rect.bottom, Val::ZERO);
/// ```
pub fn right(value: Val) -> Self {
UiRect {
@ -279,7 +286,7 @@ impl UiRect {
}
/// Creates a new [`UiRect`] where `top` takes the given value,
/// and the other fields are set to `Val::Px(0.)`.
/// and the other fields are set to `Val::ZERO`.
///
/// # Example
///
@ -288,10 +295,10 @@ impl UiRect {
/// #
/// let ui_rect = UiRect::top(Val::Px(10.0));
///
/// assert_eq!(ui_rect.left, Val::Px(0.));
/// assert_eq!(ui_rect.right, Val::Px(0.));
/// assert_eq!(ui_rect.left, Val::ZERO);
/// assert_eq!(ui_rect.right, Val::ZERO);
/// assert_eq!(ui_rect.top, Val::Px(10.0));
/// assert_eq!(ui_rect.bottom, Val::Px(0.));
/// assert_eq!(ui_rect.bottom, Val::ZERO);
/// ```
pub fn top(value: Val) -> Self {
UiRect {
@ -301,7 +308,7 @@ impl UiRect {
}
/// Creates a new [`UiRect`] where `bottom` takes the given value,
/// and the other fields are set to `Val::Px(0.)`.
/// and the other fields are set to `Val::ZERO`.
///
/// # Example
///
@ -310,9 +317,9 @@ impl UiRect {
/// #
/// let ui_rect = UiRect::bottom(Val::Px(10.0));
///
/// assert_eq!(ui_rect.left, Val::Px(0.));
/// assert_eq!(ui_rect.right, Val::Px(0.));
/// assert_eq!(ui_rect.top, Val::Px(0.));
/// assert_eq!(ui_rect.left, Val::ZERO);
/// assert_eq!(ui_rect.right, Val::ZERO);
/// assert_eq!(ui_rect.top, Val::ZERO);
/// assert_eq!(ui_rect.bottom, Val::Px(10.0));
/// ```
pub fn bottom(value: Val) -> Self {
@ -338,10 +345,10 @@ mod tests {
assert_eq!(
UiRect::default(),
UiRect {
left: Val::Px(0.),
right: Val::Px(0.),
top: Val::Px(0.),
bottom: Val::Px(0.)
left: Val::ZERO,
right: Val::ZERO,
top: Val::ZERO,
bottom: Val::ZERO
}
);
assert_eq!(UiRect::default(), UiRect::DEFAULT);

View File

@ -397,14 +397,15 @@ mod tests {
#[test]
fn test_convert_from() {
use sh::TaffyZero;
use taffy::style_helpers as sh;
let bevy_style = crate::Style {
display: Display::Flex,
position_type: PositionType::Absolute,
left: Val::Px(0.),
right: Val::Percent(0.),
top: Val::Auto,
left: Val::ZERO,
right: Val::Percent(50.),
top: Val::Px(12.),
bottom: Val::Auto,
direction: crate::Direction::Inherit,
flex_direction: FlexDirection::ColumnReverse,
@ -416,36 +417,36 @@ mod tests {
justify_self: JustifySelf::Center,
justify_content: JustifyContent::SpaceEvenly,
margin: UiRect {
left: Val::Percent(0.),
right: Val::Px(0.),
top: Val::Auto,
left: Val::ZERO,
right: Val::Px(10.),
top: Val::Percent(15.),
bottom: Val::Auto,
},
padding: UiRect {
left: Val::Percent(0.),
right: Val::Px(0.),
top: Val::Percent(0.),
bottom: Val::Percent(0.),
left: Val::Percent(13.),
right: Val::Px(21.),
top: Val::Auto,
bottom: Val::ZERO,
},
border: UiRect {
left: Val::Px(0.),
right: Val::Px(0.),
left: Val::Px(14.),
right: Val::ZERO,
top: Val::Auto,
bottom: Val::Px(0.),
bottom: Val::Percent(31.),
},
flex_grow: 1.,
flex_shrink: 0.,
flex_basis: Val::Px(0.),
width: Val::Px(0.),
flex_basis: Val::ZERO,
width: Val::ZERO,
height: Val::Auto,
min_width: Val::Px(0.),
min_height: Val::Percent(0.),
min_width: Val::ZERO,
min_height: Val::ZERO,
max_width: Val::Auto,
max_height: Val::Px(0.),
max_height: Val::ZERO,
aspect_ratio: None,
overflow: crate::Overflow::clip(),
column_gap: Val::Px(0.),
row_gap: Val::Percent(0.),
column_gap: Val::ZERO,
row_gap: Val::ZERO,
grid_auto_flow: GridAutoFlow::ColumnDense,
grid_template_rows: vec![
GridTrack::px(10.0),
@ -470,22 +471,22 @@ mod tests {
let taffy_style = from_style(&viewport_values, &bevy_style);
assert_eq!(taffy_style.display, taffy::style::Display::Flex);
assert_eq!(taffy_style.position, taffy::style::Position::Absolute);
assert!(matches!(
assert_eq!(
taffy_style.inset.left,
taffy::style::LengthPercentageAuto::Points(_)
));
assert!(matches!(
taffy::style::LengthPercentageAuto::ZERO
);
assert_eq!(
taffy_style.inset.right,
taffy::style::LengthPercentageAuto::Percent(_)
));
assert!(matches!(
taffy::style::LengthPercentageAuto::Percent(0.5)
);
assert_eq!(
taffy_style.inset.top,
taffy::style::LengthPercentageAuto::Auto
));
assert!(matches!(
taffy::style::LengthPercentageAuto::Points(12.)
);
assert_eq!(
taffy_style.inset.bottom,
taffy::style::LengthPercentageAuto::Auto
));
);
assert_eq!(
taffy_style.flex_direction,
taffy::style::FlexDirection::ColumnReverse
@ -509,93 +510,63 @@ mod tests {
taffy_style.justify_self,
Some(taffy::style::JustifySelf::Center)
);
assert!(matches!(
assert_eq!(
taffy_style.margin.left,
taffy::style::LengthPercentageAuto::Percent(_)
));
assert!(matches!(
taffy::style::LengthPercentageAuto::ZERO
);
assert_eq!(
taffy_style.margin.right,
taffy::style::LengthPercentageAuto::Points(_)
));
assert!(matches!(
taffy::style::LengthPercentageAuto::Points(10.)
);
assert_eq!(
taffy_style.margin.top,
taffy::style::LengthPercentageAuto::Auto
));
assert!(matches!(
taffy::style::LengthPercentageAuto::Percent(0.15)
);
assert_eq!(
taffy_style.margin.bottom,
taffy::style::LengthPercentageAuto::Auto
));
assert!(matches!(
);
assert_eq!(
taffy_style.padding.left,
taffy::style::LengthPercentage::Percent(_)
));
assert!(matches!(
taffy::style::LengthPercentage::Percent(0.13)
);
assert_eq!(
taffy_style.padding.right,
taffy::style::LengthPercentage::Points(_)
));
assert!(matches!(
taffy::style::LengthPercentage::Points(21.)
);
assert_eq!(
taffy_style.padding.top,
taffy::style::LengthPercentage::Percent(_)
));
assert!(matches!(
taffy::style::LengthPercentage::ZERO
);
assert_eq!(
taffy_style.padding.bottom,
taffy::style::LengthPercentage::Percent(_)
));
assert!(matches!(
taffy::style::LengthPercentage::ZERO
);
assert_eq!(
taffy_style.border.left,
taffy::style::LengthPercentage::Points(_)
));
assert!(matches!(
taffy::style::LengthPercentage::Points(14.)
);
assert_eq!(
taffy_style.border.right,
taffy::style::LengthPercentage::Points(_)
));
assert!(matches!(
taffy_style.border.top,
taffy::style::LengthPercentage::Points(_)
));
assert!(matches!(
taffy::style::LengthPercentage::ZERO
);
assert_eq!(taffy_style.border.top, taffy::style::LengthPercentage::ZERO);
assert_eq!(
taffy_style.border.bottom,
taffy::style::LengthPercentage::Points(_)
));
taffy::style::LengthPercentage::Percent(0.31)
);
assert_eq!(taffy_style.flex_grow, 1.);
assert_eq!(taffy_style.flex_shrink, 0.);
assert!(matches!(
taffy_style.flex_basis,
taffy::style::Dimension::Points(_)
));
assert!(matches!(
taffy_style.size.width,
taffy::style::Dimension::Points(_)
));
assert!(matches!(
taffy_style.size.height,
taffy::style::Dimension::Auto
));
assert!(matches!(
taffy_style.min_size.width,
taffy::style::Dimension::Points(_)
));
assert!(matches!(
taffy_style.min_size.height,
taffy::style::Dimension::Percent(_)
));
assert!(matches!(
taffy_style.max_size.width,
taffy::style::Dimension::Auto
));
assert!(matches!(
taffy_style.max_size.height,
taffy::style::Dimension::Points(_)
));
assert_eq!(taffy_style.flex_basis, taffy::style::Dimension::ZERO);
assert_eq!(taffy_style.size.width, taffy::style::Dimension::ZERO);
assert_eq!(taffy_style.size.height, taffy::style::Dimension::Auto);
assert_eq!(taffy_style.min_size.width, taffy::style::Dimension::ZERO);
assert_eq!(taffy_style.min_size.height, taffy::style::Dimension::ZERO);
assert_eq!(taffy_style.max_size.width, taffy::style::Dimension::Auto);
assert_eq!(taffy_style.max_size.height, taffy::style::Dimension::ZERO);
assert_eq!(taffy_style.aspect_ratio, None);
assert_eq!(
taffy_style.gap.width,
taffy::style::LengthPercentage::Points(0.)
);
assert_eq!(
taffy_style.gap.height,
taffy::style::LengthPercentage::Percent(0.)
);
assert_eq!(taffy_style.gap.width, taffy::style::LengthPercentage::ZERO);
assert_eq!(taffy_style.gap.height, taffy::style::LengthPercentage::ZERO);
assert_eq!(
taffy_style.grid_auto_flow,
taffy::style::GridAutoFlow::ColumnDense

View File

@ -82,7 +82,7 @@ impl Default for Node {
///
/// This enum allows specifying values for various [`Style`] properties in different units,
/// such as logical pixels, percentages, or automatically determined values.
#[derive(Copy, Clone, PartialEq, Debug, Serialize, Deserialize, Reflect)]
#[derive(Copy, Clone, Debug, Serialize, Deserialize, Reflect)]
#[reflect(PartialEq, Serialize, Deserialize)]
pub enum Val {
/// Automatically determine the value based on the context and other [`Style`] properties.
@ -112,8 +112,51 @@ pub enum Val {
VMax(f32),
}
impl PartialEq for Val {
fn eq(&self, other: &Self) -> bool {
let same_unit = matches!(
(self, other),
(Self::Auto, Self::Auto)
| (Self::Px(_), Self::Px(_))
| (Self::Percent(_), Self::Percent(_))
| (Self::Vw(_), Self::Vw(_))
| (Self::Vh(_), Self::Vh(_))
| (Self::VMin(_), Self::VMin(_))
| (Self::VMax(_), Self::VMax(_))
);
let left = match self {
Self::Auto => None,
Self::Px(v)
| Self::Percent(v)
| Self::Vw(v)
| Self::Vh(v)
| Self::VMin(v)
| Self::VMax(v) => Some(v),
};
let right = match other {
Self::Auto => None,
Self::Px(v)
| Self::Percent(v)
| Self::Vw(v)
| Self::Vh(v)
| Self::VMin(v)
| Self::VMax(v) => Some(v),
};
match (same_unit, left, right) {
(true, a, b) => a == b,
// All zero-value variants are considered equal.
(false, Some(&a), Some(&b)) => a == 0. && b == 0.,
_ => false,
}
}
}
impl Val {
pub const DEFAULT: Self = Self::Auto;
pub const ZERO: Self = Self::Px(0.0);
}
impl Default for Val {
@ -599,8 +642,8 @@ impl Style {
max_height: Val::Auto,
aspect_ratio: None,
overflow: Overflow::DEFAULT,
row_gap: Val::Px(0.0),
column_gap: Val::Px(0.0),
row_gap: Val::ZERO,
column_gap: Val::ZERO,
grid_auto_flow: GridAutoFlow::DEFAULT,
grid_template_rows: Vec::new(),
grid_template_columns: Vec::new(),

View File

@ -237,7 +237,7 @@ fn setup(
TextBundle::from_section(label, label_text_style.clone())
.with_style(Style {
position_type: PositionType::Absolute,
bottom: Val::Px(0.),
bottom: Val::ZERO,
..default()
})
.with_no_wrap(),

View File

@ -98,7 +98,7 @@ fn setup(
style: Style {
position_type: PositionType::Absolute,
top: Val::Px(130.0),
right: Val::Px(0.0),
right: Val::ZERO,
..default()
},
transform: Transform {

View File

@ -50,7 +50,7 @@ fn atlas_render_system(
image: texture_atlas.texture.clone().into(),
style: Style {
position_type: PositionType::Absolute,
top: Val::Px(0.0),
top: Val::ZERO,
left: Val::Px(512.0 * x_offset),
..default()
},
@ -83,7 +83,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, mut state: ResM
background_color: Color::NONE.into(),
style: Style {
position_type: PositionType::Absolute,
bottom: Val::Px(0.0),
bottom: Val::ZERO,
..default()
},
..default()