Skip to content

Named global Z layers for bevy_ui - #26263

Open
ickshonpe wants to merge 12 commits into
bevyengine:mainfrom
ickshonpe:global-z-layer
Open

ickshonpe wants to merge 12 commits into
bevyengine:mainfrom
ickshonpe:global-z-layer

Conversation

@ickshonpe

@ickshonpe ickshonpe commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Objective

Replace the i32 indices with string names in GlobalZIndex.

Related issues (doesn't entirely solve) #1275, #24564.

Solution

GlobalZIndex now wraps a Cow<'static, str> instead of an i32.

The ordering of the GlobalZIndex strings is stored the GlobalZLayers resource, which wraps a `Vec<Cow<'static, str>>.

Calling get_index on GlobalZLayers with the string layer name returns an index that used by ui_stack_system to determine the final UiStack ordering.


  • Initially I used the design from Local named Z layers for bevy_ui_render #26260, using a procedural macro and define_label!. There were problems though that I realised once I started trying to migrate over the examples and the widgets and feathers crates. The interned labels complicated serialization and reflection. bevy_ui_render's local sub layer labels don't need to be changed at runtime and they don't need to be stored in components on entities. GlobalZIndex is a component though and we need to able to change the order arbitrarily.

  • Kept the name GlobalZIndex for now just to reduce the number of changes.

  • Maybe it should use SmolStr and not Cow for consistancy with bevy_feathers.

  • Not sure if this sufficient for an intial PR or whether it needs more, like some notion of sub layers. GlobalZIndex can still be combined with ZIndex to get numbered sub layers though.

Testing

The output from the UI examples should be unchanged.

AI Disclosure

I wrote the initial implementation using a proc macro but after I realised I had to redo everything to use strings, I had claude do most of the migration and then cleaned up a few things like the floating layers afterwards.

- Added macros crate, GlobalZLayer label, GlobalZLayers resource to store the ordering.
- Changed `GlobalZIndex` to wrap a `GlobalZLayer` label.
- Updated `ui_stack_system to use the new labels.
Replaces the interned `GlobalZLayer` label with a name string so that
`GlobalZIndex` can be serialized and deserialized via reflection.

Removes the `bevy_ui_macros` crate, layer names are just static cow strs.
Changed the underlying global z index value back to u32 from i32.
@ickshonpe
ickshonpe requested a review from viridia October 20, 2026 23:30
@ickshonpe ickshonpe changed the title Named global UI Z layers Named global Z layers for bevy_ui Oct 20, 2026
@viridia

viridia commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

@alice-i-cecile One thing your original criteria list never mentioned is whether layers need to be definable at runtime - that is, I presume that scene files will contain layer assignments, but it's not clear if scene files will also decide the ordering between layers, like in a CSS layers declaration.

My questions are:

  • Can layers be registered at runtime?
  • Can plugins contribute layers, and with what ordering semantics?
  • Is the final order intended to eventually be serializable or asset-backed?
  • What happens when a scene references a name that isn’t registered?

So for example feathers dialog box or menu defines layers which need to be ordered relative to the game's layers.

@ickshonpe ickshonpe added A-UI Graphical user interfaces, styles, layouts, and widgets X-Contentious There are nontrivial implications that should be thought through D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Oct 21, 2026
@github-project-automation github-project-automation Bot moved this to Needs SME Triage in UI Oct 21, 2026
@alice-i-cecile

Copy link
Copy Markdown
Member

I think that runtime-defined layers are going to be essential here for UX when using tools to define these layers.

@ickshonpe

Copy link
Copy Markdown
Contributor Author

My questions are:

  • Can layers be registered at runtime?

Yes, the layers are just stored in an ordinary resource, GlobalZLayers, that wraps a Vec storing the names of each layer in back-to-front order. You can modify it anytime and the changes will be applied the next frame.

  • Can plugins contribute layers, and with what ordering semantics?

Yes, plugins can just add new layers to the GlobalZLayers list. There are insert_before and insert_after methods that let you add a layer relative to an already added layer, or you can just push to the vec to add a new layer on top.

  • Is the final order intended to eventually be serializable or asset-backed?

It's just a list of strings, so making it loadable from an asset should be trivial. I'm less sure about merging

  • What happens when a scene references a name that isn’t registered?

ATM if a name isn't registered it just fails silently and the UI element is drawn to the default layer.

@ickshonpe

ickshonpe commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor Author

I've been thinking that one option might be to use GhostNodes to create sub layers and force an ordering.

Non-ghost nodes under a root ghost node are promoted to become layout root nodes. If GlobalZIndex/ZIndex on a ghostnode was propagated to its children then we could use that to create ordered sub layers.

It would probably need us to unrequire ZIndex from node though and make it an optional component.

@viridia

viridia commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Yet another argument why ghost nodes need a rebranding...

@Zeophlite Zeophlite added S-Merge-Conflicts Merge conflicts :( Add this label on top of other S- labels. AI-Assisted Discloses the use of AI in any way labels Oct 22, 2026
@Cyannide

Copy link
Copy Markdown
Contributor

Could it just use a small set of built-in layers like DEFAULT, MODAL, POPUP, DEBUG with before/after constraints that get resolved together, kinda like configure_sets? That way the order wouldn't depend on plugin build order.

@ickshonpe

ickshonpe commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor Author

Could it just use a small set of built-in layers like DEFAULT, MODAL, POPUP, DEBUG with before/after constraints that get resolved together, kinda like configure_sets? That way the order wouldn't depend on plugin build order.

I think we're all agreed that named layers are desireable, so maybe I've been overthinking this a bit. Ideas about constraints, sub layers, and plugin build order probably can probably be put aside for this PR? Those things are already a problem with integer indices. The only advantage with integers is that the ordering is obvious.

So then the only questions this PR needs to answer are:

  • How to represent the names?
    My answer: string ids are the better option over Interned type labels. Easy to examine and work with, and serialization is trivial.
  • How to store the ordering:?
    My answer: a flat list of the string names stored in a resource is sufficient. It's trivial to examine and rearrange to resolve any ordering issues. Maybe in the future we could store a list of constraints as well and resolve the layer ordering automatically, but I don't think it's needed for the initial PR.

@ickshonpe

Copy link
Copy Markdown
Contributor Author

Yet another argument why ghost nodes need a rebranding...

Maybe we won't need them anymore, nicoburns is working on Display::Contents support in Taffy:
DioxusLabs/taffy#1301

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-UI Graphical user interfaces, styles, layouts, and widgets AI-Assisted Discloses the use of AI in any way D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes S-Merge-Conflicts Merge conflicts :( Add this label on top of other S- labels. S-Needs-Review Needs reviewer attention (from anyone!) to move forward X-Contentious There are nontrivial implications that should be thought through

Projects

Status: Needs SME Triage

Development

Successfully merging this pull request may close these issues.

5 participants