Update layout/style when scale factor changes too (#4689)

# Objective

- Fix https://github.com/bevyengine/bevy/issues/4688

## Solution

- Fixes https://github.com/bevyengine/bevy/issues/4688
- This raises an interesting question about our change detection system - is filtered queries actually a good UX for this? They're ergonomic in the easy case, but what do we recommend when it's not so.
- In this case, the system should have been migrated similary to https://github.com/bevyengine/bevy/pull/4180 anyway, so I've done that.
This commit is contained in:
Daniel McNab 2022-05-09 14:18:02 +00:00
parent fca1c861d2
commit 33a4df8008
2 changed files with 25 additions and 32 deletions

View file

@ -47,7 +47,10 @@ impl Plugin for TextPlugin {
.register_type::<HorizontalAlign>()
.init_asset_loader::<FontLoader>()
.insert_resource(DefaultTextPipeline::default())
.add_system_to_stage(CoreStage::PostUpdate, text2d_system.after(ModifiesWindows));
.add_system_to_stage(
CoreStage::PostUpdate,
update_text2d_layout.after(ModifiesWindows),
);
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
render_app.add_system_to_stage(

View file

@ -3,16 +3,18 @@ use bevy_ecs::{
bundle::Bundle,
component::Component,
entity::Entity,
query::{Changed, With},
event::EventReader,
query::Changed,
reflect::ReflectComponent,
system::{Local, ParamSet, Query, Res, ResMut},
system::{Local, Query, Res, ResMut},
};
use bevy_math::{Vec2, Vec3};
use bevy_reflect::Reflect;
use bevy_render::{texture::Image, view::Visibility, RenderWorld};
use bevy_sprite::{Anchor, ExtractedSprite, ExtractedSprites, TextureAtlas};
use bevy_transform::prelude::{GlobalTransform, Transform};
use bevy_window::{WindowId, Windows};
use bevy_utils::HashSet;
use bevy_window::{WindowId, WindowScaleFactorChanged, Windows};
use crate::{
DefaultTextPipeline, Font, FontAtlasSet, HorizontalAlign, Text, TextError, VerticalAlign,
@ -123,44 +125,34 @@ pub fn extract_text2d_sprite(
}
}
#[derive(Debug, Default)]
pub struct QueuedText2d {
entities: Vec<Entity>,
}
/// Updates the layout and size information whenever the text or style is changed.
/// This information is computed by the `TextPipeline` on insertion, then stored.
#[allow(clippy::too_many_arguments, clippy::type_complexity)]
pub fn text2d_system(
mut queued_text: Local<QueuedText2d>,
pub fn update_text2d_layout(
// Text items which should be reprocessed again, generally when the font hasn't loaded yet.
mut queue: Local<HashSet<Entity>>,
mut textures: ResMut<Assets<Image>>,
fonts: Res<Assets<Font>>,
windows: Res<Windows>,
mut scale_factor_changed: EventReader<WindowScaleFactorChanged>,
mut texture_atlases: ResMut<Assets<TextureAtlas>>,
mut font_atlas_set_storage: ResMut<Assets<FontAtlasSet>>,
mut text_pipeline: ResMut<DefaultTextPipeline>,
mut text_queries: ParamSet<(
Query<Entity, (With<Text2dSize>, Changed<Text>)>,
Query<(&Text, Option<&Text2dBounds>, &mut Text2dSize), With<Text2dSize>>,
mut text_query: Query<(
Entity,
Changed<Text>,
&Text,
Option<&Text2dBounds>,
&mut Text2dSize,
)>,
) {
// Adds all entities where the text or the style has changed to the local queue
for entity in text_queries.p0().iter_mut() {
queued_text.entities.push(entity);
}
if queued_text.entities.is_empty() {
return;
}
// We need to consume the entire iterator, hence `last`
let factor_changed = scale_factor_changed.iter().last().is_some();
let scale_factor = windows.scale_factor(WindowId::primary());
// Computes all text in the local queue
let mut new_queue = Vec::new();
let mut query = text_queries.p1();
for entity in queued_text.entities.drain(..) {
if let Ok((text, bounds, mut calculated_size)) = query.get_mut(entity) {
let text_bounds = match bounds {
for (entity, text_changed, text, maybe_bounds, mut calculated_size) in text_query.iter_mut() {
if factor_changed || text_changed || queue.remove(&entity) {
let text_bounds = match maybe_bounds {
Some(bounds) => Vec2::new(
scale_value(bounds.size.x, scale_factor),
scale_value(bounds.size.y, scale_factor),
@ -181,7 +173,7 @@ pub fn text2d_system(
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);
queue.insert(entity);
}
Err(e @ TextError::FailedToAddGlyph(_)) => {
panic!("Fatal error when processing text: {}.", e);
@ -198,8 +190,6 @@ pub fn text2d_system(
}
}
}
queued_text.entities = new_queue;
}
pub fn scale_value(value: f32, factor: f64) -> f32 {