Simplified ui_stack_system#9889
Conversation
…ering away those nodes.
clean up and cargo fmt
…ZIndex` and `GlobalZIndex` respectively.
|
That makes sense to me. While both are kinds of zindex, they have different implications, both conceptually and in the implementation. I'm curious to know what maintainers think of the naming, i.e. should ZIndex be renamed to |
oceantume
left a comment
There was a problem hiding this comment.
There are a few minor missing changes I commented about, but otherwise this looks good to me. This makes ZIndex a simpler component and "hides" global z-index behavior which is probably a good thing since it's an escape hatch and isn't meant to be used in most UI's. Unlike the previous PR, this is not a feature regression so it's less controversial in my opinion (as long as the API change is deemed uncontroversial as well).
Co-authored-by: Gabriel Bourgeois <gabriel.bourgeoisv4si@gmail.com>
Co-authored-by: Gabriel Bourgeois <gabriel.bourgeoisv4si@gmail.com>
My thinking is that keeping I'm not bothered about the naming though, if there is a consensus in favour of |
atlv24
left a comment
There was a problem hiding this comment.
This makes a lot of sense and uses the ECS better. Im in favor of the current naming (ZIndex + GlobalZIndex)
crates/bevy_ui/src/stack.rs
Outdated
| .ok() | ||
| .map(|zindex| (*entity, zindex.map(|zindex| zindex.0).unwrap_or(0))) | ||
| }) | ||
| .collect(); |
There was a problem hiding this comment.
No need to collect, use a shared vec sourced from a local and clear -> extend here.
crates/bevy_ui/src/stack.rs
Outdated
| .map(|zindex| (*entity, zindex.map(|zindex| zindex.0).unwrap_or(0))) | ||
| }) | ||
| .collect(); | ||
| radsort::sort_by_key(&mut z_children, |k| k.1); |
There was a problem hiding this comment.
Not clear that radsort is better than std::sort here either, since most nodes will have only a handful of children. To use std::sort_unstable you can add an index for each child and sort by (z_index, child_index).
There was a problem hiding this comment.
Another reviewer said to try using radsort and it seemed to be an improvement with my benchmarks but I forgot that those benchmarks were with very large numbers of children which isn't the typical usage case.
| for (i, entity) in ui_stack.uinodes.iter().enumerate() { | ||
| if let Ok(mut node) = update_query.get_mut(*entity) { | ||
| node.bypass_change_detection().stack_index = i as u32; | ||
| } | ||
| } |
There was a problem hiding this comment.
The traversal_stack is never inserted to ui_stack. Am I missing something here? Also how are children supposed to be inserted relative to their parents within the global stack?
There was a problem hiding this comment.
I'm puzzled how this passes CI, it appears to have serious bugs.
There was a problem hiding this comment.
traversal_stack is used to navigate the tree, not insert the nodes.
There was a problem hiding this comment.
Abandoned the iterative version using stack traversal anyway, and went back to walking the tree recursively, copying your stack of cached buffers approach from main to avoid the vec allocations. I don't understand why the iterative version is so much less efficient though. It just has one buffer for storing and sorting the children it reuses, which seems so much better.
UkoeHB
left a comment
There was a problem hiding this comment.
Looks correct now, minor doc comments. Also would like to see an updated perf graph.
Co-authored-by: UkoeHB <37489173+UkoeHB@users.noreply.github.com>
# Objective `ui_stack_system` generates a tree of `StackingContexts` which it then flattens to get the `UiStack`. But there's no need to construct a new tree. We can query for nodes with a global `ZIndex`, add those nodes to the root nodes list and then build the `UiStack` from a walk of the existing layout tree, ignoring any branches that have a global `Zindex`. Fixes bevyengine#9877 ## Solution Split the `ZIndex` enum into two separate components, `ZIndex` and `GlobalZIndex` Query for nodes with a `GlobalZIndex`, add those nodes to the root nodes list and then build the `UiStack` from a walk of the existing layout tree, filtering branches by `Without<GlobalZIndex>` so we don't revisit nodes. ``` cargo run --profile stress-test --features trace_tracy --example many_buttons ``` <img width="672" alt="ui-stack-system-walk-split-enum" src="https://github.com/bevyengine/bevy/assets/27962798/11e357a5-477f-4804-8ada-c4527c009421"> (Yellow is this PR, red is main) --- ## Changelog `Zindex` * The `ZIndex` enum has been split into two separate components `ZIndex` (which replaces `ZIndex::Local`) and `GlobalZIndex` (which replaces `ZIndex::Global`). An entity can have both a `ZIndex` and `GlobalZIndex`, in comparisons `ZIndex` breaks ties if two `GlobalZIndex` values are equal. `ui_stack_system` * Instead of generating a tree of `StackingContexts`, query for nodes with a `GlobalZIndex`, add those nodes to the root nodes list and then build the `UiStack` from a walk of the existing layout tree, filtering branches by `Without<GlobalZIndex` so we don't revisit nodes. ## Migration Guide The `ZIndex` enum has been split into two separate components `ZIndex` (which replaces `ZIndex::Local`) and `GlobalZIndex` (which replaces `ZIndex::Global`). An entity can have both a `ZIndex` and `GlobalZIndex`, in comparisons `ZIndex` breaks ties if two `GlobalZindex` values are equal. --------- Co-authored-by: Gabriel Bourgeois <gabriel.bourgeoisv4si@gmail.com> Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: UkoeHB <37489173+UkoeHB@users.noreply.github.com>
Objective
ui_stack_systemgenerates a tree ofStackingContextswhich it then flattens to get theUiStack.But there's no need to construct a new tree. We can query for nodes with a global
ZIndex, add those nodes to the root nodes list and then build theUiStackfrom a walk of the existing layout tree, ignoring any branches that have a globalZindex.Fixes #9877
Solution
Split the
ZIndexenum into two separate components,ZIndexandGlobalZIndexQuery for nodes with a
GlobalZIndex, add those nodes to the root nodes list and then build theUiStackfrom a walk of the existing layout tree, filtering branches byWithout<GlobalZIndex>so we don't revisit nodes.(Yellow is this PR, red is main)
Changelog
ZindexZIndexenum has been split into two separate componentsZIndex(which replacesZIndex::Local) andGlobalZIndex(which replacesZIndex::Global). An entity can have both aZIndexandGlobalZIndex, in comparisonsZIndexbreaks ties if twoGlobalZIndexvalues are equal.ui_stack_systemStackingContexts, query for nodes with aGlobalZIndex, add those nodes to the root nodes list and then build theUiStackfrom a walk of the existing layout tree, filtering branches byWithout<GlobalZIndexso we don't revisit nodes.Migration Guide
The
ZIndexenum has been split into two separate componentsZIndex(which replacesZIndex::Local) andGlobalZIndex(which replacesZIndex::Global). An entity can have both aZIndexandGlobalZIndex, in comparisonsZIndexbreaks ties if twoGlobalZindexvalues are equal.