Merge 03b5d3a2e7
into f964ee1e3a
This commit is contained in:
commit
4f50daf682
@ -117,19 +117,25 @@ impl Plugin for TextPlugin {
|
|||||||
.add_systems(
|
.add_systems(
|
||||||
PostUpdate,
|
PostUpdate,
|
||||||
(
|
(
|
||||||
remove_dropped_font_atlas_sets.before(AssetEventSystems),
|
(
|
||||||
detect_text_needs_rerender::<Text2d>,
|
remove_dropped_font_atlas_sets.before(AssetEventSystems),
|
||||||
update_text2d_layout
|
detect_text_root_needs_rerender::<Text2d>,
|
||||||
// Potential conflict: `Assets<Image>`
|
update_text2d_layout
|
||||||
// In practice, they run independently since `bevy_render::camera_update_system`
|
// Potential conflict: `Assets<Image>`
|
||||||
// will only ever observe its own render target, and `update_text2d_layout`
|
// In practice, they run independently since `bevy_render::camera_update_system`
|
||||||
// will never modify a pre-existing `Image` asset.
|
// will only ever observe its own render target, and `update_text2d_layout`
|
||||||
.ambiguous_with(CameraUpdateSystems),
|
// will never modify a pre-existing `Image` asset.
|
||||||
calculate_bounds_text2d.in_set(VisibilitySystems::CalculateBounds),
|
.ambiguous_with(CameraUpdateSystems),
|
||||||
)
|
calculate_bounds_text2d.in_set(VisibilitySystems::CalculateBounds),
|
||||||
.chain()
|
)
|
||||||
.in_set(Text2dUpdateSystems)
|
.chain()
|
||||||
.after(AnimationSystems),
|
.in_set(Text2dUpdateSystems)
|
||||||
|
.after(AnimationSystems),
|
||||||
|
detect_text_span_needs_rerender
|
||||||
|
.before(Text2dUpdateSystems)
|
||||||
|
.ambiguous_with(CameraUpdateSystems)
|
||||||
|
.after(AnimationSystems),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.add_systems(Last, trim_cosmic_cache);
|
.add_systems(Last, trim_cosmic_cache);
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ impl ComputedTextBlock {
|
|||||||
|
|
||||||
/// Indicates if the text needs to be refreshed in [`TextLayoutInfo`].
|
/// Indicates if the text needs to be refreshed in [`TextLayoutInfo`].
|
||||||
///
|
///
|
||||||
/// Updated automatically by [`detect_text_needs_rerender`] and cleared
|
/// Updated automatically by [`detect_text_root_needs_rerender`] and [`detect_text_span_needs_rerender`], and cleared
|
||||||
/// by [`TextPipeline`](crate::TextPipeline) methods.
|
/// by [`TextPipeline`](crate::TextPipeline) methods.
|
||||||
pub fn needs_rerender(&self) -> bool {
|
pub fn needs_rerender(&self) -> bool {
|
||||||
self.needs_rerender
|
self.needs_rerender
|
||||||
@ -472,11 +472,10 @@ pub enum FontSmoothing {
|
|||||||
|
|
||||||
/// System that detects changes to text blocks and sets `ComputedTextBlock::should_rerender`.
|
/// System that detects changes to text blocks and sets `ComputedTextBlock::should_rerender`.
|
||||||
///
|
///
|
||||||
/// Generic over the root text component and text span component. For example, [`Text2d`](crate::Text2d)/[`TextSpan`] for
|
/// Generic over the root text component.
|
||||||
/// 2d or `Text`/[`TextSpan`] for UI.
|
pub fn detect_text_root_needs_rerender<Root: Component>(
|
||||||
pub fn detect_text_needs_rerender<Root: Component>(
|
mut changed_roots: Query<
|
||||||
changed_roots: Query<
|
&mut ComputedTextBlock,
|
||||||
Entity,
|
|
||||||
(
|
(
|
||||||
Or<(
|
Or<(
|
||||||
Changed<Root>,
|
Changed<Root>,
|
||||||
@ -489,6 +488,30 @@ pub fn detect_text_needs_rerender<Root: Component>(
|
|||||||
With<TextLayout>,
|
With<TextLayout>,
|
||||||
),
|
),
|
||||||
>,
|
>,
|
||||||
|
roots_without_computed_block: Query<Entity, (With<Root>, Without<ComputedTextBlock>)>,
|
||||||
|
) {
|
||||||
|
// Root entity:
|
||||||
|
// - Root component changed.
|
||||||
|
// - TextFont on root changed.
|
||||||
|
// - TextLayout changed.
|
||||||
|
// - Root children changed (can include additions and removals).
|
||||||
|
for mut computed in changed_roots.iter_mut() {
|
||||||
|
computed.needs_rerender = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for entity in roots_without_computed_block.iter() {
|
||||||
|
// If the root entity does not have a ComputedTextBlock, then it needs one.
|
||||||
|
// This can happen if the root was spawned without a ComputedTextBlock, or if it was removed.
|
||||||
|
once!(warn!(
|
||||||
|
"found entity {} with a root text component ({}) that has no ComputedTextBlock; this warning only prints once",
|
||||||
|
entity,
|
||||||
|
core::any::type_name::<Root>()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// System that detects changes to text spans and sets `ComputedTextBlock::should_rerender`.
|
||||||
|
pub fn detect_text_span_needs_rerender(
|
||||||
changed_spans: Query<
|
changed_spans: Query<
|
||||||
(Entity, Option<&ChildOf>, Has<TextLayout>),
|
(Entity, Option<&ChildOf>, Has<TextLayout>),
|
||||||
(
|
(
|
||||||
@ -509,20 +532,6 @@ pub fn detect_text_needs_rerender<Root: Component>(
|
|||||||
Has<TextSpan>,
|
Has<TextSpan>,
|
||||||
)>,
|
)>,
|
||||||
) {
|
) {
|
||||||
// Root entity:
|
|
||||||
// - Root component changed.
|
|
||||||
// - TextFont on root changed.
|
|
||||||
// - TextLayout changed.
|
|
||||||
// - Root children changed (can include additions and removals).
|
|
||||||
for root in changed_roots.iter() {
|
|
||||||
let Ok((_, Some(mut computed), _)) = computed.get_mut(root) else {
|
|
||||||
once!(warn!("found entity {} with a root text component ({}) but no ComputedTextBlock; this warning only \
|
|
||||||
prints once", root, core::any::type_name::<Root>()));
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
computed.needs_rerender = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Span entity:
|
// Span entity:
|
||||||
// - Span component changed.
|
// - Span component changed.
|
||||||
// - Span TextFont changed.
|
// - Span TextFont changed.
|
||||||
@ -530,16 +539,15 @@ pub fn detect_text_needs_rerender<Root: Component>(
|
|||||||
for (entity, maybe_span_child_of, has_text_block) in changed_spans.iter() {
|
for (entity, maybe_span_child_of, has_text_block) in changed_spans.iter() {
|
||||||
if has_text_block {
|
if has_text_block {
|
||||||
once!(warn!("found entity {} with a TextSpan that has a TextLayout, which should only be on root \
|
once!(warn!("found entity {} with a TextSpan that has a TextLayout, which should only be on root \
|
||||||
text entities (that have {}); this warning only prints once",
|
text entities; this warning only prints once",
|
||||||
entity, core::any::type_name::<Root>()));
|
entity));
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(span_child_of) = maybe_span_child_of else {
|
let Some(span_child_of) = maybe_span_child_of else {
|
||||||
once!(warn!(
|
once!(warn!(
|
||||||
"found entity {} with a TextSpan that has no parent; it should have an ancestor \
|
"found entity {} with a TextSpan that has no parent; it should have an ancestor \
|
||||||
with a root text component ({}); this warning only prints once",
|
with a root text component; this warning only prints once",
|
||||||
entity,
|
entity
|
||||||
core::any::type_name::<Root>()
|
|
||||||
));
|
));
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
@ -568,9 +576,8 @@ pub fn detect_text_needs_rerender<Root: Component>(
|
|||||||
let Some(next_child_of) = maybe_child_of else {
|
let Some(next_child_of) = maybe_child_of else {
|
||||||
once!(warn!(
|
once!(warn!(
|
||||||
"found entity {} with a TextSpan that has no ancestor with the root text \
|
"found entity {} with a TextSpan that has no ancestor with the root text \
|
||||||
component ({}); this warning only prints once",
|
component; this warning only prints once",
|
||||||
entity,
|
entity,
|
||||||
core::any::type_name::<Root>()
|
|
||||||
));
|
));
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
@ -389,7 +389,9 @@ mod tests {
|
|||||||
use bevy_asset::{load_internal_binary_asset, Handle};
|
use bevy_asset::{load_internal_binary_asset, Handle};
|
||||||
use bevy_ecs::schedule::IntoScheduleConfigs;
|
use bevy_ecs::schedule::IntoScheduleConfigs;
|
||||||
|
|
||||||
use crate::{detect_text_needs_rerender, TextIterScratch};
|
use crate::{
|
||||||
|
detect_text_root_needs_rerender, detect_text_span_needs_rerender, TextIterScratch,
|
||||||
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@ -409,7 +411,8 @@ mod tests {
|
|||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
(
|
(
|
||||||
detect_text_needs_rerender::<Text2d>,
|
detect_text_root_needs_rerender::<Text2d>,
|
||||||
|
detect_text_span_needs_rerender,
|
||||||
update_text2d_layout,
|
update_text2d_layout,
|
||||||
calculate_bounds_text2d,
|
calculate_bounds_text2d,
|
||||||
)
|
)
|
||||||
|
@ -34,6 +34,7 @@ mod layout;
|
|||||||
mod stack;
|
mod stack;
|
||||||
mod ui_node;
|
mod ui_node;
|
||||||
|
|
||||||
|
use bevy_text::detect_text_span_needs_rerender;
|
||||||
pub use focus::*;
|
pub use focus::*;
|
||||||
pub use geometry::*;
|
pub use geometry::*;
|
||||||
pub use gradients::*;
|
pub use gradients::*;
|
||||||
@ -201,7 +202,7 @@ impl Plugin for UiPlugin {
|
|||||||
let ui_layout_system_config = ui_layout_system_config
|
let ui_layout_system_config = ui_layout_system_config
|
||||||
// Text and Text2D operate on disjoint sets of entities
|
// Text and Text2D operate on disjoint sets of entities
|
||||||
.ambiguous_with(bevy_text::update_text2d_layout)
|
.ambiguous_with(bevy_text::update_text2d_layout)
|
||||||
.ambiguous_with(bevy_text::detect_text_needs_rerender::<bevy_text::Text2d>);
|
.ambiguous_with(bevy_text::detect_text_root_needs_rerender::<bevy_text::Text2d>);
|
||||||
|
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
PostUpdate,
|
PostUpdate,
|
||||||
@ -252,26 +253,27 @@ fn build_text_interop(app: &mut App) {
|
|||||||
PostUpdate,
|
PostUpdate,
|
||||||
(
|
(
|
||||||
(
|
(
|
||||||
bevy_text::detect_text_needs_rerender::<Text>,
|
bevy_text::detect_text_root_needs_rerender::<Text>,
|
||||||
widget::measure_text_system,
|
widget::measure_text_system,
|
||||||
)
|
)
|
||||||
.chain()
|
.chain()
|
||||||
.in_set(UiSystems::Content)
|
.in_set(UiSystems::Content)
|
||||||
// Text and Text2d are independent.
|
// Text and Text2d are independent.
|
||||||
.ambiguous_with(bevy_text::detect_text_needs_rerender::<bevy_text::Text2d>)
|
.ambiguous_with(bevy_text::detect_text_root_needs_rerender::<bevy_text::Text2d>)
|
||||||
// Potential conflict: `Assets<Image>`
|
// Potential conflict: `Assets<Image>`
|
||||||
// Since both systems will only ever insert new [`Image`] assets,
|
// Since both systems will only ever insert new [`Image`] assets,
|
||||||
// they will never observe each other's effects.
|
// they will never observe each other's effects.
|
||||||
.ambiguous_with(bevy_text::update_text2d_layout)
|
.ambiguous_with(bevy_text::update_text2d_layout)
|
||||||
// We assume Text is on disjoint UI entities to ImageNode and UiTextureAtlasImage
|
// We assume Text is on disjoint UI entities to ImageNode and UiTextureAtlasImage
|
||||||
// FIXME: Add an archetype invariant for this https://github.com/bevyengine/bevy/issues/1481.
|
// FIXME: Add an archetype invariant for this https://github.com/bevyengine/bevy/issues/1481.
|
||||||
.ambiguous_with(widget::update_image_content_size_system),
|
.ambiguous_with(widget::update_image_content_size_system)
|
||||||
|
.after(detect_text_span_needs_rerender),
|
||||||
widget::text_system
|
widget::text_system
|
||||||
.in_set(UiSystems::PostLayout)
|
.in_set(UiSystems::PostLayout)
|
||||||
.after(bevy_text::remove_dropped_font_atlas_sets)
|
.after(bevy_text::remove_dropped_font_atlas_sets)
|
||||||
.before(bevy_asset::AssetEventSystems)
|
.before(bevy_asset::AssetEventSystems)
|
||||||
// Text2d and bevy_ui text are entirely on separate entities
|
// Text2d and bevy_ui text are entirely on separate entities
|
||||||
.ambiguous_with(bevy_text::detect_text_needs_rerender::<bevy_text::Text2d>)
|
.ambiguous_with(bevy_text::detect_text_root_needs_rerender::<bevy_text::Text2d>)
|
||||||
.ambiguous_with(bevy_text::update_text2d_layout)
|
.ambiguous_with(bevy_text::update_text2d_layout)
|
||||||
.ambiguous_with(bevy_text::calculate_bounds_text2d),
|
.ambiguous_with(bevy_text::calculate_bounds_text2d),
|
||||||
),
|
),
|
||||||
|
@ -111,7 +111,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if args.recompute_text {
|
if args.recompute_text {
|
||||||
app.add_systems(Update, |mut text_query: Query<&mut Text>| {
|
app.add_systems(Update, |mut text_query: Query<&mut TextSpan>| {
|
||||||
text_query
|
text_query
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.for_each(|mut text| text.set_changed());
|
.for_each(|mut text| text.set_changed());
|
||||||
|
Loading…
Reference in New Issue
Block a user