From 9d9750b928e9ec6a9447370400bc7e22d3d86e97 Mon Sep 17 00:00:00 2001 From: ickshonpe Date: Mon, 11 Sep 2023 19:56:16 +0100 Subject: [PATCH] `TextLayoutInfo::size` should hold the drawn size of the text, and not a scaled value. (#7794) # Objective `TextLayoutInfo::size` isn't the drawn size of the text, but a scaled value. This is fragile, counter-intuitive and makes it awkward to retrieve the correct value. ## Solution Multiply `TextLayoutInfo::size` by the reciprocal of the window's scale factor after generating the text layout in `update_text2d_layout` and `bevy_ui::widget::text_system`. --- fixes: #7787 ## Changelog * Multiply `TextLayoutInfo::size` by the reciprocal of the scale factor after text computation to reflect the actual size of the text as drawn. * Reorder the operations in `extract_text2d_sprite` to apply the alignment offset before the scale factor scaling. ## Migration Guide The `size` value of `TextLayoutInfo` is stored in logical pixels and has been renamed to `logical_size`. There is no longer any need to divide by the window's scale factor to get the logical size. --- crates/bevy_text/src/pipeline.rs | 7 +++++-- crates/bevy_text/src/text2d.rs | 16 +++++++++++----- crates/bevy_ui/src/widget/text.rs | 13 +++++++++---- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/crates/bevy_text/src/pipeline.rs b/crates/bevy_text/src/pipeline.rs index fa616e499944b..6a83a446479b6 100644 --- a/crates/bevy_text/src/pipeline.rs +++ b/crates/bevy_text/src/pipeline.rs @@ -25,7 +25,7 @@ pub struct TextPipeline { #[derive(Component, Clone, Default, Debug)] pub struct TextLayoutInfo { pub glyphs: Vec, - pub size: Vec2, + pub logical_size: Vec2, } impl TextPipeline { @@ -97,7 +97,10 @@ impl TextPipeline { y_axis_orientation, )?; - Ok(TextLayoutInfo { glyphs, size }) + Ok(TextLayoutInfo { + glyphs, + logical_size: size, + }) } } diff --git a/crates/bevy_text/src/text2d.rs b/crates/bevy_text/src/text2d.rs index 1f26e47d21367..956029b696b46 100644 --- a/crates/bevy_text/src/text2d.rs +++ b/crates/bevy_text/src/text2d.rs @@ -36,6 +36,7 @@ use bevy_window::{PrimaryWindow, Window, WindowScaleFactorChanged}; #[derive(Component, Copy, Clone, Debug, Reflect)] #[reflect(Component)] pub struct Text2dBounds { + /// The maximum width and height of text in logical pixels. pub size: Vec2, } @@ -105,10 +106,10 @@ pub fn extract_text2d_sprite( } let text_anchor = -(anchor.as_vec() + 0.5); - let alignment_translation = text_layout_info.size * text_anchor; + let alignment_translation = text_layout_info.logical_size * text_anchor; let transform = *global_transform - * scaling - * GlobalTransform::from_translation(alignment_translation.extend(0.)); + * GlobalTransform::from_translation(alignment_translation.extend(0.)) + * scaling; let mut color = Color::WHITE; let mut current_section = usize::MAX; for PositionedGlyph { @@ -172,6 +173,8 @@ pub fn update_text2d_layout( .map(|window| window.resolution.scale_factor()) .unwrap_or(1.0); + let inverse_scale_factor = scale_factor.recip(); + for (entity, text, bounds, mut text_layout_info) in &mut text_query { if factor_changed || text.is_changed() || bounds.is_changed() || queue.remove(&entity) { let text_bounds = Vec2::new( @@ -182,7 +185,6 @@ pub fn update_text2d_layout( }, scale_value(bounds.size.y, scale_factor), ); - match text_pipeline.queue_text( &fonts, &text.sections, @@ -205,7 +207,11 @@ pub fn update_text2d_layout( Err(e @ TextError::FailedToAddGlyph(_)) => { panic!("Fatal error when processing text: {e}."); } - Ok(info) => *text_layout_info = info, + Ok(mut info) => { + info.logical_size.x = scale_value(info.logical_size.x, inverse_scale_factor); + info.logical_size.y = scale_value(info.logical_size.y, inverse_scale_factor); + *text_layout_info = info; + } } } } diff --git a/crates/bevy_ui/src/widget/text.rs b/crates/bevy_ui/src/widget/text.rs index ff042093c5dfa..9700d77c967bd 100644 --- a/crates/bevy_ui/src/widget/text.rs +++ b/crates/bevy_ui/src/widget/text.rs @@ -12,8 +12,8 @@ use bevy_reflect::{std_traits::ReflectDefault, Reflect}; use bevy_render::texture::Image; use bevy_sprite::TextureAtlas; use bevy_text::{ - BreakLineOn, Font, FontAtlasSets, FontAtlasWarning, Text, TextError, TextLayoutInfo, - TextMeasureInfo, TextPipeline, TextSettings, YAxisOrientation, + scale_value, BreakLineOn, Font, FontAtlasSets, FontAtlasWarning, Text, TextError, + TextLayoutInfo, TextMeasureInfo, TextPipeline, TextSettings, YAxisOrientation, }; use bevy_window::{PrimaryWindow, Window}; use taffy::style::AvailableSpace; @@ -153,6 +153,7 @@ fn queue_text( textures: &mut Assets, text_settings: &TextSettings, scale_factor: f64, + inverse_scale_factor: f64, text: &Text, node: Ref, mut text_flags: Mut, @@ -189,7 +190,9 @@ fn queue_text( Err(e @ TextError::FailedToAddGlyph(_)) => { panic!("Fatal error when processing text: {e}."); } - Ok(info) => { + Ok(mut info) => { + info.logical_size.x = scale_value(info.logical_size.x, inverse_scale_factor); + info.logical_size.y = scale_value(info.logical_size.y, inverse_scale_factor); *text_layout_info = info; text_flags.needs_recompute = false; } @@ -226,7 +229,7 @@ pub fn text_system( .unwrap_or(1.); let scale_factor = ui_scale.0 * window_scale_factor; - + let inverse_scale_factor = scale_factor.recip(); if *last_scale_factor == scale_factor { // Scale factor unchanged, only recompute text for modified text nodes for (node, text, text_layout_info, text_flags) in text_query.iter_mut() { @@ -240,6 +243,7 @@ pub fn text_system( &mut textures, &text_settings, scale_factor, + inverse_scale_factor, text, node, text_flags, @@ -261,6 +265,7 @@ pub fn text_system( &mut textures, &text_settings, scale_factor, + inverse_scale_factor, text, node, text_flags,