CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/Common/Input/GestureDetector.cpp
Views: 1401
1
// Unfinished.
2
// TODO:
3
// Zoom gesture a la http://www.zdnet.com/blog/burnette/how-to-use-multi-touch-in-android-2-part-6-implementing-the-pinch-zoom-gesture/1847
4
5
#include <cstring>
6
7
#include "Common/TimeUtil.h"
8
#include "Common/Input/GestureDetector.h"
9
10
const float estimatedInertiaDamping = 0.75f;
11
12
GestureDetector::GestureDetector() {
13
memset(pointers, 0, sizeof(pointers));
14
}
15
16
TouchInput GestureDetector::Update(const TouchInput &touch, const Bounds &bounds) {
17
if (touch.id < 0 || touch.id >= MAX_PTRS) {
18
return touch;
19
}
20
// Mouse / 1-finger-touch control.
21
Pointer &p = pointers[touch.id];
22
if ((touch.flags & TOUCH_DOWN) && bounds.Contains(touch.x, touch.y)) {
23
p.down = true;
24
p.downTime = time_now_d();
25
p.downX = touch.x;
26
p.downY = touch.y;
27
p.lastX = touch.x;
28
p.lastY = touch.y;
29
p.distanceX = 0.0f;
30
p.distanceY = 0.0f;
31
p.estimatedInertiaX = 0.0f;
32
p.estimatedInertiaY = 0.0f;
33
} else if (touch.flags & TOUCH_UP) {
34
p.down = false;
35
} else {
36
p.distanceX += fabsf(touch.x - p.lastX);
37
p.distanceY += fabsf(touch.y - p.lastY);
38
39
p.estimatedInertiaX += touch.x - p.lastX;
40
p.estimatedInertiaY += touch.y - p.lastY;
41
p.estimatedInertiaX *= estimatedInertiaDamping;
42
p.estimatedInertiaY *= estimatedInertiaDamping;
43
44
p.lastX = touch.x;
45
p.lastY = touch.y;
46
}
47
48
if (p.distanceY > p.distanceX) {
49
if (p.down) {
50
double timeDown = time_now_d() - p.downTime;
51
if (!p.active && p.distanceY * timeDown > 3) {
52
p.active |= GESTURE_DRAG_VERTICAL;
53
// Kill the drag. TODO: Only cancel the drag in one direction.
54
TouchInput inp2 = touch;
55
inp2.flags = TOUCH_UP | TOUCH_CANCEL;
56
return inp2;
57
}
58
} else {
59
p.active = 0;
60
}
61
}
62
63
if (p.distanceX > p.distanceY) {
64
if (p.down) {
65
double timeDown = time_now_d() - p.downTime;
66
if (!p.active && p.distanceX * timeDown > 3) {
67
p.active |= GESTURE_DRAG_HORIZONTAL;
68
// Kill the drag. TODO: Only cancel the drag in one direction.
69
TouchInput inp2 = touch;
70
inp2.flags = TOUCH_UP | TOUCH_CANCEL;
71
return inp2;
72
}
73
} else {
74
p.active = 0;
75
}
76
}
77
78
return touch;
79
}
80
81
void GestureDetector::UpdateFrame() {
82
for (int i = 0; i < MAX_PTRS; i++) {
83
pointers[i].estimatedInertiaX *= estimatedInertiaDamping;
84
pointers[i].estimatedInertiaY *= estimatedInertiaDamping;
85
}
86
}
87
88
bool GestureDetector::IsGestureActive(Gesture gesture, int touchId) const {
89
if (touchId < 0 || touchId >= MAX_PTRS)
90
return false;
91
return (pointers[touchId].active & gesture) != 0;
92
}
93
94
bool GestureDetector::GetGestureInfo(Gesture gesture, int touchId, float info[4]) const {
95
if (touchId < 0 || touchId >= MAX_PTRS)
96
return false;
97
memset(info, 0, sizeof(float) * 4);
98
if (!(pointers[touchId].active & gesture)) {
99
return false;
100
}
101
102
switch (gesture) {
103
case GESTURE_DRAG_HORIZONTAL:
104
info[0] = pointers[touchId].lastX - pointers[touchId].downX;
105
info[1] = pointers[touchId].estimatedInertiaX;
106
return true;
107
case GESTURE_DRAG_VERTICAL:
108
info[0] = pointers[touchId].lastY - pointers[touchId].downY;
109
info[1] = pointers[touchId].estimatedInertiaY;
110
return true;
111
default:
112
return false;
113
}
114
}
115
116