aboutsummaryrefslogtreecommitdiff
path: root/pointer_input_sensor.gd
blob: 95e1b4bf9af062addb642258e5d8bab685680976 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
extends Control
class_name PointerInputSensor

export var drag_threshold_cm: float = 0.250

signal on_press
signal on_release
#signal on_release_outside
signal on_click
signal on_enter
signal on_exit
#signal on_exit_app_window
signal on_begin_drag
signal on_drag
signal on_end_drag

class PointerInputData:
	var target: PointerInputSensor
	var index := -1
	var initial_position := Vector2.ZERO
	var current_position := Vector2.ZERO
	var relative_position = Vector2.ZERO
	var velocity := Vector2.ZERO
	var was_dragged := false
	var is_pressed := false

var pointer: PointerInputData
var screen_dpcm: float
var on_process: FuncRef


func _ready():
	screen_dpcm = float(OS.get_screen_dpi()) / 2.54
	pointer = PointerInputData.new()
	pointer.target = self
	connect("mouse_entered", self, "_on_enter_exit", [true])
	connect("mouse_entered", self, "_on_enter_exit", [false])


func _process(delta: float):
	if on_process != null && on_process.is_valid():
		on_process.call_func(delta, self)


func _on_enter_exit(is_inside: bool):
	emit_signal("on_enter" if is_inside else "on_exit", pointer)


func _gui_input(event: InputEvent):
	
	# @DAM A bug on GODOT-3.X makes events from non-mouse-emulated pointers (index > 0) unreliable.
	if event is InputEventScreenTouch || event is InputEventScreenDrag:
		if event.index != 0:
			return
	
	if event is InputEventScreenTouch && (pointer.is_pressed == false || pointer.index == event.index):
		var touch := event as InputEventScreenTouch
		pointer.is_pressed = event.pressed
		pointer.current_position = get_global_mouse_position()
		if pointer.is_pressed:
			pointer.index = touch.index
			pointer.initial_position = get_global_mouse_position()
			emit_signal("on_press", pointer)
		else:
			emit_signal("on_release", pointer)
			if pointer.was_dragged == false:
				emit_signal("on_click", pointer)
			else:
				emit_signal("on_end_drag", pointer)
			pointer.index = -1
			pointer.was_dragged = false
	
	if event is InputEventScreenDrag && event.index == pointer.index:
		var drag := event as InputEventScreenDrag
		pointer.current_position = get_global_mouse_position()
		pointer.velocity = drag.speed
		pointer.relative_position = drag.relative
		# @DAM Instead of constantly converting the pointer distance to cm... just conver the drag_threshold_cm to pixels
		if pointer.was_dragged == false && pointer.current_position.distance_to(pointer.initial_position) / screen_dpcm > drag_threshold_cm:
			pointer.was_dragged = true
			emit_signal("on_begin_drag", pointer)
		emit_signal("on_drag", pointer)