From cd6f9a774de6f6928ee7b441c51b2666bd283ce8 Mon Sep 17 00:00:00 2001 From: dante ruiz Date: Thu, 31 Oct 2019 14:38:14 -0700 Subject: [PATCH 1/5] implement gesture pinch to camera zoom --- .../resources/controllers/keyboardMouse.json | 2 ++ interface/src/Application.cpp | 5 ++- .../src/input-plugins/KeyboardMouseDevice.cpp | 33 +++++++++++++++++++ .../src/input-plugins/KeyboardMouseDevice.h | 5 +++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/interface/resources/controllers/keyboardMouse.json b/interface/resources/controllers/keyboardMouse.json index d6ecc540c2..11c80a4dd2 100644 --- a/interface/resources/controllers/keyboardMouse.json +++ b/interface/resources/controllers/keyboardMouse.json @@ -269,6 +269,8 @@ { "from": "Keyboard.MouseWheelDown", "to": "Actions.LATERAL_LEFT" }, { "from": "Keyboard.MouseWheelLeft", "to": "Actions.BOOM_OUT", "filters": [ { "type": "scale", "scale": 0.02 } ]}, { "from": "Keyboard.MouseWheelRight", "to": "Actions.BOOM_IN", "filters": [ { "type": "scale", "scale": 0.02 } ]}, + { "from": "Keyboard.GesturePinchOut", "to": "Actions.BOOM_OUT"}, + { "from": "Keyboard.GesturePinchIn", "to": "Actions.BOOM_IN"}, { "from": "Keyboard.Space", "to": "Actions.VERTICAL_UP" }, { "from": "Keyboard.R", "to": "Actions.ACTION1" }, diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 28e3368b30..221ab211f4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4871,6 +4871,9 @@ void Application::touchEndEvent(QTouchEvent* event) { } void Application::touchGestureEvent(QGestureEvent* event) { + if (_keyboardMouseDevice->isActive()) { + _keyboardMouseDevice->touchGestureEvent(event); + } if (_touchscreenDevice && _touchscreenDevice->isActive()) { _touchscreenDevice->touchGestureEvent(event); } @@ -6262,7 +6265,7 @@ void Application::update(float deltaTime) { myAvatar->setDriveKey(MyAvatar::TRANSLATE_Z, -1.0f * userInputMapper->getActionState(controller::Action::TRANSLATE_Z)); myAvatar->setDriveKey(MyAvatar::TRANSLATE_Y, userInputMapper->getActionState(controller::Action::TRANSLATE_Y)); myAvatar->setDriveKey(MyAvatar::TRANSLATE_X, userInputMapper->getActionState(controller::Action::TRANSLATE_X)); - if (deltaTime > FLT_EPSILON) { + if (deltaTime > FLT_EPSILON && userInputMapper->getActionState(controller::Action::TRANSLATE_CAMERA_Z) == 0.0f) { myAvatar->setDriveKey(MyAvatar::PITCH, -1.0f * userInputMapper->getActionState(controller::Action::PITCH)); myAvatar->setDriveKey(MyAvatar::YAW, -1.0f * userInputMapper->getActionState(controller::Action::YAW)); myAvatar->setDriveKey(MyAvatar::DELTA_PITCH, -1.0f * userInputMapper->getActionState(controller::Action::DELTA_PITCH)); diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index b1746951bb..50c9f6aa3b 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -145,6 +146,36 @@ glm::vec2 evalAverageTouchPoints(const QList& points) { return averagePoint; } +void KeyboardMouseDevice::touchGestureEvent(const QGestureEvent* event) { + QPinchGesture* pinchGesture = (QPinchGesture*) event->gesture(Qt::PinchGesture); + + if (pinchGesture) { + switch (pinchGesture->state()) { + case Qt::GestureStarted: + _lastTotalScaleFactor = pinchGesture->totalScaleFactor(); + break; + + case Qt::GestureUpdated: { + qreal totalScaleFactor = pinchGesture->totalScaleFactor(); + qreal scaleFactorDelta = totalScaleFactor - _lastTotalScaleFactor; + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_GESTURE_PINCH_POS).getChannel()].value = (float) (scaleFactorDelta > 0 ? scaleFactorDelta : 0.0f); + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_GESTURE_PINCH_NEG).getChannel()].value = (float) (scaleFactorDelta < 0 ? -scaleFactorDelta : 0.0f); + _lastTotalScaleFactor = totalScaleFactor; + break; + } + + case Qt::GestureFinished: { + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_GESTURE_PINCH_POS).getChannel()].value = 0.0f; + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_GESTURE_PINCH_NEG).getChannel()].value = 0.0f; + break; + } + + default: + break; + } + } +} + void KeyboardMouseDevice::touchBeginEvent(const QTouchEvent* event) { if (_enableTouch) { _isTouching = event->touchPointStates().testFlag(Qt::TouchPointPressed); @@ -344,6 +375,8 @@ controller::Input::NamedVector KeyboardMouseDevice::InputDevice::getAvailableInp availableInputs.append(Input::NamedPair(makeInput(TOUCH_AXIS_X_NEG), "TouchpadLeft")); availableInputs.append(Input::NamedPair(makeInput(TOUCH_AXIS_Y_POS), "TouchpadUp")); availableInputs.append(Input::NamedPair(makeInput(TOUCH_AXIS_Y_NEG), "TouchpadDown")); + availableInputs.append(Input::NamedPair(makeInput(TOUCH_GESTURE_PINCH_POS), "GesturePinchOut")); + availableInputs.append(Input::NamedPair(makeInput(TOUCH_GESTURE_PINCH_NEG), "GesturePinchIn")); }); return availableInputs; } diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h index f6921c8e23..f53190b6ad 100644 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h @@ -23,6 +23,7 @@ class QTouchEvent; class QKeyEvent; class QMouseEvent; class QWheelEvent; +class QGestureEvent; class KeyboardMouseDevice : public InputPlugin { Q_OBJECT @@ -60,6 +61,8 @@ public: TOUCH_AXIS_X_NEG, TOUCH_AXIS_Y_POS, TOUCH_AXIS_Y_NEG, + TOUCH_GESTURE_PINCH_POS, + TOUCH_GESTURE_PINCH_NEG, }; enum TouchButtonChannel { @@ -81,6 +84,7 @@ public: void mouseReleaseEvent(QMouseEvent* event); void eraseMouseClicked(); + void touchGestureEvent(const QGestureEvent* event); void touchBeginEvent(const QTouchEvent* event); void touchEndEvent(const QTouchEvent* event); void touchUpdateEvent(const QTouchEvent* event); @@ -121,6 +125,7 @@ protected: QPoint _previousCursor; QPoint _mousePressPos; quint64 _mousePressTime; + qreal _lastTotalScaleFactor; bool _clickDeadspotActive; glm::vec2 _lastTouch; std::shared_ptr _inputDevice { std::make_shared() }; From 1338cbd94338a4829f01e2c9555169a608b0726a Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Mon, 18 Nov 2019 11:38:12 -0700 Subject: [PATCH 2/5] Fix touch event timeout on mac and allow camera orbit using the touchpad on windows --- .../src/input-plugins/KeyboardMouseDevice.cpp | 60 ++++++++++++++++--- .../src/input-plugins/KeyboardMouseDevice.h | 3 + 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index 50c9f6aa3b..c1e937ac72 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -127,12 +127,53 @@ void KeyboardMouseDevice::mouseMoveEvent(QMouseEvent* event) { } } -void KeyboardMouseDevice::wheelEvent(QWheelEvent* event) { - auto currentMove = event->angleDelta() / 120.0f; - _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_X_POS).getChannel()].value = currentMove.x() > 0 ? currentMove.x() : 0; - _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_X_NEG).getChannel()].value = currentMove.x() < 0 ? -currentMove.x() : 0; - _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_Y_POS).getChannel()].value = currentMove.y() > 0 ? currentMove.y() : 0; - _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_Y_NEG).getChannel()].value = currentMove.y() < 0 ? -currentMove.y() : 0; +bool KeyboardMouseDevice::isWheelByTouchPad(QWheelEvent* event) { + QPoint delta = event->angleDelta(); + int deltaValueX = abs(delta.manhattanLength()); + int deltaValueY = abs(delta.manhattanLength()); + const int MAX_WHEEL_DELTA_REPEAT = 20; + const int COMMON_WHEEL_DELTA_VALUE = 120; + if (deltaValueX != 0) { + if (abs(_lastWheelDelta.x()) == deltaValueX) { + _wheelDeltaRepeatCount.setX(_wheelDeltaRepeatCount.x() + 1); + } else { + _wheelDeltaRepeatCount.setX(0); + } + return deltaValueX != COMMON_WHEEL_DELTA_VALUE && _wheelDeltaRepeatCount.x() < MAX_WHEEL_DELTA_REPEAT; + } + if (deltaValueY != 0) { + if (abs(_lastWheelDelta.y()) == deltaValueY) { + _wheelDeltaRepeatCount.setY(_wheelDeltaRepeatCount.y() + 1); + } else { + _wheelDeltaRepeatCount.setY(0); + } + return deltaValueY != COMMON_WHEEL_DELTA_VALUE && _wheelDeltaRepeatCount.y() < MAX_WHEEL_DELTA_REPEAT; + } + return false; +} + +void KeyboardMouseDevice::wheelEvent(QWheelEvent* event) { + if (isWheelByTouchPad(event)) { + // Check for horizontal and vertical scroll not triggered by the mouse. + // These are most likelly triggered by two fingers gesture on touchpad for windows. + QPoint delta = event->angleDelta(); + float deltaX = (float)delta.x(); + float deltaY = (float)delta.y(); + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_X_POS).getChannel()].value = (deltaX > 0 ? deltaX : 0.0f); + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_X_NEG).getChannel()].value = (deltaX < 0 ? -deltaX : 0.0f); + // Y mouse is inverted positive is pointing up the screen + const float WHEEL_Y_ATTENUATION = 0.02f; + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_Y_POS).getChannel()].value = (deltaY < 0 ? -WHEEL_Y_ATTENUATION * deltaY : 0.0f); + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_Y_NEG).getChannel()].value = (deltaY > 0 ? WHEEL_Y_ATTENUATION * deltaY : 0.0f); + } else { + auto currentMove = event->angleDelta() / 120.0f; + float currentMoveX = (float)currentMove.x(); + float currentMoveY = (float)currentMove.y(); + _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_X_POS).getChannel()].value = currentMoveX > 0 ? currentMoveX : 0.0f; + _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_X_NEG).getChannel()].value = currentMoveX < 0 ? -currentMoveX : 0.0f; + _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_Y_POS).getChannel()].value = currentMoveY > 0 ? currentMoveY : 0.0f; + _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_Y_NEG).getChannel()].value = currentMoveY < 0 ? -currentMoveY : 0.0f; + } } glm::vec2 evalAverageTouchPoints(const QList& points) { @@ -156,10 +197,11 @@ void KeyboardMouseDevice::touchGestureEvent(const QGestureEvent* event) { break; case Qt::GestureUpdated: { + const float PINCH_DELTA_STEP = 0.05f; qreal totalScaleFactor = pinchGesture->totalScaleFactor(); qreal scaleFactorDelta = totalScaleFactor - _lastTotalScaleFactor; - _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_GESTURE_PINCH_POS).getChannel()].value = (float) (scaleFactorDelta > 0 ? scaleFactorDelta : 0.0f); - _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_GESTURE_PINCH_NEG).getChannel()].value = (float) (scaleFactorDelta < 0 ? -scaleFactorDelta : 0.0f); + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_GESTURE_PINCH_POS).getChannel()].value = scaleFactorDelta > 0.0 ? PINCH_DELTA_STEP : 0.0f; + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_GESTURE_PINCH_NEG).getChannel()].value = scaleFactorDelta < 0.0 ? PINCH_DELTA_STEP : 0.0f; _lastTotalScaleFactor = totalScaleFactor; break; } @@ -198,7 +240,7 @@ void KeyboardMouseDevice::touchUpdateEvent(const QTouchEvent* event) { _lastTouchTime = _clock.now(); if (!_isTouching) { - _isTouching = event->touchPointStates().testFlag(Qt::TouchPointPressed); + _isTouching = true; } else { auto currentMove = currentPos - _lastTouch; _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_X_POS).getChannel()].value = (currentMove.x > 0 ? currentMove.x : 0.0f); diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h index f53190b6ad..4286ced477 100644 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h @@ -90,6 +90,7 @@ public: void touchUpdateEvent(const QTouchEvent* event); void wheelEvent(QWheelEvent* event); + bool isWheelByTouchPad(QWheelEvent* event); static void enableTouch(bool enableTouch) { _enableTouch = enableTouch; } @@ -135,6 +136,8 @@ protected: std::chrono::high_resolution_clock::time_point _lastTouchTime; static bool _enableTouch; + QPoint _lastWheelDelta; + QPoint _wheelDeltaRepeatCount; private: void updateDeltaAxisValue(int channel, float value); From e06e1bb377146dabe173abe7cd728cc76a3bf0f3 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Mon, 18 Nov 2019 14:49:35 -0700 Subject: [PATCH 3/5] Fix wheel touch interference with mac camera orbit --- .../src/input-plugins/KeyboardMouseDevice.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index c1e937ac72..5a39781430 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -128,9 +128,12 @@ void KeyboardMouseDevice::mouseMoveEvent(QMouseEvent* event) { } bool KeyboardMouseDevice::isWheelByTouchPad(QWheelEvent* event) { +#ifdef Q_OS_MAC + return false; +#endif QPoint delta = event->angleDelta(); - int deltaValueX = abs(delta.manhattanLength()); - int deltaValueY = abs(delta.manhattanLength()); + int deltaValueX = abs(delta.x()); + int deltaValueY = abs(delta.y()); const int MAX_WHEEL_DELTA_REPEAT = 20; const int COMMON_WHEEL_DELTA_VALUE = 120; if (deltaValueX != 0) { From f1a9f52ee1f75ac3151d2a77e16f7066d15ee9c3 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Mon, 18 Nov 2019 15:59:45 -0700 Subject: [PATCH 4/5] Set pinch to unzoom --- .../input-plugins/src/input-plugins/KeyboardMouseDevice.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index 5a39781430..9df9bda71b 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -200,9 +200,9 @@ void KeyboardMouseDevice::touchGestureEvent(const QGestureEvent* event) { break; case Qt::GestureUpdated: { - const float PINCH_DELTA_STEP = 0.05f; + const float PINCH_DELTA_STEP = 0.04f; qreal totalScaleFactor = pinchGesture->totalScaleFactor(); - qreal scaleFactorDelta = totalScaleFactor - _lastTotalScaleFactor; + qreal scaleFactorDelta = _lastTotalScaleFactor - totalScaleFactor; _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_GESTURE_PINCH_POS).getChannel()].value = scaleFactorDelta > 0.0 ? PINCH_DELTA_STEP : 0.0f; _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_GESTURE_PINCH_NEG).getChannel()].value = scaleFactorDelta < 0.0 ? PINCH_DELTA_STEP : 0.0f; _lastTotalScaleFactor = totalScaleFactor; From 45aca5115d534e7c3fe59a0c20b9c0c289d1a210 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 19 Nov 2019 12:20:54 -0700 Subject: [PATCH 5/5] Add missing comment --- .../input-plugins/src/input-plugins/KeyboardMouseDevice.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index 9df9bda71b..f17caf22db 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -128,6 +128,10 @@ void KeyboardMouseDevice::mouseMoveEvent(QMouseEvent* event) { } bool KeyboardMouseDevice::isWheelByTouchPad(QWheelEvent* event) { + // This function is only used to track two finger swipe using the touchPad on Windows. + // That gesture gets sent as a wheel event. This wheel delta values are used to orbit the camera. + // On MacOS the two finger swipe fires touch events and wheel events. + // In that case we always return false to avoid interference between both. #ifdef Q_OS_MAC return false; #endif