Reputation: 45
I was trying to make a set of Area2Ds that would display a value when the mouse is hovering over them. They're children of a control node (technically children of buttons in that node, the exact order is Control > Panel > Panel > Vbox > Hbox > Button > Area2D, yes the two panels are not a typo, no I'm not good at UI design). The control node has it's own scene where I edit it, and when I run just that scene everything works fine. The issue arises when I bring it into my main scene, everything loads correctly, but the Area2Ds no longer work. I have absolutely no idea why this is.
I've checked that the collision layers of the Area2Ds and the mouse tracker aren't somehow changed, I've confirmed that the Area2Ds aren't being deleted or moved out of place or having their collision shapes changed, I've tried changing the Mouse Filter setting in the control node since I saw someone with a (seemingly) similar issue who was able to solve it that way. No luck
Any help on figuring this out would be massively appreciated, thanks.
Alternatively, if there's a way for buttons to send a signal when the mouse is hovering over them that would also be useful.
Upvotes: 1
Views: 263
Reputation: 40295
I have to assume either something is up with the coordinates, or the mouse event simply won't reach the Area2D
inside a Button
(in fact, it sounds likely to me that the Button
shallows these events).
Regardless, you should NOT need an Area2D
for this.
First of all, I should also note that Control
has mouse_entered
and mouse_exited
signals. However, they will consider that the mouse exited when it is hovering a child Control
, which might or might not be what you want.
Since you are working on a Control
, I suspect what you want is _gui_input
. You can get the mouse position in local coordinates in _gui_input
like this:
First make sure the InputEvent
you get InputEventMouse
:
func _gui_input(event: InputEvent) -> void:
var mouse_event := event as InputEventMouse
if mouse_event != null:
var local_mouse_pos = mouse_event.position
You could emit your own signal from there, or do whatever you need.
Assuming _gui_input
does not work for you, then you could use good old _input
. The caveat is that the position you get is in viewport coordinates, so it requires a conversion:
func _input(event: InputEvent) -> void:
var mouse_event := event as InputEventMouse
if mouse_event != null:
var local_mouse_pos = make_input_local(mouse_event).position
Here make_input_local
will convert from viewport to local coordinates of the CanvasItem
(which includes all Node2D
s, such as Area2D
... And also Control
s, such as a Button
).
And again, you could emit your own signal from there, or do whatever you need.
If everything else fails...
From a CanvasItem
you can use get_local_mouse_position
to get the mouse position in local coordinates.
var local_mouse_pos := get_local_mouse_position()
Then you can check if that position is inside the Control
's size
:
var local_mouse_pos := get_local_mouse_position()
var hovering := Rect2(Vector2(), size).has_point(local_mouse_pos)
You could run that code in _process
so you have it updated every frame. And using that information you can emit a custom signal or whatever you need.
Upvotes: 0