This worked - with what you were saying before about setting the ordering to true, thanks!!! - I should’ve been more thorough with my testing.
For the benefit of anyone else who was struggling with this here is the code that worked thanks to @Sauermann.
Working example
Both the stage and item objects are StaticBody2D with a Sprite2D and CollisionBody2D - the _on_input_event
is signalled from the CollisionBody2D so the clicks match the shape.
(Edit) Oh also - don’t forget to set the objects as pickable under Input in the inspector!!
Code for Stage:
extends StaticBody2D
@export var item : PackedScene
func _ready():
get_parent().get_viewport().set_physics_object_picking_sort(true)
func _on_input_event(_viewport, event, _shape_idx):
if event is InputEventMouseButton and event.is_pressed():
var new_item = item.instantiate()
new_item.global_position = event.position
get_parent().add_child(new_item)
The get_parent().get_viewport().set_physics_object_picking_sort(true)
was what was missing from every other post I’ve seen about this. Note that the docs state this is off by default as it can be expensive.
Code for item
extends StaticBody2D
#tracking state
var button_down : bool = false
var dragging : bool = false
#used to offset start position for mouse so item doesn't snap centre to mouse position
var pos_delta : Vector2 = Vector2(0,0)
#used to switch to drag mode if mouse is moved further than limit while button pressed
var drag_distance = 3
var mouse_start : Vector2 = Vector2(0,0)
#used to show clicks
@export var costumes : Array[CompressedTexture2D]
var costume_num = 0
func _physics_process(_delta):
if dragging:
drag()
func drag():
global_position = get_global_mouse_position() + pos_delta
func _on_input_event(viewport, event, _shape_idx):
viewport.set_input_as_handled() #items with lower z-index will then ignore
if event is InputEventMouseButton:
if event.is_pressed():
button_down = true
pos_delta = global_position - get_global_mouse_position()
mouse_start = get_global_mouse_position()
if event.is_released():
if button_down and not dragging:
costume_num = (costume_num + 1) % costumes.size()
%Sprite2D.texture = costumes[costume_num]
button_down = false
dragging = false
if event is InputEventMouseMotion:
if button_down and !dragging:
if get_global_mouse_position().distance_to(mouse_start) > drag_distance:
dragging = true