So I can detect mouse event like in code below. But I want to know what’s the best way to unselect an element. I want to detect a mouse click on elements that are area2D nodes (this works) but then a click on anything that’s not an area2D node should also do a function so I can unselect everything (this doesn’t work).
I tried a few options.
- _unhandled_input_event but it didn’t really seem to work, the click input just went through anyway while clicking on area2D elements or empty space.
- Placing an area2D node as a background to detect inputs. This works fine but I was unable to scale the collisionshape to scale with the viewport.
- _gui_input_event that was just weird and I soon gave up on that option
func _input(event):
var event_is_mouse_click: bool = (
event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed()
)
if event_is_mouse_click:
select_unit()
What is the parent node’s Type
that holds the children nodes you are clicking on?
There’s 2 types of entities currently.
- Literally just Area2D node as the parent
- CharacterBody2D > Area2D node as child
What I want to happen is to click on the background to execute a function. And not execute that function when I click on the entities.
ATM I don’t really have a quick answer, I am used to more DOM bubble type event handlers with a target, as far as I can see you would have to mediate scripts between the 2 targets individually.
BUT I am not an expert with the 2D stuff so I could be missing something similar.
This would be really easy with bubbling event graph.
So looking at that commit, this is basically adding an un-handled stage to the input flow correct?
Where you could override in any node to catch things like the above.
How about the 2nd solution I proposed then? Placing an Area2D on the background for click events. It works but I had trouble resizing my collisionshape2D to the viewport at different resolutions. I’m pretty sure there’s a handy script I could tag on the collisionshape to resize it according to the viewport dimensions.
I don’t have enough exp. with 2D to say what the best solution would be.
Thinking abstractly, I would want to listen to a parent of some kind, resize/bounds change signals/notifications, then figure out what the Area2D
immediate parent’s size/scale is, then calculate what’s needed to set the Area2D
to match it’s parent.
With 2D you have scaling and such, so the exact implementation is beyond me atm.
In the meantime I made a band-aid solution. Just added an invisible button on the entities (flat property enabled), and an Area_2D node on the background. Seems to work for now. The button eats up the mouse input and it doesn’t go through to the background.
The entities already have an Area_2D node attached so the only downside I’m wondering is the performance impact of having an additional button node on all entities.
1 Like
I noticed there was pickable
property on the Area2D
and CharacterBody2D
, no idea what they do, they are set to false
by default.
The pickable property needs to be true for it to “pick up” mouse events on it. Like mouse_clicks, mouse_entering and mouse_leaving. I’m pretty sure it auto sets to true if your script has a function with input events on that node.
OK, the auto-set thing had me confused, I would have NEVER guessed that.
I would think you add a listener and you get it explicitly. So seeing false
(not On) was confusing to say the least, that is actually why I mentioned it.
HA now I know. 
(Need to look at the C++ more in the future…)
So some more weird things. If I also put an invisible button on the background to track inputs. The input doesn’t go through if the button is a child of the CanvasLayer and the CanvasLayer has a Layer index of anything negative, like -2.
But it works if the CanvasLayer is a child of the Button.
Currently I’m unsure whether to use an Area2D or a an invisible Button on the background to track inputs. My guess is the button would be more performance friendly but I don’t really know.