diff --git a/crates/bevy_text/src/lib.rs b/crates/bevy_text/src/lib.rs index b36f5fa2bb..6932425db8 100644 --- a/crates/bevy_text/src/lib.rs +++ b/crates/bevy_text/src/lib.rs @@ -131,7 +131,9 @@ impl Plugin for TextPlugin { .in_set(Text2dUpdateSystems) .after(AnimationSystems), ) - .add_systems(Last, trim_cosmic_cache); + .add_systems(Last, trim_cosmic_cache) + .add_observer(enable_text_node_needs_rerender_detection::) + .add_observer(enable_text_node_needs_rerender_detection::); if let Some(render_app) = app.get_sub_app_mut(RenderApp) { render_app.add_systems( diff --git a/crates/bevy_text/src/text.rs b/crates/bevy_text/src/text.rs index ccfdb2a372..a7a4c28f48 100644 --- a/crates/bevy_text/src/text.rs +++ b/crates/bevy_text/src/text.rs @@ -578,3 +578,44 @@ pub fn detect_text_needs_rerender( } } } + +/// Observer system that ensures all entities with the `Tracked` [`Component`] will be able to trigger +/// [`detect_text_needs_rerender_on_child_removed`]. +pub fn enable_text_node_needs_rerender_detection( + trigger: On, + mut commands: Commands, +) { + let Ok(mut entity) = commands.get_entity(trigger.target()) else { + return; + }; + + entity.observe(detect_text_needs_rerender_on_child_removed); +} + +/// Observer system that detects when text blocks get their last child removed and sets +/// `ComputedTextBlock::should_rerender`. +pub fn detect_text_needs_rerender_on_child_removed( + trigger: On, + // `With` included to bail on non-text nodes + mut texts: Query<(&ChildOf, Option<&mut ComputedTextBlock>), With>, +) { + let mut entity = trigger.target(); + let mut computed = loop { + match texts.get_mut(entity) { + // we stop at the first computed text block encountered + Ok((_, Some(computed))) => break computed, + Ok((parent, None)) => entity = parent.0, + Err(_) => { + // This warning is less useful than the one in `detect_text_needs_rerender`, + // we don't know the type name of the root + once!(warn!( + "found entity {} with a TextFont that has no ancestor with a root text \ + component; this warning only prints once", + entity, + )); + return; + } + } + }; + computed.needs_rerender = true; +} diff --git a/crates/bevy_ui/src/lib.rs b/crates/bevy_ui/src/lib.rs index ac70897d06..00512b4f57 100644 --- a/crates/bevy_ui/src/lib.rs +++ b/crates/bevy_ui/src/lib.rs @@ -318,6 +318,7 @@ fn build_text_interop(app: &mut App) { .ambiguous_with(bevy_text::calculate_bounds_text2d), ), ); + app.add_observer(bevy_text::enable_text_node_needs_rerender_detection::); app.add_plugins(accessibility::AccessibilityPlugin);