aboutsummaryrefslogtreecommitdiff
path: root/pointer_input_sensor.gd
blob: be4d158cc65de6e7eb8f7ec8296010c589d3f991 (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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
extends Control
class_name PointerInputSensor

# All on_ACTION signals have a single argument of type PointerInputData.
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
signal on_scroll

enum PointerInputAction {
	UNDEFINED,
	ON_PRESS,
	ON_RELEASE,
#	ON_RELEASE_OUTSIDE,
	ON_CLICK,
	ON_ENTER,
	ON_EXIT,
#	ON_EXIT_APP_WINDOW,
	ON_BEGIN_DRAG,
	ON_DRAG,
	ON_END_DRAG,
	ON_SCROLL,
}

class PointerInputData:
	var target: PointerInputSensor
	var event: InputEvent
	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 scroll := 0.0
	var action: int = PointerInputAction.UNDEFINED


export var drag_threshold_cm: float = 0.250

var pointer: PointerInputData
var screen_dpcm: float


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_exited", self, "_on_enter_exit", [false])


func _on_enter_exit(is_inside: bool):
	pointer.action = PointerInputAction.ON_ENTER if is_inside else PointerInputAction.ON_EXIT
	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
	
	pointer.event = event
#	pointer.index = -1
#	pointer.scroll = 0.0
#	pointer.action = PointerInputAction.UNDEFINED
#	pointer.velocity = Vector2.ZERO
	
	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()
			pointer.action = PointerInputAction.ON_PRESS
			emit_signal("on_press", pointer)
		else:
			pointer.action = PointerInputAction.ON_RELEASE
			emit_signal("on_release", pointer)
			if pointer.was_dragged == false:
				pointer.action = PointerInputAction.ON_CLICK
				emit_signal("on_click", pointer)
			else:
				pointer.action = PointerInputAction.ON_END_DRAG
				emit_signal("on_end_drag", pointer)
			pointer.index = -1
			pointer.was_dragged = false
			# @DAM Maybe add this.
#			pointer.initial_position = Vector2.ZERO
#			pointer.current_position = Vector2.ZERO
#			pointer.relative_position = Vector2.ZERO
	
	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
		if pointer.was_dragged == false && pointer.current_position.distance_to(pointer.initial_position) > drag_threshold_cm * screen_dpcm:
			pointer.was_dragged = true
			pointer.action = PointerInputAction.ON_BEGIN_DRAG
			emit_signal("on_begin_drag", pointer)
		pointer.action = PointerInputAction.ON_DRAG
		emit_signal("on_drag", pointer)
	
	# @DAM Clean this code please.
	if event is InputEventMouseButton && event.is_pressed():
		if event.button_index == BUTTON_WHEEL_UP || event.button_index == BUTTON_WHEEL_DOWN:
			pointer.scroll = -1.0 if event.button_index == BUTTON_WHEEL_UP else 1.0
			pointer.action = PointerInputAction.ON_SCROLL
			emit_signal("on_scroll", pointer)