Skip to content

feat(ui): add RenderOrder property for UI component stacking#3104

Closed
laske185 wants to merge 1 commit intostride3d:masterfrom
laske185:feature/ui-render-order
Closed

feat(ui): add RenderOrder property for UI component stacking#3104
laske185 wants to merge 1 commit intostride3d:masterfrom
laske185:feature/ui-render-order

Conversation

@laske185
Copy link
Copy Markdown
Contributor

@laske185 laske185 commented Mar 24, 2026

PR Details

Add RenderOrder property to UIComponent to control draw order of overlapping UI components. Lower values are rendered first (behind), higher values render on top. Default is 0, preserving existing behavior.

Related Issue

None.

Types of changes

  • Docs change / refactoring / dependency upgrade
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

- Introduce RenderOrder property to UIComponent for custom render order.
- Propagate RenderOrder through RenderUIElement and UIRenderProcessor.
- Sort UI elements by RenderOrder in UIRenderFeature to control stacking.
- Allows developers to specify which UI components appear in front or behind others.
@Ethereal77
Copy link
Copy Markdown
Contributor

I have not tested your changes yet, but on Discord I was talking about this recently. While you are at this, can you check what effect it has in ordering the UIElement.DrawLayerNumber? I thought it was for this very purpose, but it didn't work. I also tried setting a low depth and positioning the UIElement towards the front, but it is weird and not very intuitive.

Btw, in UIElement the term depth refers to the size in the depth dimension (same as Width and Height), but that name is a bit confusing, it may seem to refer to the depth "position", which is defined in the local matrix.

@laske185
Copy link
Copy Markdown
Contributor Author

I also played with the parameters inside the UIPage, like depth, draw layer number, and alignment of the container components. Additionally, I tested the position and the z-coordinate of resolution and size. But all did not work.

In my scenario, I have a split-screen setup with its own UIComponent for the render-to-texture images and a UI for the HUD. It is not deterministic whether the hub is before or behind the split-screen UI. I started to combine the complete UI into one UIPage to be able to set the depth, but now I have a huge UI monolith.

With the solution from this PR, the render pipeline is manipulated to order the UI pages. This explains to me why all parameters did not have any effect on the draw order, because the pipeline renders component for component and overwrites the previous paint.

@laske185
Copy link
Copy Markdown
Contributor Author

I have not tested your changes yet, but on Discord I was talking about this recently. While you are at this, can you check what effect it has in ordering the UIElement.DrawLayerNumber? I thought it was for this very purpose, but it didn't work. I also tried setting a low depth and positioning the UIElement towards the front, but it is weird and not very intuitive.

Btw, in UIElement the term depth refers to the size in the depth dimension (same as Width and Height), but that name is a bit confusing, it may seem to refer to the depth "position", which is defined in the local matrix.

To get a quick answer, I asked Claude, and it confirmed what I had observed:

DrawLayerNumber (UIElement) — Controls the depth bias within a single UI tree. Determines how many depth layers an element needs for its own visual parts (background, border, content). For example, Button adds +1 for its design image. Accumulated in UpdateElementState so child elements don't z-fight.

RenderOrder (UIComponent) — Controls draw order between separate UIComponents in the scene, i.e. between entirely different UI hierarchies.

In short: DrawLayerNumber = z-sorting within a UI tree, RenderOrder = sorting between UI trees.

@Eideren
Copy link
Copy Markdown
Collaborator

Eideren commented Apr 5, 2026

This is not a trivial call to preform on every render, I assume by default elements are drawn in from first to last child depth first ? Is there a reason why you can't re-order the elements themselves ? You mentioned

In my scenario, I have a split-screen setup with its own UIComponent for the render-to-texture images and a UI for the HUD. It is not deterministic whether the hub is before or behind the split-screen UI. I started to combine the complete UI into one UIPage to be able to set the depth, but now I have a huge UI monolith.

Order of drawing between UI pages looks like a queue, the last one added to the scene is drawn above everything. Then it's split in render groups afair. If you want to draw a page above others, you can remove it from the scene and add it back in. Or mess with its render group I think.

@laske185
Copy link
Copy Markdown
Contributor Author

laske185 commented Apr 8, 2026

I invested days some time ago, and the order of the entities doesn't change anything. Maybe it was already fixed, or the behavior has changed.

In any case, I can adjust the layering of the UI pages by changing the order of the entities and fix my bug.

Thanks for your feedback, @Eideren! I close the PR.

@laske185 laske185 closed this Apr 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants