diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index ac086d02a5556..7cb6e01538039 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -298,6 +298,38 @@ impl ComputedNode { clip_rect } + + /// Returns the node's border-box in object-centered physical coordinates. + /// This is the full rectangle enclosing the node. + #[inline] + pub fn border_box(&self) -> Rect { + Rect::from_center_size(Vec2::ZERO, self.size) + } + + /// Returns the node's padding-box in object-centered physical coordinates. + /// This is the region inside the border containing the node's padding and content areas. + #[inline] + pub fn padding_box(&self) -> Rect { + let mut out = self.border_box(); + out.min.x += self.border.left; + out.max.x -= self.border.right; + out.min.y += self.border.top; + out.max.y -= self.border.bottom; + out + } + + /// Returns the node's padding-box in object-centered physical coordinates. + /// This is the innermost region of the node, where its content is placed. + #[inline] + pub fn content_box(&self) -> Rect { + let mut out = self.border_box(); + let content_inset = self.content_inset(); + out.min.x += content_inset.left; + out.max.x -= content_inset.right; + out.min.y += content_inset.top; + out.max.y -= content_inset.bottom; + out + } } impl ComputedNode { @@ -2916,7 +2948,10 @@ impl ComputedUiRenderTargetInfo { #[cfg(test)] mod tests { + use crate::ComputedNode; use crate::GridPlacement; + use bevy_math::Vec2; + use bevy_sprite::BorderRect; #[test] fn invalid_grid_placement_values() { @@ -2943,4 +2978,48 @@ mod tests { assert_eq!(GridPlacement::start_span(3, 5).get_end(), None); assert_eq!(GridPlacement::end_span(-4, 12).get_start(), None); } + + #[test] + fn border_box_is_centered_rect_of_node_size() { + let node = ComputedNode { + size: Vec2::new(100.0, 50.0), + ..Default::default() + }; + let border_box = node.border_box(); + + assert_eq!(border_box.min, Vec2::new(-50.0, -25.0)); + assert_eq!(border_box.max, Vec2::new(50.0, 25.0)); + } + + #[test] + fn padding_box_subtracts_border_thickness() { + let mut node = ComputedNode::default(); + node.size = Vec2::new(100.0, 60.0); + node.border = BorderRect { + left: 5.0, + right: 7.0, + top: 3.0, + bottom: 9.0, + }; + let padding_box = node.padding_box(); + + assert_eq!(padding_box.min, Vec2::new(-50.0 + 5.0, -30.0 + 3.0)); + assert_eq!(padding_box.max, Vec2::new(50.0 - 7.0, 30.0 - 9.0)); + } + + #[test] + fn content_box_uses_content_inset() { + let mut node = ComputedNode::default(); + node.size = Vec2::new(80.0, 40.0); + node.padding = BorderRect { + left: 4.0, + right: 6.0, + top: 2.0, + bottom: 8.0, + }; + let content_box = node.content_box(); + + assert_eq!(content_box.min, Vec2::new(-40.0 + 4.0, -20.0 + 2.0)); + assert_eq!(content_box.max, Vec2::new(40.0 - 6.0, 20.0 - 8.0)); + } } diff --git a/release-content/release-notes/computed_node_helper_functions.md b/release-content/release-notes/computed_node_helper_functions.md new file mode 100644 index 0000000000000..b9a08ab8440ca --- /dev/null +++ b/release-content/release-notes/computed_node_helper_functions.md @@ -0,0 +1,7 @@ +--- +title: "`ComputedNode` helper functions" +authors: ["@ickshonpe"] +pull_requests: [21903] +--- + +Helper functions `border_box`, `padding_box`, and `content_box` that return a node’s object-centered border, padding, and content boxes have been added to `ComputedNode`.