Skip to content

Commit

Permalink
Update layout/style when scale factor changes too (#4689)
Browse files Browse the repository at this point in the history
# Objective

- Fix #4688

## Solution

- Fixes #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 #4180 anyway, so I've done that.
  • Loading branch information
DJMcNab committed May 9, 2022
1 parent 352bc9e commit a8bc123
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 32 deletions.
5 changes: 4 additions & 1 deletion crates/bevy_text/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
52 changes: 21 additions & 31 deletions crates/bevy_text/src/text2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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),
Expand All @@ -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);
Expand All @@ -198,8 +190,6 @@ pub fn text2d_system(
}
}
}

queued_text.entities = new_queue;
}

pub fn scale_value(value: f32, factor: f64) -> f32 {
Expand Down

0 comments on commit a8bc123

Please sign in to comment.