diff --git a/crates/bevy_text/src/lib.rs b/crates/bevy_text/src/lib.rs index 12075643ea2a5..4dc1fc3b34070 100644 --- a/crates/bevy_text/src/lib.rs +++ b/crates/bevy_text/src/lib.rs @@ -47,7 +47,10 @@ impl Plugin for TextPlugin { .register_type::() .init_asset_loader::() .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( diff --git a/crates/bevy_text/src/text2d.rs b/crates/bevy_text/src/text2d.rs index 9127c5932bfcf..a9eefb7528d36 100644 --- a/crates/bevy_text/src/text2d.rs +++ b/crates/bevy_text/src/text2d.rs @@ -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, -} - /// 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, +pub fn update_text2d_layout( + // Text items which should be reprocessed again, generally when the font hasn't loaded yet. + mut queue: Local>, mut textures: ResMut>, fonts: Res>, windows: Res, + mut scale_factor_changed: EventReader, mut texture_atlases: ResMut>, mut font_atlas_set_storage: ResMut>, mut text_pipeline: ResMut, - mut text_queries: ParamSet<( - Query, Changed)>, - Query<(&Text, Option<&Text2dBounds>, &mut Text2dSize), With>, + mut text_query: Query<( + Entity, + Changed, + &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 {