Skip to content

OverrideClip interaction fix#20064

Merged
alice-i-cecile merged 6 commits into
bevyengine:mainfrom
ickshonpe:ui_clipping_override_picking_fix
Jul 11, 2025
Merged

OverrideClip interaction fix#20064
alice-i-cecile merged 6 commits into
bevyengine:mainfrom
ickshonpe:ui_clipping_override_picking_fix

Conversation

@ickshonpe

@ickshonpe ickshonpe commented Jul 9, 2025

Copy link
Copy Markdown
Contributor

Objective

Picking was changed in the UI transform PR to walk up the tree recursively to check if an interaction was on a clipped node. OverrideClip only affects a node's local clipping rect, so valid interactions can be ignored if a node has clipped ancestors.

Solution

Add a Without<OverrideClip> query filter to the picking systems' child_of_querys.

Testing

This modified button example can be used to test the change:

//! This example illustrates how to create a button that changes color and text based on its
//! interaction state.

use bevy::{color::palettes::basic::*, input_focus::InputFocus, prelude::*, winit::WinitSettings};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        // Only run the app when there is user input. This will significantly reduce CPU/GPU use.
        .insert_resource(WinitSettings::desktop_app())
        // `InputFocus` must be set for accessibility to recognize the button.
        .init_resource::<InputFocus>()
        .add_systems(Startup, setup)
        .add_systems(Update, button_system)
        .run();
}

const NORMAL_BUTTON: Color = Color::srgb(0.15, 0.15, 0.15);
const HOVERED_BUTTON: Color = Color::srgb(0.25, 0.25, 0.25);
const PRESSED_BUTTON: Color = Color::srgb(0.35, 0.75, 0.35);

fn button_system(
    mut input_focus: ResMut<InputFocus>,
    mut interaction_query: Query<
        (
            Entity,
            &Interaction,
            &mut BackgroundColor,
            &mut BorderColor,
            &mut Button,
            &Children,
        ),
        Changed<Interaction>,
    >,
    mut text_query: Query<&mut Text>,
) {
    for (entity, interaction, mut color, mut border_color, mut button, children) in
        &mut interaction_query
    {
        let mut text = text_query.get_mut(children[0]).unwrap();

        match *interaction {
            Interaction::Pressed => {
                input_focus.set(entity);
                **text = "Press".to_string();
                *color = PRESSED_BUTTON.into();
                *border_color = BorderColor::all(RED.into());

                // The accessibility system's only update the button's state when the `Button` component is marked as changed.
                button.set_changed();
            }
            Interaction::Hovered => {
                input_focus.set(entity);
                **text = "Hover".to_string();
                *color = HOVERED_BUTTON.into();
                *border_color = BorderColor::all(Color::WHITE);
                button.set_changed();
            }
            Interaction::None => {
                input_focus.clear();
                **text = "Button".to_string();
                *color = NORMAL_BUTTON.into();
                *border_color = BorderColor::all(Color::BLACK);
            }
        }
    }
}

fn setup(mut commands: Commands, assets: Res<AssetServer>) {
    // ui camera
    commands.spawn(Camera2d);
    commands.spawn(button(&assets));
}

fn button(asset_server: &AssetServer) -> impl Bundle + use<> {
    (
        Node {
            width: Val::Percent(100.0),
            height: Val::Percent(100.0),
            align_items: AlignItems::Center,
            justify_content: JustifyContent::Center,
            ..default()
        },
        children![(
            Node {
                width: Val::Px(0.),
                height: Val::Px(0.),
                overflow: Overflow::clip(),
                ..default()
            },
            children![(
                //OverrideClip,
                Button,
                Node {
                    position_type: PositionType::Absolute,
                    width: Val::Px(150.0),
                    height: Val::Px(65.0),
                    border: UiRect::all(Val::Px(5.0)),
                    // horizontally center child text
                    justify_content: JustifyContent::Center,
                    // vertically center child text
                    align_items: AlignItems::Center,
                    ..default()
                },
                BorderColor::all(Color::WHITE),
                BorderRadius::MAX,
                BackgroundColor(Color::BLACK),
                children![(
                    Text::new("Button"),
                    TextFont {
                        font: asset_server.load("fonts/FiraSans-Bold.ttf"),
                        font_size: 33.0,
                        ..default()
                    },
                    TextColor(Color::srgb(0.9, 0.9, 0.9)),
                    TextShadow::default(),
                )]
            )],
        )],
    )
}

On main the button ignores interactions, with this PR it should respond correctly.

ickshonpe added 2 commits July 9, 2025 17:29
…`child_of_query`s.

Interactions were changed in the UI transform PR to walk up the tree recursively to check if the interaction hit a visible node. `OverrideClip` only affects the node's local clipping rect, so without this filter interactions can be incorrectly ignored if a node has clipped ancestors.
@ickshonpe ickshonpe added C-Bug An unexpected or incorrect behavior A-UI Graphical user interfaces, styles, layouts, and widgets D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Needs-Review Needs reviewer attention (from anyone!) to move forward A-Picking Pointing at and selecting objects of all sorts labels Jul 9, 2025
@alice-i-cecile alice-i-cecile added this to the 0.17 milestone Jul 9, 2025
Comment thread crates/bevy_ui/src/focus.rs Outdated
@ickshonpe ickshonpe added S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Jul 9, 2025
@alice-i-cecile
alice-i-cecile added this pull request to the merge queue Jul 11, 2025
Merged via the queue into bevyengine:main with commit df5dfcd Jul 11, 2025
34 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Picking Pointing at and selecting objects of all sorts A-UI Graphical user interfaces, styles, layouts, and widgets C-Bug An unexpected or incorrect behavior D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants