When having multiple TextureButtons that are overlapping, the events InputEventMouseMotion and InputEventScreenTouch is prioritized by the order they are added to the scenetree. The nodes added last have priority.

However, if the nodes are moved around in the scenetree using for instance Node.raise() or Node.move_child() etc, the old priority order is still kept. It's not updated.

This becomes a problem in the project I am working on, a Jigsaw game. So, when I drag pieces around I use raise() to have my dragged pieces to render on top. But if I have a bunch of pieces in a pile and then click on the pile, it's not the topmost piece that gets the event, it's the one that was last in the scenetree originally.

So, the render order seems to get updated, but the capture of events doesn't seem to get updated.

I have been experimenting with Godot 4.1 and the same problem seems to be around there as well.

Any suggestions how to solve this would be welcome, if anyone knows a workaround until the bug is fixed?

  • xyz replied to this.
  • dlccmind Your button's parent is plain Node2D. It must be Control (or anything inherited) in order for _gui_input() to propagate properly.

    dlccmind So, the render order seems to get updated, but the capture of events doesn't seem to get updated.

    Are you sure about that? It'd be useful to post some code that demonstrates this.

    The order of siblings definitely affects the order of _input() invocation and signal callbacks. The sibling with the highest index will be called first because it's visually "on top". So if you want a sibling to be processes first, you should move it to the end of the array using move_child(child,-1)

    In the case of event processing with _input(), note that whichever order you use all of the overlapping objects will still receive the event. If you want to stop it from propagating, you should use _unhadnled_input instead of input() and call _set_input_as_handled() to consume the event.

      xyz Pretty sure yes. There is quite a lot of code, I can try making a minimal demo to show this behaviour. They reached the ones below the others in a "pile". The order of siblings absolutely affects the order, but AFTER I have used either raise() or move_child() or something else, they are still affected in the original order before I moved them. But if you are certain perhaps I have some bug forcing this behaviour, I will doublecheck. Not sure if this will affect it, but the pieces are using a texture_click_mask, because the pieces are not entirely square.

      • xyz replied to this.

        dlccmind There may be problems elsewhere in the code. Best to try to reproduce it in a minimal project.

          xyz Ah, just to clarify, I use:
          func _gui_input(event):

          Since I use TextureButtons this seemed to be the best approach. If I use _input I have to do extra code to see if my button (that uses a clickmap) is pressed, otherwise all the pieces on the screen will be affected simultaneously.

          Working on a minimal project atm.

          • xyz replied to this.

            dlccmind Why not just use pressed signal? It'll consume events properly.

              xyz

              Why not just use pressed signal? It'll consume events properly.

              Ok, I'll try if I can get that to work.

              [Edit:] Doesn't work, same result.

              • xyz replied to this.

                dlccmind Your button's parent is plain Node2D. It must be Control (or anything inherited) in order for _gui_input() to propagate properly.

                  xyz Omg this was it. It works!

                  Finally, just changed my type and everything started working perfectly!

                  Thank you so much!!!

                  This is again one of those things that I'm not sure if they're a bug or a feature. It looks like the engine is maintaining a separate z-order list for controls and doesn't update it in cases like yours. Maybe it wouldn't be a bad idea to ask the devs if this is by design. It may indeed be a bug.

                    xyz
                    I can imagine that there is some performance reason that only Controls would keep track of the events, maybe. Not sure since I haven't deep dived in the engine source yet. I feel a little silly that I missed this, it seems a bit logical in hindsight.