Rename TextAlignment to JustifyText. (#10854)

# Objective

The name `TextAlignment` is really deceptive and almost every new user
gets confused about the differences between aligning text with
`TextAlignment`, aligning text with `Style` and aligning text with
anchor (when using `Text2d`).

## Solution

* Rename `TextAlignment` to `JustifyText`. The associated helper methods
are also renamed.
* Improve the doc comments for text explaining explicitly how the
`JustifyText` component affects the arrangement of text.
* Add some extra cases to the `text_debug` example that demonstate the
differences between alignment using `JustifyText` and alignment using
`Style`.
<img width="757" alt="text_debug_2"
src="https://github.com/bevyengine/bevy/assets/27962798/9d53e647-93f9-4bc7-8a20-0d9f783304d2">

---

## Changelog
* `TextAlignment` has been renamed to `JustifyText`
* `TextBundle::with_text_alignment` has been renamed to
`TextBundle::with_text_justify`
* `Text::with_alignment` has been renamed to `Text::with_justify`
* The `text_alignment` field of `TextMeasureInfo` has been renamed to
`justification`

## Migration Guide
* `TextAlignment` has been renamed to `JustifyText`
* `TextBundle::with_text_alignment` has been renamed to
`TextBundle::with_text_justify`
* `Text::with_alignment` has been renamed to `Text::with_justify`
* The `text_alignment` field of `TextMeasureInfo` has been renamed to
`justification`
This commit is contained in:
ickshonpe 2023-12-05 03:00:41 +00:00 committed by GitHub
parent 72adf2ae2a
commit 166686e0f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 205 additions and 145 deletions

View File

@ -12,7 +12,7 @@ use glyph_brush_layout::{
use crate::{ use crate::{
error::TextError, BreakLineOn, Font, FontAtlasSet, FontAtlasSets, FontAtlasWarning, error::TextError, BreakLineOn, Font, FontAtlasSet, FontAtlasSets, FontAtlasWarning,
GlyphAtlasInfo, TextAlignment, TextSettings, YAxisOrientation, GlyphAtlasInfo, JustifyText, TextSettings, YAxisOrientation,
}; };
pub struct GlyphBrush { pub struct GlyphBrush {
@ -36,7 +36,7 @@ impl GlyphBrush {
&self, &self,
sections: &[S], sections: &[S],
bounds: Vec2, bounds: Vec2,
text_alignment: TextAlignment, text_alignment: JustifyText,
linebreak_behavior: BreakLineOn, linebreak_behavior: BreakLineOn,
) -> Result<Vec<SectionGlyph>, TextError> { ) -> Result<Vec<SectionGlyph>, TextError> {
let geom = SectionGeometry { let geom = SectionGeometry {

View File

@ -20,7 +20,7 @@ pub use text2d::*;
pub mod prelude { pub mod prelude {
#[doc(hidden)] #[doc(hidden)]
pub use crate::{Font, Text, Text2dBundle, TextAlignment, TextError, TextSection, TextStyle}; pub use crate::{Font, JustifyText, Text, Text2dBundle, TextError, TextSection, TextStyle};
} }
use bevy_app::prelude::*; use bevy_app::prelude::*;
@ -83,7 +83,7 @@ impl Plugin for TextPlugin {
.register_type::<TextSection>() .register_type::<TextSection>()
.register_type::<Vec<TextSection>>() .register_type::<Vec<TextSection>>()
.register_type::<TextStyle>() .register_type::<TextStyle>()
.register_type::<TextAlignment>() .register_type::<JustifyText>()
.register_type::<BreakLineOn>() .register_type::<BreakLineOn>()
.init_asset_loader::<FontLoader>() .init_asset_loader::<FontLoader>()
.init_resource::<TextSettings>() .init_resource::<TextSettings>()

View File

@ -1,7 +1,7 @@
use crate::{ use crate::{
compute_text_bounds, error::TextError, glyph_brush::GlyphBrush, scale_value, BreakLineOn, Font, compute_text_bounds, error::TextError, glyph_brush::GlyphBrush, scale_value, BreakLineOn, Font,
FontAtlasSets, FontAtlasWarning, PositionedGlyph, Text, TextAlignment, TextSection, FontAtlasSets, FontAtlasWarning, JustifyText, PositionedGlyph, Text, TextSection, TextSettings,
TextSettings, YAxisOrientation, YAxisOrientation,
}; };
use ab_glyph::PxScale; use ab_glyph::PxScale;
use bevy_asset::{AssetId, Assets, Handle}; use bevy_asset::{AssetId, Assets, Handle};
@ -47,7 +47,7 @@ impl TextPipeline {
fonts: &Assets<Font>, fonts: &Assets<Font>,
sections: &[TextSection], sections: &[TextSection],
scale_factor: f64, scale_factor: f64,
text_alignment: TextAlignment, text_alignment: JustifyText,
linebreak_behavior: BreakLineOn, linebreak_behavior: BreakLineOn,
bounds: Vec2, bounds: Vec2,
font_atlas_sets: &mut FontAtlasSets, font_atlas_sets: &mut FontAtlasSets,
@ -119,7 +119,7 @@ pub struct TextMeasureSection {
pub struct TextMeasureInfo { pub struct TextMeasureInfo {
pub fonts: Box<[ab_glyph::FontArc]>, pub fonts: Box<[ab_glyph::FontArc]>,
pub sections: Box<[TextMeasureSection]>, pub sections: Box<[TextMeasureSection]>,
pub text_alignment: TextAlignment, pub justification: JustifyText,
pub linebreak_behavior: glyph_brush_layout::BuiltInLineBreaker, pub linebreak_behavior: glyph_brush_layout::BuiltInLineBreaker,
pub min: Vec2, pub min: Vec2,
pub max: Vec2, pub max: Vec2,
@ -158,20 +158,20 @@ impl TextMeasureInfo {
Ok(Self::new( Ok(Self::new(
auto_fonts, auto_fonts,
sections, sections,
text.alignment, text.justify,
text.linebreak_behavior.into(), text.linebreak_behavior.into(),
)) ))
} }
fn new( fn new(
fonts: Vec<ab_glyph::FontArc>, fonts: Vec<ab_glyph::FontArc>,
sections: Vec<TextMeasureSection>, sections: Vec<TextMeasureSection>,
text_alignment: TextAlignment, justification: JustifyText,
linebreak_behavior: glyph_brush_layout::BuiltInLineBreaker, linebreak_behavior: glyph_brush_layout::BuiltInLineBreaker,
) -> Self { ) -> Self {
let mut info = Self { let mut info = Self {
fonts: fonts.into_boxed_slice(), fonts: fonts.into_boxed_slice(),
sections: sections.into_boxed_slice(), sections: sections.into_boxed_slice(),
text_alignment, justification,
linebreak_behavior, linebreak_behavior,
min: Vec2::ZERO, min: Vec2::ZERO,
max: Vec2::ZERO, max: Vec2::ZERO,
@ -191,7 +191,7 @@ impl TextMeasureInfo {
..Default::default() ..Default::default()
}; };
let section_glyphs = glyph_brush_layout::Layout::default() let section_glyphs = glyph_brush_layout::Layout::default()
.h_align(self.text_alignment.into()) .h_align(self.justification.into())
.line_breaker(self.linebreak_behavior) .line_breaker(self.linebreak_behavior)
.calculate_glyphs(&self.fonts, &geom, sections); .calculate_glyphs(&self.fonts, &geom, sections);

View File

@ -13,7 +13,7 @@ pub struct Text {
pub sections: Vec<TextSection>, pub sections: Vec<TextSection>,
/// The text's internal alignment. /// The text's internal alignment.
/// Should not affect its position within a container. /// Should not affect its position within a container.
pub alignment: TextAlignment, pub justify: JustifyText,
/// How the text should linebreak when running out of the bounds determined by max_size /// How the text should linebreak when running out of the bounds determined by max_size
pub linebreak_behavior: BreakLineOn, pub linebreak_behavior: BreakLineOn,
} }
@ -22,7 +22,7 @@ impl Default for Text {
fn default() -> Self { fn default() -> Self {
Self { Self {
sections: Default::default(), sections: Default::default(),
alignment: TextAlignment::Left, justify: JustifyText::Left,
linebreak_behavior: BreakLineOn::WordBoundary, linebreak_behavior: BreakLineOn::WordBoundary,
} }
} }
@ -34,7 +34,7 @@ impl Text {
/// ``` /// ```
/// # use bevy_asset::Handle; /// # use bevy_asset::Handle;
/// # use bevy_render::color::Color; /// # use bevy_render::color::Color;
/// # use bevy_text::{Font, Text, TextStyle, TextAlignment}; /// # use bevy_text::{Font, Text, TextStyle, JustifyText};
/// # /// #
/// # let font_handle: Handle<Font> = Default::default(); /// # let font_handle: Handle<Font> = Default::default();
/// # /// #
@ -50,14 +50,14 @@ impl Text {
/// ); /// );
/// ///
/// let hello_bevy = Text::from_section( /// let hello_bevy = Text::from_section(
/// "hello bevy!", /// "hello world\nand bevy!",
/// TextStyle { /// TextStyle {
/// font: font_handle, /// font: font_handle,
/// font_size: 60.0, /// font_size: 60.0,
/// color: Color::WHITE, /// color: Color::WHITE,
/// }, /// },
/// ) // You can still add an alignment. /// ) // You can still add text justifaction.
/// .with_alignment(TextAlignment::Center); /// .with_justify(JustifyText::Center);
/// ``` /// ```
pub fn from_section(value: impl Into<String>, style: TextStyle) -> Self { pub fn from_section(value: impl Into<String>, style: TextStyle) -> Self {
Self { Self {
@ -101,9 +101,9 @@ impl Text {
} }
} }
/// Returns this [`Text`] with a new [`TextAlignment`]. /// Returns this [`Text`] with a new [`JustifyText`].
pub const fn with_alignment(mut self, alignment: TextAlignment) -> Self { pub const fn with_justify(mut self, justify: JustifyText) -> Self {
self.alignment = alignment; self.justify = justify;
self self
} }
@ -159,28 +159,32 @@ impl From<String> for TextSection {
} }
} }
/// Describes horizontal alignment preference for positioning & bounds. /// Describes the horizontal alignment of multiple lines of text relative to each other.
/// This only affects the internal positioning of the lines of text within a text entity and
/// does not affect the text entity's position.
///
/// _Has no affect on a single line text entity._
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, Reflect, Serialize, Deserialize)] #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, Reflect, Serialize, Deserialize)]
#[reflect(Serialize, Deserialize)] #[reflect(Serialize, Deserialize)]
pub enum TextAlignment { pub enum JustifyText {
/// Leftmost character is immediately to the right of the render position.<br/> /// Leftmost character is immediately to the right of the render position.
/// Bounds start from the render position and advance rightwards. /// Bounds start from the render position and advance rightwards.
#[default] #[default]
Left, Left,
/// Leftmost & rightmost characters are equidistant to the render position.<br/> /// Leftmost & rightmost characters are equidistant to the render position.
/// Bounds start from the render position and advance equally left & right. /// Bounds start from the render position and advance equally left & right.
Center, Center,
/// Rightmost character is immediately to the left of the render position.<br/> /// Rightmost character is immediately to the left of the render position.
/// Bounds start from the render position and advance leftwards. /// Bounds start from the render position and advance leftwards.
Right, Right,
} }
impl From<TextAlignment> for glyph_brush_layout::HorizontalAlign { impl From<JustifyText> for glyph_brush_layout::HorizontalAlign {
fn from(val: TextAlignment) -> Self { fn from(val: JustifyText) -> Self {
match val { match val {
TextAlignment::Left => glyph_brush_layout::HorizontalAlign::Left, JustifyText::Left => glyph_brush_layout::HorizontalAlign::Left,
TextAlignment::Center => glyph_brush_layout::HorizontalAlign::Center, JustifyText::Center => glyph_brush_layout::HorizontalAlign::Center,
TextAlignment::Right => glyph_brush_layout::HorizontalAlign::Right, JustifyText::Right => glyph_brush_layout::HorizontalAlign::Right,
} }
} }
} }

View File

@ -28,7 +28,7 @@ use bevy_window::{PrimaryWindow, Window, WindowScaleFactorChanged};
/// The maximum width and height of text. The text will wrap according to the specified size. /// The maximum width and height of text. The text will wrap according to the specified size.
/// Characters out of the bounds after wrapping will be truncated. Text is aligned according to the /// Characters out of the bounds after wrapping will be truncated. Text is aligned according to the
/// specified [`TextAlignment`](crate::text::TextAlignment). /// specified [`JustifyText`](crate::text::JustifyText).
/// ///
/// Note: only characters that are completely out of the bounds will be truncated, so this is not a /// Note: only characters that are completely out of the bounds will be truncated, so this is not a
/// reliable limit if it is necessary to contain the text strictly in the bounds. Currently this /// reliable limit if it is necessary to contain the text strictly in the bounds. Currently this
@ -196,7 +196,7 @@ pub fn update_text2d_layout(
&fonts, &fonts,
&text.sections, &text.sections,
scale_factor, scale_factor,
text.alignment, text.justify,
text.linebreak_behavior, text.linebreak_behavior,
text_bounds, text_bounds,
&mut font_atlas_sets, &mut font_atlas_sets,

View File

@ -15,7 +15,7 @@ use bevy_render::{
}; };
use bevy_sprite::TextureAtlas; use bevy_sprite::TextureAtlas;
#[cfg(feature = "bevy_text")] #[cfg(feature = "bevy_text")]
use bevy_text::{BreakLineOn, Text, TextAlignment, TextLayoutInfo, TextSection, TextStyle}; use bevy_text::{BreakLineOn, JustifyText, Text, TextLayoutInfo, TextSection, TextStyle};
use bevy_transform::prelude::{GlobalTransform, Transform}; use bevy_transform::prelude::{GlobalTransform, Transform};
/// The basic UI node /// The basic UI node
@ -245,9 +245,9 @@ impl TextBundle {
} }
} }
/// Returns this [`TextBundle`] with a new [`TextAlignment`] on [`Text`]. /// Returns this [`TextBundle`] with a new [`JustifyText`] on [`Text`].
pub const fn with_text_alignment(mut self, alignment: TextAlignment) -> Self { pub const fn with_text_justify(mut self, justify: JustifyText) -> Self {
self.text.alignment = alignment; self.text.justify = justify;
self self
} }

View File

@ -182,7 +182,7 @@ fn queue_text(
fonts, fonts,
&text.sections, &text.sections,
scale_factor, scale_factor,
text.alignment, text.justify,
text.linebreak_behavior, text.linebreak_behavior,
physical_node_size, physical_node_size,
font_atlas_sets, font_atlas_sets,

View File

@ -38,14 +38,14 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
font_size: 60.0, font_size: 60.0,
color: Color::WHITE, color: Color::WHITE,
}; };
let text_alignment = TextAlignment::Center; let text_justification = JustifyText::Center;
// 2d camera // 2d camera
commands.spawn(Camera2dBundle::default()); commands.spawn(Camera2dBundle::default());
// Demonstrate changing translation // Demonstrate changing translation
commands.spawn(( commands.spawn((
Text2dBundle { Text2dBundle {
text: Text::from_section("translation", text_style.clone()) text: Text::from_section("translation", text_style.clone())
.with_alignment(text_alignment), .with_justify(text_justification),
..default() ..default()
}, },
AnimateTranslation, AnimateTranslation,
@ -53,7 +53,8 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// Demonstrate changing rotation // Demonstrate changing rotation
commands.spawn(( commands.spawn((
Text2dBundle { Text2dBundle {
text: Text::from_section("rotation", text_style.clone()).with_alignment(text_alignment), text: Text::from_section("rotation", text_style.clone())
.with_justify(text_justification),
..default() ..default()
}, },
AnimateRotation, AnimateRotation,
@ -61,7 +62,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// Demonstrate changing scale // Demonstrate changing scale
commands.spawn(( commands.spawn((
Text2dBundle { Text2dBundle {
text: Text::from_section("scale", text_style).with_alignment(text_alignment), text: Text::from_section("scale", text_style).with_justify(text_justification),
..default() ..default()
}, },
AnimateScale, AnimateScale,
@ -91,7 +92,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
"this text wraps in the box\n(Unicode linebreaks)", "this text wraps in the box\n(Unicode linebreaks)",
slightly_smaller_text_style.clone(), slightly_smaller_text_style.clone(),
)], )],
alignment: TextAlignment::Left, justify: JustifyText::Left,
linebreak_behavior: BreakLineOn::WordBoundary, linebreak_behavior: BreakLineOn::WordBoundary,
}, },
text_2d_bounds: Text2dBounds { text_2d_bounds: Text2dBounds {
@ -123,7 +124,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
"this text wraps in the box\n(AnyCharacter linebreaks)", "this text wraps in the box\n(AnyCharacter linebreaks)",
slightly_smaller_text_style.clone(), slightly_smaller_text_style.clone(),
)], )],
alignment: TextAlignment::Left, justify: JustifyText::Left,
linebreak_behavior: BreakLineOn::AnyCharacter, linebreak_behavior: BreakLineOn::AnyCharacter,
}, },
text_2d_bounds: Text2dBounds { text_2d_bounds: Text2dBounds {

View File

@ -277,7 +277,7 @@ fn setup_image_viewer_scene(
..default() ..default()
}, },
) )
.with_text_alignment(TextAlignment::Center) .with_text_justify(JustifyText::Center)
.with_style(Style { .with_style(Style {
align_self: AlignSelf::Center, align_self: AlignSelf::Center,
margin: UiRect::all(Val::Auto), margin: UiRect::all(Val::Auto),

View File

@ -60,7 +60,7 @@ fn spawn_text(mut commands: Commands, mut reader: EventReader<StreamEvent>) {
for (per_frame, event) in reader.read().enumerate() { for (per_frame, event) in reader.read().enumerate() {
commands.spawn(Text2dBundle { commands.spawn(Text2dBundle {
text: Text::from_section(event.0.to_string(), text_style.clone()) text: Text::from_section(event.0.to_string(), text_style.clone())
.with_alignment(TextAlignment::Center), .with_justify(JustifyText::Center),
transform: Transform::from_xyz(per_frame as f32 * 100.0, 300.0, 0.0), transform: Transform::from_xyz(per_frame as f32 * 100.0, 300.0, 0.0),
..default() ..default()
}); });

View File

@ -129,7 +129,7 @@ fn setup_scene(
..default() ..default()
}, },
) )
.with_text_alignment(TextAlignment::Center), .with_text_justify(JustifyText::Center),
); );
}); });
} }

View File

@ -47,7 +47,7 @@ fn setup(mut commands: Commands) {
..default() ..default()
}, },
}], }],
alignment: TextAlignment::Left, justify: JustifyText::Left,
linebreak_behavior: BreakLineOn::AnyCharacter, linebreak_behavior: BreakLineOn::AnyCharacter,
}; };

