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:
parent
fca1c861d2
commit
33a4df8008
@ -47,7 +47,10 @@ impl Plugin for TextPlugin {
|
|||||||
.register_type::<HorizontalAlign>()
|
.register_type::<HorizontalAlign>()
|
||||||
.init_asset_loader::<FontLoader>()
|
.init_asset_loader::<FontLoader>()
|
||||||
.insert_resource(DefaultTextPipeline::default())
|
.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) {
|
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
|
||||||
render_app.add_system_to_stage(
|
render_app.add_system_to_stage(
|
||||||
|
|||||||
@ -3,16 +3,18 @@ use bevy_ecs::{
|
|||||||
bundle::Bundle,
|
bundle::Bundle,
|
||||||
component::Component,
|
component::Component,
|
||||||
entity::Entity,
|
entity::Entity,
|
||||||
query::{Changed, With},
|
event::EventReader,
|
||||||
|
query::Changed,
|
||||||
reflect::ReflectComponent,
|
reflect::ReflectComponent,
|
||||||
system::{Local, ParamSet, Query, Res, ResMut},
|
system::{Local, Query, Res, ResMut},
|
||||||
};
|
};
|
||||||
use bevy_math::{Vec2, Vec3};
|
use bevy_math::{Vec2, Vec3};
|
||||||
use bevy_reflect::Reflect;
|
use bevy_reflect::Reflect;
|
||||||
use bevy_render::{texture::Image, view::Visibility, RenderWorld};
|
use bevy_render::{texture::Image, view::Visibility, RenderWorld};
|
||||||
use bevy_sprite::{Anchor, ExtractedSprite, ExtractedSprites, TextureAtlas};
|
use bevy_sprite::{Anchor, ExtractedSprite, ExtractedSprites, TextureAtlas};
|
||||||
use bevy_transform::prelude::{GlobalTransform, Transform};
|
use bevy_transform::prelude::{GlobalTransform, Transform};
|
||||||
use bevy_window::{WindowId, Windows};
|
use bevy_utils::HashSet;
|
||||||
|
use bevy_window::{WindowId, WindowScaleFactorChanged, Windows};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
DefaultTextPipeline, Font, FontAtlasSet, HorizontalAlign, Text, TextError, VerticalAlign,
|
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.
|
/// Updates the layout and size information whenever the text or style is changed.
|
||||||
/// This information is computed by the `TextPipeline` on insertion, then stored.
|
/// This information is computed by the `TextPipeline` on insertion, then stored.
|
||||||
#[allow(clippy::too_many_arguments, clippy::type_complexity)]
|
#[allow(clippy::too_many_arguments, clippy::type_complexity)]
|
||||||
pub fn text2d_system(
|
pub fn update_text2d_layout(
|
||||||
mut queued_text: Local<QueuedText2d>,
|
// 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>>,
|
mut textures: ResMut<Assets<Image>>,
|
||||||
fonts: Res<Assets<Font>>,
|
fonts: Res<Assets<Font>>,
|
||||||
windows: Res<Windows>,
|
windows: Res<Windows>,
|
||||||
|
mut scale_factor_changed: EventReader<WindowScaleFactorChanged>,
|
||||||
mut texture_atlases: ResMut<Assets<TextureAtlas>>,
|
mut texture_atlases: ResMut<Assets<TextureAtlas>>,
|
||||||
mut font_atlas_set_storage: ResMut<Assets<FontAtlasSet>>,
|
mut font_atlas_set_storage: ResMut<Assets<FontAtlasSet>>,
|
||||||
mut text_pipeline: ResMut<DefaultTextPipeline>,
|
mut text_pipeline: ResMut<DefaultTextPipeline>,
|
||||||
mut text_queries: ParamSet<(
|
mut text_query: Query<(
|
||||||
Query<Entity, (With<Text2dSize>, Changed<Text>)>,
|
Entity,
|
||||||
Query<(&Text, Option<&Text2dBounds>, &mut Text2dSize), With<Text2dSize>>,
|
Changed<Text>,
|
||||||
|
&Text,
|
||||||
|
Option<&Text2dBounds>,
|
||||||
|
&mut Text2dSize,
|
||||||
)>,
|
)>,
|
||||||
) {
|
) {
|
||||||
// Adds all entities where the text or the style has changed to the local queue
|
// We need to consume the entire iterator, hence `last`
|
||||||
for entity in text_queries.p0().iter_mut() {
|
let factor_changed = scale_factor_changed.iter().last().is_some();
|
||||||
queued_text.entities.push(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
if queued_text.entities.is_empty() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let scale_factor = windows.scale_factor(WindowId::primary());
|
let scale_factor = windows.scale_factor(WindowId::primary());
|
||||||
|
|
||||||
// Computes all text in the local queue
|
for (entity, text_changed, text, maybe_bounds, mut calculated_size) in text_query.iter_mut() {
|
||||||
let mut new_queue = Vec::new();
|
if factor_changed || text_changed || queue.remove(&entity) {
|
||||||
let mut query = text_queries.p1();
|
let text_bounds = match maybe_bounds {
|
||||||
for entity in queued_text.entities.drain(..) {
|
|
||||||
if let Ok((text, bounds, mut calculated_size)) = query.get_mut(entity) {
|
|
||||||
let text_bounds = match bounds {
|
|
||||||
Some(bounds) => Vec2::new(
|
Some(bounds) => Vec2::new(
|
||||||
scale_value(bounds.size.x, scale_factor),
|
scale_value(bounds.size.x, scale_factor),
|
||||||
scale_value(bounds.size.y, scale_factor),
|
scale_value(bounds.size.y, scale_factor),
|
||||||
@ -181,7 +173,7 @@ pub fn text2d_system(
|
|||||||
Err(TextError::NoSuchFont) => {
|
Err(TextError::NoSuchFont) => {
|
||||||
// There was an error processing the text layout, let's add this entity to the
|
// There was an error processing the text layout, let's add this entity to the
|
||||||
// queue for further processing
|
// queue for further processing
|
||||||
new_queue.push(entity);
|
queue.insert(entity);
|
||||||
}
|
}
|
||||||
Err(e @ TextError::FailedToAddGlyph(_)) => {
|
Err(e @ TextError::FailedToAddGlyph(_)) => {
|
||||||
panic!("Fatal error when processing text: {}.", e);
|
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 {
|
pub fn scale_value(value: f32, factor: f64) -> f32 {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user