From 919919c998cfde8cbee15245e942f8ecd67638f6 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 17 Apr 2023 20:59:42 +0100 Subject: [PATCH] Fix text measurement algorithm (#8425) # Objective Followup to #7779 which tweaks the actual text measurement algorithm to be more robust. Before: Screenshot 2023-04-17 at 18 12 05 After: Screenshot 2023-04-17 at 18 41 40 (note extra space taken up in header in before example) ## Solution - Text layout of horizontal text (currently the only kind of text we support) is now based solely on the layout constraints in the horizontal axis. It ignores constraints in the vertical axis and computes vertical size based on wrapping subject to the horizontal axis constraints. - I've also added a paragraph to the `grid` example for testing / demo purposes. --- crates/bevy_ui/src/widget/text.rs | 16 +++++----------- examples/ui/grid.rs | 20 +++++++++++++++++--- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/crates/bevy_ui/src/widget/text.rs b/crates/bevy_ui/src/widget/text.rs index 0181a8a579..d8395d4f26 100644 --- a/crates/bevy_ui/src/widget/text.rs +++ b/crates/bevy_ui/src/widget/text.rs @@ -30,7 +30,7 @@ impl Measure for TextMeasure { width: Option, height: Option, available_width: AvailableSpace, - available_height: AvailableSpace, + _available_height: AvailableSpace, ) -> Vec2 { let x = width.unwrap_or_else(|| match available_width { AvailableSpace::Definite(x) => x.clamp( @@ -43,16 +43,10 @@ impl Measure for TextMeasure { height .map_or_else( - || match available_height { - AvailableSpace::Definite(y) => { - let y = y.clamp( - self.info.max_width_content_size.y, - self.info.min_width_content_size.y, - ); - self.info.compute_size(Vec2::new(x, y)) - } - AvailableSpace::MinContent => Vec2::new(x, self.info.max_width_content_size.y), - AvailableSpace::MaxContent => Vec2::new(x, self.info.min_width_content_size.y), + || match available_width { + AvailableSpace::Definite(_) => self.info.compute_size(Vec2::new(x, f32::MAX)), + AvailableSpace::MinContent => Vec2::new(x, self.info.min_width_content_size.y), + AvailableSpace::MaxContent => Vec2::new(x, self.info.max_width_content_size.y), }, |y| Vec2::new(x, y), ) diff --git a/examples/ui/grid.rs b/examples/ui/grid.rs index 7a2a5503fb..df674067f7 100644 --- a/examples/ui/grid.rs +++ b/examples/ui/grid.rs @@ -124,8 +124,13 @@ fn spawn_layout(mut commands: Commands, asset_server: Res) { align_items: AlignItems::Start, // Align content towards the center in the horizontal axis justify_items: JustifyItems::Center, - // Add 20px padding to the top - padding: UiRect::top(Val::Px(20.)), + // Add 10px padding + padding: UiRect::all(Val::Px(10.)), + // Add an fr track to take up all the available space at the bottom of the column so that the text nodes + // can be top-aligned. Normally you'd use flexbox for this, but this is the CSS Grid example so we're using grid. + grid_template_rows: vec![GridTrack::auto(), GridTrack::auto(), GridTrack::fr(1.0)], + // Add a 10px gap between rows + gap: Size::height(Val::Px(10.)), ..default() }, background_color: BackgroundColor(Color::BLACK), @@ -135,11 +140,20 @@ fn spawn_layout(mut commands: Commands, asset_server: Res) { builder.spawn(TextBundle::from_section( "Sidebar", TextStyle { - font, + font: font.clone(), font_size: 24.0, color: Color::WHITE, }, )); + builder.spawn(TextBundle::from_section( + "A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely. A paragraph of text which ought to wrap nicely.", + TextStyle { + font: font.clone(), + font_size: 16.0, + color: Color::WHITE, + }, + )); + builder.spawn(NodeBundle::default()); }); // Footer / status bar