Upgrade to Taffy 0.2 (#6743)

# Objective

Upgrade to Taffy 0.2

## Solution

Do it

## Changelog

Upgraded to Taffy 0.2, improving UI layout performance significantly and adding the flexbox `gap` property and `AlignContent::SpaceEvenly`.

## Notes

`many_buttons` is 8% faster! speed improvements for more highly nested UIs will be much more dramatic. Great work, Team Taffy.
This commit is contained in:
Rob Parrett 2022-12-21 02:15:53 +00:00
parent 025996b18c
commit 2938792c7d
4 changed files with 28 additions and 23 deletions

View File

@ -30,7 +30,7 @@ bevy_window = { path = "../bevy_window", version = "0.9.0" }
bevy_utils = { path = "../bevy_utils", version = "0.9.0" } bevy_utils = { path = "../bevy_utils", version = "0.9.0" }
# other # other
taffy = "0.1.0" taffy = "0.2.2"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
smallvec = { version = "1.6", features = ["union", "const_generics"] } smallvec = { version = "1.6", features = ["union", "const_generics"] }
bytemuck = { version = "1.5", features = ["derive"] } bytemuck = { version = "1.5", features = ["derive"] }

View File

@ -8,8 +8,8 @@ pub fn from_rect(
rect: UiRect, rect: UiRect,
) -> taffy::geometry::Rect<taffy::style::Dimension> { ) -> taffy::geometry::Rect<taffy::style::Dimension> {
taffy::geometry::Rect { taffy::geometry::Rect {
start: from_val(scale_factor, rect.left), left: from_val(scale_factor, rect.left),
end: from_val(scale_factor, rect.right), right: from_val(scale_factor, rect.right),
top: from_val(scale_factor, rect.top), top: from_val(scale_factor, rect.top),
bottom: from_val(scale_factor, rect.bottom), bottom: from_val(scale_factor, rect.bottom),
} }
@ -52,10 +52,8 @@ pub fn from_style(scale_factor: f64, value: &Style) -> taffy::style::Style {
size: from_val_size(scale_factor, value.size), size: from_val_size(scale_factor, value.size),
min_size: from_val_size(scale_factor, value.min_size), min_size: from_val_size(scale_factor, value.min_size),
max_size: from_val_size(scale_factor, value.max_size), max_size: from_val_size(scale_factor, value.max_size),
aspect_ratio: match value.aspect_ratio { aspect_ratio: value.aspect_ratio,
Some(value) => taffy::number::Number::Defined(value), gap: from_val_size(scale_factor, value.gap),
None => taffy::number::Number::Undefined,
},
} }
} }

View File

