How to identify which Area2D has mouse click

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By whitelegs

Hi, I have a number of Area2Ds with CircleShape2D collision shapes attached, all set as clickable. They are basically numbers on a dial (sprite) and are children of it, which in turn is a child of a TextureRec. I have it working on a test basis by using signals & procedures attached to a couple of them but I would prefer a single input event procedure to handle all of them as the action to be taken is almost identical in each case, varied only by a calculation based on a number in the area name. To do that I need to identify in which Area2D the mouse has been clicked. How can I get the name of the relevant area?

:bust_in_silhouette: Reply From: GameSchool

Hi
If you’re using signals you can always bind arguments to them. It’s not necessary the best way to identify the node, but it’s an easy option to just manually add a string with the name of the node or a path to it as a variable in your signal function

As GameSchool has answered, below is a sample code that worked for me. Hope this suits what you need:

extends TextureRect

@onready var sprite = $Sprite2D

func _ready():
    for child in sprite.get_children():
        child.input_event.connect(do_something.bind(child.name))
	
func do_something(viewport, event, shape, name_of_clicked_area):
    if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT):
        print(name_of_clicked_area)
        # do someting else below

I made a scene with TextureRect as root node and attached this script to the TextureRect node. The node structure I used is as below. The labels are just simulating the numbers on dials:

TextureRect
|_Sprite2D
    |_Area2D
        |_CollisionShape2D
        |_Label1
    |_Area2D2
        |_CollisionShape2D
        |_Label2
    |_Area2D3
        |_CollisionShape2D
        |_Label3

coffeepot95 | 2023-06-01 10:50

For anyone who comes to this post later, I found out that I didn’t need to use the for loop in TextureRect in the previous answer if the Area2Ds are scenes instanced into the TextureRect. According to the KidsCanCode Website their is a property called “owner” that can be used in the scenes to be instanced to connect automatically to whatever root node it might be where the scene is instanced. Their example code for Godot 4 is as below, where the Button will be instanced:

extends Button

func _ready():
    pressed.connect(owner._on_button_pressed.bind(name))

This would give the code and node arrangements even greater flexibility.

The referenced KidsCanCode website: Node communication (the right way) :: Godot 4 Recipes

coffeepot95 | 2023-06-03 04:25