From 6825274b65b366569ec58228b86abf226cc1fa60 Mon Sep 17 00:00:00 2001 From: Eric Johnston Date: Fri, 21 Jun 2013 13:43:23 -0700 Subject: [PATCH] Re-issue of change which adds two-finger touch look to avatar. The option is un-checked by default because of an unsolved problem: We're getting the events into Qt very slowly, so input from several seconds ago is still active when the user has stopped the touch action. This needs to be fixed before this can be turned on full-time. Corrections were made per feedback, and the change has been merged with the latest. --- interface/src/Application.cpp | 67 +++++++++++++++++++++++++++++++++++ interface/src/Application.h | 13 +++++++ interface/src/Avatar.cpp | 8 +++++ interface/src/Avatar.h | 1 + 4 files changed, 89 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 64020355d8..73816571fa 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -89,11 +89,14 @@ protected: virtual void mousePressEvent(QMouseEvent* event); virtual void mouseReleaseEvent(QMouseEvent* event); + virtual bool event(QEvent* event); + virtual void wheelEvent(QWheelEvent* event); }; void GLCanvas::initializeGL() { Application::getInstance()->initializeGL(); + setAttribute(Qt::WA_AcceptTouchEvents); } void GLCanvas::paintGL() { @@ -124,6 +127,25 @@ void GLCanvas::mouseReleaseEvent(QMouseEvent* event) { Application::getInstance()->mouseReleaseEvent(event); } +int updateTime = 0; +bool GLCanvas::event(QEvent* event) { + switch (event->type()) { + case QEvent::TouchBegin: + Application::getInstance()->touchBeginEvent(static_cast(event)); + event->accept(); + return true; + case QEvent::TouchEnd: + Application::getInstance()->touchEndEvent(static_cast(event)); + return true; + case QEvent::TouchUpdate: + Application::getInstance()->touchUpdateEvent(static_cast(event)); + return true; + default: + break; + } + return QGLWidget::event(event); +} + void GLCanvas::wheelEvent(QWheelEvent* event) { Application::getInstance()->wheelEvent(event); } @@ -146,6 +168,9 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _audioScope(256, 200, true), _mouseX(0), _mouseY(0), + _touchAvgX(0.0f), + _touchAvgY(0.0f), + _isTouchPressed(false), _mousePressed(false), _mouseVoxelScale(1.0f / 1024.0f), _justEditedVoxel(false), @@ -754,6 +779,40 @@ void Application::mouseReleaseEvent(QMouseEvent* event) { } } +void Application::touchUpdateEvent(QTouchEvent* event) { + bool validTouch = false; + if (activeWindow() == _window) { + const QList& tPoints = event->touchPoints(); + _touchAvgX = 0.0f; + _touchAvgY = 0.0f; + int numTouches = tPoints.count(); + if (numTouches > 1) { + for (int i = 0; i < numTouches; ++i) { + _touchAvgX += tPoints[i].pos().x(); + _touchAvgY += tPoints[i].pos().y(); + } + _touchAvgX /= (float)(numTouches); + _touchAvgY /= (float)(numTouches); + validTouch = true; + } + } + if (!_isTouchPressed) { + _touchDragStartedAvgX = _touchAvgX; + _touchDragStartedAvgY = _touchAvgY; + } + _isTouchPressed = validTouch; +} + +void Application::touchBeginEvent(QTouchEvent* event) { + touchUpdateEvent(event); +} + +void Application::touchEndEvent(QTouchEvent* event) { + _touchDragStartedAvgX = _touchAvgX; + _touchDragStartedAvgY = _touchAvgY; + _isTouchPressed = false; +} + void Application::wheelEvent(QWheelEvent* event) { if (activeWindow() == _window) { if (checkedVoxelModeAction() == 0) { @@ -1256,6 +1315,8 @@ void Application::initMenu() { _gyroLook->setChecked(false); (_mouseLook = optionsMenu->addAction("Mouse Look"))->setCheckable(true); _mouseLook->setChecked(true); + (_touchLook = optionsMenu->addAction("Touch Look"))->setCheckable(true); + _touchLook->setChecked(false); (_showHeadMouse = optionsMenu->addAction("Head Mouse"))->setCheckable(true); _showHeadMouse->setChecked(false); (_transmitterDrives = optionsMenu->addAction("Transmitter Drive"))->setCheckable(true); @@ -1581,6 +1642,12 @@ void Application::update(float deltaTime) { _glWidget->height()); } + // Update from Touch + if (_isTouchPressed && _touchLook->isChecked()) { + _myAvatar.updateFromTouch(_touchAvgX - _touchDragStartedAvgX, + _touchAvgY - _touchDragStartedAvgY); + } + // Read serial port interface devices if (_serialHeadSensor.isActive()) { _serialHeadSensor.readData(deltaTime); diff --git a/interface/src/Application.h b/interface/src/Application.h index b7211187de..06d48b9b4f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -66,6 +67,10 @@ public: void mousePressEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event); + void touchBeginEvent(QTouchEvent* event); + void touchEndEvent(QTouchEvent* event); + void touchUpdateEvent(QTouchEvent* event); + void wheelEvent(QWheelEvent* event); const glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail _mouseVoxel); @@ -183,6 +188,7 @@ private: QAction* _gyroLook; // Whether to allow the gyro data from head to move your view QAction* _renderAvatarBalls; // Switch between voxels and joints/balls for avatar render QAction* _mouseLook; // Whether the have the mouse near edge of screen move your view + QAction* _touchLook; // Whether a 2-finger touch may be used to control look direction QAction* _showHeadMouse; // Whether the have the mouse near edge of screen move your view QAction* _transmitterDrives; // Whether to have Transmitter data move/steer the Avatar QAction* _gravityUse; // Whether gravity is on or not @@ -268,6 +274,13 @@ private: int _mouseY; int _mouseDragStartedX; int _mouseDragStartedY; + + float _touchAvgX; + float _touchAvgY; + float _touchDragStartedAvgX; + float _touchDragStartedAvgY; + bool _isTouchPressed; // true if multitouch has been pressed (clear when finished) + VoxelDetail _mouseVoxelDragging; glm::vec3 _voxelThrust; bool _mousePressed; // true if mouse has been pressed (clear when finished) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index ab4417a927..dc8e1dbc40 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -350,6 +350,14 @@ void Avatar::updateFromMouse(int mouseX, int mouseY, int screenWidth, int scree } } +void Avatar::updateFromTouch(float touchAvgDistX, float touchAvgDistY) { + const float TOUCH_ROTATE_SPEED = 0.01f; + const float TOUCH_PITCH_SPEED = 0.02f; + + _head.addYaw(-touchAvgDistX * TOUCH_ROTATE_SPEED); + _head.addPitch(-touchAvgDistY * TOUCH_PITCH_SPEED); +} + void Avatar::updateThrust(float deltaTime, Transmitter * transmitter) { // // Gather thrust information from keyboard and sensors to apply to avatar motion diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index aefeb91187..b7d424de29 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -88,6 +88,7 @@ public: void updateThrust(float deltaTime, Transmitter * transmitter); void updateHeadFromGyrosAndOrWebcam(); void updateFromMouse(int mouseX, int mouseY, int screenWidth, int screenHeight); + void updateFromTouch(float touchAvgDistX, float touchAvgDistY); void addBodyYaw(float y) {_bodyYaw += y;}; void render(bool lookingInMirror, bool renderAvatarBalls);