diff --git a/crates/bevy_text/src/draw.rs b/crates/bevy_text/src/draw.rs index 9e26a456b5..e4dd639d37 100644 --- a/crates/bevy_text/src/draw.rs +++ b/crates/bevy_text/src/draw.rs @@ -1,4 +1,6 @@ +use crate::{PositionedGlyph, TextSection}; use bevy_math::{Mat4, Vec3}; +use bevy_render::pipeline::IndexFormat; use bevy_render::{ draw::{Draw, DrawContext, DrawError, Drawable}, mesh, @@ -8,19 +10,18 @@ use bevy_render::{ renderer::{BindGroup, RenderResourceBindings, RenderResourceId}, }; use bevy_sprite::TextureAtlasSprite; +use bevy_transform::prelude::GlobalTransform; use bevy_utils::tracing::error; -use crate::{PositionedGlyph, TextSection}; -use bevy_render::pipeline::IndexFormat; - pub struct DrawableText<'a> { pub render_resource_bindings: &'a mut RenderResourceBindings, - pub position: Vec3, + pub global_transform: GlobalTransform, pub scale_factor: f32, pub sections: &'a [TextSection], pub text_glyphs: &'a Vec, pub msaa: &'a Msaa, pub font_quad_vertex_layout: &'a VertexBufferLayout, + pub alignment_offset: Vec3, } impl<'a> Drawable for DrawableText<'a> { @@ -76,19 +77,12 @@ impl<'a> Drawable for DrawableText<'a> { flip_y: false, }; - // To get the rendering right for non-one scaling factors, we need - // the sprite to be drawn in "physical" coordinates. This is because - // the shader uses the size of the sprite to control the size on - // screen. To accomplish this we make the sprite transform - // convert from physical coordinates to logical coordinates in - // addition to altering the origin. Since individual glyphs will - // already be in physical coordinates, we just need to convert the - // overall position to physical coordinates to get the sprites - // physical position. - - let transform = Mat4::from_scale(Vec3::splat(1. / self.scale_factor)) + let transform = Mat4::from_rotation_translation( + self.global_transform.rotation, + self.global_transform.translation, + ) * Mat4::from_scale(self.global_transform.scale / self.scale_factor) * Mat4::from_translation( - self.position * self.scale_factor + tv.position.extend(0.), + self.alignment_offset * self.scale_factor + tv.position.extend(0.), ); let transform_buffer = context.get_uniform_buffer(&transform).unwrap(); diff --git a/crates/bevy_text/src/text2d.rs b/crates/bevy_text/src/text2d.rs index e08258b686..7d778a9943 100644 --- a/crates/bevy_text/src/text2d.rs +++ b/crates/bevy_text/src/text2d.rs @@ -93,26 +93,25 @@ pub fn draw_text2d_system( 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.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.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 alignment_offset = match text.alignment.vertical { + VerticalAlign::Top => Vec3::new(0.0, -height, 0.0), + 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 drawable_text = DrawableText { render_resource_bindings: &mut render_resource_bindings, - position, + global_transform: *global_transform, + scale_factor, msaa: &msaa, text_glyphs: &text_glyphs.glyphs, font_quad_vertex_layout: &font_quad_vertex_layout, - scale_factor, sections: &text.sections, + alignment_offset, }; drawable_text.draw(&mut draw, &mut context).unwrap(); diff --git a/crates/bevy_ui/src/widget/text.rs b/crates/bevy_ui/src/widget/text.rs index a8dce7ea1a..e5657e71da 100644 --- a/crates/bevy_ui/src/widget/text.rs +++ b/crates/bevy_ui/src/widget/text.rs @@ -167,16 +167,15 @@ pub fn draw_text_system( } if let Some(text_glyphs) = text_pipeline.get_glyphs(&entity) { - let position = global_transform.translation - (node.size / 2.0).extend(0.0); - let mut drawable_text = DrawableText { render_resource_bindings: &mut render_resource_bindings, - position, + global_transform: *global_transform, scale_factor: scale_factor as f32, msaa: &msaa, text_glyphs: &text_glyphs.glyphs, font_quad_vertex_layout: &vertex_buffer_layout, sections: &text.sections, + alignment_offset: (node.size / -2.0).extend(0.0), }; drawable_text.draw(&mut draw, &mut context).unwrap(); diff --git a/examples/2d/text2d.rs b/examples/2d/text2d.rs index a8cbf3c38a..86232ecab5 100644 --- a/examples/2d/text2d.rs +++ b/examples/2d/text2d.rs @@ -4,36 +4,79 @@ fn main() { App::build() .add_plugins(DefaultPlugins) .add_startup_system(setup.system()) - .add_system(animate.system()) + .add_system(animate_translation.system()) + .add_system(animate_rotation.system()) + .add_system(animate_scale.system()) .run(); } +struct AnimateTranslation; +struct AnimateRotation; +struct AnimateScale; + fn setup(mut commands: Commands, asset_server: Res) { + let font = asset_server.load("fonts/FiraSans-Bold.ttf"); + let text_style = TextStyle { + font, + font_size: 60.0, + color: Color::WHITE, + }; + let text_alignment = TextAlignment { + vertical: VerticalAlign::Center, + horizontal: HorizontalAlign::Center, + }; // 2d camera commands.spawn_bundle(OrthographicCameraBundle::new_2d()); - commands.spawn_bundle(Text2dBundle { - text: Text::with_section( - "This text is in the 2D scene.", - TextStyle { - font: asset_server.load("fonts/FiraSans-Bold.ttf"), - font_size: 60.0, - color: Color::WHITE, - }, - TextAlignment { - vertical: VerticalAlign::Center, - horizontal: HorizontalAlign::Center, - }, - ), - ..Default::default() - }); + // Demonstrate changing translation + commands + .spawn_bundle(Text2dBundle { + text: Text::with_section("translation", text_style.clone(), text_alignment), + ..Default::default() + }) + .insert(AnimateTranslation); + // Demonstrate changing rotation + commands + .spawn_bundle(Text2dBundle { + text: Text::with_section("rotation", text_style.clone(), text_alignment), + ..Default::default() + }) + .insert(AnimateRotation); + // Demonstrate changing scale + commands + .spawn_bundle(Text2dBundle { + text: Text::with_section("scale", text_style, text_alignment), + ..Default::default() + }) + .insert(AnimateScale); } -fn animate(time: Res