//! This example illustrates how to create UI text and update it in a system. //! //! It displays the current FPS in the top left corner, as well as text that changes color //! in the bottom right. For text within a scene, please see the text2d example. use bevy::{ color::palettes::css::GOLD, diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin}, prelude::*, text::FontFeatures, }; fn main() { App::new() .add_plugins((DefaultPlugins, FrameTimeDiagnosticsPlugin::default())) .add_systems(Startup, setup) .add_systems(Update, (text_update_system, text_color_system)) .run(); } // Marker struct to help identify the FPS UI component, since there may be many Text components #[derive(Component)] struct FpsText; // Marker struct to help identify the color-changing Text component #[derive(Component)] struct AnimatedText; fn setup(mut commands: Commands, asset_server: Res) { // UI camera commands.spawn(Camera2d); // Text with one section commands.spawn(( // Accepts a `String` or any type that converts into a `String`, such as `&str` Text::new("hello\nbevy!"), TextFont { // This font is loaded and will be used instead of the default font. font: asset_server.load("fonts/FiraSans-Bold.ttf"), font_size: 67.0, ..default() }, TextShadow::default(), // Set the justification of the Text TextLayout::new_with_justify(Justify::Center), // Set the style of the Node itself. Node { position_type: PositionType::Absolute, bottom: Val::Px(5.0), right: Val::Px(5.0), ..default() }, AnimatedText, )); // Text with multiple sections commands .spawn(( // Create a Text with multiple child spans. Text::new("FPS: "), TextFont { // This font is loaded and will be used instead of the default font. font: asset_server.load("fonts/FiraSans-Bold.ttf"), font_size: 42.0, ..default() }, )) .with_child(( TextSpan::default(), if cfg!(feature = "default_font") { ( TextFont { font_size: 33.0, // If no font is specified, the default font (a minimal subset of FiraMono) will be used. ..default() }, TextColor(GOLD.into()), ) } else { ( // "default_font" feature is unavailable, load a font to use instead. TextFont { font: asset_server.load("fonts/FiraMono-Medium.ttf"), font_size: 33.0, ..Default::default() }, TextColor(GOLD.into()), ) }, FpsText, )); // Text with OpenType features let opentype_font_handle = asset_server.load("fonts/EBGaramond12-Regular.otf"); commands .spawn(( Node { margin: UiRect::all(Val::Px(12.0)), position_type: PositionType::Absolute, top: Val::Px(5.0), right: Val::Px(5.0), ..default() }, Text::new("Opentype features:\n"), TextFont { font: opentype_font_handle.clone(), font_size: 32.0, ..default() }, )) .with_children(|parent| { let text_rows = [ ("Smallcaps: ", FontFeatures::SMALL_CAPS, "Hello World"), ( "Ligatures: ", FontFeatures::STANDARD_LIGATURES, "fi fl ff ffi ffl", ), ("Fractions: ", FontFeatures::FRACTIONS, "12/134"), ("Superscript: ", FontFeatures::SUPERSCRIPT, "Up here!"), ("Subscript: ", FontFeatures::SUBSCRIPT, "Down here!"), ( "Oldstyle figures: ", FontFeatures::OLDSTYLE_FIGURES, "1234567890", ), ( "Lining figures: ", FontFeatures::LINING_FIGURES, "1234567890", ), ]; for (title, feature, text) in text_rows { parent.spawn(( TextSpan::new(title), TextFont { font: opentype_font_handle.clone(), font_size: 24.0, ..default() }, )); parent.spawn(( TextSpan::new(format!("{text}\n")), TextFont { font: opentype_font_handle.clone(), font_size: 24.0, font_features: FontFeatures::builder().enable(feature).build(), ..default() }, )); } }); #[cfg(feature = "default_font")] commands.spawn(( // Here we are able to call the `From` method instead of creating a new `TextSection`. // This will use the default font (a minimal subset of FiraMono) and apply the default styling. Text::new("From an &str into a Text with the default font!"), Node { position_type: PositionType::Absolute, bottom: Val::Px(5.0), left: Val::Px(15.0), ..default() }, )); #[cfg(not(feature = "default_font"))] commands.spawn(( Text::new("Default font disabled"), TextFont { font: asset_server.load("fonts/FiraMono-Medium.ttf"), ..default() }, Node { position_type: PositionType::Absolute, bottom: Val::Px(5.0), left: Val::Px(15.0), ..default() }, )); } fn text_color_system(time: Res