Add sprite layer render order override and parent/child layer rendering#6341
Open
SlamBamActionman wants to merge 2 commits intospace-wizards:masterfrom
Open
Add sprite layer render order override and parent/child layer rendering#6341SlamBamActionman wants to merge 2 commits intospace-wizards:masterfrom
SlamBamActionman wants to merge 2 commits intospace-wizards:masterfrom
Conversation
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds two main features to
SpriteComponent:Sprite layer rendering order override
By default, a sprite renders the layers in the order they are in the
List<Layer> Layersproperty.There is now a new property added to
LinkedList<int>? LayersOrderOverride. Its contents are meant to represent indexes of layers in the mainLayerslist. When set, instead of rendering the layers in the order of theLayerslist, the sprite layers are rendered in the order their indexes are listed in the override. E.g.LayersOrderOverride = { 2, 0, 1 }will render the layers in that order.Of note is that this order is only followed up until the highest index in the override. This means if an override's highest index is e.g.
2, any layer in theLayerslist with a higher index will also render after the override (in the order listed in theLayerslist). This is because these types of layers are often intended to be rendered on top of the existing sprite and may be difficult to account for in the override.The
LayersOrderOverridedoes not update automatically based on changes in theLayerslist order. It is expected that whatever function sets it also accounts for changes throughout the codebase.- Is this reasonable? Arguably one could also update the property if a layer is added/removed, but that might be a lot of overhead work. Let me know if we want this instead of updating via Content.
Parent/Child layers
A child layer is a layer that will always follow its parent in the layer order, regardless of its index (override or not). This is set in the child via the property
int? ParentLayerand in the parent viaList<int> ChildLayers.These properties are inaccessible outside the API to (hopefully) avoid accidental endless recursion. When a layer is added, it can optionally include a
parentIndexwhich refers to the index of a layer in theLayerslist. The parent layer gets the new layer added as a child, and when processing the rendering order any child layer gets selected for rendering after the parent layer has been rendered.Adding/removing layers will shift the parent/child indexes accordingly, similar to how the
Indexproperty is shifted. Removing a parent layer orphans any children it may have.As a parent can have multiple children, each child will render in the order they are added to the parent. The function runs recursively, so a child can also be a parent.
There is also the
SetToParentmethod which assigns an existing layer as a parent to another existing layer, using the indexes. Of note is that if the child already has a parent, the new parent is given the child's old parent as its parent. This meansSetToParentcan be used to insert a layer in the middle of a chain of parent-children relationship.- This is necessary for displacement maps, as they require the layer sprite they're modifying to exist when being made, but prefer to be before said layer in the rendering order.
- SetToParent is potentially risky as I think it would be possible to create a Parent/Child recursive loop; I am not sure how to fool-proof this however outside of tracking which layers have already been rendered, and that seems unperformant.
Issues
Sprite rendering is an area that is meant for heavy optimization, and that is unfortunately not my forté. I've done my best to preserve what I hope are performant methods but I there are areas where I'm uncertain if it has been made worse.
LayerRenderingStrategy
My understanding is that generating the matrices is a bit of a heavy operation. Previously this was easily avoided since the layers rendered in a simple foreach loop, but now that the behavior is more complex I needed to find a way to pass these on to the actual
RenderLayerfunction. I've opted to, in caseGranularLayersRenderingis false, include the calculated matrices in a Dictionary and then retrieve them later on whenRenderLayeris called. I'm not sure the dict is performant here though.Parent/Child architecture
I think there is a case one could make that defining either the parent or the child layer isn't necessary, or that making a parent able to have multiple children is a bad idea. It seems to me that including both allows for the most flexibility but they also aren't hard-coupled and there could theoretically be a situation where there's recursion or indexes point incorrectly. Let me know if this is wrong.
LayersOrderOverride doesn't update
As mentioned earlier, adding/removing layers doesn't update the override. In my implementation I update these in Content so that isn't an issue, but maybe they should here as well, similar to how Parent/Children/Index indexes are?
Why?
Being able to override the sprite layer order means we can make much nicer-looking content via directional sprites. There will be a Content PR up soon after this one that attempts this using the features here. The override ensures "bookmark" layers can layer sprites in the correct order depending on which direction a character is facing, while a parent/child relationship allows there to be further customization of the rendering order by not just moving the "bookmark" layers.