How do you get an Area2D to send a signal to the main Node when the mouse enters said Area2D

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Noob_Maker
:warning: Old Version Published before Godot 3 was released.

Or to be more specific, how do you get an Area2D(it’s a child node) to send a signal to the main Node(Area2D is the child of this node) when the mouse enters said Area2D? I’m asking this because I’m using a mouse_enter() signal for my Area2D child node so that it will detect if the mouse hovers into the main node. I’m using a simple click and drag interaction because I’m making a game where you left click things to interact which is essentially EVERYTHING from UI to NPC interactions. Any tips and/or suggestions?

Here’s the code for the object. Please keep in mind that the signal is connected via Godot’s own set of signals and not manually.

extends Node2D
var Click = Input.is_action_pressed("Interaction")
var Ready = null

func _ready():
	set_fixed_process(true)#I used this when I was testing the main aspect of what I want the object to do
	get_node("Position2D")

func _on_Area2D_mouse_enter():
	Click = Input.is_action_pressed("Interaction")
	if Click ==  true:
		set_global_pos(get_global_mouse_pos())

You can add your own signal to your script by adding signal name_of_signal and emitting it in the function which is called when the mouse enters the Area2D using emit_signal("name_of_signal"). Then you can connect the signal via Godot or manually from script.

tam0705 | 2017-06-30 03:06

I KNEW THAT WAS THE PROBLEM! Thank you very much. I just need to go back to that video on how to make custom signals ^-^

Noob_Maker | 2017-06-30 11:34

…It didn’t work. I don’t know what’s the problem.

Here’s the Area2D script:

extends Area2D

signal MouseHover

func _ready():
	set_fixed_process(true)


func _on_Area2D_mouse_enter():
	if true:
		emit_signal("MouseHover")

and here’s the main Node’s script which Area2D is communicating with:

extends Node2D
var Click = Input.is_action_pressed("Interaction")
var Ready = null

func _ready():
	set_fixed_process(true)#I used this when I was testing the main aspect of what I want the object to do
	get_node("Area2D").connect("mouse_enter", self, "MouseHover")

func MouseHover():
	print ("THE MOUSE IS HOVERING!!!")

Noob_Maker | 2017-06-30 14:07

I’m not sure if Input will work right inside a signal, you can try to use _input_event for event detection inside the area instead.

Look at the “Area 2D input events” demo.

eons | 2017-07-03 10:48

:bust_in_silhouette: Reply From: Will Nations

When I tried it in the current Godot 3.0 build, for whatever reason it seemed like Area2D’s mouse_entered and mouse_exited events weren’t firing properly. Maybe this is a long-standing bug even in 2.1.x?

When I changed the parent node to be a Control item like a PanelContainer, put the Area2D under that, and used the Control’s mouse_entered and mouse_exited events, it worked fine.

Here is the code that I wrote. Assuming a .tscn with the root as a PanelContainer with name “PanelContainer” and a single child Area2D node with name “Area2D”

NOTE: You can also do this in JUST a Container-derived class, without the child class at all. I have written up an example here

# "PanelContainer"
extends PanelContainer

func _ready():
    connect("mouse_entered", get_node("Area2D"), "on_mouse_entered")
    connect("mouse_exited", get_node("Area2D"), "on_mouse_exited")

func on_mouse_hovering(p_mouse_position, p_mouse_speed):
    print("hovering at position " + str(p_mouse_position) + " with velocity " + str(p_mouse_speed))

# Area2D
extends Area2D

signal mouse_hovering(position, velocity)

var is_hovering = false
export var hover_emission_rate = 1.0
var hover_accumulator = 0.0

func _ready():
    set_fixed_process(true)
    connect("mouse_hovering", get_parent(), "on_mouse_hovering")

func _fixed_process(delta):
    hover_accumulator += delta
    if is_hovering && hover_accumulator >= hover_emission_rate:
        var true_speed = Vector2(0,0)
        # if we changed position
        if get_viewport().get_mouse_position() != last_mouse_position:
            # then grab the latest mouse velocity
            true_speed = Input.get_last_mouse_speed()
        # Regardless, update the last known mouse position
        last_mouse_position = get_viewport().get_mouse_position()
        emit_signal("mouse_hovering", last_mouse_position, true_speed)
        while hover_accumulator >= hover_emission_rate:
            hover_accumulator -= hover_emission_rate

func on_mouse_entered():
    is_hovering = true

func on_mouse_exited():
    is_hovering = false