How to detect both click and doubleclick on the same control separately

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By fur-id

Hello. I can’t figure out how to detect both click and doubleclick on the same control separately. Is it ever possible?

Simple test

func _on_gui_input(ev):
	if ev is InputEventMouseButton:
		printt(ev.pressed, ev.doubleclick)

shows that:

click is 2 events

mouse_down = pressed and not doubleclick
mouse_up = not pressed and not doubleclick

doubleclick is 4 events

mouse_down = pressed and not doubleclick
mouse_up = not pressed and not doubleclick
mouse_down = pressed and doubleclick
mouse_up = not pressed and not doubleclick

First 2 events are exactly the same as click and click will be fired too even if I doubleclicked only.

:bust_in_silhouette: Reply From: coffeeDragon

Well just check if it was doubleClicked before you check if it was just clicked:

func _on_gui_input(ev):
	if ev is InputEventMouseButton:
		if ev.doubleclick:
			pass
			#do on double click
		elif ev.pressed:
			pass
			#do on simple click
		printt(ev.pressed, ev.doubleclick)

This would be fine if it worked.

extends Area2D

func _on_Area2D_input_event(viewport, event, shape_idx):
	if event is InputEventMouseButton and event.button_index == BUTTON_LEFT:
		if event.doubleclick:
			printt("doubleclick")
		elif event.pressed:
			printt("pressed")

And the output is

pressed
doubleclick

This issue has been haunting me for quite a while, is it a bug in Godot?

mjtorn | 2018-11-28 09:29

:bust_in_silhouette: Reply From: GrayDwarf

Better late than never?

One decent way is to use a timer. For example, start a 0.2 timer (adjust time as needed) in the MouseUp event. If DblClick fires, it will set the _mouseEvent which we can check before triggering the MouseUp workflow.

gui_input(event):
  if event is InputEventMouseButton and event.button_index == BUTTON_LEFT and event.doubleclick:
    _mouseEvent = "DblClick"
    DoSomething()
  elif event is InputEventMouseButton and event.button_index == BUTTON_LEFT and !event.is_pressed():
     _mouseUpTimer.start()

When the timer finishes, check the _mouseEvent variable to see if the DblClick event was triggered. If so, reset the variable and return. If it wasn’t, perform the MouseUp workflow. MouseDown can be handled in a similar fashion.

func _on_MouseUpTimer_timeout():
  if _mouseEvent == "DblClick":
    _mouseEvent = ""
    return

  DoSomethingForMouseUpEvent()