-
-
Notifications
You must be signed in to change notification settings - Fork 4k
Add ZIndex
, YSort
, and SortBias
2d components
#19463
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
base: main
Are you sure you want to change the base?
Conversation
It looks like your PR is a breaking change, but you didn't provide a migration guide. Please review the instructions for writing migration guides, then expand or revise the content in the migration guides directory to reflect your changes. |
It looks like your PR has been selected for a highlight in the next release blog post, but you didn't provide a release note. Please review the instructions for writing release notes, then expand or revise the content in the release notes directory to showcase your changes. |
Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke! If it's expected, please add the M-Deliberate-Rendering-Change label. If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it. |
/// A marker component that enables Y-sorting (depth sorting) for sprites and meshes. | ||
/// | ||
/// When attached to an entity, this component indicates that the entity should be rendered | ||
/// in draw order based on its Y position. Entities with lower Y values (higher on screen) | ||
/// are drawn first, creating a depth illusion where objects lower on the screen appear | ||
/// in front of objects higher on the screen. | ||
#[derive(Component, Default, Debug, Clone)] | ||
pub struct YSort; |
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.
Setting YSort
per-sprite seems like it might be confusing to me. Will we be able to resolve situations where you have multiple overlapping sprites, some with YSort
, some without, in a consistant way?
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.
Right now, for entities on the same z index layer, an entity with y sort enabled will always sort before one without it. Not sure if this is intuitive but it is consistent.
z_index: 0, | ||
y_sort: false, | ||
sort_bias: None, |
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.
Text2d
needs to support z index too.
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.
As long as they both just wrap an i32
and higher values are on top, I think it would be okay to use the same ZIndex
component for both UI and 2d. bevy_ui
already depends on bevy_sprite
for the texture slicing API. We'd just need to be careful to make sure all the documentation points out clearly how it behaves in each context.
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.
What about propagation? It feels like this needs some sort of local ordering support so children are drawn above their ancestors and inherit their parent's z-ordering.
We just merged #17575 which could help. I'm the wrong person to ask about 2d design patterns, but it's not clear to me that children should always be drawn above their ancestors, although I realize this is a pattern that using z position plus transform propagation makes trivial and we are breaking. Would appreciate input here from others. |
I don't think we can assume this. We need to make it possible for children to be drawn in front of behind their ancestors, depending on artist intent. |
I don't think we can assume it, but I do think it's a good default :) |
I guess the question is, what does this look like? Do we have a |
It feels to me like y-sorting is more a property of an individual layer rather than individual sprites. Wouldn't you want all sprites in the same layer to be y sorted? Does the y sort take into account the anchor point at all? |
Probably? But again I think this is more a function of questions around patterns for inheritance/propagation. At the end of the day, they will be sorted one by one and so I think it still makes sense for the components to apply to individual entities if you want. I wouldn't want to take away this fine grained control just add other tools for making common use cases easier. |
bevy_lunex does this. by default every child is one z step above its parent. and there's an override component (with i wonder if different variants like that can be useful 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.
I like this design, especially as it helps to unblock #19389.
What should we do with the name conflict with the existing ui ZIndex.
I think it will be confusing if we use the same component for both UI and 2d here, because UI currently always draws on top of 2d. Changing that is out of scope for this PR. My suggestion is to fold all the new components introduced by this PR into fields on the the new 2d transform, and move the existing ZIndex
and GlobalZIndex
into the new ui transform.
How should 2d mesh opaque behave? Right now, using any of these components opts you into transparent sorting on the CPU, but ideally we'd be able to do GPU based fragment sorting as well.
I think this is an acceptable limitation for now. We should work to fix it as follow up.
This is an advantage that using the transform Z has that we should take into consideration.
Maybe we just make the z_index
or depth
field on a 2d transform behave the same was as the z
position component on a 3d transform (by which I mean the current Transform
). Have it propagate into the GlobalTransform
the same way, I mean, so that a given z_index
will result in an actual translation in 3d space. Originally I was against this idea, but I've come around. It would totally resolve this issue, I think.
This would also give us z index propagation for free, as part of transform propagation.
I've collected some of my thoughts on this here.
Objective
Using Z transform for sprites and 2d meshes is gross! Users expect familiar sorting strategies.
Solution
Adds 3 new sorting components for 2d:
ZIndex
: sorts entities into layers and always takes priority.YSort
: sorts entities in eachZIndex
layer by their Y transform.SortBias
: an arbitrary bias that is either added to Y transform or used as a secondary sort value.TODO:
ZIndex
.Testing
Tested a bunch of examples, might be more broken.