//! Shows text rendering with moving, rotating and scaling text. //! //! Note that this uses [`Text2d`] to display text alongside your other entities in a 2D scene. //! //! For an example on how to render text as part of a user interface, independent from the world //! viewport, you may want to look at `showcase/contributors.rs` or `ui/text.rs`. use bevy::{ color::palettes::css::*, math::ops, prelude::*, sprite::{Anchor, Text2dShadow}, text::{FontSmoothing, LineBreak, TextBounds}, }; fn main() { App::new() .add_plugins(DefaultPlugins) .add_systems(Startup, setup) .add_systems( Update, (animate_translation, animate_rotation, animate_scale), ) .run(); } #[derive(Component)] struct AnimateTranslation; #[derive(Component)] struct AnimateRotation; #[derive(Component)] struct AnimateScale; fn setup(mut commands: Commands, asset_server: Res) { let font = asset_server.load("fonts/FiraSans-Bold.ttf"); let text_font = TextFont { font: font.clone().into(), font_size: FontSize::Px(50.0), ..default() }; let text_justification = Justify::Center; commands.spawn(Camera2d); // Demonstrate changing translation commands.spawn(( Text2d::new(" translation "), text_font.clone(), TextLayout::justify(text_justification), TextBackgroundColor(Color::BLACK.with_alpha(0.5)), Text2dShadow::default(), AnimateTranslation, )); // Demonstrate changing rotation commands.spawn(( Text2d::new(" rotation "), text_font.clone(), TextLayout::justify(text_justification), TextBackgroundColor(Color::BLACK.with_alpha(0.5)), Text2dShadow::default(), AnimateRotation, )); // Demonstrate changing scale commands.spawn(( Text2d::new(" scale "), text_font, TextLayout::justify(text_justification), Transform::from_translation(Vec3::new(400.0, 0.0, 0.0)), TextBackgroundColor(Color::BLACK.with_alpha(0.5)), Text2dShadow::default(), AnimateScale, )); // Demonstrate text wrapping let slightly_smaller_text_font = TextFont { font: font.into(), font_size: FontSize::Px(35.0), ..default() }; let box_size = Vec2::new(300.0, 200.0); let box_position = Vec2::new(0.0, -250.0); let box_color = Color::srgb(0.25, 0.25, 0.55); let text_shadow_color = box_color.darker(0.05); commands.spawn(( Sprite::from_color(Color::srgb(0.25, 0.25, 0.55), box_size), Transform::from_translation(box_position.extend(0.0)), children![( Text2d::new("this text wraps in the box\n(Unicode linebreaks)"), slightly_smaller_text_font.clone(), TextLayout::new(Justify::Left, LineBreak::WordBoundary), // Wrap text in the rectangle TextBounds::from(box_size), // Ensure the text is drawn on top of the box Transform::from_translation(Vec3::Z), // Add a shadow to the text Text2dShadow { color: text_shadow_color, ..default() }, Underline, )], )); let other_box_size = Vec2::new(300.0, 200.0); let other_box_position = Vec2::new(320.0, -250.0); commands.spawn(( Sprite::from_color(Color::srgb(0.25, 0.25, 0.55), other_box_size), Transform::from_translation(other_box_position.extend(0.0)), children![( Text2d::new("this text wraps in the box\n(AnyCharacter linebreaks)"), slightly_smaller_text_font.clone(), TextLayout::new(Justify::Left, LineBreak::AnyCharacter), // Wrap text in the rectangle TextBounds::from(other_box_size), // Ensure the text is drawn on top of the box Transform::from_translation(Vec3::Z), // Add a shadow to the text Text2dShadow { color: text_shadow_color, ..default() } )], )); // Demonstrate font smoothing off commands.spawn(( Text2d::new("This text has\nFontSmoothing::None\nAnd Justify::Center"), slightly_smaller_text_font .clone() .with_font_smoothing(FontSmoothing::None), TextLayout::justify(Justify::Center), Transform::from_translation(Vec3::new(-400.0, -250.0, 0.0)), // Add a black shadow to the text Text2dShadow::default(), )); let make_child = move |(text_anchor, color): (Anchor, Color)| { ( Text2d::new(" Anchor".to_string()), slightly_smaller_text_font.clone(), text_anchor, TextBackgroundColor(Color::WHITE.darker(0.8)), Transform::from_translation(-1. * Vec3::Z), children![ ( TextSpan("::".to_string()), slightly_smaller_text_font.clone(), TextColor(LIGHT_GREY.into()), TextBackgroundColor(DARK_BLUE.into()), ), ( TextSpan(format!("{text_anchor:?} ")), slightly_smaller_text_font.clone(), TextColor(color), TextBackgroundColor(color.darker(0.3)), ) ], ) }; commands.spawn(( Sprite { color: Color::Srgba(LIGHT_CYAN), custom_size: Some(Vec2::new(10., 10.)), ..Default::default() }, Transform::from_translation(250. * Vec3::Y), children![ make_child((Anchor::TOP_LEFT, Color::Srgba(LIGHT_SALMON))), make_child((Anchor::TOP_RIGHT, Color::Srgba(LIGHT_GREEN))), make_child((Anchor::BOTTOM_RIGHT, Color::Srgba(LIGHT_BLUE))), make_child((Anchor::BOTTOM_LEFT, Color::Srgba(LIGHT_YELLOW))), ], )); } fn animate_translation( time: Res