Make the gesture detector treat all touches fully individually. Fixes issues with last commit.

This commit is contained in:
Henrik Rydgard 2017-04-06 15:51:00 +02:00
parent a8d6de26e3
commit 19bf222ea4
3 changed files with 39 additions and 44 deletions

View File

@ -9,14 +9,7 @@
const float estimatedInertiaDamping = 0.75f;
GestureDetector::GestureDetector()
: active_(0),
estimatedInertiaX_(0.0f),
estimatedInertiaY_(0.0f) {
memset(pointers, 0, sizeof(pointers));
}
TouchInput GestureDetector::Update(const TouchInput &touch, int scrollTouchId, const Bounds &bounds) {
TouchInput GestureDetector::Update(const TouchInput &touch, const Bounds &bounds) {
// Mouse / 1-finger-touch control.
Pointer &p = pointers[touch.id];
if ((touch.flags & TOUCH_DOWN) && bounds.Contains(touch.x, touch.y)) {
@ -28,50 +21,50 @@ TouchInput GestureDetector::Update(const TouchInput &touch, int scrollTouchId, c
p.lastY = touch.y;
p.distanceX = 0.0f;
p.distanceY = 0.0f;
estimatedInertiaX_ = 0.0f;
estimatedInertiaY_ = 0.0f;
p.estimatedInertiaX = 0.0f;
p.estimatedInertiaY = 0.0f;
} else if (touch.flags & TOUCH_UP) {
p.down = false;
} else {
p.distanceX += fabsf(touch.x - p.lastX);
p.distanceY += fabsf(touch.y - p.lastY);
estimatedInertiaX_ += touch.x - p.lastX;
estimatedInertiaY_ += touch.y - p.lastY;
estimatedInertiaX_ *= estimatedInertiaDamping;
estimatedInertiaY_ *= estimatedInertiaDamping;
p.estimatedInertiaX += touch.x - p.lastX;
p.estimatedInertiaY += touch.y - p.lastY;
p.estimatedInertiaX *= estimatedInertiaDamping;
p.estimatedInertiaY *= estimatedInertiaDamping;
p.lastX = touch.x;
p.lastY = touch.y;
}
if (touch.id == scrollTouchId && p.distanceY > p.distanceX) {
if (p.distanceY > p.distanceX) {
if (p.down) {
double timeDown = time_now_d() - p.downTime;
if (!active_ && p.distanceY * timeDown > 3) {
active_ |= GESTURE_DRAG_VERTICAL;
if (!p.active && p.distanceY * timeDown > 3) {
p.active |= GESTURE_DRAG_VERTICAL;
// Kill the drag
TouchInput inp2 = touch;
inp2.flags = TOUCH_UP | TOUCH_CANCEL;
return inp2;
}
} else {
active_ = 0;
p.active = 0;
}
}
if (touch.id == scrollTouchId && p.distanceX > p.distanceY) {
if (p.distanceX > p.distanceY) {
if (p.down) {
double timeDown = time_now_d() - p.downTime;
if (!active_ && p.distanceX * timeDown > 3) {
active_ |= GESTURE_DRAG_HORIZONTAL;
if (!p.active && p.distanceX * timeDown > 3) {
p.active |= GESTURE_DRAG_HORIZONTAL;
// Kill the drag
TouchInput inp2 = touch;
inp2.flags = TOUCH_UP | TOUCH_CANCEL;
return inp2;
}
} else {
active_ = 0;
p.active = 0;
}
}
@ -79,28 +72,34 @@ TouchInput GestureDetector::Update(const TouchInput &touch, int scrollTouchId, c
}
void GestureDetector::UpdateFrame() {
estimatedInertiaX_ *= estimatedInertiaDamping;
estimatedInertiaY_ *= estimatedInertiaDamping;
for (int i = 0; i < MAX_PTRS; i++) {
pointers[i].estimatedInertiaX *= estimatedInertiaDamping;
pointers[i].estimatedInertiaY *= estimatedInertiaDamping;
}
}
bool GestureDetector::IsGestureActive(Gesture gesture) const {
return (active_ & gesture) != 0;
bool GestureDetector::IsGestureActive(Gesture gesture, int touchId) const {
if (touchId < 0)
return false;
return (pointers[touchId].active & gesture) != 0;
}
bool GestureDetector::GetGestureInfo(Gesture gesture, int touchId, float info[4]) const {
if (touchId < 0)
return false;
memset(info, 0, sizeof(float) * 4);
if (!(active_ & gesture)) {
if (!(pointers[touchId].active & gesture)) {
return false;
}
switch (gesture) {
case GESTURE_DRAG_HORIZONTAL:
info[0] = pointers[touchId].lastX - pointers[touchId].downX;
info[1] = estimatedInertiaX_;
info[1] = pointers[touchId].estimatedInertiaX;
return true;
case GESTURE_DRAG_VERTICAL:
info[0] = pointers[touchId].lastY - pointers[touchId].downY;
info[1] = estimatedInertiaY_;
info[1] = pointers[touchId].estimatedInertiaY;
return true;
default:
return false;

View File

@ -16,14 +16,12 @@ enum Gesture {
// with the gesture you are interested in.
class GestureDetector {
public:
GestureDetector();
TouchInput Update(const TouchInput &touch, int scrollTouchId, const Bounds &bounds);
TouchInput Update(const TouchInput &touch, const Bounds &bounds);
void UpdateFrame();
bool IsGestureActive(Gesture gesture) const;
bool IsGestureActive(Gesture gesture, int touchId) const;
bool GetGestureInfo(Gesture gesture, int touchId, float info[4]) const;
private:
// jazzhands!
enum Locals {
MAX_PTRS = 10,
};
@ -39,13 +37,11 @@ private:
float deltaY;
float distanceX;
float distanceY;
float estimatedInertiaX;
float estimatedInertiaY;
uint32_t active;
};
Pointer pointers[MAX_PTRS];
uint32_t active_;
// For inertia estimation
float estimatedInertiaX_;
float estimatedInertiaY_;
Pointer pointers[MAX_PTRS]{};
};

View File

@ -752,7 +752,7 @@ void ScrollView::Touch(const TouchInput &input) {
TouchInput input2;
if (CanScroll()) {
input2 = gesture_.Update(input, scrollTouchId_, bounds_);
input2 = gesture_.Update(input, bounds_);
float info[4];
if (input.id == scrollTouchId_ && gesture_.GetGestureInfo(gesture, input.id, info) && !(input.flags & TOUCH_DOWN)) {
float pos = scrollStart_ - info[0];
@ -890,7 +890,7 @@ float ScrollView::ClampedScrollPos(float pos) {
Gesture gesture = orientation_ == ORIENT_VERTICAL ? GESTURE_DRAG_VERTICAL : GESTURE_DRAG_HORIZONTAL;
if (gesture_.IsGestureActive(gesture)) {
if (scrollTouchId_ != -1 && gesture_.IsGestureActive(gesture, scrollTouchId_)) {
float maxPull = bounds_.h * 0.1f;
if (pos < 0.0f) {
float dist = std::min(-pos * (1.0f / bounds_.h), 1.0f);
@ -951,14 +951,14 @@ void ScrollView::Update() {
} else {
scrollPos_ += (target - scrollPos_) * 0.3f;
}
} else if (inertia_ != 0.0f && !gesture_.IsGestureActive(gesture)) {
} else if (inertia_ != 0.0f && !gesture_.IsGestureActive(gesture, scrollTouchId_)) {
scrollPos_ -= inertia_;
inertia_ *= friction;
if (fabsf(inertia_) < stop_threshold)
inertia_ = 0.0f;
}
if (!gesture_.IsGestureActive(gesture)) {
if (!gesture_.IsGestureActive(gesture, scrollTouchId_)) {
scrollPos_ = ClampedScrollPos(scrollPos_);
pull_ *= friction;