parent
							
								
									c32c78fc66
								
							
						
					
					
						commit
						f574c2c547
					
				@ -102,6 +102,10 @@ path = "examples/2d/texture_atlas.rs"
 | 
			
		||||
name = "contributors"
 | 
			
		||||
path = "examples/2d/contributors.rs"
 | 
			
		||||
 | 
			
		||||
[[example]]
 | 
			
		||||
name = "text2d"
 | 
			
		||||
path = "examples/2d/text2d.rs"
 | 
			
		||||
 | 
			
		||||
[[example]]
 | 
			
		||||
name = "load_gltf"
 | 
			
		||||
path = "examples/3d/load_gltf.rs"
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ use bevy_reflect::{Reflect, ReflectComponent};
 | 
			
		||||
use bevy_window::WindowId;
 | 
			
		||||
 | 
			
		||||
/// A component that indicates that an entity should be drawn in the "main pass"
 | 
			
		||||
#[derive(Default, Reflect)]
 | 
			
		||||
#[derive(Clone, Debug, Default, Reflect)]
 | 
			
		||||
#[reflect(Component)]
 | 
			
		||||
pub struct MainPass;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -37,7 +37,7 @@ pub struct PassNode<Q: WorldQuery> {
 | 
			
		||||
 | 
			
		||||
impl<Q: WorldQuery> fmt::Debug for PassNode<Q> {
 | 
			
		||||
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 | 
			
		||||
        f.debug_struct("PassNose")
 | 
			
		||||
        f.debug_struct("PassNode")
 | 
			
		||||
            .field("descriptor", &self.descriptor)
 | 
			
		||||
            .field("inputs", &self.inputs)
 | 
			
		||||
            .field("cameras", &self.cameras)
 | 
			
		||||
 | 
			
		||||
@ -22,6 +22,7 @@ bevy_math = { path = "../bevy_math", version = "0.4.0" }
 | 
			
		||||
bevy_reflect = { path = "../bevy_reflect", version = "0.4.0", features = ["bevy"] }
 | 
			
		||||
bevy_render = { path = "../bevy_render", version = "0.4.0" }
 | 
			
		||||
bevy_sprite = { path = "../bevy_sprite", version = "0.4.0" }
 | 
			
		||||
bevy_transform = { path = "../bevy_transform", version = "0.4.0" }
 | 
			
		||||
bevy_utils = { path = "../bevy_utils", version = "0.4.0" }
 | 
			
		||||
 | 
			
		||||
# other
 | 
			
		||||
 | 
			
		||||
@ -6,6 +6,8 @@ mod font_atlas_set;
 | 
			
		||||
mod font_loader;
 | 
			
		||||
mod glyph_brush;
 | 
			
		||||
mod pipeline;
 | 
			
		||||
mod text;
 | 
			
		||||
mod text2d;
 | 
			
		||||
 | 
			
		||||
pub use draw::*;
 | 
			
		||||
pub use error::*;
 | 
			
		||||
@ -15,15 +17,17 @@ pub use font_atlas_set::*;
 | 
			
		||||
pub use font_loader::*;
 | 
			
		||||
pub use glyph_brush::*;
 | 
			
		||||
pub use pipeline::*;
 | 
			
		||||
pub use text::*;
 | 
			
		||||
pub use text2d::*;
 | 
			
		||||
 | 
			
		||||
pub mod prelude {
 | 
			
		||||
    pub use crate::{Font, TextAlignment, TextError, TextStyle};
 | 
			
		||||
    pub use crate::{Font, Text, Text2dBundle, TextAlignment, TextError, TextStyle};
 | 
			
		||||
    pub use glyph_brush_layout::{HorizontalAlign, VerticalAlign};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
use bevy_app::prelude::*;
 | 
			
		||||
use bevy_asset::AddAsset;
 | 
			
		||||
use bevy_ecs::Entity;
 | 
			
		||||
use bevy_ecs::{Entity, IntoSystem};
 | 
			
		||||
 | 
			
