diff --git a/crates/bevy_ui/src/flex/convert.rs b/crates/bevy_ui/src/flex/convert.rs index a2bb1af48c053..1e8f073671488 100644 --- a/crates/bevy_ui/src/flex/convert.rs +++ b/crates/bevy_ui/src/flex/convert.rs @@ -13,9 +13,7 @@ impl Val { match self { Val::Auto => taffy::style::LengthPercentageAuto::Auto, Val::Percent(value) => taffy::style::LengthPercentageAuto::Percent(value / 100.), - Val::Px(value) => taffy::style::LengthPercentageAuto::Points( - (context.scale_factor * value as f64) as f32, - ), + Val::Px(value) => taffy::style::LengthPercentageAuto::Points(value), Val::VMin(value) => { taffy::style::LengthPercentageAuto::Points(context.min_size * value / 100.) } @@ -23,10 +21,10 @@ impl Val { taffy::style::LengthPercentageAuto::Points(context.max_size * value / 100.) } Val::Vw(value) => { - taffy::style::LengthPercentageAuto::Points(context.physical_size.x * value / 100.) + taffy::style::LengthPercentageAuto::Points(context.logical_size.x * value / 100.) } Val::Vh(value) => { - taffy::style::LengthPercentageAuto::Points(context.physical_size.y * value / 100.) + taffy::style::LengthPercentageAuto::Points(context.logical_size.y * value / 100.) } } } diff --git a/crates/bevy_ui/src/flex/mod.rs b/crates/bevy_ui/src/flex/mod.rs index d59d8c544164c..44c4d3ab5009c 100644 --- a/crates/bevy_ui/src/flex/mod.rs +++ b/crates/bevy_ui/src/flex/mod.rs @@ -14,7 +14,7 @@ use bevy_log::warn; use bevy_math::Vec2; use bevy_transform::components::Transform; use bevy_utils::HashMap; -use bevy_window::{PrimaryWindow, Window, WindowResolution, WindowScaleFactorChanged}; +use bevy_window::{PrimaryWindow, Window, WindowScaleFactorChanged}; use std::fmt; use taffy::{ prelude::{AvailableSpace, Size}, @@ -22,9 +22,11 @@ use taffy::{ Taffy, }; +#[derive(Debug)] pub struct LayoutContext { pub scale_factor: f64, pub physical_size: Vec2, + pub logical_size: Vec2, pub min_size: f32, pub max_size: f32, } @@ -32,11 +34,13 @@ pub struct LayoutContext { impl LayoutContext { /// create new a [`LayoutContext`] from the window's physical size and scale factor fn new(scale_factor: f64, physical_size: Vec2) -> Self { + let logical_size = physical_size / scale_factor as f32; Self { scale_factor, physical_size, - min_size: physical_size.x.min(physical_size.y), - max_size: physical_size.x.max(physical_size.y), + logical_size, + min_size: logical_size.min_element(), + max_size: logical_size.max_element(), } } } @@ -102,12 +106,11 @@ impl FlexSurface { ) { let taffy = &mut self.taffy; let taffy_style = convert::from_style(context, style); - let scale_factor = context.scale_factor; let measure = taffy::node::MeasureFunc::Boxed(Box::new( move |constraints: Size>, _available: Size| { let mut size = Size { - width: (scale_factor * calculated_size.size.x as f64) as f32, - height: (scale_factor * calculated_size.size.y as f64) as f32, + width: calculated_size.size.x as f32, + height: calculated_size.size.y as f32, }; match (constraints.width, constraints.height) { (None, None) => {} @@ -173,7 +176,7 @@ without UI components as a child of an entity with UI components, results may be } } - pub fn update_window(&mut self, window: Entity, window_resolution: &WindowResolution) { + pub fn update_window(&mut self, window: Entity, logical_size: Vec2) { let taffy = &mut self.taffy; let node = self .window_nodes @@ -185,12 +188,8 @@ without UI components as a child of an entity with UI components, results may be *node, taffy::style::Style { size: taffy::geometry::Size { - width: taffy::style::Dimension::Points( - window_resolution.physical_width() as f32 - ), - height: taffy::style::Dimension::Points( - window_resolution.physical_height() as f32, - ), + width: taffy::style::Dimension::Points(logical_size.x), + height: taffy::style::Dimension::Points(logical_size.y), }, ..Default::default() }, @@ -251,7 +250,7 @@ pub enum FlexError { #[allow(clippy::too_many_arguments)] pub fn flex_node_system( primary_window: Query<(Entity, &Window), With>, - windows: Query<(Entity, &Window)>, + windows: Query>, ui_scale: Res, mut scale_factor_events: EventReader, mut resize_events: EventReader, @@ -284,20 +283,18 @@ pub fn flex_node_system( } else { return; }; + let scale_factor = logical_to_physical_factor * ui_scale.scale; + let layout_context = LayoutContext::new(scale_factor, physical_size); let resized = resize_events .iter() .any(|resized_window| resized_window.window == primary_window_entity); // update window root nodes - for (entity, window) in windows.iter() { - flex_surface.update_window(entity, &window.resolution); + for entity in windows.iter() { + flex_surface.update_window(entity, layout_context.logical_size); } - let scale_factor = logical_to_physical_factor * ui_scale.scale; - - let viewport_values = LayoutContext::new(scale_factor, physical_size); - fn update_changed( flex_surface: &mut FlexSurface, viewport_values: &LayoutContext, @@ -316,13 +313,13 @@ pub fn flex_node_system( if !scale_factor_events.is_empty() || ui_scale.is_changed() || resized { scale_factor_events.clear(); - update_changed(&mut flex_surface, &viewport_values, full_node_query); + update_changed(&mut flex_surface, &layout_context, full_node_query); } else { - update_changed(&mut flex_surface, &viewport_values, node_query); + update_changed(&mut flex_surface, &layout_context, node_query); } for (entity, style, calculated_size) in &changed_size_query { - flex_surface.upsert_leaf(entity, style, *calculated_size, &viewport_values); + flex_surface.upsert_leaf(entity, style, *calculated_size, &layout_context); } // clean up removed nodes @@ -347,28 +344,21 @@ pub fn flex_node_system( // compute layouts flex_surface.compute_window_layouts(); - let physical_to_logical_factor = 1. / logical_to_physical_factor; - - let to_logical = |v| (physical_to_logical_factor * v as f64) as f32; - // PERF: try doing this incrementally for (entity, mut node, mut transform, parent) in &mut node_transform_query { let layout = flex_surface.get_layout(entity).unwrap(); - let new_size = Vec2::new( - to_logical(layout.size.width), - to_logical(layout.size.height), - ); + let new_size = Vec2::new(layout.size.width, layout.size.height); // only trigger change detection when the new value is different if node.calculated_size != new_size { node.calculated_size = new_size; } let mut new_position = transform.translation; - new_position.x = to_logical(layout.location.x + layout.size.width / 2.0); - new_position.y = to_logical(layout.location.y + layout.size.height / 2.0); + new_position.x = layout.location.x + layout.size.width / 2.0; + new_position.y = layout.location.y + layout.size.height / 2.0; if let Some(parent) = parent { if let Ok(parent_layout) = flex_surface.get_layout(**parent) { - new_position.x -= to_logical(parent_layout.size.width / 2.0); - new_position.y -= to_logical(parent_layout.size.height / 2.0); + new_position.x -= parent_layout.size.width / 2.0; + new_position.y -= parent_layout.size.height / 2.0; } } // only trigger change detection when the new value is different