Skip to content
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

Update ZIndex and LayoutOrder when late renders occur #60

Merged
merged 2 commits into from
Jul 18, 2024

Conversation

OverHash
Copy link
Contributor

Currently, Iris does not well support components which conditionally render, or render later (see #58 and #48).

This patch marks parents as dirty when a new component is rendered, which triggers an update of the computed ZIndex and LayoutOrder for those future children of the parent. This correctly orders elements, albeit with a ~1 cycle delay in the order looking correct (minor flickering).

This patch is not completely ideal -- as we naively assume that setting the LayoutOrder and ZIndex of the widget's root Instance is sufficient. This assumption breaks down as Iris uses ZIndexBehavior=Global, and so we need to propagate an update of ZIndex/LayoutOrder to all instances generated by a widget -- not just the root widget.

For simple cases however, this patch is suitable.

Currently, Iris does not well support components which conditionally
render, or render later (see SirMallard#58 and SirMallard#48).

This patch marks parents as dirty when a new component is rendered,
which triggers an update of the computed ZIndex and LayoutOrder for
those future children of the parent. This correctly orders elements,
albeit with a ~1 cycle delay in the order looking correct (minor
flickering).

This patch is not completely ideal -- as we naively assume that setting
the LayoutOrder and ZIndex of the widget's root Instance is sufficient.
This assumption breaks down as Iris uses ZIndexBehavior=Global, and so
we need to propagate an update of ZIndex/LayoutOrder to all instances
generated by a widget -- not just the root widget.

For simple cases however, this patch is suitable.
@OverHash
Copy link
Contributor Author

I am wondering if we should make this PR introduce a new lifecycle method, something alike OnComponentReoredered which will update the root instance and all its children to have correct ZIndex/LayoutOrder properties.

For example, InputText creates a few elements:

  • Iris_InputText (this is what thisWidget.Instance is set to)
    • InputField (with ZIndex/LayoutOrder set to Iris_InputText + 1)
    • any frame styles
    • a size constraint
    • a text label

a theoretical OnComponentReordered component would be responsible for updating all of these Roblox instances to have the correct ZIndex and LayoutOrder, based on the (updated) widget.ZIndex property.

@SirMallard
Copy link
Owner

This would seem to work, but I'm still wary of the implications of possibly regenerating an entire widget's children because one of them moved.

My assumption was that a child instance will always render above its parent regardless of the ZIndex being lower than the parent. Ultimately, the issue is not the ZIndex but the LayoutOrder which affects the offending and positioning. If the ZIndex rules were relaxed, with no change to visual layout, then only the top widget's instance's LayoutOrder would need to change, making it much easier.

Therefore, you would only need to modify the direct children of any widget where one of the children had been moved, which would not involve a complete regeneration.

@SirMallard
Copy link
Owner

If this is the case, only parent widgets would need to keep a LayoutOrder count for their direct children, since each LayoutOrder is only relative to its direct siblings. And possibly ZIndex would be the same for all siblings. I can't think of any widget which draws over other widgets except using a popup which is inherently on another layer and window.

@SirMallard SirMallard linked an issue Jul 10, 2024 that may be closed by this pull request
Regenerating the component leads to broken internal state. We now simply
update the LayoutOrder property.
@OverHash
Copy link
Contributor Author

My assumption was that a child instance will always render above its parent regardless of the ZIndex being lower than the parent. Ultimately, the issue is not the ZIndex but the LayoutOrder which affects the offending and positioning.

Yes. My apologies -- the initial submission of this PR included regenerating the underlying Roblox instance, but I found this lead to broken internal state of widgets. I found that the new commit I just put up is much more stable (only updating the widgets LayoutOrder).

I believe you are correct that this PR can be further simplified if we relax the assumptions on the Widget.ZIndex behavior to only be about relative layout ordering, rather than global ZIndex. If that's the case, we don't have to propagate LayoutOrder updates to children of our widget -- only the siblings.

@Michael-48 Michael-48 merged commit 37fd6d7 into SirMallard:main Jul 18, 2024
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.

Widget layout order does not update for dynamically visible widgets
3 participants