@ -14,7 +14,10 @@ use bevy_transform::components::Transform;
use bevy_utils::HashMap; use bevy_utils::HashMap;
use bevy_window::{Window, WindowId, WindowScaleFactorChanged, Windows}; use bevy_window::{Window, WindowId, WindowScaleFactorChanged, Windows};
use std::fmt; use std::fmt;
use taffy::{number::Number, Taffy}; use taffy::{
prelude::{AvailableSpace, Size},
Taffy,
};
#[derive(Resource)] #[derive(Resource)]
pub struct FlexSurface { pub struct FlexSurface {
@ -63,7 +66,7 @@ impl FlexSurface {
let taffy_style = convert::from_style(scale_factor, style); let taffy_style = convert::from_style(scale_factor, style);
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.new_node(taffy_style, &Vec::new()).unwrap() taffy.new_leaf(taffy_style).unwrap()
}); });
if !added { if !added {
@ -81,23 +84,23 @@ impl FlexSurface {
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(scale_factor, style);
let measure = taffy::node::MeasureFunc::Boxed(Box::new( let measure = taffy::node::MeasureFunc::Boxed(Box::new(
move |constraints: taffy::geometry::Size<Number>| { move |constraints: Size<Option<f32>>, _available: Size<AvailableSpace>| {
let mut size = convert::from_f32_size(scale_factor, calculated_size.size); let mut size = convert::from_f32_size(scale_factor, calculated_size.size);
match (constraints.width, constraints.height) { match (constraints.width, constraints.height) {
(Number::Undefined, Number::Undefined) => {} (None, None) => {}
(Number::Defined(width), Number::Undefined) => { (Some(width), None) => {
if calculated_size.preserve_aspect_ratio { if calculated_size.preserve_aspect_ratio {
size.height = width * size.height / size.width; size.height = width * size.height / size.width;
} }
size.width = width; size.width = width;
} }
(Number::Undefined, Number::Defined(height)) => { (None, Some(height)) => {
if calculated_size.preserve_aspect_ratio { if calculated_size.preserve_aspect_ratio {
size.width = height * size.width / size.height; size.width = height * size.width / size.height;
} }
size.height = height; size.height = height;
} }
(Number::Defined(width), Number::Defined(height)) => { (Some(width), Some(height)) => {
size.width = width; size.width = width;
size.height = height; size.height = height;
} }
@ -110,7 +113,7 @@ impl FlexSurface {
self.taffy.set_style(*taffy_node, taffy_style).unwrap(); self.taffy.set_style(*taffy_node, taffy_style).unwrap();
self.taffy.set_measure(*taffy_node, Some(measure)).unwrap(); self.taffy.set_measure(*taffy_node, Some(measure)).unwrap();
} else { } else {
let taffy_node = taffy.new_leaf(taffy_style, measure).unwrap(); let taffy_node = taffy.new_leaf(taffy_style).unwrap();
self.entity_to_taffy.insert(entity, taffy_node); self.entity_to_taffy.insert(entity, taffy_node);
} }
} }
@ -143,11 +146,10 @@ without UI components as a child of an entity with UI components, results may be
pub fn update_window(&mut self, window: &Window) { pub fn update_window(&mut self, window: &Window) {
let taffy = &mut self.taffy; let taffy = &mut self.taffy;
let node = self.window_nodes.entry(window.id()).or_insert_with(|| { let node = self
taffy .window_nodes
.new_node(taffy::style::Style::default(), &Vec::new()) .entry(window.id())
.unwrap() .or_insert_with(|| taffy.new_leaf(taffy::style::Style::default()).unwrap());
});
taffy taffy
.set_style( .set_style(
@ -178,7 +180,7 @@ without UI components as a child of an entity with UI components, results may be
pub fn compute_window_layouts(&mut self) { pub fn compute_window_layouts(&mut self) {
for window_node in self.window_nodes.values() { for window_node in self.window_nodes.values() {
self.taffy self.taffy
.compute_layout(*window_node, taffy::geometry::Size::undefined()) .compute_layout(*window_node, Size::MAX_CONTENT)
.unwrap(); .unwrap();
} }
} }
@ -187,7 +189,7 @@ without UI components as a child of an entity with UI components, results may be
pub fn remove_entities(&mut self, entities: impl IntoIterator<Item = Entity>) { pub fn remove_entities(&mut self, entities: impl IntoIterator<Item = Entity>) {
for entity in entities { for entity in entities {
if let Some(node) = self.entity_to_taffy.remove(&entity) { if let Some(node) = self.entity_to_taffy.remove(&entity) {
self.taffy.remove(node); self.taffy.remove(node).unwrap();
} }
} }
} }
@ -210,7 +212,7 @@ with UI components as a child of an entity without UI components, results may be
#[derive(Debug)] #[derive(Debug)]
pub enum FlexError { pub enum FlexError {
InvalidHierarchy, InvalidHierarchy,
TaffyError(taffy::Error), TaffyError(taffy::error::TaffyError),
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]

View File

@ -237,6 +237,10 @@ pub struct Style {
pub aspect_ratio: Option<f32>, pub aspect_ratio: Option<f32>,
/// How to handle overflow /// How to handle overflow
pub overflow: Overflow, pub overflow: Overflow,
/// The size of the gutters between the rows and columns of the flexbox layout
///
/// Values of `Size::UNDEFINED` and `Size::AUTO` are treated as zero.
pub gap: Size,
} }
impl Default for Style { impl Default for Style {
@ -263,6 +267,7 @@ impl Default for Style {
max_size: Size::AUTO, max_size: Size::AUTO,
aspect_ratio: Default::default(), aspect_ratio: Default::default(),
overflow: Default::default(), overflow: Default::default(),
gap: Size::UNDEFINED,
} }
} }
} }