From 19bf222ea423ab8f394c6f9219e84b87a50fde03 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 6 Apr 2017 15:51:00 +0200 Subject: [PATCH] Make the gesture detector treat all touches fully individually. Fixes issues with last commit. --- ext/native/input/gesture_detector.cpp | 57 +++++++++++++-------------- ext/native/input/gesture_detector.h | 18 ++++----- ext/native/ui/viewgroup.cpp | 8 ++-- 3 files changed, 39 insertions(+), 44 deletions(-) diff --git a/ext/native/input/gesture_detector.cpp b/ext/native/input/gesture_detector.cpp index a5ca7ef9e5..4c181413ed 100644 --- a/ext/native/input/gesture_detector.cpp +++ b/ext/native/input/gesture_detector.cpp @@ -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; diff --git a/ext/native/input/gesture_detector.h b/ext/native/input/gesture_detector.h index 8529096011..a5d028bc5d 100644 --- a/ext/native/input/gesture_detector.h +++ b/ext/native/input/gesture_detector.h @@ -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]{}; }; diff --git a/ext/native/ui/viewgroup.cpp b/ext/native/ui/viewgroup.cpp index e89a5efb97..52effb0861 100644 --- a/ext/native/ui/viewgroup.cpp +++ b/ext/native/ui/viewgroup.cpp @@ -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;