From eff097638ce6c12e700e561331594b8b6976f986 Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Wed, 11 Jun 2014 17:02:08 -0700 Subject: [PATCH] Implementd sixense mouse emulation --- interface/src/Application.cpp | 10 +++- interface/src/devices/SixenseManager.cpp | 68 +++++++++++++++++++++ interface/src/devices/SixenseManager.h | 9 +++ interface/src/ui/ApplicationOverlay.cpp | 75 +++++++++++++++++++++++- 4 files changed, 159 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2b3256141e..6035cdd7cb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1090,6 +1090,13 @@ void Application::focusOutEvent(QFocusEvent* event) { } void Application::mouseMoveEvent(QMouseEvent* event) { + + bool showMouse = true; + // If this mouse move event is emitted by a controller, dont show the mouse cursor + if (event->type() == CONTROLLER_MOVE_EVENT) { + showMouse = false; + } + _controllerScriptingInterface.emitMouseMoveEvent(event); // send events to any registered scripts // if one of our scripts have asked to capture this event, then stop processing it @@ -1097,10 +1104,9 @@ void Application::mouseMoveEvent(QMouseEvent* event) { return; } - _lastMouseMove = usecTimestampNow(); - if (_mouseHidden && !OculusManager::isConnected()) { + if (_mouseHidden && showMouse && !OculusManager::isConnected()) { getGLWidget()->setCursor(Qt::ArrowCursor); _mouseHidden = false; _seenMouseMove = true; diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index 8cd3cc059e..4ecb416a92 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -39,6 +39,10 @@ SixenseManager::SixenseManager() { sixenseInit(); #endif + _triggerPressed = false; + _bumperPressed = false; + _oldPos.setX(-1); + _oldPos.setY(-1); } SixenseManager::~SixenseManager() { @@ -107,6 +111,12 @@ void SixenseManager::update(float deltaTime) { palm->setTrigger(data->trigger); palm->setJoystick(data->joystick_x, data->joystick_y); + + // Emulate the mouse so we can use scripts + if (numActiveControllers == 2) { + emulateMouse(palm); + } + // NOTE: Sixense API returns pos data in millimeters but we IMMEDIATELY convert to meters. glm::vec3 position(data->pos[0], data->pos[1], data->pos[2]); position *= METERS_PER_MILLIMETER; @@ -313,5 +323,63 @@ void SixenseManager::updateCalibration(const sixenseControllerData* controllers) } } } + +//Injecting mouse movements and clicks +void SixenseManager::emulateMouse(PalmData *palm) { + MyAvatar* avatar = Application::getInstance()->getAvatar(); + QPoint pos; + // Get directon relative to avatar orientation + glm::vec3 direction = glm::inverse(avatar->getOrientation()) * palm->getFingerDirection(); + + // Get the angles, scaled between 0-1 + float xAngle = (atan2(direction.z, direction.x) + M_PI_2) + 0.5f; + float yAngle = 1.0f - ((atan2(direction.z, direction.y) + M_PI_2) + 0.5f); + + float cursorRange = Application::getInstance()->getGLWidget()->width(); + + pos.setX(cursorRange * xAngle); + pos.setY(cursorRange * yAngle); + + //If position has changed, emit a mouse move to the application + if (pos.x() != _oldPos.x() || pos.y() != _oldPos.y()) { + QMouseEvent mouseEvent(static_cast(CONTROLLER_MOVE_EVENT), pos, Qt::NoButton, Qt::NoButton, 0); + + Application::getInstance()->mouseMoveEvent(&mouseEvent); + } + _oldPos = pos; + + //Check for bumper press ( Right Click ) + if (palm->getControllerButtons() & BUTTON_FWD) { + if (!_bumperPressed) { + _bumperPressed = true; + QMouseEvent mouseEvent(QEvent::MouseButtonPress, pos, Qt::RightButton, Qt::RightButton, 0); + + Application::getInstance()->mousePressEvent(&mouseEvent); + } + } else if (_bumperPressed) { + QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, Qt::RightButton, Qt::RightButton, 0); + + Application::getInstance()->mouseReleaseEvent(&mouseEvent); + + _bumperPressed = false; + } + + //Check for trigger press ( Left Click ) + if (palm->getTrigger() == 1.0f) { + if (!_triggerPressed) { + _triggerPressed = true; + QMouseEvent mouseEvent(QEvent::MouseButtonPress, pos, Qt::LeftButton, Qt::LeftButton, 0); + + Application::getInstance()->mousePressEvent(&mouseEvent); + } + } else if (_triggerPressed) { + QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, Qt::LeftButton, Qt::LeftButton, 0); + + Application::getInstance()->mouseReleaseEvent(&mouseEvent); + + _triggerPressed = false; + } +} + #endif // HAVE_SIXENSE diff --git a/interface/src/devices/SixenseManager.h b/interface/src/devices/SixenseManager.h index a98d4c0e4e..061b3cc625 100644 --- a/interface/src/devices/SixenseManager.h +++ b/interface/src/devices/SixenseManager.h @@ -27,6 +27,9 @@ const unsigned int BUTTON_3 = 1U << 3; const unsigned int BUTTON_4 = 1U << 4; const unsigned int BUTTON_FWD = 1U << 7; +// Event type that represents moving the controller +const unsigned int CONTROLLER_MOVE_EVENT = 1500U; + /// Handles interaction with the Sixense SDK (e.g., Razer Hydra). class SixenseManager : public QObject { Q_OBJECT @@ -44,6 +47,7 @@ public slots: private: #ifdef HAVE_SIXENSE void updateCalibration(const sixenseControllerData* controllers); + void emulateMouse(PalmData *palm); int _calibrationState; @@ -65,6 +69,11 @@ private: #endif quint64 _lastMovement; glm::vec3 _amountMoved; + + // for mouse emulation + bool _triggerPressed; + bool _bumperPressed; + QPoint _oldPos; }; #endif // hifi_SixenseManager_h diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index a48e0a2c1a..750be96cc9 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -35,6 +35,78 @@ ApplicationOverlay::~ApplicationOverlay() { const float WHITE_TEXT[] = { 0.93f, 0.93f, 0.93f }; +void renderControllerPointer() +{ + Application* application = Application::getInstance(); + QGLWidget* glWidget = application->getGLWidget(); + MyAvatar* myAvatar = application->getAvatar(); + + const HandData* handData = Application::getInstance()->getAvatar()->getHandData(); + int numberOfPalms = handData->getNumPalms(); + + + int palmIndex = 3; + const PalmData* palmData = NULL; + + if (palmIndex >= handData->getPalms().size()) { + return; + } + + if (handData->getPalms()[palmIndex].isActive()) { + palmData = &handData->getPalms()[palmIndex]; + } else { + return; + } + + // Get directon relative to avatar orientation + glm::vec3 direction = glm::inverse(myAvatar->getOrientation()) * palmData->getFingerDirection(); + + // Get the angles, scaled between 0-1 + float xAngle = (atan2(direction.z, direction.x) + M_PI_2) + 0.5f; + float yAngle = 1.0f - ((atan2(direction.z, direction.y) + M_PI_2) + 0.5f); + + float cursorRange = glWidget->width(); + + int mouseX = cursorRange * xAngle; + int mouseY = cursorRange * yAngle; + + if (mouseX < 0) { + mouseX = 0; + } else if (mouseX > glWidget->width()) { + mouseX = glWidget->width(); + } + if (mouseY < 0) { + mouseY = 0; + } else if (mouseY > glWidget->width()) { + mouseY = glWidget->width(); + } + + const float pointerWidth = 40; + const float pointerHeight = 40; + const float crossPad = 16; + + mouseX -= pointerWidth / 2.0f; + mouseY += pointerHeight / 2.0f; + + glBegin(GL_QUADS); + + glColor3f(0, 0, 1); + + //Horizontal crosshair + glVertex2i(mouseX, mouseY - crossPad); + glVertex2i(mouseX + pointerWidth, mouseY - crossPad); + glVertex2i(mouseX + pointerWidth, mouseY - pointerHeight + crossPad); + glVertex2i(mouseX, mouseY - pointerHeight + crossPad); + + //Vertical crosshair + glVertex2i(mouseX + crossPad, mouseY); + glVertex2i(mouseX + pointerWidth - crossPad, mouseY); + glVertex2i(mouseX + pointerWidth - crossPad, mouseY - pointerHeight); + glVertex2i(mouseX + crossPad, mouseY - pointerHeight); + + glEnd(); +} + // Renders the overlays either to a texture or to the screen void ApplicationOverlay::renderOverlay(bool renderToTexture) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); @@ -254,8 +326,9 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { glVertex2i(mouseX + crossPad, mouseY - pointerHeight); glEnd(); + } else { //only render controller pointer if we aren't already rendering a mouse pointer + renderControllerPointer(); } - glPopMatrix(); glMatrixMode(GL_MODELVIEW);