I’m in 2D and have placed 2 Area2D nodes. One is a large one which covers the entire screen, and the other is a smaller one, which is entirely inside (and on top) of the big one.
Both have the same script:
func _input_event(viewport: Viewport, event: InputEvent, shape_idx: int) -> void:
if ( event is InputEventMouseMotion ):
print("Move in Big/Small")
viewport.set_input_as_handled()
I’d expect that when I move my mouse on the smaller node, I only see “Move in Small” in the debugger. However I see BOTH nodes receiving the event, albeit more in the smaller node than in the larger.
You seem to think this will mean that the smaller area will intercept all signals. What do you mean by “on top”? Its place in the tree? Its z-order? Visibly on top in the editor? And what makes you think that it should block all events from happening to nodes below it? How come if you want to intercept all mouse movement, you are using _input_event() signal of the Area2D instead of _input() and/or unhandled_input()? What is driving the choice to use Area2D instead of Control?
By “on top” I mean “overlapping”. That is, I wan to create a sort of “map” which the player can interact with. The map itself will be large - bigger than the screen. So the player should be able to pan and zoom it. This should be accomplished by clicking-and-dragging the map in an empty area. Then on the map there will be items (let’s say villages) that the player can click. So I want the village nodes to get the mouse events when the mouse is over them, otherwise the map background node gets them.
The nodes are strategically arranged in the tree. First comes the background node, then the village nodes.This both ensures that the nodes are drawn correctly; and also (according to this page), that the events should be first delivered to the village nodes first, and only then background node. And it does seem to work… mostly.
The Z-order of all the nodes is the same, but mostly because I haven’t needed to touch it yet.
I’m using Area2D and _input_event() because out of the box they give me nice “interaction area” detection. That is, they automatically filter mouse events according to the attached collision shape. Regular nodes and _input()/_unhandled_input() don’t do that. I’d need to implement it myself.
And finally, even though I’m a veteran programmer in the backend world, I’m very new to the Godot engine, so I’m just getting my bearings here. This is my first time attempting to make a game since '98. So I’m just trying things out to see what works. Control nodes were the next thing on my list of things to try. I started with Area2D because they seemed more appropriate - Control nodes seem like they’re meant for a fixed UI (like menus, HUDs, etc) that doesn’t pan and scale; as well as isn’t the primary thing the player interacts with.
I’d use controls. If you need irregular picking shapes you can use TextureButtons with bitmap click masks.
Physics object picking works a bit differently than “normal” event handling. It happens last, after the event was passed to all other types of handlers. See the diagram and descriptions here:
By default, the order of _input_event() handler calling on pickable physics objects is not guaranteed, likely for performance reasons. It can change frame to frame. So, the concept of “propagating” the event through the scene tree does not apply here and Viewport::set_input_as_handled() will have no useful effect.
If you want it to behave “as expected”, i.e. only the “topmost” area receives and consumes the event, you’ll need to enable Viewport::physics_object_picking_sort and Viewport::physics_object_picking_first_only flags. This will come with some additional performance cost, but likely not much.
Typically Control nodes are controlled by Anchors, which keep them all inside the screen regardless of screen resolution. However, you do not have to use Anchors with Control nodes. I’d recommend you go that route.