		||||
pub type DefaultTextPipeline = TextPipeline<Entity>;
 | 
			
		||||
 | 
			
		||||
@ -35,6 +39,11 @@ impl Plugin for TextPlugin {
 | 
			
		||||
        app.add_asset::<Font>()
 | 
			
		||||
            .add_asset::<FontAtlasSet>()
 | 
			
		||||
            .init_asset_loader::<FontLoader>()
 | 
			
		||||
            .add_resource(DefaultTextPipeline::default());
 | 
			
		||||
            .add_resource(DefaultTextPipeline::default())
 | 
			
		||||
            .add_system_to_stage(bevy_app::stage::POST_UPDATE, text2d_system.system())
 | 
			
		||||
            .add_system_to_stage(
 | 
			
		||||
                bevy_render::stage::DRAW,
 | 
			
		||||
                text2d::draw_text2d_system.system(),
 | 
			
		||||
            );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										16
									
								
								crates/bevy_text/src/text.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								crates/bevy_text/src/text.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
use bevy_asset::Handle;
 | 
			
		||||
use bevy_math::Size;
 | 
			
		||||
 | 
			
		||||
use crate::{Font, TextStyle};
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Default, Clone)]
 | 
			
		||||
pub struct Text {
 | 
			
		||||
    pub value: String,
 | 
			
		||||
    pub font: Handle<Font>,
 | 
			
		||||
    pub style: TextStyle,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default, Copy, Clone, Debug)]
 | 
			
		||||
pub struct CalculatedSize {
 | 
			
		||||
    pub size: Size,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										172
									
								
								crates/bevy_text/src/text2d.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								crates/bevy_text/src/text2d.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,172 @@
 | 
			
		||||
use bevy_asset::Assets;
 | 
			
		||||
use bevy_ecs::{Bundle, Changed, Entity, Local, Query, QuerySet, Res, ResMut, With};
 | 
			
		||||
use bevy_math::{Size, Vec3};
 | 
			
		||||
use bevy_render::{
 | 
			
		||||
    draw::{DrawContext, Drawable},
 | 
			
		||||
    mesh::Mesh,
 | 
			
		||||
    prelude::{Draw, Msaa, Texture, Visible},
 | 
			
		||||
    render_graph::base::MainPass,
 | 
			
		||||
    renderer::RenderResourceBindings,
 | 
			
		||||
};
 | 
			
		||||
use bevy_sprite::{TextureAtlas, QUAD_HANDLE};
 | 
			
		||||
use bevy_transform::prelude::{GlobalTransform, Transform};
 | 
			
		||||
use glyph_brush_layout::{HorizontalAlign, VerticalAlign};
 | 
			
		||||
 | 
			
		||||
use crate::{
 | 
			
		||||
    CalculatedSize, DefaultTextPipeline, DrawableText, Font, FontAtlasSet, Text, TextError,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// The bundle of components needed to draw text in a 2D scene via the Camera2dBundle.
 | 
			
		||||
#[derive(Bundle, Clone, Debug)]
 | 
			
		||||
pub struct Text2dBundle {
 | 
			
		||||
    pub draw: Draw,
 | 
			
		||||
    pub visible: Visible,
 | 
			
		||||
    pub text: Text,
 | 
			
		||||
    pub transform: Transform,
 | 
			
		||||
    pub global_transform: GlobalTransform,
 | 
			
		||||
    pub main_pass: MainPass,
 | 
			
		||||
    pub calculated_size: CalculatedSize,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for Text2dBundle {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            draw: Draw {
 | 
			
		||||
                ..Default::default()
 | 
			
		||||
            },
 | 
			
		||||
            visible: Visible {
 | 
			
		||||
                is_transparent: true,
 | 
			
		||||
                ..Default::default()
 | 
			
		||||
            },
 | 
			
		||||
            text: Default::default(),
 | 
			
		||||
            transform: Default::default(),
 | 
			
		||||
            global_transform: Default::default(),
 | 
			
		||||
            main_pass: MainPass {},
 | 
			
		||||
            calculated_size: CalculatedSize {
 | 
			
		||||
                size: Size::default(),
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// System for drawing text in a 2D scene via the Camera2dBundle.  Included in the default
 | 
			
		||||
/// `TextPlugin`. Position is determined by the `Transform`'s translation, though scale and rotation
 | 
			
		||||
/// are ignored.
 | 
			
		||||
pub fn draw_text2d_system(
 | 
			
		||||
    mut context: DrawContext,
 | 
			
		||||
    msaa: Res<Msaa>,
 | 
			
		||||
    meshes: Res<Assets<Mesh>>,
 | 
			
		||||
    mut render_resource_bindings: ResMut<RenderResourceBindings>,
 | 
			
		||||
    text_pipeline: Res<DefaultTextPipeline>,
 | 
			
		||||
    mut query: Query<
 | 
			
		||||
        (
 | 
			
		||||
            Entity,
 | 
			
		||||
            &mut Draw,
 | 
			
		||||
            &Visible,
 | 
			
		||||
            &Text,
 | 
			
		||||
            &GlobalTransform,
 | 
			
		||||
            &CalculatedSize,
 | 
			
		||||
        ),
 | 
			
		||||
        With<MainPass>,
 | 
			
		||||
    >,
 | 
			
		||||
) {
 | 
			
		||||
    let font_quad = meshes.get(&QUAD_HANDLE).unwrap();
 | 
			
		||||
    let vertex_buffer_descriptor = font_quad.get_vertex_buffer_descriptor();
 | 
			
		||||
 | 
			
		||||
    for (entity, mut draw, visible, text, global_transform, calculated_size) in query.iter_mut() {
 | 
			
		||||
        if !visible.is_visible {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let (width, height) = (calculated_size.size.width, calculated_size.size.height);
 | 
			
		||||
 | 
			
		||||
        if let Some(text_glyphs) = text_pipeline.get_glyphs(&entity) {
 | 
			
		||||
            let position = global_transform.translation
 | 
			
		||||
                + match text.style.alignment.vertical {
 | 
			
		||||
                    VerticalAlign::Top => Vec3::zero(),
 | 
			
		||||
                    VerticalAlign::Center => Vec3::new(0.0, -height * 0.5, 0.0),
 | 
			
		||||
                    VerticalAlign::Bottom => Vec3::new(0.0, -height, 0.0),
 | 
			
		||||
                }
 | 
			
		||||
                + match text.style.alignment.horizontal {
 | 
			
		||||
                    HorizontalAlign::Left => Vec3::new(-width, 0.0, 0.0),
 | 
			
		||||
                    HorizontalAlign::Center => Vec3::new(-width * 0.5, 0.0, 0.0),
 | 
			
		||||
                    HorizontalAlign::Right => Vec3::zero(),
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
            let mut drawable_text = DrawableText {
 | 
			
		||||
                render_resource_bindings: &mut render_resource_bindings,
 | 
			
		||||
                position,
 | 
			
		||||
                msaa: &msaa,
 | 
			
		||||
                text_glyphs: &text_glyphs.glyphs,
 | 
			
		||||
                font_quad_vertex_descriptor: &vertex_buffer_descriptor,
 | 
			
		||||
                style: &text.style,
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            drawable_text.draw(&mut draw, &mut context).unwrap();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Default)]
 | 
			
		||||
pub struct QueuedText2d {
 | 
			
		||||
    entities: Vec<Entity>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Updates the TextGlyphs with the new computed glyphs from the layout
 | 
			
		||||
pub fn text2d_system(
 | 
			
		||||
    mut queued_text: Local<QueuedText2d>,
 | 
			
		||||
    mut textures: ResMut<Assets<Texture>>,
 | 
			
		||||
    fonts: Res<Assets<Font>>,
 | 
			
		||||
    mut texture_atlases: ResMut<Assets<TextureAtlas>>,
 | 
			
		||||
    mut font_atlas_set_storage: ResMut<Assets<FontAtlasSet>>,
 | 
			
		||||
    mut text_pipeline: ResMut<DefaultTextPipeline>,
 | 
			
		||||
    mut text_queries: QuerySet<(
 | 
			
		||||
        Query<Entity, Changed<Text>>,
 | 
			
		||||
        Query<(&Text, &mut CalculatedSize)>,
 | 
			
		||||
    )>,
 | 
			
		||||
) {
 | 
			
		||||
    // Adds all entities where the text or the style has changed to the local queue
 | 
			
		||||
    for entity in text_queries.q0_mut().iter_mut() {
 | 
			
		||||
        queued_text.entities.push(entity);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if queued_text.entities.is_empty() {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Computes all text in the local queue
 | 
			
		||||
    let mut new_queue = Vec::new();
 | 
			
		||||
    let query = text_queries.q1_mut();
 | 
			
		||||
    for entity in queued_text.entities.drain(..) {
 | 
			
		||||
        if let Ok((text, mut calculated_size)) = query.get_mut(entity) {
 | 
			
		||||
            match text_pipeline.queue_text(
 | 
			
		||||
                entity,
 | 
			
		||||
                text.font.clone(),
 | 
			
		||||
                &fonts,
 | 
			
		||||
                &text.value,
 | 
			
		||||
                text.style.font_size,
 | 
			
		||||
                text.style.alignment,
 | 
			
		||||
                Size::new(f32::MAX, f32::MAX),
 | 
			
		||||
                &mut *font_atlas_set_storage,
 | 
			
		||||
                &mut *texture_atlases,
 | 
			
		||||
                &mut *textures,
 | 
			
		||||
            ) {
 | 
			
		||||
                Err(TextError::NoSuchFont) => {
 | 
			
		||||
                    // There was an error processing the text layout, let's add this entity to the queue for further processing
 | 
			
		||||
                    new_queue.push(entity);
 | 
			
		||||
                }
 | 
			
		||||
                Err(e @ TextError::FailedToAddGlyph(_)) => {
 | 
			
		||||
                    panic!("Fatal error when processing text: {}.", e);
 | 
			
		||||
                }
 | 
			
		||||
                Ok(()) => {
 | 
			
		||||
                    let text_layout_info = text_pipeline.get_glyphs(&entity).expect(
 | 
			
		||||
                        "Failed to get glyphs from the pipeline that have just been computed",
 | 
			
		||||
                    );
 | 
			
		||||
                    calculated_size.size = text_layout_info.size;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    queued_text.entities = new_queue;
 | 
			
		||||
}
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
use super::Node;
 | 
			
		||||
use crate::{
 | 
			
		||||
    render::UI_PIPELINE_HANDLE,
 | 
			
		||||
    widget::{Button, Image, Text},
 | 
			
		||||
    CalculatedSize, FocusPolicy, Interaction, Style,
 | 
			
		||||
    widget::{Button, Image},
 | 
			
		||||
    FocusPolicy, Interaction, Style,
 | 
			
		||||
};
 | 
			
		||||
use bevy_asset::Handle;
 | 
			
		||||
use bevy_ecs::Bundle;
 | 
			
		||||
@ -15,6 +15,7 @@ use bevy_render::{
 | 
			
		||||
    prelude::Visible,
 | 
			
		||||
};
 | 
			
		||||
use bevy_sprite::{ColorMaterial, QUAD_HANDLE};
 | 
			
		||||
use bevy_text::{CalculatedSize, Text};
 | 
			
		||||
use bevy_transform::prelude::{GlobalTransform, Transform};
 | 
			
		||||
 | 
			
		||||
#[derive(Bundle, Clone, Debug)]
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,9 @@
 | 
			
		||||
mod convert;
 | 
			
		||||
 | 
			
		||||
use crate::{CalculatedSize, Node, Style};
 | 
			
		||||
use crate::{Node, Style};
 | 
			
		||||
use bevy_ecs::{Changed, Entity, Query, Res, ResMut, With, Without};
 | 
			
		||||
use bevy_math::Vec2;
 | 
			
		||||
use bevy_text::CalculatedSize;
 | 
			
		||||
use bevy_transform::prelude::{Children, Parent, Transform};
 | 
			
		||||
use bevy_utils::HashMap;
 | 
			
		||||
use bevy_window::{Window, WindowId, Windows};
 | 
			
		||||
 | 
			
		||||
@ -16,12 +16,7 @@ pub use node::*;
 | 
			
		||||
pub use render::*;
 | 
			
		||||
 | 
			
		||||
pub mod prelude {
 | 
			
		||||
    pub use crate::{
 | 
			
		||||
        entity::*,
 | 
			
		||||
        node::*,
 | 
			
		||||
        widget::{Button, Text},
 | 
			
		||||
        Anchors, Interaction, Margins,
 | 
			
		||||
    };
 | 
			
		||||
    pub use crate::{entity::*, node::*, widget::Button, Anchors, Interaction, Margins};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
use bevy_app::prelude::*;
 | 
			
		||||
 | 
			
		||||
@ -48,11 +48,6 @@ impl AddAssign<f32> for Val {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default, Copy, Clone, Debug)]
 | 
			
		||||
pub struct CalculatedSize {
 | 
			
		||||
    pub size: Size,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, PartialEq, Debug, Reflect)]
 | 
			
		||||
pub struct Style {
 | 
			
		||||
    pub display: Display,
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,9 @@
 | 
			
		||||
use crate::CalculatedSize;
 | 
			
		||||
use bevy_asset::{Assets, Handle};
 | 
			
		||||
use bevy_ecs::{Query, Res, With};
 | 
			
		||||
use bevy_math::Size;
 | 
			
		||||
use bevy_render::texture::Texture;
 | 
			
		||||
use bevy_sprite::ColorMaterial;
 | 
			
		||||
use bevy_text::CalculatedSize;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
pub enum Image {
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
use crate::{CalculatedSize, Node, Style, Val};
 | 
			
		||||
use bevy_asset::{Assets, Handle};
 | 
			
		||||
use crate::{Node, Style, Val};
 | 
			
		||||
use bevy_asset::Assets;
 | 
			
		||||
use bevy_ecs::{Changed, Entity, Local, Or, Query, QuerySet, Res, ResMut};
 | 
			
		||||
use bevy_math::Size;
 | 
			
		||||
use bevy_render::{
 | 
			
		||||
@ -10,7 +10,9 @@ use bevy_render::{
 | 
			
		||||
    texture::Texture,
 | 
			
		||||
};
 | 
			
		||||
use bevy_sprite::{TextureAtlas, QUAD_HANDLE};
 | 
			
		||||
use bevy_text::{DefaultTextPipeline, DrawableText, Font, FontAtlasSet, TextError, TextStyle};
 | 
			
		||||
use bevy_text::{
 | 
			
		||||
    CalculatedSize, DefaultTextPipeline, DrawableText, Font, FontAtlasSet, Text, TextError,
 | 
			
		||||
};
 | 
			
		||||
use bevy_transform::prelude::GlobalTransform;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Default)]
 | 
			
		||||
@ -18,13 +20,6 @@ pub struct QueuedText {
 | 
			
		||||
    entities: Vec<Entity>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Default, Clone)]
 | 
			
		||||
pub struct Text {
 | 
			
		||||
    pub value: String,
 | 
			
		||||
    pub font: Handle<Font>,
 | 
			
		||||
    pub style: TextStyle,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Defines how min_size, size, and max_size affects the bounds of a text
 | 
			
		||||
/// block.
 | 
			
		||||
pub fn text_constraint(min_size: Val, size: Val, max_size: Val) -> f32 {
 | 
			
		||||
@ -66,26 +61,40 @@ pub fn text_system(
 | 
			
		||||
    let query = text_queries.q1_mut();
 | 
			
		||||
    for entity in queued_text.entities.drain(..) {
 | 
			
		||||
        if let Ok((text, style, mut calculated_size)) = query.get_mut(entity) {
 | 
			
		||||
            match add_text_to_pipeline(
 | 
			
		||||
            let node_size = Size::new(
 | 
			
		||||
                text_constraint(style.min_size.width, style.size.width, style.max_size.width),
 | 
			
		||||
                text_constraint(
 | 
			
		||||
                    style.min_size.height,
 | 
			
		||||
                    style.size.height,
 | 
			
		||||
                    style.max_size.height,
 | 
			
		||||
                ),
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            match text_pipeline.queue_text(
 | 
			
		||||
                entity,
 | 
			
		||||
                &*text,
 | 
			
		||||
                &*style,
 | 
			
		||||
                &mut *textures,
 | 
			
		||||
                &*fonts,
 | 
			
		||||
                &mut *texture_atlases,
 | 
			
		||||
                text.font.clone(),
 | 
			
		||||
                &fonts,
 | 
			
		||||
                &text.value,
 | 
			
		||||
                text.style.font_size,
 | 
			
		||||
                text.style.alignment,
 | 
			
		||||
                node_size,
 | 
			
		||||
                &mut *font_atlas_set_storage,
 | 
			
		||||
                &mut *text_pipeline,
 | 
			
		||||
                &mut *texture_atlases,
 | 
			
		||||
                &mut *textures,
 | 
			
		||||
            ) {
 | 
			
		||||
                TextPipelineResult::Ok => {
 | 
			
		||||
                Err(TextError::NoSuchFont) => {
 | 
			
		||||
                    // There was an error processing the text layout, let's add this entity to the queue for further processing
 | 
			
		||||
                    new_queue.push(entity);
 | 
			
		||||
                }
 | 
			
		||||
                Err(e @ TextError::FailedToAddGlyph(_)) => {
 | 
			
		||||
                    panic!("Fatal error when processing text: {}.", e);
 | 
			
		||||
                }
 | 
			
		||||
                Ok(()) => {
 | 
			
		||||
                    let text_layout_info = text_pipeline.get_glyphs(&entity).expect(
 | 
			
		||||
                        "Failed to get glyphs from the pipeline that have just been computed",
 | 
			
		||||
                    );
 | 
			
		||||
                    calculated_size.size = text_layout_info.size;
 | 
			
		||||
                }
 | 
			
		||||
                TextPipelineResult::Reschedule => {
 | 
			
		||||
                    // There was an error processing the text layout, let's add this entity to the queue for further processing
 | 
			
		||||
                    new_queue.push(entity);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -93,52 +102,6 @@ pub fn text_system(
 | 
			
		||||
    queued_text.entities = new_queue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum TextPipelineResult {
 | 
			
		||||
    Ok,
 | 
			
		||||
    Reschedule,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Computes the text layout and stores it in the TextPipeline resource.
 | 
			
		||||
#[allow(clippy::too_many_arguments)]
 | 
			
		||||
fn add_text_to_pipeline(
 | 
			
		||||
    entity: Entity,
 | 
			
		||||
    text: &Text,
 | 
			
		||||
    style: &Style,
 | 
			
		||||
    textures: &mut Assets<Texture>,
 | 
			
		||||
    fonts: &Assets<Font>,
 | 
			
		||||
    texture_atlases: &mut Assets<TextureAtlas>,
 | 
			
		||||
    font_atlas_set_storage: &mut Assets<FontAtlasSet>,
 | 
			
		||||
    text_pipeline: &mut DefaultTextPipeline,
 | 
			
		||||
) -> TextPipelineResult {
 | 
			
		||||
    let node_size = Size::new(
 | 
			
		||||
        text_constraint(style.min_size.width, style.size.width, style.max_size.width),
 | 
			
		||||
        text_constraint(
 | 
			
		||||
            style.min_size.height,
 | 
			
		||||
            style.size.height,
 | 
			
		||||
            style.max_size.height,
 | 
			
		||||
        ),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    match text_pipeline.queue_text(
 | 
			
		||||
        entity,
 | 
			
		||||
        text.font.clone(),
 | 
			
		||||
        &fonts,
 | 
			
		||||
        &text.value,
 | 
			
		||||
        text.style.font_size,
 | 
			
		||||
        text.style.alignment,
 | 
			
		||||
        node_size,
 | 
			
		||||
        font_atlas_set_storage,
 | 
			
		||||
        texture_atlases,
 | 
			
		||||
        textures,
 | 
			
		||||
    ) {
 | 
			
		||||
        Err(TextError::NoSuchFont) => TextPipelineResult::Reschedule,
 | 
			
		||||
        Err(e @ TextError::FailedToAddGlyph(_)) => {
 | 
			
		||||
            panic!("Fatal error when processing text: {}.", e);
 | 
			
		||||
        }
 | 
			
		||||
        Ok(()) => TextPipelineResult::Ok,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[allow(clippy::too_many_arguments)]
 | 
			
		||||
pub fn draw_text_system(
 | 
			
		||||
    mut context: DrawContext,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										40
									
								
								examples/2d/text2d.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								examples/2d/text2d.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
			
		||||
use bevy::prelude::*;
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    App::build()
 | 
			
		||||
        .add_plugins(DefaultPlugins)
 | 
			
		||||
        .add_startup_system(setup.system())
 | 
			
		||||
        .add_system(animate.system())
 | 
			
		||||
        .run();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn setup(commands: &mut Commands, asset_server: Res<AssetServer>) {
 | 
			
		||||
    commands
 | 
			
		||||
        // 2d camera
 | 
			
		||||
        .spawn(Camera2dBundle::default())
 | 
			
		||||
        .spawn(Text2dBundle {
 | 
			
		||||
            text: Text {
 | 
			
		||||
                value: "This text is in the 2D scene.".to_string(),
 | 
			
		||||
                font: asset_server.load("fonts/FiraSans-Bold.ttf"),
 | 
			
		||||
                style: TextStyle {
 | 
			
		||||
                    font_size: 60.0,
 | 
			
		||||
                    color: Color::WHITE,
 | 
			
		||||
                    alignment: TextAlignment {
 | 
			
		||||
                        vertical: VerticalAlign::Center,
 | 
			
		||||
                        horizontal: HorizontalAlign::Center,
 | 
			
		||||
                    },
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
            ..Default::default()
 | 
			
		||||
        });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn animate(time: Res<Time>, mut query: Query<&mut Transform, With<Text>>) {
 | 
			
		||||
    // `Transform.translation` will determine the location of the text.
 | 
			
		||||
    // `Transform.scale` and `Transform.rotation` do not yet affect text (though you can set the
 | 
			
		||||
    // size of the text via `Text.style.font_size`)
 | 
			
		||||
    for mut transform in query.iter_mut() {
 | 
			
		||||
        transform.translation.x = 100.0 * time.seconds_since_startup().sin() as f32;
 | 
			
		||||
        transform.translation.y = 100.0 * time.seconds_since_startup().cos() as f32;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -3,7 +3,8 @@ use bevy::{
 | 
			
		||||
    prelude::*,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// This example illustrates how to create text and update it in a system. It displays the current FPS in the upper left hand corner.
 | 
			
		||||
/// This example illustrates how to create UI text and update it in a system. It displays the
 | 
			
		||||
/// current FPS in the upper left hand corner.  For text within a scene, please see the text2d example.
 | 
			
		||||
fn main() {
 | 
			
		||||
    App::build()
 | 
			
		||||
        .add_plugins(DefaultPlugins)
 | 
			
		||||
@ -28,7 +29,7 @@ fn text_update_system(diagnostics: Res<Diagnostics>, mut query: Query<&mut Text,
 | 
			
		||||
 | 
			
		||||
fn setup(commands: &mut Commands, asset_server: Res<AssetServer>) {
 | 
			
		||||
    commands
 | 
			
		||||
        // 2d camera
 | 
			
		||||
        // UI camera
 | 
			
		||||
        .spawn(CameraUiBundle::default())
 | 
			
		||||
        // texture
 | 
			
		||||
        .spawn(TextBundle {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user