Skip to content

Commit

Permalink
make update_uinode_geometry_recursive slightly more readable, remove …
Browse files Browse the repository at this point in the history
…vestigial branch
  • Loading branch information
Piefayth committed Sep 20, 2024
1 parent d9db2af commit 2565183
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 135 deletions.
249 changes: 115 additions & 134 deletions crates/bevy_ui/src/layout/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,163 +311,144 @@ pub fn ui_layout_system(
parent_scroll_position: Vec2,
mut absolute_location: Vec2,
) -> Vec2 {
if let Ok((
let Ok((
mut node,
mut transform,
style,
maybe_border_radius,
maybe_outline,
maybe_scroll_position,
)) = node_transform_query.get_mut(entity)
{
let overflow = style.overflow;

let Ok(layout) = ui_surface.get_layout(entity) else {
return Vec2::ZERO;
};
let layout_size =
inverse_target_scale_factor * Vec2::new(layout.size.width, layout.size.height);
let layout_location =
inverse_target_scale_factor * Vec2::new(layout.location.x, layout.location.y);
else {
return Vec2::ZERO;
};

absolute_location += layout_location;
let Ok(layout) = ui_surface.get_layout(entity) else {
return Vec2::ZERO;
};

let rounded_size = approx_round_layout_coords(absolute_location + layout_size)
- approx_round_layout_coords(absolute_location);
let layout_size =
inverse_target_scale_factor * Vec2::new(layout.size.width, layout.size.height);
let layout_location =
inverse_target_scale_factor * Vec2::new(layout.location.x, layout.location.y);

let rounded_location =
approx_round_layout_coords(layout_location - parent_scroll_position)
+ 0.5 * (rounded_size - parent_size);
absolute_location += layout_location;

// only trigger change detection when the new values are different
if node.calculated_size != rounded_size || node.unrounded_size != layout_size {
node.calculated_size = rounded_size;
node.unrounded_size = layout_size;
}
let rounded_size = approx_round_layout_coords(absolute_location + layout_size)
- approx_round_layout_coords(absolute_location);

let viewport_size = root_size.unwrap_or(node.calculated_size);
let rounded_location = approx_round_layout_coords(layout_location - parent_scroll_position)
+ 0.5 * (rounded_size - parent_size);

if let Some(border_radius) = maybe_border_radius {
// We don't trigger change detection for changes to border radius
node.bypass_change_detection().border_radius =
border_radius.resolve(node.calculated_size, viewport_size);
}
// only trigger change detection when the new values are different
if node.calculated_size != rounded_size || node.unrounded_size != layout_size {
node.calculated_size = rounded_size;
node.unrounded_size = layout_size;
}

if let Some(outline) = maybe_outline {
// don't trigger change detection when only outlines are changed
let node = node.bypass_change_detection();
node.outline_width = outline
.width
.resolve(node.size().x, viewport_size)
.unwrap_or(0.)
.max(0.);

node.outline_offset = outline
.offset
.resolve(node.size().x, viewport_size)
.unwrap_or(0.)
.max(0.);
}
let viewport_size = root_size.unwrap_or(node.calculated_size);

if transform.translation.truncate() != rounded_location {
transform.translation = rounded_location.extend(0.);
}

let scroll_position: Vec2 = maybe_scroll_position
.map(|scroll_pos| {
Vec2::new(
if overflow.x == OverflowAxis::Scroll {
scroll_pos.offset_x
} else {
0.0
},
if overflow.y == OverflowAxis::Scroll {
scroll_pos.offset_y
} else {
0.0
},
)
})
.unwrap_or_default();
if let Some(border_radius) = maybe_border_radius {
// We don't trigger change detection for changes to border radius
node.bypass_change_detection().border_radius =
border_radius.resolve(node.calculated_size, viewport_size);
}

let mut node_scrollable_bounds =
rounded_size + approx_round_layout_coords(layout_location);
if let Some(outline) = maybe_outline {
// don't trigger change detection when only outlines are changed
let node = node.bypass_change_detection();
node.outline_width = outline
.width
.resolve(node.size().x, viewport_size)
.unwrap_or(0.)
.max(0.);

node.outline_offset = outline
.offset
.resolve(node.size().x, viewport_size)
.unwrap_or(0.)
.max(0.);
}

if let Ok(children) = children_query.get(entity) {
let mut children_bounding_box = children
.iter()
.map(|child_uinode| {
update_uinode_geometry_recursive(
commands,
*child_uinode,
ui_surface,
Some(viewport_size),
node_transform_query,
children_query,
inverse_target_scale_factor,
rounded_size,
scroll_position,
absolute_location,
)
})
.fold(scroll_position, |acc, size| {
Vec2::new(acc.x.max(size.x), acc.y.max(size.y))
});
if transform.translation.truncate() != rounded_location {
transform.translation = rounded_location.extend(0.);
}

if children_bounding_box != Vec2::ZERO && scroll_position != Vec2::ZERO {
// Cannot scroll further than the edge of the furthest child
let max_possible_offset =
(children_bounding_box - rounded_size).max(Vec2::ZERO);
let clamped_scroll_position =
scroll_position.clamp(Vec2::ZERO, max_possible_offset);

// If the size of the bounding box containing all children changed in a way that impacts the scroll position of the parent
// Re-run the layout for all children
if clamped_scroll_position != scroll_position {
commands
.entity(entity)
.insert(ScrollPosition::from(&clamped_scroll_position));

children_bounding_box = children
.iter()
.map(|child_uinode| {
update_uinode_geometry_recursive(
commands,
*child_uinode,
ui_surface,
Some(viewport_size),
node_transform_query,
children_query,
inverse_target_scale_factor,
rounded_size,
clamped_scroll_position,
absolute_location,
)
})
.fold(scroll_position, |acc, size| {
Vec2::new(acc.x.max(size.x), acc.y.max(size.y))
});
}
}
let scroll_position: Vec2 = maybe_scroll_position
.map(|scroll_pos| {
Vec2::new(
if style.overflow.x == OverflowAxis::Scroll {
scroll_pos.offset_x
} else {
0.0
},
if style.overflow.y == OverflowAxis::Scroll {
scroll_pos.offset_y
} else {
0.0
},
)
})
.unwrap_or_default();

// If overflow is visible, the bounds of the children must be considered.
// A parent of this node could scroll the overflowing children.
if overflow.x.is_visible() {
node_scrollable_bounds.x =
node_scrollable_bounds.x.max(children_bounding_box.x);
}
let node_scrollable_bounds = rounded_size + approx_round_layout_coords(layout_location);

if overflow.y.is_visible() {
node_scrollable_bounds.y =
node_scrollable_bounds.y.max(children_bounding_box.y);
if let Ok(children) = children_query.get(entity) {
let mut children_bounding_box = children
.iter()
.map(|child_uinode| {
update_uinode_geometry_recursive(
commands,
*child_uinode,
ui_surface,
Some(viewport_size),
node_transform_query,
children_query,
inverse_target_scale_factor,
rounded_size,
scroll_position,
absolute_location,
)
})
.fold(scroll_position, Vec2::max);

if children_bounding_box != Vec2::ZERO && scroll_position != Vec2::ZERO {
// Cannot scroll further than the edge of the furthest child
let max_possible_offset = (children_bounding_box - rounded_size).max(Vec2::ZERO);
let clamped_scroll_position =
scroll_position.clamp(Vec2::ZERO, max_possible_offset);

// If the size of the bounding box containing all children changed in a way that impacts the scroll position of the parent
// Re-run the layout for all children
if clamped_scroll_position != scroll_position {
commands
.entity(entity)
.insert(ScrollPosition::from(&clamped_scroll_position));

children_bounding_box = children
.iter()
.map(|child_uinode| {
update_uinode_geometry_recursive(
commands,
*child_uinode,
ui_surface,
Some(viewport_size),
node_transform_query,
children_query,
inverse_target_scale_factor,
rounded_size,
clamped_scroll_position,
absolute_location,
)
})
.fold(scroll_position, Vec2::max);
}

node_scrollable_bounds
} else {
node_scrollable_bounds
}

// The scrollable area of this node may also include overflowing children.
node_scrollable_bounds.max(children_bounding_box)
} else {
Vec2::ZERO
node_scrollable_bounds
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ impl Plugin for UiPlugin {
)
.add_systems(
PreUpdate,
(ui_focus_system.in_set(UiSystem::Focus).after(InputSystem),),
ui_focus_system.in_set(UiSystem::Focus).after(InputSystem),
);

app.add_systems(
Expand Down

0 comments on commit 2565183

Please sign in to comment.