bevy/crates
ickshonpe 6231ed02dd
Ignore clicks on uinodes outside of rounded corners (#14957)
Fixes #14941

1. Add a `resolved_border_radius` field to `Node` to hold the resolved
border radius values.
2. Remove the border radius calculations from the UI's extraction
functions.
4. Compute the border radius during UI relayouts in `ui_layout_system`
and store them in `Node`.
5. New `pick_rounded_rect` function based on the border radius SDF from
`ui.wgsl`.
6. Use `pick_rounded_rect` in `focus` and `picking_backend` to check if
the pointer is hovering UI nodes with rounded corners.
---

```
cargo run --example button
```

https://github.com/user-attachments/assets/ea951a64-17ef-455e-b5c9-a2e6f6360648

Modified button example with buttons with different corner radius:

```
use bevy::{color::palettes::basic::*, 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())
        .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 interaction_query: Query<
        (
            &Interaction,
            &mut BackgroundColor,
            &mut BorderColor,
            &Children,
        ),
        (Changed<Interaction>, With<Button>),
    >,
    mut text_query: Query<&mut Text>,
) {
    for (interaction, mut color, mut border_color, children) in &mut interaction_query {
        let mut text = text_query.get_mut(children[0]).unwrap();
        match *interaction {
            Interaction::Pressed => {
                text.sections[0].value = "Press".to_string();
                *color = PRESSED_BUTTON.into();
                border_color.0 = RED.into();
            }
            Interaction::Hovered => {
                text.sections[0].value = "Hover".to_string();
                *color = HOVERED_BUTTON.into();
                border_color.0 = Color::WHITE;
            }
            Interaction::None => {
                text.sections[0].value = "Button".to_string();
                *color = NORMAL_BUTTON.into();
                border_color.0 = Color::BLACK;
            }
        }
    }
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    // ui camera
    commands.spawn(Camera2dBundle::default());
    commands
        .spawn(NodeBundle {
            style: Style {
                width: Val::Percent(100.0),
                height: Val::Percent(100.0),
                align_items: AlignItems::Center,
                justify_content: JustifyContent::Center,
                row_gap: Val::Px(10.),
                ..default()
            },
            ..default()
        })
        .with_children(|parent| {
            for border_radius in [
                BorderRadius {
                    top_left: Val::ZERO,
                    ..BorderRadius::MAX
                },
                BorderRadius {
                    top_right: Val::ZERO,
                    ..BorderRadius::MAX
                },
                BorderRadius {
                    bottom_right: Val::ZERO,
                    ..BorderRadius::MAX
                },
                BorderRadius {
                    bottom_left: Val::ZERO,
                    ..BorderRadius::MAX
                },
            ] {
                parent
                    .spawn(ButtonBundle {
                        style: Style {
                            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()
                        },
                        border_color: BorderColor(Color::BLACK),
                        border_radius,
                        background_color: NORMAL_BUTTON.into(),
                        ..default()
                    })
                    .with_child(TextBundle::from_section(
                        "Button",
                        TextStyle {
                            font: asset_server.load("fonts/FiraSans-Bold.ttf"),
                            font_size: 40.0,
                            color: Color::srgb(0.9, 0.9, 0.9),
                        },
                    ));
            }
        });
}
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Matty <weatherleymatthew@gmail.com>
2024-09-05 22:01:05 +02:00
..
bevy_a11y Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_animation Don't require going through bevy_animation::prelude to get to certain items in bevy_animation (#14979) 2024-09-05 21:35:40 +02:00
bevy_app Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_asset Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_audio Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_color Fix hue mixing for Lcha and Oklcha (#14468) 2024-09-05 21:34:05 +02:00
bevy_core Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_core_pipeline Fix TAA on camera with viewport (#14582) 2024-09-05 21:35:40 +02:00
bevy_derive Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_dev_tools Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_diagnostic Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_dylib Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_dynamic_plugin Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_ecs Fix commands not being Send / Sync in 0.14 (#14392) 2024-09-05 21:35:40 +02:00
bevy_encase_derive Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_gilrs Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_gizmos Fix Gizmo joint rendering in webgpu (#14721) 2024-09-05 21:35:40 +02:00
bevy_gltf Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_hierarchy Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_input Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_internal Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_log Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_macro_utils Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_math Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_mikktspace Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_pbr Don’t prepare lights (and shadow map textures) for 2D cameras (#14574) 2024-09-05 21:34:05 +02:00
bevy_ptr Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_reflect Making DynamicEnum::is_dynamic() return true (#14732) 2024-09-05 21:35:40 +02:00
bevy_render Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_scene Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_sprite Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_state Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_tasks Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_text Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_time Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_transform Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_ui Ignore clicks on uinodes outside of rounded corners (#14957) 2024-09-05 22:01:05 +02:00
bevy_utils Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_window Release 0.14.1 2024-08-02 20:35:38 +02:00
bevy_winit Release 0.14.1 2024-08-02 20:35:38 +02:00