Skip to content

Commit 96b9d0a

Browse files
authored
Upgrade to Taffy 0.4 (#10690)
# Objective - Enables support for `Display::Block` - Enables support for `Overflow::Hidden` - Allows for cleaner integration with text, image and other content layout. - Unblocks #8104 - Unlocks the possibility of Bevy creating a custom layout tree over which Taffy operates. - Enables #8808 / #10193 to remove a Mutex around the font system. ## Todo - [x] ~Fix rendering of text/images to account for padding/border on nodes (should size/position to content box rather than border box)~ In order get this into a mergeable state this PR instead zeroes out padding/border when syncing leaf node styles into Taffy to preserve the existing behaviour. #6879 can be fixed in a followup PR. ## Solution - Update the version of Taffy - Update code to work with the new version Note: Taffy 0.4 has not yet been released. This PR is being created in advance of the release to ensure that there are no blockers to upgrading once the release occurs. --- ## Changelog - Bevy now supports the `Display::Block` and `Overflow::Hidden` styles.
1 parent 9973f0c commit 96b9d0a

File tree

10 files changed

+250
-123
lines changed

10 files changed

+250
-123
lines changed

crates/bevy_ui/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ bevy_window = { path = "../bevy_window", version = "0.14.0-dev" }
3131
bevy_utils = { path = "../bevy_utils", version = "0.14.0-dev" }
3232

3333
# other
34-
taffy = { version = "0.3.10" }
34+
taffy = { version = "0.4" }
3535
serde = { version = "1", features = ["derive"], optional = true }
3636
bytemuck = { version = "1.5", features = ["derive"] }
3737
thiserror = "1.0.0"

crates/bevy_ui/src/layout/convert.rs

Lines changed: 70 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use taffy::style_helpers;
33
use crate::{
44
AlignContent, AlignItems, AlignSelf, Display, FlexDirection, FlexWrap, GridAutoFlow,
55
GridPlacement, GridTrack, GridTrackRepetition, JustifyContent, JustifyItems, JustifySelf,
6-
MaxTrackSizingFunction, MinTrackSizingFunction, PositionType, RepeatedGridTrack, Style, UiRect,
7-
Val,
6+
MaxTrackSizingFunction, MinTrackSizingFunction, OverflowAxis, PositionType, RepeatedGridTrack,
7+
Style, UiRect, Val,
88
};
99

1010
use super::LayoutContext;
@@ -18,31 +18,31 @@ impl Val {
1818
Val::Auto => taffy::style::LengthPercentageAuto::Auto,
1919
Val::Percent(value) => taffy::style::LengthPercentageAuto::Percent(value / 100.),
2020
Val::Px(value) => {
21-
taffy::style::LengthPercentageAuto::Points(context.scale_factor * value)
21+
taffy::style::LengthPercentageAuto::Length(context.scale_factor * value)
2222
}
2323
Val::VMin(value) => {
24-
taffy::style::LengthPercentageAuto::Points(context.min_size * value / 100.)
24+
taffy::style::LengthPercentageAuto::Length(context.min_size * value / 100.)
2525
}
2626
Val::VMax(value) => {
27-
taffy::style::LengthPercentageAuto::Points(context.max_size * value / 100.)
27+
taffy::style::LengthPercentageAuto::Length(context.max_size * value / 100.)
2828
}
2929
Val::Vw(value) => {
30-
taffy::style::LengthPercentageAuto::Points(context.physical_size.x * value / 100.)
30+
taffy::style::LengthPercentageAuto::Length(context.physical_size.x * value / 100.)
3131
}
3232
Val::Vh(value) => {
33-
taffy::style::LengthPercentageAuto::Points(context.physical_size.y * value / 100.)
33+
taffy::style::LengthPercentageAuto::Length(context.physical_size.y * value / 100.)
3434
}
3535
}
3636
}
3737

