Val
viewport unit variants (#8137)
# Objective Add viewport variants to `Val` that specify a percentage length based on the size of the window. ## Solution Add the variants `Vw`, `Vh`, `VMin` and `VMax` to `Val`. Add a physical window size parameter to the `from_style` function and use it to convert the viewport variants to Taffy Points values. One issue: It isn't responsive to window resizes. So `flex_node_system` has to do a full update every time the window size changes. Perhaps this can be fixed with support from Taffy. --- ## Changelog * Added `Val` viewport unit variants `Vw`, `Vh`, `VMin` and `VMax`. * Modified `convert` module to support the new `Val` variants. * Changed `flex_node_system` to support the new `Val` variants. * Perform full layout update on screen resizing, to propagate the new viewport size to all nodes.
This commit is contained in:
parent
c809779b6e
commit
2d5ef75c9f
@ -1,99 +1,74 @@
|
|||||||
use taffy::style::LengthPercentageAuto;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AlignContent, AlignItems, AlignSelf, Display, FlexDirection, FlexWrap, JustifyContent,
|
AlignContent, AlignItems, AlignSelf, Display, FlexDirection, FlexWrap, JustifyContent,
|
||||||
PositionType, Size, Style, UiRect, Val,
|
PositionType, Size, Style, UiRect, Val,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::LayoutContext;
|
||||||
|
|
||||||
impl Val {
|
impl Val {
|
||||||
fn scaled(self, scale_factor: f64) -> Self {
|
fn into_length_percentage_auto(
|
||||||
|
self,
|
||||||
|
context: &LayoutContext,
|
||||||
|
) -> taffy::style::LengthPercentageAuto {
|
||||||
match self {
|
match self {
|
||||||
Val::Auto => Val::Auto,
|
Val::Auto => taffy::style::LengthPercentageAuto::Auto,
|
||||||
Val::Percent(value) => Val::Percent(value),
|
Val::Percent(value) => taffy::style::LengthPercentageAuto::Percent(value / 100.),
|
||||||
Val::Px(value) => Val::Px((scale_factor * value as f64) as f32),
|
Val::Px(value) => taffy::style::LengthPercentageAuto::Points(
|
||||||
|
(context.scale_factor * value as f64) as f32,
|
||||||
|
),
|
||||||
|
Val::VMin(value) => {
|
||||||
|
taffy::style::LengthPercentageAuto::Points(context.min_size * value / 100.)
|
||||||
|
}
|
||||||
|
Val::VMax(value) => {
|
||||||
|
taffy::style::LengthPercentageAuto::Points(context.max_size * value / 100.)
|
||||||
|
}
|
||||||
|
Val::Vw(value) => {
|
||||||
|
taffy::style::LengthPercentageAuto::Points(context.physical_size.x * value / 100.)
|
||||||
|
}
|
||||||
|
Val::Vh(value) => {
|
||||||
|
taffy::style::LengthPercentageAuto::Points(context.physical_size.y * value / 100.)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_inset(self) -> LengthPercentageAuto {
|
fn into_length_percentage(self, context: &LayoutContext) -> taffy::style::LengthPercentage {
|
||||||
match self {
|
match self.into_length_percentage_auto(context) {
|
||||||
Val::Auto => taffy::style::LengthPercentageAuto::Auto,
|
taffy::style::LengthPercentageAuto::Auto => taffy::style::LengthPercentage::Points(0.0),
|
||||||
Val::Percent(value) => taffy::style::LengthPercentageAuto::Percent(value / 100.0),
|
taffy::style::LengthPercentageAuto::Percent(value) => {
|
||||||
Val::Px(value) => taffy::style::LengthPercentageAuto::Points(value),
|
taffy::style::LengthPercentage::Percent(value)
|
||||||
|
}
|
||||||
|
taffy::style::LengthPercentageAuto::Points(value) => {
|
||||||
|
taffy::style::LengthPercentage::Points(value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn into_dimension(self, context: &LayoutContext) -> taffy::style::Dimension {
|
||||||
|
self.into_length_percentage_auto(context).into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UiRect {
|
impl UiRect {
|
||||||
fn scaled(self, scale_factor: f64) -> Self {
|
fn map_to_taffy_rect<T>(self, map_fn: impl Fn(Val) -> T) -> taffy::geometry::Rect<T> {
|
||||||
Self {
|
taffy::geometry::Rect {
|
||||||
left: self.left.scaled(scale_factor),
|
left: map_fn(self.left),
|
||||||
right: self.right.scaled(scale_factor),
|
right: map_fn(self.right),
|
||||||
top: self.top.scaled(scale_factor),
|
top: map_fn(self.top),
|
||||||
bottom: self.bottom.scaled(scale_factor),
|
bottom: map_fn(self.bottom),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Size {
|
impl Size {
|
||||||
fn scaled(self, scale_factor: f64) -> Self {
|
fn map_to_taffy_size<T>(self, map_fn: impl Fn(Val) -> T) -> taffy::geometry::Size<T> {
|
||||||
Self {
|
taffy::geometry::Size {
|
||||||
width: self.width.scaled(scale_factor),
|
width: map_fn(self.width),
|
||||||
height: self.height.scaled(scale_factor),
|
height: map_fn(self.height),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: From<Val>> From<UiRect> for taffy::prelude::Rect<T> {
|
pub fn from_style(context: &LayoutContext, style: &Style) -> taffy::style::Style {
|
||||||
fn from(value: UiRect) -> Self {
|
|
||||||
Self {
|
|
||||||
left: value.left.into(),
|
|
||||||
right: value.right.into(),
|
|
||||||
top: value.top.into(),
|
|
||||||
bottom: value.bottom.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: From<Val>> From<Size> for taffy::prelude::Size<T> {
|
|
||||||
fn from(value: Size) -> Self {
|
|
||||||
Self {
|
|
||||||
width: value.width.into(),
|
|
||||||
height: value.height.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Val> for taffy::style::Dimension {
|
|
||||||
fn from(value: Val) -> Self {
|
|
||||||
match value {
|
|
||||||
Val::Auto => taffy::style::Dimension::Auto,
|
|
||||||
Val::Percent(value) => taffy::style::Dimension::Percent(value / 100.0),
|
|
||||||
Val::Px(value) => taffy::style::Dimension::Points(value),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Val> for taffy::style::LengthPercentage {
|
|
||||||
fn from(value: Val) -> Self {
|
|
||||||
match value {
|
|
||||||
Val::Auto => taffy::style::LengthPercentage::Points(0.0),
|
|
||||||
Val::Percent(value) => taffy::style::LengthPercentage::Percent(value / 100.0),
|
|
||||||
Val::Px(value) => taffy::style::LengthPercentage::Points(value),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Val> for taffy::style::LengthPercentageAuto {
|
|
||||||
fn from(value: Val) -> Self {
|
|
||||||
match value {
|
|
||||||
Val::Auto => taffy::style::LengthPercentageAuto::Auto,
|
|
||||||
Val::Percent(value) => taffy::style::LengthPercentageAuto::Percent(value / 100.0),
|
|
||||||
Val::Px(value) => taffy::style::LengthPercentageAuto::Points(value),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_style(scale_factor: f64, style: &Style) -> taffy::style::Style {
|
|
||||||
taffy::style::Style {
|
taffy::style::Style {
|
||||||
display: style.display.into(),
|
display: style.display.into(),
|
||||||
position: style.position_type.into(),
|
position: style.position_type.into(),
|
||||||
@ -104,22 +79,34 @@ pub fn from_style(scale_factor: f64, style: &Style) -> taffy::style::Style {
|
|||||||
align_content: Some(style.align_content.into()),
|
align_content: Some(style.align_content.into()),
|
||||||
justify_content: Some(style.justify_content.into()),
|
justify_content: Some(style.justify_content.into()),
|
||||||
inset: taffy::prelude::Rect {
|
inset: taffy::prelude::Rect {
|
||||||
left: style.left.scaled(scale_factor).to_inset(),
|
left: style.left.into_length_percentage_auto(context),
|
||||||
right: style.right.scaled(scale_factor).to_inset(),
|
right: style.right.into_length_percentage_auto(context),
|
||||||
top: style.top.scaled(scale_factor).to_inset(),
|
top: style.top.into_length_percentage_auto(context),
|
||||||
bottom: style.bottom.scaled(scale_factor).to_inset(),
|
bottom: style.bottom.into_length_percentage_auto(context),
|
||||||
},
|
},
|
||||||
margin: style.margin.scaled(scale_factor).into(),
|
margin: style
|
||||||
padding: style.padding.scaled(scale_factor).into(),
|
.margin
|
||||||
border: style.border.scaled(scale_factor).into(),
|
.map_to_taffy_rect(|m| m.into_length_percentage_auto(context)),
|
||||||
|
padding: style
|
||||||
|
.padding
|
||||||
|
.map_to_taffy_rect(|m| m.into_length_percentage(context)),
|
||||||
|
border: style
|
||||||
|
.border
|
||||||
|
.map_to_taffy_rect(|m| m.into_length_percentage(context)),
|
||||||
flex_grow: style.flex_grow,
|
flex_grow: style.flex_grow,
|
||||||
flex_shrink: style.flex_shrink,
|
flex_shrink: style.flex_shrink,
|
||||||
flex_basis: style.flex_basis.scaled(scale_factor).into(),
|
flex_basis: style.flex_basis.into_dimension(context),
|
||||||
size: style.size.scaled(scale_factor).into(),
|
size: style.size.map_to_taffy_size(|s| s.into_dimension(context)),
|
||||||
min_size: style.min_size.scaled(scale_factor).into(),
|
min_size: style
|
||||||
max_size: style.max_size.scaled(scale_factor).into(),
|
.min_size
|
||||||
|
.map_to_taffy_size(|s| s.into_dimension(context)),
|
||||||
|
max_size: style
|
||||||
|
.max_size
|
||||||
|
.map_to_taffy_size(|s| s.into_dimension(context)),
|
||||||
aspect_ratio: style.aspect_ratio,
|
aspect_ratio: style.aspect_ratio,
|
||||||
gap: style.gap.scaled(scale_factor).into(),
|
gap: style
|
||||||
|
.gap
|
||||||
|
.map_to_taffy_size(|s| s.into_length_percentage(context)),
|
||||||
justify_self: None,
|
justify_self: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -283,7 +270,8 @@ mod tests {
|
|||||||
height: Val::Percent(0.),
|
height: Val::Percent(0.),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let taffy_style = from_style(1.0, &bevy_style);
|
let viewport_values = LayoutContext::new(1.0, bevy_math::Vec2::new(800., 600.));
|
||||||
|
let taffy_style = from_style(&viewport_values, &bevy_style);
|
||||||
assert_eq!(taffy_style.display, taffy::style::Display::Flex);
|
assert_eq!(taffy_style.display, taffy::style::Display::Flex);
|
||||||
assert_eq!(taffy_style.position, taffy::style::Position::Absolute);
|
assert_eq!(taffy_style.position, taffy::style::Position::Absolute);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
@ -408,4 +396,27 @@ mod tests {
|
|||||||
taffy::style::LengthPercentage::Percent(0.)
|
taffy::style::LengthPercentage::Percent(0.)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_into_length_percentage() {
|
||||||
|
use taffy::style::LengthPercentage;
|
||||||
|
let context = LayoutContext::new(2.0, bevy_math::Vec2::new(800., 600.));
|
||||||
|
let cases = [
|
||||||
|
(Val::Auto, LengthPercentage::Points(0.)),
|
||||||
|
(Val::Percent(1.), LengthPercentage::Percent(0.01)),
|
||||||
|
(Val::Px(1.), LengthPercentage::Points(2.)),
|
||||||
|
(Val::Vw(1.), LengthPercentage::Points(8.)),
|
||||||
|
(Val::Vh(1.), LengthPercentage::Points(6.)),
|
||||||
|
(Val::VMin(2.), LengthPercentage::Points(12.)),
|
||||||
|
(Val::VMax(2.), LengthPercentage::Points(16.)),
|
||||||
|
];
|
||||||
|
for (val, length) in cases {
|
||||||
|
assert!(match (val.into_length_percentage(&context), length) {
|
||||||
|
(LengthPercentage::Points(a), LengthPercentage::Points(b))
|
||||||
|
| (LengthPercentage::Percent(a), LengthPercentage::Percent(b)) =>
|
||||||
|
(a - b).abs() < 0.0001,
|
||||||
|
_ => false,
|
||||||
|
},);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,25 @@ use taffy::{
|
|||||||
Taffy,
|
Taffy,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub struct LayoutContext {
|
||||||
|
pub scale_factor: f64,
|
||||||
|
pub physical_size: Vec2,
|
||||||
|
pub min_size: f32,
|
||||||
|
pub max_size: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayoutContext {
|
||||||
|
/// create new a [`LayoutContext`] from the window's physical size and scale factor
|
||||||
|
fn new(scale_factor: f64, physical_size: Vec2) -> Self {
|
||||||
|
Self {
|
||||||
|
scale_factor,
|
||||||
|
physical_size,
|
||||||
|
min_size: physical_size.x.min(physical_size.y),
|
||||||
|
max_size: physical_size.x.max(physical_size.y),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
pub struct FlexSurface {
|
pub struct FlexSurface {
|
||||||
entity_to_taffy: HashMap<Entity, taffy::node::Node>,
|
entity_to_taffy: HashMap<Entity, taffy::node::Node>,
|
||||||
@ -59,19 +78,17 @@ impl Default for FlexSurface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FlexSurface {
|
impl FlexSurface {
|
||||||
pub fn upsert_node(&mut self, entity: Entity, style: &Style, scale_factor: f64) {
|
pub fn upsert_node(&mut self, entity: Entity, style: &Style, context: &LayoutContext) {
|
||||||
let mut added = false;
|
let mut added = false;
|
||||||
let taffy = &mut self.taffy;
|
let taffy = &mut self.taffy;
|
||||||
let taffy_node = self.entity_to_taffy.entry(entity).or_insert_with(|| {
|
let taffy_node = self.entity_to_taffy.entry(entity).or_insert_with(|| {
|
||||||
added = true;
|
added = true;
|
||||||
taffy
|
taffy.new_leaf(convert::from_style(context, style)).unwrap()
|
||||||
.new_leaf(convert::from_style(scale_factor, style))
|
|
||||||
.unwrap()
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if !added {
|
if !added {
|
||||||
self.taffy
|
self.taffy
|
||||||
.set_style(*taffy_node, convert::from_style(scale_factor, style))
|
.set_style(*taffy_node, convert::from_style(context, style))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,10 +98,11 @@ impl FlexSurface {
|
|||||||
entity: Entity,
|
entity: Entity,
|
||||||
style: &Style,
|
style: &Style,
|
||||||
calculated_size: CalculatedSize,
|
calculated_size: CalculatedSize,
|
||||||
scale_factor: f64,
|
context: &LayoutContext,
|
||||||
) {
|
) {
|
||||||
let taffy = &mut self.taffy;
|
let taffy = &mut self.taffy;
|
||||||
let taffy_style = convert::from_style(scale_factor, style);
|
let taffy_style = convert::from_style(context, style);
|
||||||
|
let scale_factor = context.scale_factor;
|
||||||
let measure = taffy::node::MeasureFunc::Boxed(Box::new(
|
let measure = taffy::node::MeasureFunc::Boxed(Box::new(
|
||||||
move |constraints: Size<Option<f32>>, _available: Size<AvailableSpace>| {
|
move |constraints: Size<Option<f32>>, _available: Size<AvailableSpace>| {
|
||||||
let mut size = Size {
|
let mut size = Size {
|
||||||
@ -229,6 +247,7 @@ pub fn flex_node_system(
|
|||||||
windows: Query<(Entity, &Window)>,
|
windows: Query<(Entity, &Window)>,
|
||||||
ui_scale: Res<UiScale>,
|
ui_scale: Res<UiScale>,
|
||||||
mut scale_factor_events: EventReader<WindowScaleFactorChanged>,
|
mut scale_factor_events: EventReader<WindowScaleFactorChanged>,
|
||||||
|
mut resize_events: EventReader<bevy_window::WindowResized>,
|
||||||
mut flex_surface: ResMut<FlexSurface>,
|
mut flex_surface: ResMut<FlexSurface>,
|
||||||
root_node_query: Query<Entity, (With<Node>, Without<Parent>)>,
|
root_node_query: Query<Entity, (With<Node>, Without<Parent>)>,
|
||||||
node_query: Query<(Entity, &Style, Option<&CalculatedSize>), (With<Node>, Changed<Style>)>,
|
node_query: Query<(Entity, &Style, Option<&CalculatedSize>), (With<Node>, Changed<Style>)>,
|
||||||
@ -244,13 +263,24 @@ pub fn flex_node_system(
|
|||||||
) {
|
) {
|
||||||
// assume one window for time being...
|
// assume one window for time being...
|
||||||
// TODO: Support window-independent scaling: https://github.com/bevyengine/bevy/issues/5621
|
// TODO: Support window-independent scaling: https://github.com/bevyengine/bevy/issues/5621
|
||||||
let (primary_window_entity, logical_to_physical_factor) =
|
let (primary_window_entity, logical_to_physical_factor, physical_size) =
|
||||||
if let Ok((entity, primary_window)) = primary_window.get_single() {
|
if let Ok((entity, primary_window)) = primary_window.get_single() {
|
||||||
(entity, primary_window.resolution.scale_factor())
|
(
|
||||||
|
entity,
|
||||||
|
primary_window.resolution.scale_factor(),
|
||||||
|
Vec2::new(
|
||||||
|
primary_window.resolution.physical_width() as f32,
|
||||||
|
primary_window.resolution.physical_height() as f32,
|
||||||
|
),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let resized = resize_events
|
||||||
|
.iter()
|
||||||
|
.any(|resized_window| resized_window.window == primary_window_entity);
|
||||||
|
|
||||||
// update window root nodes
|
// update window root nodes
|
||||||
for (entity, window) in windows.iter() {
|
for (entity, window) in windows.iter() {
|
||||||
flex_surface.update_window(entity, &window.resolution);
|
flex_surface.update_window(entity, &window.resolution);
|
||||||
@ -258,31 +288,33 @@ pub fn flex_node_system(
|
|||||||
|
|
||||||
let scale_factor = logical_to_physical_factor * ui_scale.scale;
|
let scale_factor = logical_to_physical_factor * ui_scale.scale;
|
||||||
|
|
||||||
|
let viewport_values = LayoutContext::new(scale_factor, physical_size);
|
||||||
|
|
||||||
fn update_changed<F: ReadOnlyWorldQuery>(
|
fn update_changed<F: ReadOnlyWorldQuery>(
|
||||||
flex_surface: &mut FlexSurface,
|
flex_surface: &mut FlexSurface,
|
||||||
scaling_factor: f64,
|
viewport_values: &LayoutContext,
|
||||||
query: Query<(Entity, &Style, Option<&CalculatedSize>), F>,
|
query: Query<(Entity, &Style, Option<&CalculatedSize>), F>,
|
||||||
) {
|
) {
|
||||||
// update changed nodes
|
// update changed nodes
|
||||||
for (entity, style, calculated_size) in &query {
|
for (entity, style, calculated_size) in &query {
|
||||||
// TODO: remove node from old hierarchy if its root has changed
|
// TODO: remove node from old hierarchy if its root has changed
|
||||||
if let Some(calculated_size) = calculated_size {
|
if let Some(calculated_size) = calculated_size {
|
||||||
flex_surface.upsert_leaf(entity, style, *calculated_size, scaling_factor);
|
flex_surface.upsert_leaf(entity, style, *calculated_size, viewport_values);
|
||||||
} else {
|
} else {
|
||||||
flex_surface.upsert_node(entity, style, scaling_factor);
|
flex_surface.upsert_node(entity, style, viewport_values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !scale_factor_events.is_empty() || ui_scale.is_changed() {
|
if !scale_factor_events.is_empty() || ui_scale.is_changed() || resized {
|
||||||
scale_factor_events.clear();
|
scale_factor_events.clear();
|
||||||
update_changed(&mut flex_surface, scale_factor, full_node_query);
|
update_changed(&mut flex_surface, &viewport_values, full_node_query);
|
||||||
} else {
|
} else {
|
||||||
update_changed(&mut flex_surface, scale_factor, node_query);
|
update_changed(&mut flex_surface, &viewport_values, node_query);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (entity, style, calculated_size) in &changed_size_query {
|
for (entity, style, calculated_size) in &changed_size_query {
|
||||||
flex_surface.upsert_leaf(entity, style, *calculated_size, scale_factor);
|
flex_surface.upsert_leaf(entity, style, *calculated_size, &viewport_values);
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean up removed nodes
|
// clean up removed nodes
|
||||||
|
@ -81,6 +81,14 @@ pub enum Val {
|
|||||||
/// * For `margin`, `padding`, and `border` values: the percentage is relative to the parent node's width.
|
/// * For `margin`, `padding`, and `border` values: the percentage is relative to the parent node's width.
|
||||||
/// * For positions, `left` and `right` are relative to the parent's width, while `bottom` and `top` are relative to the parent's height.
|
/// * For positions, `left` and `right` are relative to the parent's width, while `bottom` and `top` are relative to the parent's height.
|
||||||
Percent(f32),
|
Percent(f32),
|
||||||
|
/// Set this value in percent of the viewport width
|
||||||
|
Vw(f32),
|
||||||
|
/// Set this value in percent of the viewport height
|
||||||
|
Vh(f32),
|
||||||
|
/// Set this value in percent of the viewport's smaller dimension.
|
||||||
|
VMin(f32),
|
||||||
|
/// Set this value in percent of the viewport's larger dimension.
|
||||||
|
VMax(f32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Val {
|
impl Val {
|
||||||
@ -101,6 +109,10 @@ impl Mul<f32> for Val {
|
|||||||
Val::Auto => Val::Auto,
|
Val::Auto => Val::Auto,
|
||||||
Val::Px(value) => Val::Px(value * rhs),
|
Val::Px(value) => Val::Px(value * rhs),
|
||||||
Val::Percent(value) => Val::Percent(value * rhs),
|
Val::Percent(value) => Val::Percent(value * rhs),
|
||||||
|
Val::Vw(value) => Val::Vw(value * rhs),
|
||||||
|
Val::Vh(value) => Val::Vh(value * rhs),
|
||||||
|
Val::VMin(value) => Val::VMin(value * rhs),
|
||||||
|
Val::VMax(value) => Val::VMax(value * rhs),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,7 +121,12 @@ impl MulAssign<f32> for Val {
|
|||||||
fn mul_assign(&mut self, rhs: f32) {
|
fn mul_assign(&mut self, rhs: f32) {
|
||||||
match self {
|
match self {
|
||||||
Val::Auto => {}
|
Val::Auto => {}
|
||||||
Val::Px(value) | Val::Percent(value) => *value *= rhs,
|
Val::Px(value)
|
||||||
|
| Val::Percent(value)
|
||||||
|
| Val::Vw(value)
|
||||||
|
| Val::Vh(value)
|
||||||
|
| Val::VMin(value)
|
||||||
|
| Val::VMax(value) => *value *= rhs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,6 +139,10 @@ impl Div<f32> for Val {
|
|||||||
Val::Auto => Val::Auto,
|
Val::Auto => Val::Auto,
|
||||||
Val::Px(value) => Val::Px(value / rhs),
|
Val::Px(value) => Val::Px(value / rhs),
|
||||||
Val::Percent(value) => Val::Percent(value / rhs),
|
Val::Percent(value) => Val::Percent(value / rhs),
|
||||||
|
Val::Vw(value) => Val::Vw(value / rhs),
|
||||||
|
Val::Vh(value) => Val::Vh(value / rhs),
|
||||||
|
Val::VMin(value) => Val::VMin(value / rhs),
|
||||||
|
Val::VMax(value) => Val::VMax(value / rhs),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,7 +151,12 @@ impl DivAssign<f32> for Val {
|
|||||||
fn div_assign(&mut self, rhs: f32) {
|
fn div_assign(&mut self, rhs: f32) {
|
||||||
match self {
|
match self {
|
||||||
Val::Auto => {}
|
Val::Auto => {}
|
||||||
Val::Px(value) | Val::Percent(value) => *value /= rhs,
|
Val::Px(value)
|
||||||
|
| Val::Percent(value)
|
||||||
|
| Val::Vw(value)
|
||||||
|
| Val::Vh(value)
|
||||||
|
| Val::VMin(value)
|
||||||
|
| Val::VMax(value) => *value /= rhs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user