So there doesn't seem to be a built in way to do this, and since input events flow from the root upwards you'll have to wait till the last area gets the event to tell who will get picked up.
Here is my quick, simple, and naive solution which just adds a mediator node to accept pickup requests on a frame and then at the beginning of the next frame grant the request to the highest node in the tree aka the frontmost node.
Mediator
extends Node2D
var _did_pickup = false
var _node = null
var _requestees = []
func _ready():
set_process_unhandled_input(true)
func _unhandled_input(event):
if _requestees.size() > 0:
pickup(_requestees.back())
func pickup(n):
_did_pickup = true
_node = n
_requestees.clear()
func can_pickup(n):
return not (_did_pickup and _node)
func is_pickedup(n):
return _did_pickup and (_node.get_name() == n.get_name())
func drop():
_did_pickup = false
_node = null
func request_pickup(node):
# to pickup by highest z-idx, just sort requestees by
# their z-idx when inserting here
_requestees.append(node)
Area
extends Area2D
onready var mediator = get_parent()
func _input_event(viewport, event, shape_idx):
if event.type == InputEvent.MOUSE_BUTTON:
if event.pressed and mediator.can_pickup(self):
print('%s is requesting pickup.' % get_name())
mediator.request_pickup(self)
elif not event.pressed and mediator.is_pickedup(self):
print('%s has dropped itself.' % get_name())
mediator.drop()
if event.type == InputEvent.MOUSE_MOTION and mediator.is_pickedup(self):
set_global_pos(event.global_pos)