Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI borders and outlines clipping fix #16044

Merged

Conversation

ickshonpe
Copy link
Contributor

@ickshonpe ickshonpe commented Oct 21, 2024

Objective

fixes #15502

Clipped borders and outlines aren't drawn correctly.

Borders aren't clipped

Spawn two nodes with the same dimensions and border thickness, but clip on of the nodes so that only its top left quarter is visible:

clip

You can see that instead of clipping the border, instead the border is scaled to fit inside of the unclipped section.

use bevy::color::palettes::css::BLUE;
use bevy::prelude::*;
use bevy::winit::WinitSettings;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .insert_resource(WinitSettings::desktop_app())
        .add_systems(Startup, setup)
        .run();
}

fn setup(mut commands: Commands) {
    commands.spawn(Camera2d);
    commands
        .spawn(Node {
            width: Val::Percent(100.),
            height: Val::Percent(100.),
            justify_content: JustifyContent::Center,
            align_items: AlignItems::Center,
            ..Default::default()
        })
        .with_children(|commands| {
            commands
                .spawn(Node {
                    column_gap: Val::Px(10.),
                    ..Default::default()
                })
                .with_children(|commands| {
                    commands
                        .spawn(Node {
                            width: Val::Px(100.),
                            height: Val::Px(100.),
                            overflow: Overflow::clip(),
                            ..Default::default()
                        })
                        .with_child((
                            Node {
                                position_type: PositionType::Absolute,
                                width: Val::Px(100.),
                                height: Val::Px(100.),
                                border: UiRect::all(Val::Px(10.)),
                                ..Default::default()
                            },
                            BackgroundColor(Color::WHITE),
                            BorderColor(BLUE.into()),
                        ));

                    commands
                        .spawn(Node {
                            width: Val::Px(50.),
                            height: Val::Px(50.),
                            overflow: Overflow::clip(),
                            ..Default::default()
                        })
                        .with_child((
                            Node {
                                position_type: PositionType::Absolute,
                                width: Val::Px(100.),
                                height: Val::Px(100.),
                                border: UiRect::all(Val::Px(10.)),
                                ..Default::default()
                            },
                            BackgroundColor(Color::WHITE),
                            BorderColor(BLUE.into()),
                        ));
                });
        });
}

You can also see this problem in the overflow example. If you hover over any of the clipped nodes you'll see that the outline only wraps the visible section of the node

Outlines are clipped incorrectly

A UI nodes Outline's are drawn outside of its bounds, so applying the local clipping rect to the outline doesn't make any sense.
Instead an Outline should be clipped using its parent's clipping rect.

Solution

  • Pass the point value into the vertex shader instead of calculating it in the shader.
  • In extract_uinode_borders use the parents clipping rect when clipping outlines.

The extra parameter isn't a great solution I think, but I wanted to fix borders for the 0.15 release and this is the most minimal approach I could think of without replacing the whole shader and prepare function.

Showcase

clipp

@ickshonpe ickshonpe changed the title UI bordering and outlines clipping fix UI borders and outlines clipping fix Oct 21, 2024
@ickshonpe ickshonpe added A-UI Graphical user interfaces, styles, layouts, and widgets A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior labels Oct 21, 2024
@ickshonpe
Copy link
Contributor Author

I'll update the docs for the new paramater in a few hours, got some errands I need to run.

@ickshonpe ickshonpe added the S-Needs-Review Needs reviewer attention (from anyone!) to move forward label Oct 21, 2024
@alice-i-cecile alice-i-cecile added this to the 0.15 milestone Oct 21, 2024
@alice-i-cecile alice-i-cecile added S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Oct 21, 2024
@ickshonpe ickshonpe removed the S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged label Oct 21, 2024
@alice-i-cecile alice-i-cecile added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label Oct 21, 2024
@alice-i-cecile alice-i-cecile added this pull request to the merge queue Oct 21, 2024
Merged via the queue into bevyengine:main with commit 9930df8 Oct 21, 2024
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Rendering Drawing game state to the screen A-UI Graphical user interfaces, styles, layouts, and widgets C-Bug An unexpected or incorrect behavior S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

Border / radius doesn't respect full Node size.
4 participants