Merge pull request #16505 from luiscuenca/zoomAndOrbitCamUsingTouchPad

Touchpad improvements: pinch to zoom camera, two finger swipe to look around, bug fixes
This commit is contained in:
Brad Hefta-Gaub 2019-11-19 13:30:45 -08:00 committed by GitHub
commit 3b9c997317
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 103 additions and 8 deletions

View file

@ -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" },

View file

@ -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));

View file

@ -13,6 +13,7 @@
#include <QtGui/QKeyEvent>
#include <QtGui/QMouseEvent>
#include <QtGui/QTouchEvent>
#include <QGesture>
#include <controllers/UserInputMapper.h>
#include <PathUtils.h>
@ -126,12 +127,60 @@ 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) {
// 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
QPoint delta = event->angleDelta();
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) {
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<QTouchEvent::TouchPoint>& points) {
@ -145,6 +194,37 @@ glm::vec2 evalAverageTouchPoints(const QList<QTouchEvent::TouchPoint>& 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: {
const float PINCH_DELTA_STEP = 0.04f;
qreal totalScaleFactor = pinchGesture->totalScaleFactor();
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;
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);
@ -167,7 +247,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);
@ -344,6 +424,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;
}

View file

@ -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,11 +84,13 @@ 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);
void wheelEvent(QWheelEvent* event);
bool isWheelByTouchPad(QWheelEvent* event);
static void enableTouch(bool enableTouch) { _enableTouch = enableTouch; }
@ -121,6 +126,7 @@ protected:
QPoint _previousCursor;
QPoint _mousePressPos;
quint64 _mousePressTime;
qreal _lastTotalScaleFactor;
bool _clickDeadspotActive;
glm::vec2 _lastTouch;
std::shared_ptr<InputDevice> _inputDevice { std::make_shared<InputDevice>() };
@ -130,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);