Files
ppsspp/Common/Input/GestureDetector.cpp

115 lines
3.0 KiB
C++
Raw Permalink Normal View History

2013-05-25 15:12:46 +02:00
// Unfinished.
// TODO:
// 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
2023-04-01 17:59:37 +02:00
#include <cstring>
#include "Common/TimeUtil.h"
#include "Common/Input/GestureDetector.h"
2013-05-25 15:12:46 +02:00
2013-08-20 11:35:54 +02:00
const float estimatedInertiaDamping = 0.75f;
GestureDetector::GestureDetector() {
2017-05-04 08:57:06 +02:00
memset(pointers, 0, sizeof(pointers));
}
TouchInput GestureDetector::Update(const TouchInput &touch, const Bounds &bounds) {
if (touch.id < 0 || touch.id >= MAX_PTRS) {
return touch;
}
2013-05-25 15:12:46 +02:00
// Mouse / 1-finger-touch control.
Pointer &p = pointers[touch.id];
2013-05-25 16:52:27 +02:00
if ((touch.flags & TOUCH_DOWN) && bounds.Contains(touch.x, touch.y)) {
2013-05-25 15:12:46 +02:00
p.down = true;
p.downTime = time_now_d();
p.downX = touch.x;
p.downY = touch.y;
p.lastX = touch.x;
p.lastY = touch.y;
p.distanceX = 0.0f;
p.distanceY = 0.0f;
p.estimatedInertiaX = 0.0f;
p.estimatedInertiaY = 0.0f;
2013-05-25 15:12:46 +02:00
} else if (touch.flags & TOUCH_UP) {
p.down = false;
} else {
p.distanceX += fabsf(touch.x - p.lastX);
p.distanceY += fabsf(touch.y - p.lastY);
2013-08-20 11:35:54 +02:00
p.estimatedInertiaX += touch.x - p.lastX;
p.estimatedInertiaY += touch.y - p.lastY;
p.estimatedInertiaX *= estimatedInertiaDamping;
p.estimatedInertiaY *= estimatedInertiaDamping;
2013-08-20 11:35:54 +02:00
2013-05-25 15:12:46 +02:00
p.lastX = touch.x;
p.lastY = touch.y;
}
if (p.distanceY > p.distanceX) {
2013-05-25 15:12:46 +02:00
if (p.down) {
double timeDown = time_now_d() - p.downTime;
if (!p.active && p.distanceY * timeDown > 3) {
p.active |= GESTURE_DRAG_VERTICAL;
// Kill the drag. TODO: Only cancel the drag in one direction.
2013-05-25 16:52:27 +02:00
TouchInput inp2 = touch;
inp2.flags = TOUCH_UP | TOUCH_CANCEL;
2013-05-25 16:52:27 +02:00
return inp2;
2013-05-25 15:12:46 +02:00
}
} else {
p.active = 0;
2013-05-25 15:12:46 +02:00
}
}
if (p.distanceX > p.distanceY) {
if (p.down) {
double timeDown = time_now_d() - p.downTime;
if (!p.active && p.distanceX * timeDown > 3) {
p.active |= GESTURE_DRAG_HORIZONTAL;
// Kill the drag. TODO: Only cancel the drag in one direction.
TouchInput inp2 = touch;
inp2.flags = TOUCH_UP | TOUCH_CANCEL;
return inp2;
}
} else {
p.active = 0;
}
}
2013-05-25 16:52:27 +02:00
return touch;
2013-05-25 15:12:46 +02:00
}
2013-08-20 11:35:54 +02:00
void GestureDetector::UpdateFrame() {
for (int i = 0; i < MAX_PTRS; i++) {
pointers[i].estimatedInertiaX *= estimatedInertiaDamping;
pointers[i].estimatedInertiaY *= estimatedInertiaDamping;
}
2013-08-20 11:35:54 +02:00
}
bool GestureDetector::IsGestureActive(Gesture gesture, int touchId) const {
if (touchId < 0 || touchId >= MAX_PTRS)
return false;
return (pointers[touchId].active & gesture) != 0;
2013-05-25 15:12:46 +02:00
}
bool GestureDetector::GetGestureInfo(Gesture gesture, int touchId, float info[4]) const {
if (touchId < 0 || touchId >= MAX_PTRS)
return false;
2017-04-06 15:35:36 +02:00
memset(info, 0, sizeof(float) * 4);
if (!(pointers[touchId].active & gesture)) {
return false;
2013-08-20 11:35:54 +02:00
}
switch (gesture) {
case GESTURE_DRAG_HORIZONTAL:
2017-04-06 15:35:36 +02:00
info[0] = pointers[touchId].lastX - pointers[touchId].downX;
info[1] = pointers[touchId].estimatedInertiaX;
return true;
2013-08-20 11:35:54 +02:00
case GESTURE_DRAG_VERTICAL:
2017-04-06 15:35:36 +02:00
info[0] = pointers[touchId].lastY - pointers[touchId].downY;
info[1] = pointers[touchId].estimatedInertiaY;
return true;
default:
return false;
2013-05-25 15:12:46 +02:00
}
}