-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
UI node outlines #9931
UI node outlines #9931
Conversation
* 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`.
…node's border, so they are clipped using the clipping Rect of their ui node entity's parent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems useful as-is, but I wonder how hard it would be to add https://developer.mozilla.org/en-US/docs/Web/CSS/outline-offset support to this? Could be useful for people who want to draw outlines inside the node boundaries rather than outside.
Really trivial, I'll add it now |
* Added an `outline_offset: f32` field to Node. * Added an `offset: Val` field to `Outline`. * In `extract_uinode_outlines` the twice the outline offset is added to the node size before calculating
/ ui_scale.0 as f32; | ||
|
||
for (outline, mut node) in outlines_query.iter_mut() { | ||
let node = node.bypass_change_detection(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How come you're calling bypass_change_detection
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The text system queries for changes to Node
so it can recompute the text layout on changes to the UI node's size.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, do we not care about detecting changes to the outline_width
and outline_offset
fields?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not at the moment. Maybe we could have a separate component for every property but it doesn't seem very tractable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough. I'd put a comment here describing that we don't care about change detection for these fields because they're private and only used as a cache.
/ ui_scale.0 as f32; | ||
|
||
for (outline, mut node) in outlines_query.iter_mut() { | ||
let node = node.bypass_change_detection(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough. I'd put a comment here describing that we don't care about change detection for these fields because they're private and only used as a cache.
Love this feature! I have one question about the implementation: one of the main use-cases I can see would be to show the outline on the currently hovered element in a list or grid. In that case, as a user I would either be removing and adding the IMO it would be more explicit and discoverable to have an |
I think setting the outline color to transparent is clear enough as is. Maybe adding a doc line saying "Consider setting the outline color to transparent if you need to toggle the outline visibility" could fill the gap. Also the current node bundles are already way too large, and results in a lot of extra machine codes. It's reasonable to want to avoid adding more and more components to them. Also, my thinking is that |
Setting the outline's color to Most UI nodes won't use outlines, so it wouldn't be efficient to add it to every bundle. If you do need to create a lot of outlined bundles you can always use a builder method or a type alias for |
Thanks for the reply. I understand and setting the color to My main concern regards table moves when the |
I wouldn't consider the API here final by any means. I understand your concerns about table moves. As well as the performance issues, at the moment in Bevy UI they can affect the order of UI elements atm in some circumstances (this should be fixed soon though, we've fixed some of the problems already, and I've been working on changes that should fix the remaining issues). Show/Hide helper methods have similar problems to the |
@ickshonpe once merge conflicts are resolved I'll merge this. |
Head branch was pushed to by a user without write access
this is ready to merge |
# 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 😅. 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`.
# 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 😅. 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`.
# 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 😅. 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`.
Objective
Add support for drawing outlines outside the borders of UI nodes.
Solution
Add a new
Outline
component withwidth
,offset
andcolor
fields.Added
outline_width
andoutline_offset
fields toNode
. This is set after layout recomputation by theresolve_outlines_system
.Properties of outlines:
Outline
component won't be added to any of the UI node bundles, it needs to be inserted separately.Val::Percent
outline widths are resolved based on the width of the outlined UI node.Outline
adds space between an outline and the edge of its node.I was leaning towards adding an
outline
field toStyle
but a separate component seems more efficient for queries and change detection. TheOutline
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: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 😅. The outlines work nicely though (as long as you can forgive the lack of anti-aliasing):
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: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.
Outline
component adds an outline to a UI node.outline_width
field added toNode
holds the resolved width of the outline, which is set by theresolve_outlines_system
after layout recomputation.extract_uinode_outlines
.