3838
fn into_length_percentage(self, context: &LayoutContext) -> taffy::style::LengthPercentage {
3939
match self.into_length_percentage_auto(context) {
40-
taffy::style::LengthPercentageAuto::Auto => taffy::style::LengthPercentage::Points(0.0),
40+
taffy::style::LengthPercentageAuto::Auto => taffy::style::LengthPercentage::Length(0.0),
4141
taffy::style::LengthPercentageAuto::Percent(value) => {
4242
taffy::style::LengthPercentage::Percent(value)
4343
}
44-
taffy::style::LengthPercentageAuto::Points(value) => {
45-
taffy::style::LengthPercentage::Points(value)
44+
taffy::style::LengthPercentageAuto::Length(value) => {
45+
taffy::style::LengthPercentage::Length(value)
4646
}
4747
}
4848
}
@@ -63,9 +63,18 @@ impl UiRect {
6363
}
6464
}
6565

66-
pub fn from_style(context: &LayoutContext, style: &Style) -> taffy::style::Style {
66+
pub fn from_style(
67+
context: &LayoutContext,
68+
style: &Style,
69+
ignore_padding_and_border: bool,
70+
) -> taffy::style::Style {
6771
taffy::style::Style {
6872
display: style.display.into(),
73+
overflow: taffy::Point {
74+
x: style.overflow.x.into(),
75+
y: style.overflow.y.into(),
76+
},
77+
scrollbar_width: 0.0,
6978
position: style.position_type.into(),
7079
flex_direction: style.flex_direction.into(),
7180
flex_wrap: style.flex_wrap.into(),
@@ -75,7 +84,7 @@ pub fn from_style(context: &LayoutContext, style: &Style) -> taffy::style::Style
7584
justify_self: style.justify_self.into(),
7685
align_content: style.align_content.into(),
7786
justify_content: style.justify_content.into(),
78-
inset: taffy::prelude::Rect {
87+
inset: taffy::Rect {
7988
left: style.left.into_length_percentage_auto(context),
8089
right: style.right.into_length_percentage_auto(context),
8190
top: style.top.into_length_percentage_auto(context),
@@ -84,29 +93,41 @@ pub fn from_style(context: &LayoutContext, style: &Style) -> taffy::style::Style
8493
margin: style
8594
.margin
8695
.map_to_taffy_rect(|m| m.into_length_percentage_auto(context)),
87-
padding: style
88-
.padding
89-
.map_to_taffy_rect(|m| m.into_length_percentage(context)),
90-
border: style
91-
.border
92-
.map_to_taffy_rect(|m| m.into_length_percentage(context)),
96+
// Ignore padding for leaf nodes as it isn't implemented in the rendering engine.
97+
// TODO: Implement rendering of padding for leaf nodes
98+
padding: if ignore_padding_and_border {
99+
taffy::Rect::zero()
100+
} else {
101+
style
102+
.padding
103+
.map_to_taffy_rect(|m| m.into_length_percentage(context))
104+
},
105+
// Ignore border for leaf nodes as it isn't implemented in the rendering engine.
106+
// TODO: Implement rendering of border for leaf nodes
107+
border: if ignore_padding_and_border {
108+
taffy::Rect::zero()
109+
} else {
110+
style
111+
.border
112+
.map_to_taffy_rect(|m| m.into_length_percentage(context))
113+
},
93114
flex_grow: style.flex_grow,
94115
flex_shrink: style.flex_shrink,
95116
flex_basis: style.flex_basis.into_dimension(context),
96-
size: taffy::prelude::Size {
117+
size: taffy::Size {
97118
width: style.width.into_dimension(context),
98119
height: style.height.into_dimension(context),
99120
},
100-
min_size: taffy::prelude::Size {
121+
min_size: taffy::Size {
101122
width: style.min_width.into_dimension(context),
102123
height: style.min_height.into_dimension(context),
103124
},
104-
max_size: taffy::prelude::Size {
125+
max_size: taffy::Size {
105126
width: style.max_width.into_dimension(context),
106127
height: style.max_height.into_dimension(context),
107128
},
108129
aspect_ratio: style.aspect_ratio,
109-
gap: taffy::prelude::Size {
130+
gap: taffy::Size {
110131
width: style.column_gap.into_length_percentage(context),
111132
height: style.row_gap.into_length_percentage(context),
112133
},
@@ -231,11 +252,22 @@ impl From<Display> for taffy::style::Display {
231252
match value {
232253
Display::Flex => taffy::style::Display::Flex,
233254
Display::Grid => taffy::style::Display::Grid,
255+
Display::Block => taffy::style::Display::Block,
234256
Display::None => taffy::style::Display::None,
235257
}
236258
}
237259
}
238260

261+
impl From<OverflowAxis> for taffy::style::Overflow {
262+
fn from(value: OverflowAxis) -> Self {
263+
match value {
264+
OverflowAxis::Visible => taffy::style::Overflow::Visible,
265+
OverflowAxis::Clip => taffy::style::Overflow::Clip,
266+
OverflowAxis::Hidden => taffy::style::Overflow::Hidden,
267+
}
268+
}
269+
}
270+
239271
impl From<FlexDirection> for taffy::style::FlexDirection {
240272
fn from(value: FlexDirection) -> Self {
241273
match value {
@@ -489,7 +521,7 @@ mod tests {
489521
grid_row: GridPlacement::span(3),
490522
};
491523
let viewport_values = LayoutContext::new(1.0, bevy_math::Vec2::new(800., 600.));
492-
let taffy_style = from_style(&viewport_values, &bevy_style);
524+
let taffy_style = from_style(&viewport_values, &bevy_style, false);
493525
assert_eq!(taffy_style.display, taffy::style::Display::Flex);
494526
assert_eq!(taffy_style.position, taffy::style::Position::Absolute);
495527
assert_eq!(
@@ -502,7 +534,7 @@ mod tests {
502534
);
503535
assert_eq!(
504536
taffy_style.inset.top,
505-
taffy::style::LengthPercentageAuto::Points(12.)
537+
taffy::style::LengthPercentageAuto::Length(12.)
506538
);
507539
assert_eq!(
508540
taffy_style.inset.bottom,
@@ -537,7 +569,7 @@ mod tests {
537569
);
538570
assert_eq!(
539571
taffy_style.margin.right,
540-
taffy::style::LengthPercentageAuto::Points(10.)
572+
taffy::style::LengthPercentageAuto::Length(10.)
541573
);
542574
assert_eq!(
543575
taffy_style.margin.top,
@@ -553,7 +585,7 @@ mod tests {
553585
);
554586
assert_eq!(
555587
taffy_style.padding.right,
556-
taffy::style::LengthPercentage::Points(21.)
588+
taffy::style::LengthPercentage::Length(21.)
557589
);
558590
assert_eq!(
559591
taffy_style.padding.top,
@@ -565,7 +597,7 @@ mod tests {
565597
);
566598
assert_eq!(
567599
taffy_style.border.left,
568-
taffy::style::LengthPercentage::Points(14.)
600+
taffy::style::LengthPercentage::Length(14.)
569601
);
570602
assert_eq!(
571603
taffy_style.border.right,
@@ -594,18 +626,18 @@ mod tests {
594626
);
595627
assert_eq!(
596628
taffy_style.grid_template_rows,
597-
vec![sh::points(10.0), sh::percent(0.5), sh::fr(1.0)]
629+
vec![sh::length(10.0), sh::percent(0.5), sh::fr(1.0)]
598630
);
599631
assert_eq!(
600632
taffy_style.grid_template_columns,
601-
vec![sh::repeat(5, vec![sh::points(10.0)])]
633+
vec![sh::repeat(5, vec![sh::length(10.0)])]
602634
);
603635
assert_eq!(
604636
taffy_style.grid_auto_rows,
605637
vec![
606-
sh::fit_content(taffy::style::LengthPercentage::Points(10.0)),
638+
sh::fit_content(taffy::style::LengthPercentage::Length(10.0)),
607639
sh::fit_content(taffy::style::LengthPercentage::Percent(0.25)),
608-
sh::minmax(sh::points(0.0), sh::fr(2.0)),
640+
sh::minmax(sh::length(0.0), sh::fr(2.0)),
609641
]
610642
);
611643
assert_eq!(
@@ -627,17 +659,17 @@ mod tests {
627659
use taffy::style::LengthPercentage;
628660
let context = LayoutContext::new(2.0, bevy_math::Vec2::new(800., 600.));
629661
let cases = [
630-
(Val::Auto, LengthPercentage::Points(0.)),
662+
(Val::Auto, LengthPercentage::Length(0.)),
631663
(Val::Percent(1.), LengthPercentage::Percent(0.01)),
632-
(Val::Px(1.), LengthPercentage::Points(2.)),
633-
(Val::Vw(1.), LengthPercentage::Points(8.)),
634-
(Val::Vh(1.), LengthPercentage::Points(6.)),
635-
(Val::VMin(2.), LengthPercentage::Points(12.)),
636-
(Val::VMax(2.), LengthPercentage::Points(16.)),
664+
(Val::Px(1.), LengthPercentage::Length(2.)),
665+
(Val::Vw(1.), LengthPercentage::Length(8.)),
666+
(Val::Vh(1.), LengthPercentage::Length(6.)),
667+
(Val::VMin(2.), LengthPercentage::Length(12.)),
668+
(Val::VMax(2.), LengthPercentage::Length(16.)),
637669
];
638670
for (val, length) in cases {
639671
assert!(match (val.into_length_percentage(&context), length) {
640-
(LengthPercentage::Points(a), LengthPercentage::Points(b))
672+
(LengthPercentage::Length(a), LengthPercentage::Length(b))
641673
| (LengthPercentage::Percent(a), LengthPercentage::Percent(b)) =>
642674
(a - b).abs() < 0.0001,
643675
_ => false,

crates/bevy_ui/src/layout/debug.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::fmt::Write;
22

3-
use taffy::prelude::Node;
4-
use taffy::tree::LayoutTree;
3+
use taffy::{NodeId, TraversePartialTree};
54

65
use bevy_ecs::prelude::Entity;
76
use bevy_utils::HashMap;
@@ -10,7 +9,7 @@ use crate::layout::ui_surface::UiSurface;
109

1110
/// Prints a debug representation of the computed layout of the UI layout tree for each window.
1211
pub fn print_ui_layout_tree(ui_surface: &UiSurface) {
13-
let taffy_to_entity: HashMap<Node, Entity> = ui_surface
12+
let taffy_to_entity: HashMap<NodeId, Entity> = ui_surface
1413
.entity_to_taffy
1514
.iter()
1615
.map(|(entity, node)| (*node, *entity))
@@ -35,9 +34,9 @@ pub fn print_ui_layout_tree(ui_surface: &UiSurface) {
3534
/// Recursively navigates the layout tree printing each node's information.
3635
fn print_node(
3736
ui_surface: &UiSurface,
38-
taffy_to_entity: &HashMap<Node, Entity>,
37+
taffy_to_entity: &HashMap<NodeId, Entity>,
3938
entity: Entity,
40-
node: Node,
39+
node: NodeId,
4140
has_sibling: bool,
4241
lines_string: String,
4342
acc: &mut String,
@@ -46,13 +45,14 @@ fn print_node(
4645
let layout = tree.layout(node).unwrap();
4746
let style = tree.style(node).unwrap();
4847

49-
let num_children = tree.child_count(node).unwrap();
48+
let num_children = tree.child_count(node);
5049

5150
let display_variant = match (num_children, style.display) {
5251
(_, taffy::style::Display::None) => "NONE",
5352
(0, _) => "LEAF",
5453
(_, taffy::style::Display::Flex) => "FLEX",
5554
(_, taffy::style::Display::Grid) => "GRID",
55+
(_, taffy::style::Display::Block) => "BLOCK",
5656
};
5757

5858
let fork_string = if has_sibling {
@@ -70,7 +70,7 @@ fn print_node(
7070
y = layout.location.y,
7171
width = layout.size.width,
7272
height = layout.size.height,
73-
measured = if tree.needs_measure(node) { "measured" } else { "" }
73+
measured = if tree.get_node_context(node).is_some() { "measured" } else { "" }
7474
).ok();
7575
let bar = if has_sibling { "│ " } else { " " };
7676
let new_string = lines_string + bar;

0 commit comments

Comments
 (0)