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

Adjusting CanvasLayers layer on runtime, does not update _gui_input handling to match the visual rendering #59448

Closed
Arecher opened this issue Mar 23, 2022 · 5 comments · Fixed by #59479

Comments

@Arecher
Copy link

Arecher commented Mar 23, 2022

Godot version

3.4.stable

System information

Windows 10, GLES3

Issue description

It seems that updating the layer of a CanvasLayer during runtime, only changes the visual rendering of the nodes, and does not change order in which input gets handled. Which means that nodes that visually get rendered behind other nodes, due to their CanvasLayer's layer, can still act as if they are up front (and block/handle input).

Issue_Bug
After changing the CanvasLayer's layer on the right button, the button shows itself to be visually in front. However, hover feedback shows that actually, the Control on the left is still considered to be the top one.

A mismatch between visuals and collision handling happens more often in Godot (Controls clip_content only clips visuals, not input, and Controls show_behind_parent), but those behave consistently and there are ways to make the input follow the visuals. However, there doesn't seem to be a way to make sure the input follows the visuals when adjusting the CanvasLayer's layer property. Plus the fact that on start-up, Controls in a higher CanvasLayer do also handle their input first/block Controls on lower CanvasLayers. Only after adjusting the layer on runtime, does the input not follow the visual order. So there is definitely an inconsistency, even if CanvasLayers were never meant to adjust input handling.

Issue_WorkingProperly
This shows the controls behaving as expected, before the render order is changes by changing the CanvasLayers layer

I would expect changing the layer of a Canvaslayer to be up front, to automatically also adjust those nodes to take input before nodes that are rendered behind them. Or at the very least, there should be an option/method that could make it so. At the moment, there is no way that I know of to work around this issue.

Steps to reproduce

open the Reproduction Project below

  1. Hover both buttons
    Notice that the button rendered behind only becomes yellow when the button rendered in front is not blocking the input.
  2. Click the button the right.
    This will update the CanvasLayer's layer to 100, meaning the button on the right will be rendered in front of the left Button.
  3. Hover the buttons, and especially the area in which they overlap.
    You would expect that hovering the area in which the buttons intersect, to only show the Button that is rendered in front as being 'hovered' (yellow), but instead the button that is rendered behind is showing it is hovered.

Minimal reproduction project

issue_canvaslayerdoesnotupdateguiinput.zip

@Arecher
Copy link
Author

Arecher commented Mar 23, 2022

This issue is similar to #50678, but that report seems to be specifically about WindowDialogs having a similar issue on Startup. However, if that WindowDialog is changed out for any regular Control, the issue isn't there anymore. This issue seems to be with any Control, and specifically after changing the layer on runtime.

I do suspect the issues are related, since WindowDialogs might use a similar system to CanvasLayers to adjust their rendering.

@Sauermann
Copy link
Contributor

At the moment, mainly the Nodes position within the SceneTree influences event processing. The layer of the canvas has no impact on events.

@Arecher
Copy link
Author

Arecher commented Mar 23, 2022

At the moment, mainly the Nodes position within the SceneTree influences event processing. The layer of the canvas has no impact on events.

Right, I thought that might be the case, so I checked for that. But in the reproduction project, the CanvasLayer with the higher layer, is higher in the tree. Meaning on start-up, the Control that is rendered behind (lower layer) should, if the SceneTree is the one that determines processing, be handled as if it is up front. But it isn't.

And adjusting the position of the CanvasLayer in the SceneTree on runtime has no influence on which node gets processed either. [EDIT: Actually, that's a lie. It does have influence in the reproduction project.]

@Arecher
Copy link
Author

Arecher commented Mar 24, 2022

I agree with this issue being in part a documentation issue. The documentation on Canvaslayers should definitely mention that they are only a visual tool, and do not adjust the processing order/influence input handling.

However, after some more testing in the reproduction project, there is definitely something odd/inconsistent going on. The SceneTree order doesn't handle the processing order properly (if CanvasLayers are involved?). I adjusted the Controls to raise the CanvasLayers when they are clicked, meaning the Canvaslayer that is rendered in front, should also process input first. But that doesn't work consistently, raising the CanvasLayer doesnt always mean the nodes in that Layer will be processed first.

Issue_RaisingDoesNOTHandleProcessingProperly2
The X and V indications are here to indicate whether the proccessing of the Controls follows the rule of Lower down the SceneTree gets processed first
At the start, the processing happens in reverse order of how the nodes are in the scene tree. Then, upon raising (& changing the layer) of the right control, the processing follows the scene tree. Raising the left control will continue to behave properly, but then raising the right control for a second time, will have the nodes be processed in the wrong order again

To me this seems like it could only be a bug, but if there is an explanation, i'd love to understand what's going on. Here is the (updated) reproduction project: issue_canvaslayerdoesnotupdateguiinput2.zip

Lastly, I was wondering if there is a way to have nodes be processed in a certain order, regardless of their SceneTree Position, since that's what I would need for my project. If there isn't, perhaps CanvasLayers would be a good way to add that functionality for the future.

@Sauermann
Copy link
Contributor

@Arecher this is definitely a bug. Here is the solution: #59479
CanvasLayer indeed influences the order in which Control nodes receive an event in gui_input. I was not aware of that implementation detail.
With this patch you can even leave out

self.get_parent().raise()

in your MRP and it works as you intend.

@akien-mga akien-mga added this to the 4.0 milestone Sep 14, 2022
@akien-mga akien-mga modified the milestones: 4.0, 3.6 Dec 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants