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

Overflow clip margin #15561

Merged
merged 66 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
bcabdbf
Taffy returns border values now, so there is no need to compute them …
ickshonpe Sep 10, 2024
c74c0cf
Merge branch 'main' into compute-borders-in-layout
ickshonpe Sep 10, 2024
266fafc
Fixed ui_material_pipeline's border normalization
ickshonpe Sep 10, 2024
bc67d38
removed unused imports
ickshonpe Sep 10, 2024
bfea0c9
Fixed border scalings.
ickshonpe Sep 10, 2024
18bb3fd
Removed unused imports
ickshonpe Sep 10, 2024
4a6b475
Removed unneed attribute.
ickshonpe Sep 10, 2024
ceefb43
removed border radius scaling
ickshonpe Sep 10, 2024
5512508
scale border radius Px values
ickshonpe Sep 10, 2024
a76f7eb
remove more scalings
ickshonpe Sep 10, 2024
ce8006e
`Node` contains logical coords, not physical.
ickshonpe Sep 10, 2024
5d99685
Cleanup.
ickshonpe Sep 11, 2024
eefc23d
Removed the `Inset` type, use a `BorderRect` to hold the resolved bor…
ickshonpe Sep 11, 2024
a31a987
added a `ZERO` const to `BorderRect`
ickshonpe Sep 11, 2024
237fd80
Use `BorderRect` in layout updates
ickshonpe Sep 11, 2024
f8b79cd
Removed old border extraction code
ickshonpe Sep 11, 2024
86aa524
clean up unused
ickshonpe Sep 11, 2024
8e35831
removed `logical_rect` method from `Node`
ickshonpe Sep 11, 2024
62d1c06
Removed unused import
ickshonpe Sep 11, 2024
d687217
improved corner radius visualization
ickshonpe Sep 11, 2024
4c31adf
Fixed `ExtractedUiNode` doc errors
ickshonpe Sep 11, 2024
334d361
removed unneeded import
ickshonpe Sep 11, 2024
789c4de
Removed doc link to private item.
ickshonpe Sep 11, 2024
c696763
Update crates/bevy_ui/src/render/ui.wgsl
ickshonpe Sep 25, 2024
f012b66
Added `outlined_node_size` method.
ickshonpe Sep 25, 2024
9d3b761
Fixed extracted image node border values
ickshonpe Sep 25, 2024
0001986
Added some non-uniform border-radius to the borders example.
ickshonpe Sep 25, 2024
1ce5bfe
Reverted shader changes
ickshonpe Sep 25, 2024
0312753
Merge branch 'main' into update-borders-in-layout
ickshonpe Sep 25, 2024
84e0a07
Fix up imports
ickshonpe Sep 25, 2024
2b78765
Fix up imports
ickshonpe Sep 25, 2024
2be7403
use `outlined_node_size` method in extaction
ickshonpe Sep 25, 2024
7cebb61
Merge branch 'update-borders-in-layout' of https://github.com/ickshon…
ickshonpe Sep 25, 2024
2878b24
Set outline width to zero width for uinodes with `Display::None` set.
ickshonpe Sep 25, 2024
68f1478
Added padding field and accessor method to `Node`
ickshonpe Sep 26, 2024
1419830
copy padding values to nodes in `ui_layout_system`
ickshonpe Sep 26, 2024
c33150a
fixed `Node::DEFAULT`
ickshonpe Sep 26, 2024
ff258e9
Added `content_inset` method to `Node`, returns the sum of the border…
ickshonpe Sep 26, 2024
d4bacbc
Fixed `content_inset` calculations
ickshonpe Sep 26, 2024
1091755
changed `update_clipping` to clip around the content box instead of t…
ickshonpe Sep 26, 2024
551f208
Added borders to the overflow example.
ickshonpe Sep 26, 2024
ec41f95
Removed ui scaling from example
ickshonpe Sep 26, 2024
fb9dfce
Merge branch 'main' into clip-inside-padding-box
ickshonpe Sep 27, 2024
2a1bad4
Merge branch 'main' into clip-inside-padding-box
ickshonpe Sep 30, 2024
508238d
Added `OverflowClipMargin` and `OverflowClipBox` types
ickshonpe Oct 1, 2024
981c3d2
Added const `DEFAULT` for `OverflowClipMargin`
ickshonpe Oct 1, 2024
4b5655e
Added `overflow_clip_margin: OverflowClipMargin` field to `Style`.
ickshonpe Oct 1, 2024
c55c9bf
Changed `margin` field to an `f32` value
ickshonpe Oct 1, 2024
75f70af
Implemented new clipping.
ickshonpe Oct 1, 2024
09694d6
Added const constructors for `OverflowClipMargin`
ickshonpe Oct 1, 2024
e3832f0
Fixed constructor functions
ickshonpe Oct 1, 2024
47a3c71
Fixed clip rect margins
ickshonpe Oct 1, 2024
5d55bd2
Added `overflow_clip_margin` example
ickshonpe Oct 1, 2024
6318ab9
Added example to cargo and readme
ickshonpe Oct 1, 2024
d7a9de3
updated comments
ickshonpe Oct 1, 2024
7c06252
cargo run -p build-templated-pages -- update examples
ickshonpe Oct 1, 2024
02f4b92
Fixed test
ickshonpe Oct 1, 2024
bdffd80
Merge branch 'main' into overflow-clip-margin
ickshonpe Oct 14, 2024
e94b2f0
Updated the example to the support new text api.
ickshonpe Oct 14, 2024
1f44f3b
Replaced the `margin` parameter on the associated constructor functio…
ickshonpe Oct 14, 2024
788a1e2
Replaced the `margin` parameter on the associated constructor functio…
ickshonpe Oct 14, 2024
08247b3
Merge branch 'overflow-clip-margin' of https://github.com/ickshonpe/b…
ickshonpe Oct 14, 2024
b543ada
Merge branch 'main' into overflow-clip-margin
ickshonpe Oct 14, 2024
0c229ab
Merge branch 'main' into overflow-clip-margin
ickshonpe Oct 15, 2024
5727af5
Merge branch 'main' into overflow-clip-margin
ickshonpe Oct 16, 2024
417760a
Updated comments.
ickshonpe Oct 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Taffy returns border values now, so there is no need to compute them …
…ourselves in each extraction function which is really complicated and fragile and has lead to a number of bugs.

