From a6144e3e5cad6acef7b677c85d7fb38a9d655778 Mon Sep 17 00:00:00 2001 From: ickshonpe Date: Mon, 10 Mar 2025 21:22:14 +0000 Subject: [PATCH] `extract_text_shadows` camera query fix (#17930) # Objective `extract_text_shadows` was still using `UiTargetCamera` and `DefaultUiCamera` for UI camera resolution, which no longer always selects the right camera. To see this modify the last lines of the `multiple_windows` example from: ```rust commands.spawn(( Text::new("First window"), node.clone(), // Since we are using multiple cameras, we need to specify which camera UI should be rendered to UiTargetCamera(first_window_camera), )); commands.spawn(( Text::new("Second window"), node, UiTargetCamera(second_window_camera), )); ``` to: ```rust commands .spawn(( node.clone(), // Since we are using multiple cameras, we need to specify which camera UI should be rendered to UiTargetCamera(first_window_camera), )) .with_child((Text::new("First window"), TextShadow::default())); commands .spawn((node, UiTargetCamera(second_window_camera))) .with_child((Text::new("Second window"), TextShadow::default())); ``` which results in the shadow that is meant to be displayed for the "Second Window" label instead being written over the first: first_window_label ## Solution Remove the `UiTargetCamera` query and the `default_camera` parameter from `extract_text_shadows` and use `UiCameraMap` with `ComputedNodeTarget` instead. ## Testing The `multiple_windows` example for this PR has been updated to add text shadow to the window labels. You should see that it displays the "Second Window" label's shadow correctly now. --- crates/bevy_ui/src/render/mod.rs | 18 ++++++------------ examples/window/multiple_windows.rs | 21 ++++++++++----------- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index 04b0835196..3c0e353f03 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -10,8 +10,7 @@ mod debug_overlay; use crate::widget::ImageNode; use crate::{ BackgroundColor, BorderColor, BoxShadowSamples, CalculatedClip, ComputedNode, - ComputedNodeTarget, DefaultUiCamera, Outline, ResolvedBorderRadius, TextShadow, UiAntiAlias, - UiTargetCamera, + ComputedNodeTarget, Outline, ResolvedBorderRadius, TextShadow, UiAntiAlias, }; use bevy_app::prelude::*; use bevy_asset::{load_internal_asset, weak_handle, AssetEvent, AssetId, Assets, Handle}; @@ -794,47 +793,42 @@ pub fn extract_text_sections( pub fn extract_text_shadows( mut commands: Commands, mut extracted_uinodes: ResMut, - default_ui_camera: Extract, texture_atlases: Extract>>, uinode_query: Extract< Query<( Entity, &ComputedNode, + &ComputedNodeTarget, &GlobalTransform, &InheritedVisibility, Option<&CalculatedClip>, - Option<&UiTargetCamera>, &TextLayoutInfo, &TextShadow, )>, >, - mapping: Extract>, + camera_map: Extract, ) { let mut start = extracted_uinodes.glyphs.len(); let mut end = start + 1; - let default_ui_camera = default_ui_camera.get(); + let mut camera_mapper = camera_map.get_mapper(); for ( entity, uinode, + target, global_transform, inherited_visibility, clip, - camera, text_layout_info, shadow, ) in &uinode_query { - let Some(camera_entity) = camera.map(UiTargetCamera::entity).or(default_ui_camera) else { - continue; - }; - // Skip if not visible or if size is set to zero (e.g. when a parent is set to `Display::None`) if !inherited_visibility.get() || uinode.is_empty() { continue; } - let Ok(extracted_camera_entity) = mapping.get(camera_entity) else { + let Some(extracted_camera_entity) = camera_mapper.map(target) else { continue; }; diff --git a/examples/window/multiple_windows.rs b/examples/window/multiple_windows.rs index 8a0b3bee93..431e1b5de2 100644 --- a/examples/window/multiple_windows.rs +++ b/examples/window/multiple_windows.rs @@ -54,16 +54,15 @@ fn setup_scene(mut commands: Commands, asset_server: Res) { ..default() }; - commands.spawn(( - Text::new("First window"), - node.clone(), - // Since we are using multiple cameras, we need to specify which camera UI should be rendered to - UiTargetCamera(first_window_camera), - )); + commands + .spawn(( + node.clone(), + // Since we are using multiple cameras, we need to specify which camera UI should be rendered to + UiTargetCamera(first_window_camera), + )) + .with_child((Text::new("First window"), TextShadow::default())); - commands.spawn(( - Text::new("Second window"), - node, - UiTargetCamera(second_window_camera), - )); + commands + .spawn((node, UiTargetCamera(second_window_camera))) + .with_child((Text::new("Second window"), TextShadow::default())); }