godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Implement an inverse Y-Sort option #7015

Open jorgegayoso opened 1 year ago

jorgegayoso commented 1 year ago

Describe the project you are working on

A simple 2D platformer where the graphics look like 3D at an angle looking down (they are simple Sprite2D's)

Say I have a simple platform, and the player is standing in the middle of it. If he is above the platform, the platform should be behind the player, and if the player is right below the platform, the platform should be on top of the player.

Better explanation of issue -> https://github.com/godotengine/godot/issues/20431

Describe the problem or limitation you are having in your project

Y-Sort sorts its children in descending order of their Y coordinate. I need them to be sorted in ascending order.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Set Y-Sort so that it can be either Y-ascending or Y-descending / normal or inverted.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

In the editor Node > CanvasItem > Ordering:

RenderingServer code usage RenderingServer.canvas_item_set_sort_children_by_y(item: RID, enabled: bool, inverted:bool)

If this enhancement will not be used often, can it be worked around with a few lines of script?

It can be worked around via rotating the Y-Sorted node by 180deg then unrotating its children but this isn't viable, specially for big scenes, since setting positions via code is inverted, etc.

Is there a reason why this should be core and not an add-on in the asset library?

It is a simple idea, and even though I haven't seen the YSort source code, my expectation is that it isn't too big of a deal to implement (I might be wrong though!).

AThousandShips commented 1 year ago
nrmiller commented 1 year ago

Just stopping by to share my support! I came across this issue on a separate engine I'm working on and wanted to see if Godot had a solution.

Here's my use case:

2023-07-06 23-09-14

Basically, I want the most recent score additions to appear in front and on top, so Y-sort needs to be inverted from the traditional order. I could accomplish this uncleanly by recycling z-index or render layers, but the cleanest solution is to change the Y-sort behavior within a scope of nodes.

jorgegayoso commented 1 year ago

Hey @nrmiller, I actually have an easier solution for your problem!

When you instantiate a node and add it to another, it automatically goes to the bottom of the subtree, meaning that it will show on top of all other children. So you wouldnt really need a YSort, just a normal Node2D.

Note: I closed this by accident! 😭 not used to github just yet.

groud commented 1 year ago

cc @groud

I think this is a bit too corner-case to be implemented. I don't really see a huge need for it.

I could accomplish this uncleanly by recycling z-index or render layers, but the cleanest solution is to change the Y-sort behavior within a scope of nodes.

@jorgegayoso just wrote faster than I, but yeah, this is easily achievable by changing the order of your nodes.

Y-sort main interest is when you need to reorder a complex and deep hierarchy of nodes, which is super common with top-down 2D games. Other use cases can often be worked around easily. So I'd like a to see a real-life use case where a invert Y-sorting would benefit a complex hierarchy of nodes to back this proposal.

nrmiller commented 1 year ago

Sorry to dilute from the main purpose of this proposal, but thank you for the feedback! Sounds like yet another reason to prefer Godot's node-tree structure! 😄

jorgegayoso commented 1 year ago

So I'd like a to see a real-life use case where a invert Y-sorting would benefit a complex hierarchy of nodes to back this proposal.

Im making a Smash Bros remake for fun. The environment/platforms are drawn at an angle to look like 3D. This means that when Mario's body is on top of the platform, he must appear on top, and when he is below, the platform must be on top, like so: image

image

To achieve this, I have 2 Sprite2D's that both use an AtlasTexture to divide a platform into top and bottom, then simply increase the Z-Index of the bottom half. Its a simple fix, but an inverse YSort would resolve all of this much more efficiently. Inverse Y-Sort would be more for specific platformers rather than for top-downs. The use-case is slim, that is for sure!

neruthes commented 8 months ago

I am working with isometric 2D TileMap and I need inverse Y sort to combine blocks into a pillar. Now I am using multiple TileMap instances as floors in this demo but this is not maintainable. Inverse Y sort should be the final solution.

image

image

Owlmate-Julius commented 8 months ago

Just to give another use case: I'm working on a top-down dungeon where the player sprite needs to cover the bottom door until it reaches the middle half, then the player sprite should be behind the door. So basically an inverse y-sort for the door.

1

josepvalls commented 2 months ago

I wanted to present another use case for this. I'm working on a falling blocks game (i.e. Tetris) but the blocks have studs on them (i.e. Lego bricks). They can be of many shapes and fall in any order but I want the blocks on top to be drawn on top of the ones below. There is a small overlap on the blocks to "hide" the studs. Again, there are cumbersome code solutions but I'd expect this to be a simpler Boolean at engine level.