0 votes

Scene:

WorldNode2d
- "background etc"
- GridNode2d (contains instances of PieceNode2d)
-- Piece0
-- Piece
n
-- Piece_100

PieceNode2d
- Sprite
- KinematicBody2d ( can be clicked )
-- Collisionshape

I would like to handle inputs cleanly within GridNode2d script where all other game related code is but it only has _input(event) function and I'm not sure if I can get clicked object from there?

Currently I have inputevent() in KinematicBody2d script where I can get which PieceNode2d was clicked (self..) but it somehow complicates further steps.. code is not that elegant anymore :)

So how to get clicked object detected and handled in GridNode2d (which is parent of instantied PieceNode2d objects)?

asked Apr 23, 2019 in Engine by Godotmus (36 points)

2 Answers

+1 vote
Best answer

Probably the cleanest way of doing it is by handling it the way you currently are (with clickable bodies), and then signalling to parent when a pieces is clicked. I assume your parent is instancing the pieces, so the code might look something like:

For the piece:

extends KinematicBody2D
signal clicked(node)

func _input_event(event):
    emit_signal("clicked", self)

And then the parent:

extends WhatEverThisExtends
const Piece = preload(res://Piece.tscn) 
func addPiece():
    var piece = Piece.instance()
    piece.connect("clicked", self, "handle_piece_click")
    add_child(piece)

func handle_piece_click(piece):
    #do something with your piece

It is also possible to have the pieces connect their own signals on _ready()

func _ready():
    connect("clicked", get_parent(), "handle_piece_click")

But I prefer not to depend on my scenes knowing anything about their parent.

answered Apr 24, 2019 by TheThirdPerson (128 points)
selected Apr 25, 2019 by Godotmus

Thanks, looks like I was on the right track :)

0 votes

So i am not sure if i understand your question correctly, but i think you just want to handle a click event right?
Well you should make a collisionnShape a child of an Area2D note. The Area2D note has signals, which detect is the mouse has entered or exited the collisionShape. So you can do something like:

var mouse_in = false

_on_CollisionShape2D_mouse_entered():
       mouse_in = true
_on_CollisionShape2D_mouse_exited():
       mouse_in = false

Then you need to check in the process function, whether the user clicked while the mouse was inside of the collision area:

if Input.is_action_pressed("mouse_button_left") and mouse_in == true:
       #action
       pass

You can configure and add new costum input references (like my "mousebuttonleft") at project settings -> Input map.

The handling part can be done with signals. Create a signal called "clicked" or something in the instance and connect it to your GridNode2d via script after being instanced. There you can also put "self" as an argument, so GridNode2d can handle the event.

Hope this helped!

answered Apr 23, 2019 by Dr. Numerus (33 points)

Question was more of what is better & cleaner way to handle click of instantiated object.
Top-down (parent handles all child object clicks) or botton-up (each children handles it's own clicks and signals parent (or calls parent's function)

Problem is that I don't know internals of godot, is it big burden to engine if 200 child object handle their own clicked status or is it better to handle it from parent level (one _input handler, one event per click etc??)

I'm not sure if "mouse click of object" is even visible to parents.. (or just visible to collision object)
https://docs.godotengine.org/en/3.1/tutorials/inputs/inputevent.html

4 If no one wanted the event so far, and a Camera is assigned to the Viewport, a ray to the physics world (in the ray direction from the click) will be cast. If this ray hits an object, it will call the CollisionObject.inputevent() function in the relevant physics object (bodies receive this callback by default, but areas do not. This can be configured through Area properties).

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.