View File

@ -58,7 +58,7 @@ fn spawn(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Text2dBundle { commands.spawn(Text2dBundle {
text: Text { text: Text {
sections, sections,
alignment: TextAlignment::Center, justify: JustifyText::Center,
linebreak_behavior: BreakLineOn::AnyCharacter, linebreak_behavior: BreakLineOn::AnyCharacter,
}, },
..Default::default() ..Default::default()

View File

@ -118,7 +118,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, mut time: ResMu
..default() ..default()
}, },
) )
.with_text_alignment(TextAlignment::Center), .with_text_justify(JustifyText::Center),
); );
// virtual time info // virtual time info
@ -131,7 +131,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, mut time: ResMu
..default() ..default()
}, },
) )
.with_text_alignment(TextAlignment::Right), .with_text_justify(JustifyText::Right),
VirtualTime, VirtualTime,
)); ));
}); });

View File

@ -96,7 +96,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
text: Text::from_section( text: Text::from_section(
"Use the panel on the right to change the Display and Visibility properties for the respective nodes of the panel on the left", "Use the panel on the right to change the Display and Visibility properties for the respective nodes of the panel on the left",
text_style.clone(), text_style.clone(),
).with_alignment(TextAlignment::Center), ).with_justify(JustifyText::Center),
style: Style { style: Style {
margin: UiRect::bottom(Val::Px(10.)), margin: UiRect::bottom(Val::Px(10.)),
..Default::default() ..Default::default()
@ -158,14 +158,14 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
text: Text::from_section( text: Text::from_section(
"Display::None\nVisibility::Hidden\nVisibility::Inherited", "Display::None\nVisibility::Hidden\nVisibility::Inherited",
TextStyle { color: HIDDEN_COLOR, ..text_style.clone() } TextStyle { color: HIDDEN_COLOR, ..text_style.clone() }
).with_alignment(TextAlignment::Center), ).with_justify(JustifyText::Center),
..Default::default() ..Default::default()
}); });
builder.spawn(TextBundle { builder.spawn(TextBundle {
text: Text::from_section( text: Text::from_section(
"-\n-\n-", "-\n-\n-",
TextStyle { color: Color::DARK_GRAY, ..text_style.clone() } TextStyle { color: Color::DARK_GRAY, ..text_style.clone() }
).with_alignment(TextAlignment::Center), ).with_justify(JustifyText::Center),
..Default::default() ..Default::default()
}); });
builder.spawn(TextBundle::from_section( builder.spawn(TextBundle::from_section(
@ -425,7 +425,7 @@ where
format!("{}::{:?}", Target::<T>::NAME, T::default()), format!("{}::{:?}", Target::<T>::NAME, T::default()),
text_style, text_style,
) )
.with_text_alignment(TextAlignment::Center), .with_text_justify(JustifyText::Center),
); );
}); });
} }

