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:

<img width="800" alt="first_window_label"
src="https://github.com/user-attachments/assets/2eebccba-5749-4064-bb1c-e4f25ff0baf7">

## 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.
This commit is contained in:
ickshonpe 2025-03-10 21:22:14 +00:00 committed by GitHub
parent 683b08fec9
commit a6144e3e5c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 16 additions and 23 deletions

View File

@ -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<ExtractedUiNodes>,
default_ui_camera: Extract<DefaultUiCamera>,
texture_atlases: Extract<Res<Assets<TextureAtlasLayout>>>,
uinode_query: Extract<
Query<(
Entity,
&ComputedNode,
&ComputedNodeTarget,
&GlobalTransform,
&InheritedVisibility,
Option<&CalculatedClip>,
Option<&UiTargetCamera>,
&TextLayoutInfo,
&TextShadow,
)>,
>,
mapping: Extract<Query<RenderEntity>>,
camera_map: Extract<UiCameraMap>,
) {
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;
};

View File

@ -54,16 +54,15 @@ fn setup_scene(mut commands: Commands, asset_server: Res<AssetServer>) {
..default()
};
commands.spawn((
Text::new("First window"),
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()));
}