Repository: bevyengine/bevy
File: crates/bevy_ui_render/src/debug_overlay.rs (Rust)

Code before:

pub fn extract_debug_overlay(
    mut commands: Commands,
    debug_options: Extract<Res<UiDebugOptions>>,
    mut extracted_uinodes: ResMut<ExtractedUiNodes>,
    uinode_query: Extract<
        Query<(
            Entity,
            &ComputedNode,
            &UiGlobalTransform,
            &InheritedVisibility,
            Option<&CalculatedClip>,
            &ComputedUiTargetCamera,
            Option<&UiDebugOptions>,
        )>,
    >,
    ui_stack: Extract<Res<UiStack>>,
    camera_map: Extract<UiCameraMap>,
) {
    let mut camera_mapper = camera_map.get_mapper();

    for (entity, uinode, transform, visibility, maybe_clip, computed_target, debug) in &uinode_query
    {
        let debug_options = debug.unwrap_or(&debug_options);
        if !debug_options.enabled {
            continue;
        }
        if !debug_options.show_hidden && !visibility.get() {
            continue;
        }

        let Some(extracted_camera_entity) = camera_mapper.map(computed_target) else {
            continue;
        };

        let color = debug_options
            .line_color_override
            .unwrap_or_else(|| Hsla::sequential_dispersed(entity.index_u32()).into());
        let z_order = (ui_stack.uinodes.len() as u32 + uinode.stack_index()) as f32;
        let border = BorderRect::all(debug_options.line_width / uinode.inverse_scale_factor());
        let transform = transform.affine();

        let mut push_outline = |rect: Rect, radius: ResolvedBorderRadius| {
            if rect.is_empty() {
                return;
            }

            extracted_uinodes.uinodes.push(ExtractedUiNode {
                render_entity: commands.spawn(TemporaryRenderEntity).id(),
                // Keep all overlays above UI, and nudge each type slightly in Z so ordering is stable.
                z_order,

Review comment (bug):
This will make, in practice, the system look up all the nodes, even if there is no UiDebugOptions Component and the global resource is disabled, which is kind of a loss, but as this is a debug feature, maybe this can be overlooked in this case.

Code after:
        }
    }
}

pub fn extract_debug_overlay(
    mut commands: Commands,
    debug_options: Extract<Res<UiDebugOptions>>,
    mut extracted_uinodes: ResMut<ExtractedUiNodes>,
    uinode_query: Extract<
        Query<(
            Entity,
            &ComputedNode,
            &UiGlobalTransform,
            &InheritedVisibility,
            Option<&CalculatedClip>,
            &ComputedUiTargetCamera,
            Option<&UiDebugOptions>,
        )>,
    >,
    ui_stack: Extract<Res<UiStack>>,
    camera_map: Extract<UiCameraMap>,
) {
    let mut camera_mapper = camera_map.get_mapper();

    for (entity, uinode, transform, visibility, maybe_clip, computed_target, debug) in &uinode_query
    {
        let debug_options = debug.unwrap_or(&debug_options);
        if !debug_options.enabled {
            continue;
        }
        if !debug_options.show_hidden && !visibility.get() {
            continue;
        }

        let Some(extracted_camera_entity) = camera_mapper.map(computed_target) else {
            continue;
        };

        let color = debug_options
            .line_color_override
            .unwrap_or_else(|| Hsla::sequential_dispersed(entity.index_u32()).into());
        let z_order = (ui_stack.uinodes.len() as u32 + uinode.stack_index()) as f32;
        let border = BorderRect::all(debug_options.line_width / uinode.inverse_scale_factor());
        let transform = transform.affine();

        let mut push_outline = |rect: Rect, radius: ResolvedBorderRadius| {
            if rect.is_empty() {
                return;
            }

            extracted_uinodes.uinodes.push(ExtractedUiNode {