bevy/crates/bevy_ui/src
ickshonpe 9930df83ed
UI borders and outlines clipping fix (#16044)
# 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:

<img width="194" alt="clip"
src="https://github.com/user-attachments/assets/2d3f6d28-aa20-44df-967a-677725828294">

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

```rust
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

<img width="149" alt="clipp"
src="https://github.com/user-attachments/assets/19fbd3cc-e7cd-42e1-a5e0-fd92aad04dcd">

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-10-21 22:54:09 +00:00
..
experimental Migrate UI bundles to required components (#15898) 2024-10-17 21:11:02 +00:00
layout Merge Style properties into Node. Use ComputedNode for computed properties. (#15975) 2024-10-18 22:25:33 +00:00
render UI borders and outlines clipping fix (#16044) 2024-10-21 22:54:09 +00:00
widget Merge Style properties into Node. Use ComputedNode for computed properties. (#15975) 2024-10-18 22:25:33 +00:00
accessibility.rs Merge Style properties into Node. Use ComputedNode for computed properties. (#15975) 2024-10-18 22:25:33 +00:00
focus.rs Merge Style properties into Node. Use ComputedNode for computed properties. (#15975) 2024-10-18 22:25:33 +00:00
geometry.rs Merge Style properties into Node. Use ComputedNode for computed properties. (#15975) 2024-10-18 22:25:33 +00:00
lib.rs Optional UI rendering (#8997) 2024-10-19 22:52:33 +00:00
measurement.rs Remove bevy_ui's "bevy_text" feature (#15951) 2024-10-16 16:43:57 +00:00
node_bundles.rs Use en-us locale for typos (#16037) 2024-10-20 18:55:17 +00:00
picking_backend.rs Merge Style properties into Node. Use ComputedNode for computed properties. (#15975) 2024-10-18 22:25:33 +00:00
stack.rs Merge Style properties into Node. Use ComputedNode for computed properties. (#15975) 2024-10-18 22:25:33 +00:00
ui_material.rs Merge Style properties into Node. Use ComputedNode for computed properties. (#15975) 2024-10-18 22:25:33 +00:00
ui_node.rs Merge Style properties into Node. Use ComputedNode for computed properties. (#15975) 2024-10-18 22:25:33 +00:00
update.rs Merge Style properties into Node. Use ComputedNode for computed properties. (#15975) 2024-10-18 22:25:33 +00:00