Remove VerticalAlign from TextAlignment (#6807)
# Objective Remove the `VerticalAlign` enum. Text's alignment field should only affect the text's internal text alignment, not its position. The only way to control a `TextBundle`'s position and bounds should be through the manipulation of the constraints in the `Style` components of the nodes in the Bevy UI's layout tree. `Text2dBundle` should have a separate `Anchor` component that sets its position relative to its transform. Related issues: #676, #1490, #5502, #5513, #5834, #6717, #6724, #6741, #6748 ## Changelog * Changed `TextAlignment` into an enum with `Left`, `Center`, and `Right` variants. * Removed the `HorizontalAlign` and `VerticalAlign` types. * Added an `Anchor` component to `Text2dBundle` * Added `Component` derive to `Anchor` * Use `f32::INFINITY` instead of `f32::MAX` to represent unbounded text in Text2dBounds ## Migration Guide The `alignment` field of `Text` now only affects the text's internal alignment. ### Change `TextAlignment` to TextAlignment` which is now an enum. Replace: * `TextAlignment::TOP_LEFT`, `TextAlignment::CENTER_LEFT`, `TextAlignment::BOTTOM_LEFT` with `TextAlignment::Left` * `TextAlignment::TOP_CENTER`, `TextAlignment::CENTER_LEFT`, `TextAlignment::BOTTOM_CENTER` with `TextAlignment::Center` * `TextAlignment::TOP_RIGHT`, `TextAlignment::CENTER_RIGHT`, `TextAlignment::BOTTOM_RIGHT` with `TextAlignment::Right` ### Changes for `Text2dBundle` `Text2dBundle` has a new field 'text_anchor' that takes an `Anchor` component that controls its position relative to its transform.
This commit is contained in:
parent
4ff50f6b50
commit
9eefd7c022
@ -24,7 +24,7 @@ pub struct Sprite {
|
|||||||
|
|
||||||
/// How a sprite is positioned relative to its [`Transform`](bevy_transform::components::Transform).
|
/// How a sprite is positioned relative to its [`Transform`](bevy_transform::components::Transform).
|
||||||
/// It defaults to `Anchor::Center`.
|
/// It defaults to `Anchor::Center`.
|
||||||
#[derive(Debug, Clone, Default, Reflect)]
|
#[derive(Component, Debug, Clone, Default, Reflect)]
|
||||||
#[doc(alias = "pivot")]
|
#[doc(alias = "pivot")]
|
||||||
pub enum Anchor {
|
pub enum Anchor {
|
||||||
#[default]
|
#[default]
|
||||||
|
@ -41,8 +41,7 @@ impl GlyphBrush {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let section_glyphs = Layout::default()
|
let section_glyphs = Layout::default()
|
||||||
.h_align(text_alignment.horizontal.into())
|
.h_align(text_alignment.into())
|
||||||
.v_align(text_alignment.vertical.into())
|
|
||||||
.calculate_glyphs(&self.fonts, &geom, sections);
|
.calculate_glyphs(&self.fonts, &geom, sections);
|
||||||
Ok(section_glyphs)
|
Ok(section_glyphs)
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,7 @@ pub use text2d::*;
|
|||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use crate::{
|
pub use crate::{Font, Text, Text2dBundle, TextAlignment, TextError, TextSection, TextStyle};
|
||||||
Font, HorizontalAlign, Text, Text2dBundle, TextAlignment, TextError, TextSection,
|
|
||||||
TextStyle, VerticalAlign,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
use bevy_app::prelude::*;
|
use bevy_app::prelude::*;
|
||||||
@ -77,9 +74,8 @@ 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::<Text>()
|
||||||
.register_type::<TextAlignment>()
|
.register_type::<TextAlignment>()
|
||||||
.register_type::<VerticalAlign>()
|
|
||||||
.register_type::<HorizontalAlign>()
|
|
||||||
.init_asset_loader::<FontLoader>()
|
.init_asset_loader::<FontLoader>()
|
||||||
.init_resource::<TextSettings>()
|
.init_resource::<TextSettings>()
|
||||||
.init_resource::<FontAtlasWarning>()
|
.init_resource::<FontAtlasWarning>()
|
||||||
|
@ -2,24 +2,36 @@ use bevy_asset::Handle;
|
|||||||
use bevy_ecs::{prelude::Component, reflect::ReflectComponent};
|
use bevy_ecs::{prelude::Component, reflect::ReflectComponent};
|
||||||
use bevy_reflect::{prelude::*, FromReflect};
|
use bevy_reflect::{prelude::*, FromReflect};
|
||||||
use bevy_render::color::Color;
|
use bevy_render::color::Color;
|
||||||
|
use bevy_utils::default;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::Font;
|
use crate::Font;
|
||||||
|
|
||||||
#[derive(Component, Debug, Default, Clone, Reflect)]
|
#[derive(Component, Debug, Clone, Reflect)]
|
||||||
#[reflect(Component, Default)]
|
#[reflect(Component, Default)]
|
||||||
pub struct Text {
|
pub struct Text {
|
||||||
pub sections: Vec<TextSection>,
|
pub sections: Vec<TextSection>,
|
||||||
|
/// The text's internal alignment.
|
||||||
|
/// Should not affect its position within a container.
|
||||||
pub alignment: TextAlignment,
|
pub alignment: TextAlignment,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Text {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
sections: Default::default(),
|
||||||
|
alignment: TextAlignment::Left,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Text {
|
impl Text {
|
||||||
/// Constructs a [`Text`] with a single section.
|
/// Constructs a [`Text`] with a single section.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use bevy_asset::Handle;
|
/// # use bevy_asset::Handle;
|
||||||
/// # use bevy_render::color::Color;
|
/// # use bevy_render::color::Color;
|
||||||
/// # use bevy_text::{Font, Text, TextAlignment, TextStyle, HorizontalAlign, VerticalAlign};
|
/// # use bevy_text::{Font, Text, TextStyle, TextAlignment};
|
||||||
/// #
|
/// #
|
||||||
/// # let font_handle: Handle<Font> = Default::default();
|
/// # let font_handle: Handle<Font> = Default::default();
|
||||||
/// #
|
/// #
|
||||||
@ -42,12 +54,12 @@ impl Text {
|
|||||||
/// color: Color::WHITE,
|
/// color: Color::WHITE,
|
||||||
/// },
|
/// },
|
||||||
/// ) // You can still add an alignment.
|
/// ) // You can still add an alignment.
|
||||||
/// .with_alignment(TextAlignment::CENTER);
|
/// .with_alignment(TextAlignment::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 {
|
||||||
sections: vec![TextSection::new(value, style)],
|
sections: vec![TextSection::new(value, style)],
|
||||||
alignment: Default::default(),
|
..default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +94,7 @@ impl Text {
|
|||||||
pub fn from_sections(sections: impl IntoIterator<Item = TextSection>) -> Self {
|
pub fn from_sections(sections: impl IntoIterator<Item = TextSection>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
sections: sections.into_iter().collect(),
|
sections: sections.into_iter().collect(),
|
||||||
alignment: Default::default(),
|
..default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,78 +129,10 @@ impl TextSection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Reflect)]
|
|
||||||
pub struct TextAlignment {
|
|
||||||
pub vertical: VerticalAlign,
|
|
||||||
pub horizontal: HorizontalAlign,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TextAlignment {
|
|
||||||
/// A [`TextAlignment`] set to the top-left.
|
|
||||||
pub const TOP_LEFT: Self = TextAlignment {
|
|
||||||
vertical: VerticalAlign::Top,
|
|
||||||
horizontal: HorizontalAlign::Left,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A [`TextAlignment`] set to the top-center.
|
|
||||||
pub const TOP_CENTER: Self = TextAlignment {
|
|
||||||
vertical: VerticalAlign::Top,
|
|
||||||
horizontal: HorizontalAlign::Center,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A [`TextAlignment`] set to the top-right.
|
|
||||||
pub const TOP_RIGHT: Self = TextAlignment {
|
|
||||||
vertical: VerticalAlign::Top,
|
|
||||||
horizontal: HorizontalAlign::Right,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A [`TextAlignment`] set to center the center-left.
|
|
||||||
pub const CENTER_LEFT: Self = TextAlignment {
|
|
||||||
vertical: VerticalAlign::Center,
|
|
||||||
horizontal: HorizontalAlign::Left,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A [`TextAlignment`] set to center on both axes.
|
|
||||||
pub const CENTER: Self = TextAlignment {
|
|
||||||
vertical: VerticalAlign::Center,
|
|
||||||
horizontal: HorizontalAlign::Center,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A [`TextAlignment`] set to the center-right.
|
|
||||||
pub const CENTER_RIGHT: Self = TextAlignment {
|
|
||||||
vertical: VerticalAlign::Center,
|
|
||||||
horizontal: HorizontalAlign::Right,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A [`TextAlignment`] set to the bottom-left.
|
|
||||||
pub const BOTTOM_LEFT: Self = TextAlignment {
|
|
||||||
vertical: VerticalAlign::Bottom,
|
|
||||||
horizontal: HorizontalAlign::Left,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A [`TextAlignment`] set to the bottom-center.
|
|
||||||
pub const BOTTOM_CENTER: Self = TextAlignment {
|
|
||||||
vertical: VerticalAlign::Bottom,
|
|
||||||
horizontal: HorizontalAlign::Center,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A [`TextAlignment`] set to the bottom-right.
|
|
||||||
pub const BOTTOM_RIGHT: Self = TextAlignment {
|
|
||||||
vertical: VerticalAlign::Bottom,
|
|
||||||
horizontal: HorizontalAlign::Right,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for TextAlignment {
|
|
||||||
fn default() -> Self {
|
|
||||||
TextAlignment::TOP_LEFT
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Describes horizontal alignment preference for positioning & bounds.
|
/// Describes horizontal alignment preference for positioning & bounds.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Reflect, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Reflect, Serialize, Deserialize)]
|
||||||
#[reflect(Serialize, Deserialize)]
|
#[reflect(Serialize, Deserialize)]
|
||||||
pub enum HorizontalAlign {
|
pub enum TextAlignment {
|
||||||
/// Leftmost character is immediately to the right of the render position.<br/>
|
/// Leftmost character is immediately to the right of the render position.<br/>
|
||||||
/// Bounds start from the render position and advance rightwards.
|
/// Bounds start from the render position and advance rightwards.
|
||||||
Left,
|
Left,
|
||||||
@ -200,35 +144,12 @@ pub enum HorizontalAlign {
|
|||||||
Right,
|
Right,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<HorizontalAlign> for glyph_brush_layout::HorizontalAlign {
|
impl From<TextAlignment> for glyph_brush_layout::HorizontalAlign {
|
||||||
fn from(val: HorizontalAlign) -> Self {
|
fn from(val: TextAlignment) -> Self {
|
||||||
match val {
|
match val {
|
||||||
HorizontalAlign::Left => glyph_brush_layout::HorizontalAlign::Left,
|
TextAlignment::Left => glyph_brush_layout::HorizontalAlign::Left,
|
||||||
HorizontalAlign::Center => glyph_brush_layout::HorizontalAlign::Center,
|
TextAlignment::Center => glyph_brush_layout::HorizontalAlign::Center,
|
||||||
HorizontalAlign::Right => glyph_brush_layout::HorizontalAlign::Right,
|
TextAlignment::Right => glyph_brush_layout::HorizontalAlign::Right,
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Describes vertical alignment preference for positioning & bounds. Currently a placeholder
|
|
||||||
/// for future functionality.
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Reflect, Serialize, Deserialize)]
|
|
||||||
#[reflect(Serialize, Deserialize)]
|
|
||||||
pub enum VerticalAlign {
|
|
||||||
/// Characters/bounds start underneath the render position and progress downwards.
|
|
||||||
Top,
|
|
||||||
/// Characters/bounds center at the render position and progress outward equally.
|
|
||||||
Center,
|
|
||||||
/// Characters/bounds start above the render position and progress upward.
|
|
||||||
Bottom,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<VerticalAlign> for glyph_brush_layout::VerticalAlign {
|
|
||||||
fn from(val: VerticalAlign) -> Self {
|
|
||||||
match val {
|
|
||||||
VerticalAlign::Top => glyph_brush_layout::VerticalAlign::Top,
|
|
||||||
VerticalAlign::Center => glyph_brush_layout::VerticalAlign::Center,
|
|
||||||
VerticalAlign::Bottom => glyph_brush_layout::VerticalAlign::Bottom,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,17 +22,10 @@ use bevy_utils::HashSet;
|
|||||||
use bevy_window::{WindowId, WindowScaleFactorChanged, Windows};
|
use bevy_window::{WindowId, WindowScaleFactorChanged, Windows};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Font, FontAtlasSet, FontAtlasWarning, HorizontalAlign, Text, TextError, TextLayoutInfo,
|
Font, FontAtlasSet, FontAtlasWarning, Text, TextError, TextLayoutInfo, TextPipeline,
|
||||||
TextPipeline, TextSettings, VerticalAlign, YAxisOrientation,
|
TextSettings, YAxisOrientation,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The calculated size of text drawn in 2D scene.
|
|
||||||
#[derive(Component, Default, Copy, Clone, Debug, Reflect)]
|
|
||||||
#[reflect(Component)]
|
|
||||||
pub struct Text2dSize {
|
|
||||||
pub size: Vec2,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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`.
|
/// specified `TextAlignment`.
|
||||||
@ -47,21 +40,27 @@ pub struct Text2dBounds {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Text2dBounds {
|
impl Default for Text2dBounds {
|
||||||
|
#[inline]
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self::UNBOUNDED
|
||||||
size: Vec2::new(f32::MAX, f32::MAX),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Text2dBounds {
|
||||||
|
/// Unbounded text will not be truncated or wrapped.
|
||||||
|
pub const UNBOUNDED: Self = Self {
|
||||||
|
size: Vec2::splat(f32::INFINITY),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// The bundle of components needed to draw text in a 2D scene via a 2D `Camera2dBundle`.
|
/// The bundle of components needed to draw text in a 2D scene via a 2D `Camera2dBundle`.
|
||||||
/// [Example usage.](https://github.com/bevyengine/bevy/blob/latest/examples/2d/text2d.rs)
|
/// [Example usage.](https://github.com/bevyengine/bevy/blob/latest/examples/2d/text2d.rs)
|
||||||
#[derive(Bundle, Clone, Debug, Default)]
|
#[derive(Bundle, Clone, Debug, Default)]
|
||||||
pub struct Text2dBundle {
|
pub struct Text2dBundle {
|
||||||
pub text: Text,
|
pub text: Text,
|
||||||
|
pub text_anchor: Anchor,
|
||||||
pub transform: Transform,
|
pub transform: Transform,
|
||||||
pub global_transform: GlobalTransform,
|
pub global_transform: GlobalTransform,
|
||||||
pub text_2d_size: Text2dSize,
|
|
||||||
pub text_2d_bounds: Text2dBounds,
|
pub text_2d_bounds: Text2dBounds,
|
||||||
pub visibility: Visibility,
|
pub visibility: Visibility,
|
||||||
pub computed_visibility: ComputedVisibility,
|
pub computed_visibility: ComputedVisibility,
|
||||||
@ -77,32 +76,23 @@ pub fn extract_text2d_sprite(
|
|||||||
&ComputedVisibility,
|
&ComputedVisibility,
|
||||||
&Text,
|
&Text,
|
||||||
&TextLayoutInfo,
|
&TextLayoutInfo,
|
||||||
|
&Anchor,
|
||||||
&GlobalTransform,
|
&GlobalTransform,
|
||||||
&Text2dSize,
|
|
||||||
)>,
|
)>,
|
||||||
>,
|
>,
|
||||||
) {
|
) {
|
||||||
let scale_factor = windows.scale_factor(WindowId::primary()) as f32;
|
let scale_factor = windows.scale_factor(WindowId::primary()) as f32;
|
||||||
|
|
||||||
for (entity, computed_visibility, text, text_layout_info, text_transform, calculated_size) in
|
for (entity, computed_visibility, text, text_layout_info, anchor, text_transform) in
|
||||||
text2d_query.iter()
|
text2d_query.iter()
|
||||||
{
|
{
|
||||||
if !computed_visibility.is_visible() {
|
if !computed_visibility.is_visible() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let (width, height) = (calculated_size.size.x, calculated_size.size.y);
|
|
||||||
|
|
||||||
let text_glyphs = &text_layout_info.glyphs;
|
let text_glyphs = &text_layout_info.glyphs;
|
||||||
let alignment_offset = match text.alignment.vertical {
|
let text_anchor = anchor.as_vec() * Vec2::new(1., -1.) - 0.5;
|
||||||
VerticalAlign::Top => Vec3::new(0.0, -height, 0.0),
|
let alignment_offset = text_layout_info.size * text_anchor;
|
||||||
VerticalAlign::Center => Vec3::new(0.0, -height * 0.5, 0.0),
|
|
||||||
VerticalAlign::Bottom => Vec3::ZERO,
|
|
||||||
} + match text.alignment.horizontal {
|
|
||||||
HorizontalAlign::Left => Vec3::ZERO,
|
|
||||||
HorizontalAlign::Center => Vec3::new(-width * 0.5, 0.0, 0.0),
|
|
||||||
HorizontalAlign::Right => Vec3::new(-width, 0.0, 0.0),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut color = Color::WHITE;
|
let mut color = Color::WHITE;
|
||||||
let mut current_section = usize::MAX;
|
let mut current_section = usize::MAX;
|
||||||
for text_glyph in text_glyphs {
|
for text_glyph in text_glyphs {
|
||||||
@ -120,10 +110,9 @@ pub fn extract_text2d_sprite(
|
|||||||
let index = text_glyph.atlas_info.glyph_index;
|
let index = text_glyph.atlas_info.glyph_index;
|
||||||
let rect = Some(atlas.textures[index]);
|
let rect = Some(atlas.textures[index]);
|
||||||
|
|
||||||
let glyph_transform = Transform::from_translation(
|
let glyph_transform =
|
||||||
alignment_offset * scale_factor + text_glyph.position.extend(0.),
|
Transform::from_translation((alignment_offset + text_glyph.position).extend(0.));
|
||||||
);
|
|
||||||
// NOTE: Should match `bevy_ui::render::extract_text_uinodes`
|
|
||||||
let transform = *text_transform
|
let transform = *text_transform
|
||||||
* GlobalTransform::from_scale(Vec3::splat(scale_factor.recip()))
|
* GlobalTransform::from_scale(Vec3::splat(scale_factor.recip()))
|
||||||
* glyph_transform;
|
* glyph_transform;
|
||||||
@ -167,8 +156,7 @@ pub fn update_text2d_layout(
|
|||||||
mut text_query: Query<(
|
mut text_query: Query<(
|
||||||
Entity,
|
Entity,
|
||||||
Ref<Text>,
|
Ref<Text>,
|
||||||
Option<&Text2dBounds>,
|
&Text2dBounds,
|
||||||
&mut Text2dSize,
|
|
||||||
Option<&mut TextLayoutInfo>,
|
Option<&mut TextLayoutInfo>,
|
||||||
)>,
|
)>,
|
||||||
) {
|
) {
|
||||||
@ -176,15 +164,12 @@ pub fn update_text2d_layout(
|
|||||||
let factor_changed = scale_factor_changed.iter().last().is_some();
|
let factor_changed = scale_factor_changed.iter().last().is_some();
|
||||||
let scale_factor = windows.scale_factor(WindowId::primary());
|
let scale_factor = windows.scale_factor(WindowId::primary());
|
||||||
|
|
||||||
for (entity, text, maybe_bounds, mut calculated_size, text_layout_info) in &mut text_query {
|
for (entity, text, bounds, text_layout_info) in &mut text_query {
|
||||||
if factor_changed || text.is_changed() || queue.remove(&entity) {
|
if factor_changed || text.is_changed() || queue.remove(&entity) {
|
||||||
let text_bounds = match maybe_bounds {
|
let text_bounds = Vec2::new(
|
||||||
Some(bounds) => Vec2::new(
|
scale_value(bounds.size.x, scale_factor),
|
||||||
scale_value(bounds.size.x, scale_factor),
|
scale_value(bounds.size.y, scale_factor),
|
||||||
scale_value(bounds.size.y, scale_factor),
|
);
|
||||||
),
|
|
||||||
None => Vec2::new(f32::MAX, f32::MAX),
|
|
||||||
};
|
|
||||||
|
|
||||||
match text_pipeline.queue_text(
|
match text_pipeline.queue_text(
|
||||||
&fonts,
|
&fonts,
|
||||||
@ -207,18 +192,12 @@ pub fn update_text2d_layout(
|
|||||||
Err(e @ TextError::FailedToAddGlyph(_)) => {
|
Err(e @ TextError::FailedToAddGlyph(_)) => {
|
||||||
panic!("Fatal error when processing text: {e}.");
|
panic!("Fatal error when processing text: {e}.");
|
||||||
}
|
}
|
||||||
Ok(info) => {
|
Ok(info) => match text_layout_info {
|
||||||
calculated_size.size = Vec2::new(
|
Some(mut t) => *t = info,
|
||||||
scale_value(info.size.x, 1. / scale_factor),
|
None => {
|
||||||
scale_value(info.size.y, 1. / scale_factor),
|
commands.entity(entity).insert(info);
|
||||||
);
|
|
||||||
match text_layout_info {
|
|
||||||
Some(mut t) => *t = info,
|
|
||||||
None => {
|
|
||||||
commands.entity(entity).insert(info);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ 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_alignment = TextAlignment::Center;
|
||||||
// 2d camera
|
// 2d camera
|
||||||
commands.spawn(Camera2dBundle::default());
|
commands.spawn(Camera2dBundle::default());
|
||||||
// Demonstrate changing translation
|
// Demonstrate changing translation
|
||||||
@ -64,31 +64,29 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||||||
// Demonstrate text wrapping
|
// Demonstrate text wrapping
|
||||||
let box_size = Vec2::new(300.0, 200.0);
|
let box_size = Vec2::new(300.0, 200.0);
|
||||||
let box_position = Vec2::new(0.0, -250.0);
|
let box_position = Vec2::new(0.0, -250.0);
|
||||||
commands.spawn(SpriteBundle {
|
commands
|
||||||
sprite: Sprite {
|
.spawn(SpriteBundle {
|
||||||
color: Color::rgb(0.25, 0.25, 0.75),
|
sprite: Sprite {
|
||||||
custom_size: Some(Vec2::new(box_size.x, box_size.y)),
|
color: Color::rgb(0.25, 0.25, 0.75),
|
||||||
|
custom_size: Some(Vec2::new(box_size.x, box_size.y)),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
transform: Transform::from_translation(box_position.extend(0.0)),
|
||||||
..default()
|
..default()
|
||||||
},
|
})
|
||||||
transform: Transform::from_translation(box_position.extend(0.0)),
|
.with_children(|builder| {
|
||||||
..default()
|
builder.spawn(Text2dBundle {
|
||||||
});
|
text: Text::from_section("this text wraps in the box", text_style)
|
||||||
commands.spawn(Text2dBundle {
|
.with_alignment(TextAlignment::Left),
|
||||||
text: Text::from_section("this text wraps in the box", text_style),
|
text_2d_bounds: Text2dBounds {
|
||||||
text_2d_bounds: Text2dBounds {
|
// Wrap text in the rectangle
|
||||||
// Wrap text in the rectangle
|
size: box_size,
|
||||||
size: box_size,
|
},
|
||||||
},
|
// ensure the text is drawn on top of the box
|
||||||
// We align text to the top-left, so this transform is the top-left corner of our text. The
|
transform: Transform::from_translation(Vec3::Z),
|
||||||
// box is centered at box_position, so it is necessary to move by half of the box size to
|
..default()
|
||||||
// keep the text in the box.
|
});
|
||||||
transform: Transform::from_xyz(
|
});
|
||||||
box_position.x - box_size.x / 2.0,
|
|
||||||
box_position.y + box_size.y / 2.0,
|
|
||||||
1.0,
|
|
||||||
),
|
|
||||||
..default()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn animate_translation(
|
fn animate_translation(
|
||||||
|
@ -66,7 +66,7 @@ fn spawn_text(
|
|||||||
for (per_frame, event) in reader.iter().enumerate() {
|
for (per_frame, event) in reader.iter().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_alignment(TextAlignment::Center),
|
||||||
transform: Transform::from_xyz(
|
transform: Transform::from_xyz(
|
||||||
per_frame as f32 * 100.0 + rand::thread_rng().gen_range(-40.0..40.0),
|
per_frame as f32 * 100.0 + rand::thread_rng().gen_range(-40.0..40.0),
|
||||||
300.0,
|
300.0,
|
||||||
|
@ -121,7 +121,7 @@ fn setup_scene(
|
|||||||
color: Color::BLACK,
|
color: Color::BLACK,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.with_text_alignment(TextAlignment::CENTER),
|
.with_text_alignment(TextAlignment::Center),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use bevy::{
|
|||||||
GamepadAxisChangedEvent, GamepadButton, GamepadButtonChangedEvent, GamepadSettings,
|
GamepadAxisChangedEvent, GamepadButton, GamepadButtonChangedEvent, GamepadSettings,
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
sprite::{MaterialMesh2dBundle, Mesh2dHandle},
|
sprite::{Anchor, MaterialMesh2dBundle, Mesh2dHandle},
|
||||||
};
|
};
|
||||||
|
|
||||||
const BUTTON_RADIUS: f32 = 25.;
|
const BUTTON_RADIUS: f32 = 25.;
|
||||||
@ -342,8 +342,8 @@ fn setup_sticks(
|
|||||||
value: format!("{:.3}", 0.),
|
value: format!("{:.3}", 0.),
|
||||||
style,
|
style,
|
||||||
},
|
},
|
||||||
])
|
]),
|
||||||
.with_alignment(TextAlignment::BOTTOM_CENTER),
|
text_anchor: Anchor::BottomCenter,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
TextWithAxes { x_axis, y_axis },
|
TextWithAxes { x_axis, y_axis },
|
||||||
@ -409,8 +409,7 @@ fn setup_triggers(
|
|||||||
font_size: 16.,
|
font_size: 16.,
|
||||||
color: TEXT_COLOR,
|
color: TEXT_COLOR,
|
||||||
},
|
},
|
||||||
)
|
),
|
||||||
.with_alignment(TextAlignment::CENTER),
|
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
TextWithButtonValue(button_type),
|
TextWithButtonValue(button_type),
|
||||||
|
@ -41,7 +41,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||||||
color: Color::WHITE,
|
color: Color::WHITE,
|
||||||
},
|
},
|
||||||
) // Set the alignment of the Text
|
) // Set the alignment of the Text
|
||||||
.with_text_alignment(TextAlignment::TOP_CENTER)
|
.with_text_alignment(TextAlignment::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,
|
||||||
|
@ -54,7 +54,7 @@ fn infotext_system(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||||||
color: Color::rgb(0.8, 0.2, 0.7),
|
color: Color::rgb(0.8, 0.2, 0.7),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.with_text_alignment(TextAlignment::CENTER)
|
.with_text_alignment(TextAlignment::Center)
|
||||||
.with_style(Style {
|
.with_style(Style {
|
||||||
position_type: PositionType::Absolute,
|
position_type: PositionType::Absolute,
|
||||||
position: UiRect {
|
position: UiRect {
|
||||||
|
Loading…
Reference in New Issue
Block a user