//! Shows various text layout options. use std::{collections::VecDeque, time::Duration}; use bevy::{ color::palettes::css::*, diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin}, prelude::*, ui::widget::UiTextWriter, window::PresentMode, }; fn main() { App::new() .add_plugins(( DefaultPlugins.set(WindowPlugin { primary_window: Some(Window { present_mode: PresentMode::AutoNoVsync, ..default() }), ..default() }), FrameTimeDiagnosticsPlugin, )) .add_systems(Startup, infotext_system) .add_systems(Update, change_text_system) .run(); } #[derive(Component)] struct TextChanges; fn infotext_system(mut commands: Commands, asset_server: Res) { let font = asset_server.load("fonts/FiraSans-Bold.ttf"); let background_color = MAROON.into(); commands.spawn(Camera2d); let root_uinode = commands .spawn(NodeBundle { style: Style { width: Val::Percent(100.), height: Val::Percent(100.), justify_content: JustifyContent::SpaceBetween, ..default() }, ..default() }) .id(); let left_column = commands.spawn(NodeBundle { style: Style { flex_direction: FlexDirection::Column, justify_content: JustifyContent::SpaceBetween, align_items: AlignItems::Start, flex_grow: 1., margin: UiRect::axes(Val::Px(15.), Val::Px(5.)), ..default() }, ..default() }).with_children(|builder| { builder.spawn(( Text::new("This is\ntext with\nline breaks\nin the top left."), TextStyle { font: font.clone(), font_size: 25.0, ..default() }, BackgroundColor(background_color) )); builder.spawn(( Text::new( "This text is right-justified. The `JustifyText` component controls the horizontal alignment of the lines of multi-line text relative to each other, and does not affect the text node's position in the UI layout.", ), TextStyle { font: font.clone(), font_size: 25.0, color: YELLOW.into(), ..default() }, TextBlock::new_with_justify(JustifyText::Right), Style { max_width: Val::Px(300.), ..default() }, BackgroundColor(background_color) )); builder.spawn(( Text::new( "This\ntext has\nline breaks and also a set width in the bottom left."), TextStyle { font: font.clone(), font_size: 25.0, ..default() }, Style { max_width: Val::Px(300.), ..default() }, BackgroundColor(background_color) ) ); }).id(); let right_column = commands.spawn(NodeBundle { style: Style { flex_direction: FlexDirection::Column, justify_content: JustifyContent::SpaceBetween, align_items: AlignItems::End, flex_grow: 1., margin: UiRect::axes(Val::Px(15.), Val::Px(5.)), ..default() }, ..default() }).with_children(|builder| { builder.spawn((Text::new( "This text is very long, has a limited width, is center-justified, is positioned in the top right and is also colored pink."), TextStyle { font: font.clone(), font_size: 33.0, color: Color::srgb(0.8, 0.2, 0.7), ..default() }, TextBlock::new_with_justify(JustifyText::Center), Style { max_width: Val::Px(400.), ..default() },BackgroundColor(background_color)) ); builder.spawn((Text::new( "This text is left-justified and is vertically positioned to distribute the empty space equally above and below it."), TextStyle { font: font.clone(), font_size: 29.0, color: YELLOW.into(), ..default() }, TextBlock::new_with_justify(JustifyText::Left), Style { max_width: Val::Px(300.), ..default() }, BackgroundColor(background_color) )); builder.spawn(( Text::new("This text is fully justified and is positioned in the same way."), TextStyle { font: font.clone(), font_size: 29.0, color: GREEN_YELLOW.into(), ..default() }, TextBlock::new_with_justify(JustifyText::Justified), Style { max_width: Val::Px(300.), ..default() }, BackgroundColor(background_color) ) ); builder.spawn(( Text::default(), TextStyle { font: font.clone(), font_size: 21.0, ..default() }, TextChanges, BackgroundColor(background_color) )) .with_children(|p| { p.spawn(( TextSpan::new("\nThis text changes in the bottom right"), TextStyle { font: font.clone(), font_size: 21.0, ..default() }, )); p.spawn(( TextSpan::new(" this text has zero fontsize"), TextStyle { font: font.clone(), font_size: 0.0, color: BLUE.into(), ..default() }, )); p.spawn(( TextSpan::new("\nThis text changes in the bottom right - "), TextStyle { font: font.clone(), font_size: 21.0, color: RED.into(), ..default() }, )); p.spawn(( TextSpan::default(), TextStyle { font: font.clone(), font_size: 21.0, color: ORANGE_RED.into(), ..default() } )); p.spawn(( TextSpan::new(" fps, "), TextStyle { font: font.clone(), font_size: 10.0, color: YELLOW.into(), ..default() }, )); p.spawn(( TextSpan::default(), TextStyle { font: font.clone(), font_size: 21.0, color: LIME.into(), ..default() } )); p.spawn(( TextSpan::new(" ms/frame"), TextStyle { font: font.clone(), font_size: 42.0, color: BLUE.into(), ..default() }, )); p.spawn(( TextSpan::new(" this text has negative fontsize"), TextStyle { font: font.clone(), font_size: -42.0, color: BLUE.into(), ..default() }, )); }); }) .id(); commands .entity(root_uinode) .add_children(&[left_column, right_column]); } fn change_text_system( mut fps_history: Local>, mut time_history: Local>, time: Res