bevy/examples/ui/borders.rs

126 lines
3.7 KiB
Rust
Raw Normal View History

//! Example demonstrating bordered UI nodes
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.run();
}
fn setup(mut commands: Commands) {
commands.spawn(Camera2dBundle::default());
let root = commands
.spawn(NodeBundle {
style: Style {
margin: UiRect::all(Val::Px(25.0)),
Have a separate implicit viewport node per root node + make viewport node `Display::Grid` (#9637) # Objective Make `bevy_ui` "root" nodes more intuitive to use/style by: - Removing the implicit flexbox styling (such as stretch alignment) that is applied to them, and replacing it with more intuitive CSS Grid styling (notably with stretch alignment disabled in both axes). - Making root nodes layout independently of each other. Instead of there being a single implicit "viewport" node that all root nodes are children of, there is now an implicit "viewport" node *per root node*. And layout of each tree is computed separately. ## Solution - Remove the global implicit viewport node, and instead create an implicit viewport node for each user-specified root node. - Keep track of both the user-specified root nodes and the implicit viewport nodes in a separate `Vec`. - Use the window's size as the `available_space` parameter to `Taffy.compute_layout` rather than setting it on the implicit viewport node (and set the viewport to `height: 100%; width: 100%` to make this "just work"). --- ## Changelog - Bevy UI now lays out root nodes independently of each other in separate layout contexts. - The implicit viewport node (which contains each user-specified root node) is now `Display::Grid` with `align_items` and `justify_items` both set to `Start`. ## Migration Guide - Bevy UI now lays out root nodes independently of each other in separate layout contexts. If you were relying on your root nodes being able to affect each other's layouts, then you may need to wrap them in a single root node. - The implicit viewport node (which contains each user-specified root node) is now `Display::Grid` with `align_items` and `justify_items` both set to `Start`. You may need to add `height: Val::Percent(100.)` to your root nodes if you were previously relying on being implicitly set.
2023-09-19 15:14:46 +00:00
align_self: AlignSelf::Stretch,
justify_self: JustifySelf::Stretch,
flex_wrap: FlexWrap::Wrap,
justify_content: JustifyContent::FlexStart,
align_items: AlignItems::FlexStart,
align_content: AlignContent::FlexStart,
..Default::default()
},
UI node outlines (#9931) # Objective Add support for drawing outlines outside the borders of UI nodes. ## Solution Add a new `Outline` component with `width`, `offset` and `color` fields. Added `outline_width` and `outline_offset` fields to `Node`. This is set after layout recomputation by the `resolve_outlines_system`. Properties of outlines: * Unlike borders, outlines have to be the same width on each edge. * Outlines do not occupy any space in the layout. * The `Outline` component won't be added to any of the UI node bundles, it needs to be inserted separately. * Outlines are drawn outside the node's border, so they are clipped using the clipping rect of their entity's parent UI node (if it exists). * `Val::Percent` outline widths are resolved based on the width of the outlined UI node. * The offset of the `Outline` adds space between an outline and the edge of its node. I was leaning towards adding an `outline` field to `Style` but a separate component seems more efficient for queries and change detection. The `Outline` component isn't added to bundles for the same reason. --- ## Examples * This image is from the `borders` example from the Bevy UI examples but modified to include outlines. The UI nodes are the dark red rectangles, the bright red rectangles are borders and the white lines offset from each node are the outlines. The yellow rectangles are separate nodes contained with the dark red nodes: <img width="406" alt="outlines" src="https://github.com/bevyengine/bevy/assets/27962798/4e6f315a-019f-42a4-94ee-cca8e684d64a"> * This is from the same example but using a branch that implements border-radius. Here the the outlines are in orange and there is no offset applied. I broke the borders implementation somehow during the merge, which is why some of the borders from the first screenshot are missing :sweat_smile:. The outlines work nicely though (as long as you can forgive the lack of anti-aliasing): ![image](https://github.com/bevyengine/bevy/assets/27962798/d15560b6-6cd6-42e5-907b-56ccf2ad5e02) --- ## Notes As I explained above, I don't think the `Outline` component should be added to UI node bundles. We can have helper functions though, perhaps something as simple as: ```rust impl NodeBundle { pub fn with_outline(self, outline: Outline) -> (Self, Outline) { (self, outline) } } ``` I didn't include anything like this as I wanted to keep the PR's scope as narrow as possible. Maybe `with_outline` should be in a trait that we implement for each UI node bundle. --- ## Changelog Added support for outlines to Bevy UI. * The `Outline` component adds an outline to a UI node. * The `outline_width` field added to `Node` holds the resolved width of the outline, which is set by the `resolve_outlines_system` after layout recomputation. * Outlines are drawn by the system `extract_uinode_outlines`.
2023-10-05 12:10:32 +00:00
background_color: BackgroundColor(Color::DARK_GRAY),
..Default::default()
})
.id();
// all the different combinations of border edges
let borders = [
UiRect::default(),
UiRect::all(Val::Px(10.)),
UiRect::left(Val::Px(10.)),
UiRect::right(Val::Px(10.)),
UiRect::top(Val::Px(10.)),
UiRect::bottom(Val::Px(10.)),
UiRect::horizontal(Val::Px(10.)),
UiRect::vertical(Val::Px(10.)),
UiRect {
left: Val::Px(10.),
top: Val::Px(10.),
..Default::default()
},
UiRect {
left: Val::Px(10.),
bottom: Val::Px(10.),
..Default::default()
},
UiRect {
right: Val::Px(10.),
top: Val::Px(10.),
..Default::default()
},
UiRect {
right: Val::Px(10.),
bottom: Val::Px(10.),
..Default::default()
},
UiRect {
right: Val::Px(10.),
top: Val::Px(10.),
bottom: Val::Px(10.),
..Default::default()
},
UiRect {
left: Val::Px(10.),
top: Val::Px(10.),
bottom: Val::Px(10.),
..Default::default()
},
UiRect {
left: Val::Px(10.),
right: Val::Px(10.),
top: Val::Px(10.),
..Default::default()
},
UiRect {
left: Val::Px(10.),
right: Val::Px(10.),
bottom: Val::Px(10.),
..Default::default()
},
];
for i in 0..64 {
let inner_spot = commands
.spawn(NodeBundle {
style: Style {
width: Val::Px(10.),
height: Val::Px(10.),
..Default::default()
},
background_color: Color::YELLOW.into(),
..Default::default()
})
.id();
let bordered_node = commands
UI node outlines (#9931) # Objective Add support for drawing outlines outside the borders of UI nodes. ## Solution Add a new `Outline` component with `width`, `offset` and `color` fields. Added `outline_width` and `outline_offset` fields to `Node`. This is set after layout recomputation by the `resolve_outlines_system`. Properties of outlines: * Unlike borders, outlines have to be the same width on each edge. * Outlines do not occupy any space in the layout. * The `Outline` component won't be added to any of the UI node bundles, it needs to be inserted separately. * Outlines are drawn outside the node's border, so they are clipped using the clipping rect of their entity's parent UI node (if it exists). * `Val::Percent` outline widths are resolved based on the width of the outlined UI node. * The offset of the `Outline` adds space between an outline and the edge of its node. I was leaning towards adding an `outline` field to `Style` but a separate component seems more efficient for queries and change detection. The `Outline` component isn't added to bundles for the same reason. --- ## Examples * This image is from the `borders` example from the Bevy UI examples but modified to include outlines. The UI nodes are the dark red rectangles, the bright red rectangles are borders and the white lines offset from each node are the outlines. The yellow rectangles are separate nodes contained with the dark red nodes: <img width="406" alt="outlines" src="https://github.com/bevyengine/bevy/assets/27962798/4e6f315a-019f-42a4-94ee-cca8e684d64a"> * This is from the same example but using a branch that implements border-radius. Here the the outlines are in orange and there is no offset applied. I broke the borders implementation somehow during the merge, which is why some of the borders from the first screenshot are missing :sweat_smile:. The outlines work nicely though (as long as you can forgive the lack of anti-aliasing): ![image](https://github.com/bevyengine/bevy/assets/27962798/d15560b6-6cd6-42e5-907b-56ccf2ad5e02) --- ## Notes As I explained above, I don't think the `Outline` component should be added to UI node bundles. We can have helper functions though, perhaps something as simple as: ```rust impl NodeBundle { pub fn with_outline(self, outline: Outline) -> (Self, Outline) { (self, outline) } } ``` I didn't include anything like this as I wanted to keep the PR's scope as narrow as possible. Maybe `with_outline` should be in a trait that we implement for each UI node bundle. --- ## Changelog Added support for outlines to Bevy UI. * The `Outline` component adds an outline to a UI node. * The `outline_width` field added to `Node` holds the resolved width of the outline, which is set by the `resolve_outlines_system` after layout recomputation. * Outlines are drawn by the system `extract_uinode_outlines`.
2023-10-05 12:10:32 +00:00
.spawn((
NodeBundle {
style: Style {
width: Val::Px(50.),
height: Val::Px(50.),
border: borders[i % borders.len()],
margin: UiRect::all(Val::Px(20.)),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..Default::default()
},
background_color: Color::MAROON.into(),
border_color: Color::RED.into(),
..Default::default()
},
UI node outlines (#9931) # Objective Add support for drawing outlines outside the borders of UI nodes. ## Solution Add a new `Outline` component with `width`, `offset` and `color` fields. Added `outline_width` and `outline_offset` fields to `Node`. This is set after layout recomputation by the `resolve_outlines_system`. Properties of outlines: * Unlike borders, outlines have to be the same width on each edge. * Outlines do not occupy any space in the layout. * The `Outline` component won't be added to any of the UI node bundles, it needs to be inserted separately. * Outlines are drawn outside the node's border, so they are clipped using the clipping rect of their entity's parent UI node (if it exists). * `Val::Percent` outline widths are resolved based on the width of the outlined UI node. * The offset of the `Outline` adds space between an outline and the edge of its node. I was leaning towards adding an `outline` field to `Style` but a separate component seems more efficient for queries and change detection. The `Outline` component isn't added to bundles for the same reason. --- ## Examples * This image is from the `borders` example from the Bevy UI examples but modified to include outlines. The UI nodes are the dark red rectangles, the bright red rectangles are borders and the white lines offset from each node are the outlines. The yellow rectangles are separate nodes contained with the dark red nodes: <img width="406" alt="outlines" src="https://github.com/bevyengine/bevy/assets/27962798/4e6f315a-019f-42a4-94ee-cca8e684d64a"> * This is from the same example but using a branch that implements border-radius. Here the the outlines are in orange and there is no offset applied. I broke the borders implementation somehow during the merge, which is why some of the borders from the first screenshot are missing :sweat_smile:. The outlines work nicely though (as long as you can forgive the lack of anti-aliasing): ![image](https://github.com/bevyengine/bevy/assets/27962798/d15560b6-6cd6-42e5-907b-56ccf2ad5e02) --- ## Notes As I explained above, I don't think the `Outline` component should be added to UI node bundles. We can have helper functions though, perhaps something as simple as: ```rust impl NodeBundle { pub fn with_outline(self, outline: Outline) -> (Self, Outline) { (self, outline) } } ``` I didn't include anything like this as I wanted to keep the PR's scope as narrow as possible. Maybe `with_outline` should be in a trait that we implement for each UI node bundle. --- ## Changelog Added support for outlines to Bevy UI. * The `Outline` component adds an outline to a UI node. * The `outline_width` field added to `Node` holds the resolved width of the outline, which is set by the `resolve_outlines_system` after layout recomputation. * Outlines are drawn by the system `extract_uinode_outlines`.
2023-10-05 12:10:32 +00:00
Outline {
width: Val::Px(6.),
offset: Val::Px(6.),
color: Color::WHITE,
},
))
.add_child(inner_spot)
.id();
commands.entity(root).add_child(bordered_node);
}
}