Adds an `Inset` type, a `border: Inset` field to `Node`, updates the border field in `ui_layout_system`, and removes the border calculations and extra queries from the extraction functions.
  • Loading branch information
ickshonpe committed Sep 10, 2024
commit bcabdbff8afcdabaaccbbcfdfd16bfe4c93dde99
9 changes: 8 additions & 1 deletion crates/bevy_ui/src/layout/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
BorderRadius, ContentSize, DefaultUiCamera, Node, Outline, Style, TargetCamera, UiScale,
BorderRadius, ContentSize, DefaultUiCamera, Inset, Node, Outline, Style, TargetCamera, UiScale,
};
use bevy_ecs::{
change_detection::{DetectChanges, DetectChangesMut},
Expand Down Expand Up @@ -323,6 +323,13 @@ pub fn ui_layout_system(
node.unrounded_size = layout_size;
}

node.bypass_change_detection().border = Inset {
left: layout.border.left * inverse_target_scale_factor,
right: layout.border.right * inverse_target_scale_factor,
top: layout.border.top * inverse_target_scale_factor,
bottom: layout.border.bottom * inverse_target_scale_factor,
};

let viewport_size = root_size.unwrap_or(node.calculated_size);

if let Some(border_radius) = maybe_border_radius {
Expand Down
130 changes: 25 additions & 105 deletions crates/bevy_ui/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ pub struct ExtractedUiNodes {

pub fn extract_uinode_background_colors(
mut extracted_uinodes: ResMut<ExtractedUiNodes>,
camera_query: Extract<Query<(Entity, &Camera)>>,
default_ui_camera: Extract<DefaultUiCamera>,
ui_scale: Extract<Res<UiScale>>,
uinode_query: Extract<
Expand All @@ -201,23 +200,11 @@ pub fn extract_uinode_background_colors(
Option<&CalculatedClip>,
Option<&TargetCamera>,
&BackgroundColor,
&Style,
Option<&Parent>,
)>,
>,
node_query: Extract<Query<&Node>>,
) {
for (
entity,
uinode,
transform,
view_visibility,
clip,
camera,
background_color,
style,
parent,
) in &uinode_query
for (entity, uinode, transform, view_visibility, clip, camera, background_color) in
&uinode_query
{
let Some(camera_entity) = camera.map(TargetCamera::entity).or(default_ui_camera.get())
else {
Expand All @@ -229,31 +216,13 @@ pub fn extract_uinode_background_colors(
continue;
}

let ui_logical_viewport_size = camera_query
.get(camera_entity)
.ok()
.and_then(|(_, c)| c.logical_viewport_size())
.unwrap_or(Vec2::ZERO)
// The logical window resolution returned by `Window` only takes into account the window scale factor and not `UiScale`,
// so we have to divide by `UiScale` to get the size of the UI viewport.
/ ui_scale.0;

// Both vertical and horizontal percentage border values are calculated based on the width of the parent node
// <https://developer.mozilla.org/en-US/docs/Web/CSS/border-width>
let parent_width = parent
.and_then(|parent| node_query.get(parent.get()).ok())
.map(|parent_node| parent_node.size().x)
.unwrap_or(ui_logical_viewport_size.x);
let left =
resolve_border_thickness(style.border.left, parent_width, ui_logical_viewport_size);
let right =
resolve_border_thickness(style.border.right, parent_width, ui_logical_viewport_size);
let top =
resolve_border_thickness(style.border.top, parent_width, ui_logical_viewport_size);
let bottom =
resolve_border_thickness(style.border.bottom, parent_width, ui_logical_viewport_size);

let border = [left, top, right, bottom];
let border = [
uinode.border.left,
uinode.border.top,
uinode.border.right,
uinode.border.bottom,
]
.map(|b| b * ui_scale.0);

let border_radius = [
uinode.border_radius.top_left,
Expand Down Expand Up @@ -291,7 +260,6 @@ pub fn extract_uinode_background_colors(
pub fn extract_uinode_images(
mut commands: Commands,
mut extracted_uinodes: ResMut<ExtractedUiNodes>,
camera_query: Extract<Query<(Entity, &Camera)>>,
texture_atlases: Extract<Res<Assets<TextureAtlasLayout>>>,
ui_scale: Extract<Res<UiScale>>,
default_ui_camera: Extract<DefaultUiCamera>,
Expand All @@ -305,17 +273,12 @@ pub fn extract_uinode_images(
Option<&TargetCamera>,
&UiImage,
Option<&TextureAtlas>,
Option<&Parent>,
&Style,
),
Without<ImageScaleMode>,
>,
>,
node_query: Extract<Query<&Node>>,
) {
for (uinode, transform, view_visibility, clip, camera, image, atlas, parent, style) in
&uinode_query
{
for (uinode, transform, view_visibility, clip, camera, image, atlas) in &uinode_query {
let Some(camera_entity) = camera.map(TargetCamera::entity).or(default_ui_camera.get())
else {
continue;
Expand Down Expand Up @@ -356,31 +319,13 @@ pub fn extract_uinode_images(
None
};

let ui_logical_viewport_size = camera_query
.get(camera_entity)
.ok()
.and_then(|(_, c)| c.logical_viewport_size())
.unwrap_or(Vec2::ZERO)
// The logical window resolution returned by `Window` only takes into account the window scale factor and not `UiScale`,
// so we have to divide by `UiScale` to get the size of the UI viewport.
/ ui_scale.0;

// Both vertical and horizontal percentage border values are calculated based on the width of the parent node
// <https://developer.mozilla.org/en-US/docs/Web/CSS/border-width>
let parent_width = parent
.and_then(|parent| node_query.get(parent.get()).ok())
.map(|parent_node| parent_node.size().x)
.unwrap_or(ui_logical_viewport_size.x);
let left =
resolve_border_thickness(style.border.left, parent_width, ui_logical_viewport_size);
let right =
resolve_border_thickness(style.border.right, parent_width, ui_logical_viewport_size);
let top =
resolve_border_thickness(style.border.top, parent_width, ui_logical_viewport_size);
let bottom =
resolve_border_thickness(style.border.bottom, parent_width, ui_logical_viewport_size);

let border = [left, top, right, bottom];
let border = [
uinode.border.left,
uinode.border.top,
uinode.border.right,
uinode.border.bottom,
]
.map(|b| b * ui_scale.0);

let border_radius = [
uinode.border_radius.top_left,
Expand Down Expand Up @@ -448,7 +393,6 @@ fn clamp_radius(
pub fn extract_uinode_borders(
mut commands: Commands,
mut extracted_uinodes: ResMut<ExtractedUiNodes>,
camera_query: Extract<Query<(Entity, &Camera)>>,
default_ui_camera: Extract<DefaultUiCamera>,
ui_scale: Extract<Res<UiScale>>,
uinode_query: Extract<
Expand All @@ -458,12 +402,9 @@ pub fn extract_uinode_borders(
&ViewVisibility,
Option<&CalculatedClip>,
Option<&TargetCamera>,
Option<&Parent>,
&Style,
AnyOf<(&BorderColor, &Outline)>,
)>,
>,
node_query: Extract<Query<&Node>>,
) {
let image = AssetId::<Image>::default();

Expand All @@ -473,8 +414,6 @@ pub fn extract_uinode_borders(
view_visibility,
maybe_clip,
maybe_camera,
maybe_parent,
style,
(maybe_border_color, maybe_outline),
) in &uinode_query
{
Expand All @@ -487,38 +426,19 @@ pub fn extract_uinode_borders(

// Skip invisible borders
if !view_visibility.get()
|| style.display == Display::None
|| maybe_border_color.is_some_and(|border_color| border_color.0.is_fully_transparent())
&& maybe_outline.is_some_and(|outline| outline.color.is_fully_transparent())
{
continue;
}

let ui_logical_viewport_size = camera_query
.get(camera_entity)
.ok()
.and_then(|(_, c)| c.logical_viewport_size())
.unwrap_or(Vec2::ZERO)
// The logical window resolution returned by `Window` only takes into account the window scale factor and not `UiScale`,
// so we have to divide by `UiScale` to get the size of the UI viewport.
/ ui_scale.0;

// Both vertical and horizontal percentage border values are calculated based on the width of the parent node
// <https://developer.mozilla.org/en-US/docs/Web/CSS/border-width>
let parent_width = maybe_parent
.and_then(|parent| node_query.get(parent.get()).ok())
.map(|parent_node| parent_node.size().x)
.unwrap_or(ui_logical_viewport_size.x);
let left =
resolve_border_thickness(style.border.left, parent_width, ui_logical_viewport_size);
let right =
resolve_border_thickness(style.border.right, parent_width, ui_logical_viewport_size);
let top =
resolve_border_thickness(style.border.top, parent_width, ui_logical_viewport_size);
let bottom =
resolve_border_thickness(style.border.bottom, parent_width, ui_logical_viewport_size);

let border = [left, top, right, bottom];
let border = [
uinode.border.left,
uinode.border.top,
uinode.border.right,
uinode.border.bottom,
]
.map(|b| b * ui_scale.0);

let border_radius = [
uinode.border_radius.top_left,
Expand All @@ -531,7 +451,7 @@ pub fn extract_uinode_borders(
let border_radius = clamp_radius(border_radius, uinode.size(), border.into());

// don't extract border if no border or the node is zero-sized (a zero sized node can still have an outline).
if !uinode.is_empty() && border != [0.; 4] {
if !uinode.is_empty() && !border.is_empty() {
if let Some(border_color) = maybe_border_color {
extracted_uinodes.uinodes.insert(
commands.spawn_empty().id(),
Expand Down
32 changes: 31 additions & 1 deletion crates/bevy_ui/src/ui_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ pub struct Node {
///
/// Automatically calculated by [`super::layout::ui_layout_system`].
pub(crate) unrounded_size: Vec2,
/// Resolved border values in logical pixels
/// Border updates bypass change detection.
///
/// Automatically calculated by [`super::layout::ui_layout_system`].
pub(crate) border: Inset,
/// Resolved border radius values in logical pixels.
/// Border radius updates bypass change detection.
///
Expand Down Expand Up @@ -141,6 +146,7 @@ impl Node {
outline_offset: 0.,
unrounded_size: Vec2::ZERO,
border_radius: ResolvedBorderRadius::ZERO,
border: Inset::ZERO,
};
}

Expand Down Expand Up @@ -2249,7 +2255,7 @@ impl BorderRadius {
/// Represents the resolved border radius values for a UI node.
///
/// The values are in logical pixels.
#[derive(Copy, Clone, Debug, PartialEq, Reflect)]
#[derive(Copy, Clone, Debug, Default, PartialEq, Reflect)]
pub struct ResolvedBorderRadius {
pub top_left: f32,
pub top_right: f32,
Expand All @@ -2266,6 +2272,30 @@ impl ResolvedBorderRadius {
};
}

/// Represents the space or inset from the left, right, top, and bottom edges within a rectangle.
///
/// The values are in logical pixels.
#[derive(Copy, Clone, Debug, Default, PartialEq, Reflect)]
pub struct Inset {
pub left: f32,
pub right: f32,
pub top: f32,
pub bottom: f32,
}

impl Inset {
pub fn is_empty(&self) -> bool {
*self == Self::ZERO
}

pub const ZERO: Self = Self {
left: 0.,
right: 0.,
top: 0.,
bottom: 0.,
};
}

#[cfg(test)]
mod tests {
use crate::GridPlacement;
Expand Down