From 4a41525cd0bac044fba95dddeed60a15431c9763 Mon Sep 17 00:00:00 2001 From: Rob Parrett Date: Mon, 10 Mar 2025 15:04:14 -0700 Subject: [PATCH] Add more to the 2d testbed for text (#18240) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Objective `Text2d` testing hasn't been as thorough as text in the UI, and it suffered a bunch of bugs / perf issues in recent cycles. ## Solution Add some more `Text2d` scenarios to the 2d testbed to catch bugs, testing bounded and unbounded text with various justification. ## Testing `cargo run --example testbed_2d` (press space a few times) Screenshot 2025-03-10 at 1 02 03 PM --------- Co-authored-by: Ben Frankel --- examples/testbed/2d.rs | 111 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 102 insertions(+), 9 deletions(-) diff --git a/examples/testbed/2d.rs b/examples/testbed/2d.rs index 61d1ee7bd2..d74e198f0e 100644 --- a/examples/testbed/2d.rs +++ b/examples/testbed/2d.rs @@ -143,22 +143,115 @@ mod bloom { } mod text { + use bevy::color::palettes; use bevy::prelude::*; + use bevy::sprite::Anchor; + use bevy::text::TextBounds; - pub fn setup(mut commands: Commands) { - let text_font = TextFont { - font_size: 50.0, - ..default() - }; - let text_justification = JustifyText::Center; + pub fn setup(mut commands: Commands, asset_server: Res) { commands.spawn((Camera2d, StateScoped(super::Scene::Text))); + + for (i, justify) in [ + JustifyText::Left, + JustifyText::Right, + JustifyText::Center, + JustifyText::Justified, + ] + .into_iter() + .enumerate() + { + let y = 230. - 150. * i as f32; + spawn_anchored_text(&mut commands, -300. * Vec3::X + y * Vec3::Y, justify, None); + spawn_anchored_text( + &mut commands, + 300. * Vec3::X + y * Vec3::Y, + justify, + Some(TextBounds::new(150., 55.)), + ); + } + + let sans_serif = TextFont::from_font(asset_server.load("fonts/FiraSans-Bold.ttf")); + + const NUM_ITERATIONS: usize = 10; + for i in 0..NUM_ITERATIONS { + let fraction = i as f32 / (NUM_ITERATIONS - 1) as f32; + + commands.spawn(( + Text2d::new("Bevy"), + sans_serif.clone(), + Transform::from_xyz(0.0, fraction * 200.0, i as f32) + .with_scale(1.0 + Vec2::splat(fraction).extend(1.)) + .with_rotation(Quat::from_rotation_z(fraction * core::f32::consts::PI)), + TextColor(Color::hsla(fraction * 360.0, 0.8, 0.8, 0.8)), + StateScoped(super::Scene::Text), + )); + } + commands.spawn(( - Text2d::new("Hello World"), - text_font, - TextLayout::new_with_justify(text_justification), + Text2d::new("This text is invisible."), + Visibility::Hidden, StateScoped(super::Scene::Text), )); } + + fn spawn_anchored_text( + commands: &mut Commands, + dest: Vec3, + justify: JustifyText, + bounds: Option, + ) { + commands.spawn(( + Sprite { + color: palettes::css::YELLOW.into(), + custom_size: Some(5. * Vec2::ONE), + ..Default::default() + }, + Transform::from_translation(dest), + StateScoped(super::Scene::Text), + )); + + for anchor in [ + Anchor::TopLeft, + Anchor::TopRight, + Anchor::BottomRight, + Anchor::BottomLeft, + ] { + let mut text = commands.spawn(( + Text2d::new("L R\n"), + TextLayout::new_with_justify(justify), + Transform::from_translation(dest + Vec3::Z), + anchor, + StateScoped(super::Scene::Text), + )); + text.with_children(|parent| { + parent.spawn(( + TextSpan::new(format!("{anchor:?}\n")), + TextFont::from_font_size(14.0), + TextColor(palettes::tailwind::BLUE_400.into()), + )); + parent.spawn(( + TextSpan::new(format!("{justify:?}")), + TextFont::from_font_size(14.0), + TextColor(palettes::tailwind::GREEN_400.into()), + )); + }); + + if let Some(bounds) = bounds { + text.insert(bounds); + + commands.spawn(( + Sprite { + color: palettes::tailwind::GRAY_900.into(), + custom_size: Some(Vec2::new(bounds.width.unwrap(), bounds.height.unwrap())), + anchor, + ..Default::default() + }, + Transform::from_translation(dest - Vec3::Z), + StateScoped(super::Scene::Text), + )); + } + } + } } mod sprite {