How do you send a mouse click via gdscript?

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

I need to programatically “click” on items using the joystick. I’ve attempted a few methods to cause a left mouse click on whatever the mouse cursor is hovering over but I have had no luck. Here is what I’ve tried so far:

if event.is_action_pressed("ui_accept"):
    Input.action_press("mouse_click")

And

if event.is_action_pressed("ui_accept"):
    event.set_as_action("mouse_click", true)

“mouse_click” is simply set to the left mouse button in the Input Mappings. So it most likely isn’t actually triggering a true click event. My game has lots of control widgets and I can’t think of an easy way outside of causing a mouse down signal to know what the the user intends to click on.

:bust_in_silhouette: Reply From: Shin-NiL

If your item is a button, you can try emit a pressed signal. Something like this:

my_button.emit_signal("pressed")

It could be any control or object on the screen the user could click on with a mouse.

zombieCraig | 2016-03-04 03:59

This doesn’t work. It only simulates that button emitting the pressed signal. It doesn’t actually press the button.

This matters in the case of a toggle button. It won’t toggle.

Allen Kennedy Jr. | 2020-06-24 23:12

:bust_in_silhouette: Reply From: PixelWizzard

I prefer to do it like this:

if Input.is_action_pressed("mouse_click"):
pass #whatever you want to do here

Note: You can still drag while holding down and it will trigger :stuck_out_tongue: Might return unexpected results, haha.

wombatTurkey | 2016-05-26 20:54

:bust_in_silhouette: Reply From: Akien

You could add other inputs for the mouse_click action, e.g. you should be able to assign a joystick button to act as mouse click. This way you wouldn’t have to handle faking mouse clicks yourself, as both a physical mouse click and a joystick input would be considered as the same actions.

If you do need to send a physical mouse click event from GDScript though, you can do that too. You need to craft an event, and send it. Something like:

var event = InputEvent()
event.type = InputEvent.MOUSE_BUTTON
event.button_index = BUTTON_LEFT
event.pos = selected_button.get_pos() # add here the proper position
get_tree().input_event(event)

(see the docs about InputEvent, InputEventMouseButton and @Global Scope

Alternatively you could also create an InputEventAction, see e.g. the InputEvent tutorial.

This is exactly what I was looking for. I didn’t now how to pass the created InputEvent back into the stack to be processed. I have a screen of sliders and buttons. Using get_tree().input_event(event) still didn’t seem to cause the click on the controls. But I feel I’m on the right track.

zombieCraig | 2016-03-04 22:28

In my above code snippet, I had forgotten to define the position of the mouse click event, I’ve fixed that.

Akien | 2016-03-04 22:49

You might also need to set event.pressed = true, I’m not sure. Check the class reference and experiment :slight_smile:

Akien | 2016-03-04 22:51

Got to work! You need to send event.pressed = true followed by a false to simulate a “click”

	var evt = InputEvent()
	evt.type = InputEvent.MOUSE_BUTTON
	evt.button_index = BUTTON_LEFT
	evt.pos = self.get_global_mouse_pos()
	evt.pressed = true
	get_tree().input_event(evt)
	evt.pressed = false
	get_tree().input_event(evt)

zombieCraig | 2016-03-04 22:56

This helped me out a lot! Exactly what I was looking for! Thank you!

For anyone coming across this using Godot 3.2, I found a few minor modifications were needed. The following function worked for me:

func click_the_left_mouse_button():
    var evt = InputEventMouseButton.new()
    evt.button_index = BUTTON_LEFT
    evt.position = get_viewport().get_mouse_position()
    evt.pressed = true
    get_tree().input_event(evt)
    evt.pressed = false
    get_tree().input_event(evt)	

Smij | 2019-07-07 17:31