View File

@ -287,7 +287,7 @@ fn spawn_button(
..text_style ..text_style
}, },
) )
.with_alignment(TextAlignment::Center), .with_justify(JustifyText::Center),
..Default::default() ..Default::default()
}); });
}); });

View File

@ -39,8 +39,8 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
font_size: 100.0, font_size: 100.0,
..default() ..default()
}, },
) // Set the alignment of the Text ) // Set the justification of the Text
.with_text_alignment(TextAlignment::Center) .with_text_justify(JustifyText::Center)
// Set the style of the TextBundle itself. // Set the style of the TextBundle itself.
.with_style(Style { .with_style(Style {
position_type: PositionType::Absolute, position_type: PositionType::Absolute,

View File

@ -29,110 +29,165 @@ struct TextChanges;
fn infotext_system(mut commands: Commands, asset_server: Res<AssetServer>) { fn infotext_system(mut commands: Commands, asset_server: Res<AssetServer>) {
let font = asset_server.load("fonts/FiraSans-Bold.ttf"); let font = asset_server.load("fonts/FiraSans-Bold.ttf");
commands.spawn(Camera2dBundle::default()); commands.spawn(Camera2dBundle::default());
commands.spawn( let root_uinode = commands
TextBundle::from_section( .spawn(NodeBundle {
"This is\ntext with\nline breaks\nin the top left", style: Style {
TextStyle { width: Val::Percent(100.),
font: font.clone(), height: Val::Percent(100.),
font_size: 50.0, justify_content: JustifyContent::SpaceBetween,
..default() ..default()
}, },
)
.with_style(Style {
position_type: PositionType::Absolute,
top: Val::Px(5.0),
left: Val::Px(15.0),
..default()
}),
);
commands.spawn(TextBundle::from_section(
"This text is very long, has a limited width, is centered, is positioned in the top right and is also colored pink.",
TextStyle {
font: font.clone(),
font_size: 50.0,
color: Color::rgb(0.8, 0.2, 0.7),
},
)
.with_text_alignment(TextAlignment::Center)
.with_style(Style {
position_type: PositionType::Absolute,
top: Val::Px(5.0),
right: Val::Px(15.0),
max_width: Val::Px(400.),
..default() ..default()
}) })
); .id();
commands.spawn((
TextBundle::from_sections([ let left_column = commands.spawn(NodeBundle {
TextSection::new( style: Style {
"This text changes in the bottom right", 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(
TextBundle::from_section(
"This is\ntext with\nline breaks\nin the top left.",
TextStyle {
font: font.clone(),
font_size: 30.0,
..default()
},
)
);
builder.spawn(TextBundle::from_section(
"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: 30.0,
color: Color::YELLOW,
},
)
.with_text_justify(JustifyText::Right)
.with_style(Style {
max_width: Val::Px(300.),
..default()
})
);
builder.spawn(
TextBundle::from_section(
"This\ntext has\nline breaks and also a set width in the bottom left.",
TextStyle { TextStyle {
font: font.clone(), font: font.clone(),
font_size: 30.0, font_size: 30.0,
color: Color::WHITE, color: Color::WHITE,
}, },
), )
TextSection::new( .with_style(Style {
"\nThis text changes in the bottom right - ", max_width: Val::Px(300.),
..default()
})
);
}).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(TextBundle::from_section(
"This text is very long, has a limited width, is center-justified, is positioned in the top right and is also colored pink.",
TextStyle { TextStyle {
font: font.clone(), font: font.clone(),
font_size: 30.0, font_size: 40.0,
color: Color::RED, color: Color::rgb(0.8, 0.2, 0.7),
}, },
), )
TextSection::from_style(TextStyle { .with_text_justify(JustifyText::Center)
font: font.clone(), .with_style(Style {
font_size: 30.0, max_width: Val::Px(400.),
color: Color::ORANGE_RED, ..default()
}), })
TextSection::new( );
" fps, ",
builder.spawn(
TextBundle::from_section(
"This text is left-justified and is vertically positioned to distribute the empty space equally above and below it.",
TextStyle { TextStyle {
font: font.clone(), font: font.clone(),
font_size: 30.0, font_size: 35.0,
color: Color::YELLOW, color: Color::YELLOW,
}, },
), )
TextSection::from_style(TextStyle { .with_text_justify(JustifyText::Left)
font: font.clone(), .with_style(Style {
font_size: 30.0, max_width: Val::Px(300.),
color: Color::GREEN, ..default()
}), }),
TextSection::new( );
" ms/frame",
TextStyle { builder.spawn((
TextBundle::from_sections([
TextSection::new(
"This text changes in the bottom right",
TextStyle {
font: font.clone(),
font_size: 25.0,
color: Color::WHITE,
},
),
TextSection::new(
"\nThis text changes in the bottom right - ",
TextStyle {
font: font.clone(),
font_size: 25.0,
color: Color::RED,
},
),
TextSection::from_style(TextStyle {
font: font.clone(), font: font.clone(),
font_size: 30.0, font_size: 25.0,
color: Color::BLUE, color: Color::ORANGE_RED,
}, }),
), TextSection::new(
]) " fps, ",
.with_style(Style { TextStyle {
position_type: PositionType::Absolute, font: font.clone(),
bottom: Val::Px(5.0), font_size: 25.0,
right: Val::Px(15.0), color: Color::YELLOW,
..default() },
}), ),
TextChanges, TextSection::from_style(TextStyle {
)); font: font.clone(),
commands.spawn( font_size: 25.0,
TextBundle::from_section( color: Color::GREEN,
"This\ntext has\nline breaks and also a set width in the bottom left", }),
TextStyle { TextSection::new(
font, " ms/frame",
font_size: 50.0, TextStyle {
color: Color::WHITE, font: font.clone(),
}, font_size: 25.0,
) color: Color::BLUE,
.with_style(Style { },
align_self: AlignSelf::FlexEnd, ),
position_type: PositionType::Absolute, ]),
bottom: Val::Px(5.0), TextChanges,
left: Val::Px(15.0), ));
width: Val::Px(200.0), })
..default() .id();
}),
); commands
.entity(root_uinode)
.push_children(&[left_column, right_column]);
} }
fn change_text_system( fn change_text_system(

View File

@ -120,7 +120,7 @@ fn spawn(mut commands: Commands, asset_server: Res<AssetServer>) {
value: message.clone(), value: message.clone(),
style: text_style.clone(), style: text_style.clone(),
}], }],
alignment: TextAlignment::Left, justify: JustifyText::Left,
linebreak_behavior, linebreak_behavior,
}; };
let text_id = commands let text_id = commands