blob: f2aeca7999bdd270c4faa6aba2597ab6f006edc0 (
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
|
extends Control
const VELOCITY_DECAYING_FACTOR: float = 5.5
const DRAG_THRESHOLD_CM: float = 0.250
var pointer: Dictionary
var anchor: float
var offset: float
var screen_dpcm: float
onready var target: Control = get_parent()
onready var target_scroll: VScrollBar = get_parent().get_v_scroll()
func _ready():
pointer = {
index = -1,
initial_position = Vector2.ZERO,
current_position = Vector2.ZERO,
velocity = Vector2.ZERO,
was_dragged = false,
is_active = false,
}
screen_dpcm = float(OS.get_screen_dpi()) / 2.54
func _process(delta: float):
if pointer.is_active:
var dragged_distance: float = - (pointer.current_position.y - pointer.initial_position.y)
offset = anchor + dragged_distance
self.target_scroll.value = offset
elif pointer.velocity.length() > 0.5:
pointer.velocity *= clamp((1.0 - VELOCITY_DECAYING_FACTOR * delta), 0.0, 1.0)
offset -= pointer.velocity.y * delta
self.target_scroll.value = offset
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_active == false || pointer.index == event.index):
var touch := event as InputEventScreenTouch
pointer.is_active = event.pressed
pointer.current_position = touch.position
if pointer.is_active:
pointer.index = touch.index
pointer.initial_position = touch.position
anchor = self.target_scroll.value
else:
if pointer.was_dragged == false: # Click detected.
simulate_gui_click()
pointer.index = -1
pointer.was_dragged = false
if event is InputEventScreenDrag && event.index == pointer.index:
var drag := event as InputEventScreenDrag
pointer.current_position = drag.position
pointer.velocity = drag.speed
if pointer.current_position.distance_to(pointer.initial_position) / screen_dpcm > DRAG_THRESHOLD_CM:
pointer.was_dragged = true
func simulate_gui_click():
var position := self.get_global_mouse_position() - target.rect_global_position
var event_touch := InputEventScreenTouch.new()
event_touch.index = 0
event_touch.position = position
var event_mouse := InputEventMouseButton.new()
event_mouse.button_index = BUTTON_LEFT
event_mouse.button_mask = BUTTON_MASK_LEFT
event_mouse.position = position
event_mouse.pressed = true
event_touch.pressed = true
target._gui_input(event_mouse)
target._gui_input(event_touch)
event_mouse.pressed = false
event_touch.pressed = false
target._gui_input(event_mouse)
target._gui_input(event_touch)
|