diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8bff0f87dc..7a564bbbf0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -653,7 +653,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : userInputMapper->registerDevice(_applicationStateDevice); // Setup the keyboardMouseDevice and the user input mapper with the default bindings - userInputMapper->registerDevice(_keyboardMouseDevice); + userInputMapper->registerDevice(_keyboardMouseDevice->getInputDevice()); userInputMapper->loadDefaultMapping(userInputMapper->getStandardDeviceID()); @@ -729,8 +729,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : // Now that menu is initalized we can sync myAvatar with it's state. getMyAvatar()->updateMotionBehaviorFromMenu(); +// FIXME spacemouse code still needs cleanup +#if 0 // the 3Dconnexion device wants to be initiliazed after a window is displayed. SpacemouseManager::getInstance().init(); +#endif auto& packetReceiver = nodeList->getPacketReceiver(); packetReceiver.registerListener(PacketType::DomainConnectionDenied, this, "handleDomainConnectionDeniedPacket"); @@ -1850,9 +1853,12 @@ void Application::focusOutEvent(QFocusEvent* event) { } } +// FIXME spacemouse code still needs cleanup +#if 0 //SpacemouseDevice::getInstance().focusOutEvent(); //SpacemouseManager::getInstance().getDevice()->focusOutEvent(); SpacemouseManager::getInstance().ManagerFocusOutEvent(); +#endif // synthesize events for keys currently pressed, since we may not get their release events foreach (int key, _keysPressed) { diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 162b713948..92ff39a489 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -465,8 +465,6 @@ Menu::Menu() { avatar, SLOT(setEnableMeshVisible(bool))); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::DisableEyelidAdjustment, 0, false); - addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::Connexion, 0, false, &SpacemouseManager::getInstance(), SLOT(toggleSpacemouse(bool))); - addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ComfortMode, 0, true); MenuWrapper* handOptionsMenu = developerMenu->addMenu("Hands"); diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp index 174bf1bf36..bb39c7bb7a 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp @@ -37,8 +37,6 @@ const QString & OpenVrDisplayPlugin::getName() const { return NAME; } -vr::IVRSystem* _hmd{ nullptr }; -int hmdRefCount = 0; static vr::IVRCompositor* _compositor{ nullptr }; vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount]; mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount]; @@ -78,24 +76,17 @@ mat4 toGlm(const vr::HmdMatrix34_t& m) { } bool OpenVrDisplayPlugin::isSupported() const { - bool success = vr::VR_IsHmdPresent(); - if (success) { - vr::HmdError eError = vr::HmdError_None; - auto hmd = vr::VR_Init(&eError); - success = (hmd != nullptr); - vr::VR_Shutdown(); - } + auto hmd = acquireOpenVrSystem(); + bool success = nullptr != hmd; + releaseOpenVrSystem(); return success; } void OpenVrDisplayPlugin::activate() { _container->setIsOptionChecked(StandingHMDSensorMode, true); - hmdRefCount++; - vr::HmdError eError = vr::HmdError_None; if (!_hmd) { - _hmd = vr::VR_Init(&eError); - Q_ASSERT(eError == vr::HmdError_None); + _hmd = acquireOpenVrSystem(); } Q_ASSERT(_hmd); @@ -114,6 +105,7 @@ void OpenVrDisplayPlugin::activate() { }); + vr::HmdError eError = vr::HmdError_None; _compositor = (vr::IVRCompositor*)vr::VR_GetGenericInterface(vr::IVRCompositor_Version, &eError); Q_ASSERT(eError == vr::HmdError_None); Q_ASSERT(_compositor); @@ -133,11 +125,8 @@ void OpenVrDisplayPlugin::activate() { void OpenVrDisplayPlugin::deactivate() { _container->setIsOptionChecked(StandingHMDSensorMode, false); - - hmdRefCount--; - - if (hmdRefCount == 0 && _hmd) { - vr::VR_Shutdown(); + if (_hmd) { + releaseOpenVrSystem(); _hmd = nullptr; } _compositor = nullptr; diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h index 7849623552..15d37d9de8 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h @@ -10,6 +10,7 @@ #include #if defined(Q_OS_WIN) +#include #include "../WindowOpenGLDisplayPlugin.h" @@ -39,6 +40,7 @@ protected: virtual void finishFrame() override; private: + vr::IVRSystem* _hmd { nullptr }; static const QString NAME; }; diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.cpp b/libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.cpp new file mode 100644 index 0000000000..44d30962bd --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.cpp @@ -0,0 +1,73 @@ +// +// Created by Bradley Austin Davis on 2015/11/01 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "OpenVrHelpers.h" + +#if defined(Q_OS_WIN) + +#include + +#include +#include + +using Mutex = std::mutex; +using Lock = std::unique_lock; + +static int refCount { 0 }; +static Mutex mutex; +static vr::IVRSystem* activeHmd { nullptr }; +static bool hmdPresent = vr::VR_IsHmdPresent(); + +static const uint32_t RELEASE_OPENVR_HMD_DELAY_MS = 5000; + +vr::IVRSystem* acquireOpenVrSystem() { + if (hmdPresent) { + Lock lock(mutex); + if (!activeHmd) { + qDebug() << "openvr: No vr::IVRSystem instance active, building"; + vr::HmdError eError = vr::HmdError_None; + activeHmd = vr::VR_Init(&eError); + qDebug() << "openvr display: HMD is " << activeHmd << " error is " << eError; + } + if (activeHmd) { + qDebug() << "openvr: incrementing refcount"; + ++refCount; + } + } + return activeHmd; +} + +void releaseOpenVrSystem() { + if (activeHmd) { + Lock lock(mutex); + qDebug() << "openvr: decrementing refcount"; + --refCount; + if (0 == refCount) { + qDebug() << "openvr: zero refcount, deallocate VR system"; + // Avoid spamming the VR system with activate/deactivate calls at system startup by + // putting in a delay before we destory the shutdown the VR subsystem + + // FIXME releasing the VR system at all seems to trigger an exception deep inside the Oculus DLL. + // disabling for now. + //QTimer* releaseTimer = new QTimer(); + //releaseTimer->singleShot(RELEASE_OPENVR_HMD_DELAY_MS, [releaseTimer] { + // Lock lock(mutex); + // qDebug() << "Delayed openvr destroy activated"; + // if (0 == refCount && nullptr != activeHmd) { + // qDebug() << "Delayed openvr destroy: releasing resources"; + // activeHmd = nullptr; + // vr::VR_Shutdown(); + // } else { + // qDebug() << "Delayed openvr destroy: HMD still in use"; + // } + // releaseTimer->deleteLater(); + //}); + } + } +} + +#endif diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.h b/libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.h index 761bef8cfc..3e445d90ba 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.h +++ b/libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.h @@ -7,10 +7,16 @@ // #pragma once +#include + #if defined(Q_OS_WIN) #include #include #include #include + +vr::IVRSystem* acquireOpenVrSystem(); +void releaseOpenVrSystem(); + #endif diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index 2157a3a010..e91ea90aaf 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -19,8 +19,8 @@ const QString KeyboardMouseDevice::NAME = "Keyboard/Mouse"; -void KeyboardMouseDevice::update(float deltaTime, bool jointsCaptured) { - _axisStateMap.clear(); +void KeyboardMouseDevice::pluginUpdate(float deltaTime, bool jointsCaptured) { + _inputDevice->update(deltaTime, jointsCaptured); // For touch event, we need to check that the last event is not too long ago // Maybe it's a Qt issue, but the touch event sequence (begin, update, end) is not always called properly @@ -35,26 +35,30 @@ void KeyboardMouseDevice::update(float deltaTime, bool jointsCaptured) { } } -void KeyboardMouseDevice::focusOutEvent() { +void KeyboardMouseDevice::InputDevice::update(float deltaTime, bool jointsCaptured) { + _axisStateMap.clear(); +} + +void KeyboardMouseDevice::InputDevice::focusOutEvent() { _buttonPressedMap.clear(); -}; +} void KeyboardMouseDevice::keyPressEvent(QKeyEvent* event) { - auto input = makeInput((Qt::Key) event->key()); - auto result = _buttonPressedMap.insert(input.getChannel()); + auto input = _inputDevice->makeInput((Qt::Key) event->key()); + auto result = _inputDevice->_buttonPressedMap.insert(input.getChannel()); if (!result.second) { // key pressed again ? without catching the release event ? } } void KeyboardMouseDevice::keyReleaseEvent(QKeyEvent* event) { - auto input = makeInput((Qt::Key) event->key()); - _buttonPressedMap.erase(input.getChannel()); + auto input = _inputDevice->makeInput((Qt::Key) event->key()); + _inputDevice->_buttonPressedMap.erase(input.getChannel()); } void KeyboardMouseDevice::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { - auto input = makeInput((Qt::MouseButton) event->button()); - auto result = _buttonPressedMap.insert(input.getChannel()); + auto input = _inputDevice->makeInput((Qt::MouseButton) event->button()); + auto result = _inputDevice->_buttonPressedMap.insert(input.getChannel()); if (!result.second) { // key pressed again ? without catching the release event ? } @@ -65,32 +69,32 @@ void KeyboardMouseDevice::mousePressEvent(QMouseEvent* event, unsigned int devic } void KeyboardMouseDevice::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { - auto input = makeInput((Qt::MouseButton) event->button()); - _buttonPressedMap.erase(input.getChannel()); + auto input = _inputDevice->makeInput((Qt::MouseButton) event->button()); + _inputDevice->_buttonPressedMap.erase(input.getChannel()); // if we pressed and released at the same location, then create a "_CLICKED" input for this button // we might want to add some small tolerance to this so if you do a small drag it still counts as // a clicked. if (_mousePressAt == event->pos()) { - _buttonPressedMap.insert(makeInput((Qt::MouseButton) event->button(), true).getChannel()); + _inputDevice->_buttonPressedMap.insert(_inputDevice->makeInput((Qt::MouseButton) event->button(), true).getChannel()); } } void KeyboardMouseDevice::eraseMouseClicked() { - _buttonPressedMap.erase(makeInput(Qt::LeftButton, true).getChannel()); - _buttonPressedMap.erase(makeInput(Qt::MiddleButton, true).getChannel()); - _buttonPressedMap.erase(makeInput(Qt::RightButton, true).getChannel()); + _inputDevice->_buttonPressedMap.erase(_inputDevice->makeInput(Qt::LeftButton, true).getChannel()); + _inputDevice->_buttonPressedMap.erase(_inputDevice->makeInput(Qt::MiddleButton, true).getChannel()); + _inputDevice->_buttonPressedMap.erase(_inputDevice->makeInput(Qt::RightButton, true).getChannel()); } void KeyboardMouseDevice::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { QPoint currentPos = event->pos(); QPoint currentMove = currentPos - _lastCursor; - _axisStateMap[makeInput(MOUSE_AXIS_X_POS).getChannel()] = (currentMove.x() > 0 ? currentMove.x() : 0.0f); - _axisStateMap[makeInput(MOUSE_AXIS_X_NEG).getChannel()] = (currentMove.x() < 0 ? -currentMove.x() : 0.0f); + _inputDevice->_axisStateMap[MOUSE_AXIS_X_POS] = (currentMove.x() > 0 ? currentMove.x() : 0.0f); + _inputDevice->_axisStateMap[MOUSE_AXIS_X_NEG] = (currentMove.x() < 0 ? -currentMove.x() : 0.0f); // Y mouse is inverted positive is pointing up the screen - _axisStateMap[makeInput(MOUSE_AXIS_Y_POS).getChannel()] = (currentMove.y() < 0 ? -currentMove.y() : 0.0f); - _axisStateMap[makeInput(MOUSE_AXIS_Y_NEG).getChannel()] = (currentMove.y() > 0 ? currentMove.y() : 0.0f); + _inputDevice->_axisStateMap[MOUSE_AXIS_Y_POS] = (currentMove.y() < 0 ? -currentMove.y() : 0.0f); + _inputDevice->_axisStateMap[MOUSE_AXIS_Y_NEG] = (currentMove.y() > 0 ? currentMove.y() : 0.0f); _lastCursor = currentPos; @@ -100,10 +104,10 @@ void KeyboardMouseDevice::mouseMoveEvent(QMouseEvent* event, unsigned int device void KeyboardMouseDevice::wheelEvent(QWheelEvent* event) { auto currentMove = event->angleDelta() / 120.0f; - _axisStateMap[makeInput(MOUSE_AXIS_WHEEL_X_POS).getChannel()] = (currentMove.x() > 0 ? currentMove.x() : 0.0f); - _axisStateMap[makeInput(MOUSE_AXIS_WHEEL_X_NEG).getChannel()] = (currentMove.x() < 0 ? -currentMove.x() : 0.0f); - _axisStateMap[makeInput(MOUSE_AXIS_WHEEL_Y_POS).getChannel()] = (currentMove.y() > 0 ? currentMove.y() : 0.0f); - _axisStateMap[makeInput(MOUSE_AXIS_WHEEL_Y_NEG).getChannel()] = (currentMove.y() < 0 ? -currentMove.y() : 0.0f); + _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_X_POS).getChannel()] = (currentMove.x() > 0 ? currentMove.x() : 0.0f); + _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_X_NEG).getChannel()] = (currentMove.x() < 0 ? -currentMove.x() : 0.0f); + _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_Y_POS).getChannel()] = (currentMove.y() > 0 ? currentMove.y() : 0.0f); + _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_Y_NEG).getChannel()] = (currentMove.y() < 0 ? -currentMove.y() : 0.0f); } glm::vec2 evalAverageTouchPoints(const QList& points) { @@ -138,17 +142,17 @@ void KeyboardMouseDevice::touchUpdateEvent(const QTouchEvent* event) { } else { auto currentMove = currentPos - _lastTouch; - _axisStateMap[makeInput(TOUCH_AXIS_X_POS).getChannel()] = (currentMove.x > 0 ? currentMove.x : 0.0f); - _axisStateMap[makeInput(TOUCH_AXIS_X_NEG).getChannel()] = (currentMove.x < 0 ? -currentMove.x : 0.0f); + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_X_POS).getChannel()] = (currentMove.x > 0 ? currentMove.x : 0.0f); + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_X_NEG).getChannel()] = (currentMove.x < 0 ? -currentMove.x : 0.0f); // Y mouse is inverted positive is pointing up the screen - _axisStateMap[makeInput(TOUCH_AXIS_Y_POS).getChannel()] = (currentMove.y < 0 ? -currentMove.y : 0.0f); - _axisStateMap[makeInput(TOUCH_AXIS_Y_NEG).getChannel()] = (currentMove.y > 0 ? currentMove.y : 0.0f); + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_Y_POS).getChannel()] = (currentMove.y < 0 ? -currentMove.y : 0.0f); + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_Y_NEG).getChannel()] = (currentMove.y > 0 ? currentMove.y : 0.0f); } _lastTouch = currentPos; } -controller::Input KeyboardMouseDevice::makeInput(Qt::Key code) const { +controller::Input KeyboardMouseDevice::InputDevice::makeInput(Qt::Key code) const { auto shortCode = (uint16_t)(code & KEYBOARD_MASK); if (shortCode != code) { shortCode |= 0x0800; // add this bit instead of the way Qt::Key add a bit on the 3rd byte for some keys @@ -156,7 +160,7 @@ controller::Input KeyboardMouseDevice::makeInput(Qt::Key code) const { return controller::Input(_deviceID, shortCode, controller::ChannelType::BUTTON); } -controller::Input KeyboardMouseDevice::makeInput(Qt::MouseButton code, bool clicked) const { +controller::Input KeyboardMouseDevice::InputDevice::makeInput(Qt::MouseButton code, bool clicked) const { switch (code) { case Qt::LeftButton: return controller::Input(_deviceID, clicked ? MOUSE_BUTTON_LEFT_CLICKED : @@ -172,19 +176,19 @@ controller::Input KeyboardMouseDevice::makeInput(Qt::MouseButton code, bool clic }; } -controller::Input KeyboardMouseDevice::makeInput(KeyboardMouseDevice::MouseAxisChannel axis) const { +controller::Input KeyboardMouseDevice::InputDevice::makeInput(KeyboardMouseDevice::MouseAxisChannel axis) const { return controller::Input(_deviceID, axis, controller::ChannelType::AXIS); } -controller::Input KeyboardMouseDevice::makeInput(KeyboardMouseDevice::TouchAxisChannel axis) const { +controller::Input KeyboardMouseDevice::InputDevice::makeInput(KeyboardMouseDevice::TouchAxisChannel axis) const { return controller::Input(_deviceID, axis, controller::ChannelType::AXIS); } -controller::Input KeyboardMouseDevice::makeInput(KeyboardMouseDevice::TouchButtonChannel button) const { +controller::Input KeyboardMouseDevice::InputDevice::makeInput(KeyboardMouseDevice::TouchButtonChannel button) const { return controller::Input(_deviceID, button, controller::ChannelType::BUTTON); } -controller::Input::NamedVector KeyboardMouseDevice::getAvailableInputs() const { +controller::Input::NamedVector KeyboardMouseDevice::InputDevice::getAvailableInputs() const { using namespace controller; static QVector availableInputs; static std::once_flag once; @@ -229,7 +233,7 @@ controller::Input::NamedVector KeyboardMouseDevice::getAvailableInputs() const { return availableInputs; } -QString KeyboardMouseDevice::getDefaultMappingConfig() const { +QString KeyboardMouseDevice::InputDevice::getDefaultMappingConfig() const { static const QString MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/keyboardMouse.json"; return MAPPING_JSON; } diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h index 5d86821db1..b0578e3a99 100644 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h @@ -24,7 +24,7 @@ class QKeyEvent; class QMouseEvent; class QWheelEvent; -class KeyboardMouseDevice : public InputPlugin, public controller::InputDevice { +class KeyboardMouseDevice : public InputPlugin { Q_OBJECT public: enum KeyboardChannel { @@ -64,22 +64,20 @@ public: TOUCH_BUTTON_PRESS = TOUCH_AXIS_Y_NEG + 1, }; - KeyboardMouseDevice() : InputDevice("Keyboard") {} + KeyboardMouseDevice() {} + + virtual ~KeyboardMouseDevice() {} + + controller::InputDevice::Pointer getInputDevice() { return _inputDevice; } // Plugin functions virtual bool isSupported() const override { return true; } virtual bool isJointController() const override { return false; } const QString& getName() const override { return NAME; } - virtual void pluginFocusOutEvent() override { focusOutEvent(); } - virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override { update(deltaTime, jointsCaptured); } + virtual void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); } + virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override; - // Device functions - virtual controller::Input::NamedVector getAvailableInputs() const override; - virtual QString getDefaultMappingConfig() const override; - virtual void update(float deltaTime, bool jointsCaptured) override; - virtual void focusOutEvent() override; - void keyPressEvent(QKeyEvent* event); void keyReleaseEvent(QKeyEvent* event); @@ -94,21 +92,36 @@ public: void wheelEvent(QWheelEvent* event); - // Let's make it easy for Qt because we assume we love Qt forever - controller::Input makeInput(Qt::Key code) const; - controller::Input makeInput(Qt::MouseButton code, bool clicked = false) const; - controller::Input makeInput(MouseAxisChannel axis) const; - controller::Input makeInput(TouchAxisChannel axis) const; - controller::Input makeInput(TouchButtonChannel button) const; - static const QString NAME; protected: + + class InputDevice : public controller::InputDevice { + public: + InputDevice() : controller::InputDevice("Keyboard") {} + private: + // Device functions + virtual controller::Input::NamedVector getAvailableInputs() const override; + virtual QString getDefaultMappingConfig() const override; + virtual void update(float deltaTime, bool jointsCaptured) override; + virtual void focusOutEvent() override; + + // Let's make it easy for Qt because we assume we love Qt forever + controller::Input makeInput(Qt::Key code) const; + controller::Input makeInput(Qt::MouseButton code, bool clicked = false) const; + controller::Input makeInput(MouseAxisChannel axis) const; + controller::Input makeInput(TouchAxisChannel axis) const; + controller::Input makeInput(TouchButtonChannel button) const; + + friend class KeyboardMouseDevice; + }; + QPoint _lastCursor; QPoint _mousePressAt; glm::vec2 _lastTouch; + std::shared_ptr _inputDevice { std::make_shared() }; + bool _isTouching = false; - std::chrono::high_resolution_clock _clock; std::chrono::high_resolution_clock::time_point _lastTouchTime; }; diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp index 024eb86182..33b4332430 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp @@ -30,6 +30,11 @@ #ifdef HAVE_SIXENSE #include "sixense.h" + +#ifdef __APPLE__ +static QLibrary* _sixenseLibrary { nullptr }; +#endif + #endif // TODO: This should not be here @@ -39,13 +44,10 @@ Q_LOGGING_CATEGORY(inputplugins, "hifi.inputplugins") #ifdef HAVE_SIXENSE -const int CALIBRATION_STATE_IDLE = 0; -const int CALIBRATION_STATE_IN_PROGRESS = 1; -const int CALIBRATION_STATE_COMPLETE = 2; -const glm::vec3 DEFAULT_AVATAR_POSITION(-0.25f, -0.35f, -0.3f); // in hydra frame - -const float CONTROLLER_THRESHOLD = 0.35f; +const glm::vec3 SixenseManager::DEFAULT_AVATAR_POSITION { -0.25f, -0.35f, -0.3f }; // in hydra frame +const float SixenseManager::CONTROLLER_THRESHOLD { 0.35f }; +const float SixenseManager::DEFAULT_REACH_LENGTH { 1.5f }; #endif @@ -66,14 +68,6 @@ const QString MENU_PATH = MENU_PARENT + ">" + MENU_NAME; const QString TOGGLE_SMOOTH = "Smooth Sixense Movement"; const float DEFAULT_REACH_LENGTH = 1.5f; -static std::shared_ptr instance; -SixenseManager::SixenseManager() : - InputDevice("Hydra"), - _reachLength(DEFAULT_REACH_LENGTH) -{ - instance = std::shared_ptr(this); -} - bool SixenseManager::isSupported() const { #ifdef HAVE_SIXENSE @@ -91,8 +85,6 @@ bool SixenseManager::isSupported() const { void SixenseManager::activate() { InputPlugin::activate(); #ifdef HAVE_SIXENSE - _calibrationState = CALIBRATION_STATE_IDLE; - _avatarPosition = DEFAULT_AVATAR_POSITION; _container->addMenu(MENU_PATH); _container->addMenuItem(MENU_PATH, TOGGLE_SMOOTH, @@ -100,7 +92,7 @@ void SixenseManager::activate() { true, true); auto userInputMapper = DependencyManager::get(); - userInputMapper->registerDevice(instance); + userInputMapper->registerDevice(_inputDevice); #ifdef __APPLE__ @@ -139,12 +131,12 @@ void SixenseManager::deactivate() { _container->removeMenuItem(MENU_NAME, TOGGLE_SMOOTH); _container->removeMenu(MENU_PATH); - _poseStateMap.clear(); - _collectedSamples.clear(); + _inputDevice->_poseStateMap.clear(); + _inputDevice->_collectedSamples.clear(); - if (_deviceID != controller::Input::INVALID_DEVICE) { + if (_inputDevice->_deviceID != controller::Input::INVALID_DEVICE) { auto userInputMapper = DependencyManager::get(); - userInputMapper->removeDevice(_deviceID); + userInputMapper->removeDevice(_inputDevice->_deviceID); } #ifdef __APPLE__ @@ -170,7 +162,15 @@ void SixenseManager::setSixenseFilter(bool filter) { #endif } -void SixenseManager::update(float deltaTime, bool jointsCaptured) { +void SixenseManager::pluginUpdate(float deltaTime, bool jointsCaptured) { + _inputDevice->update(deltaTime, jointsCaptured); + if (_inputDevice->_calibrationState == CALIBRATION_STATE_COMPLETE) { + _container->requestReset(); + _inputDevice->_calibrationState = CALIBRATION_STATE_IDLE; + } +} + +void SixenseManager::InputDevice::update(float deltaTime, bool jointsCaptured) { // FIXME - Some of the code in update() will crash if you haven't actually activated the // plugin. But we want register with the UserInputMapper if we don't call this. // We need to clean this up. @@ -297,7 +297,7 @@ const float MINIMUM_ARM_REACH = 0.3f; // meters const float MAXIMUM_NOISE_LEVEL = 0.05f; // meters const quint64 LOCK_DURATION = USECS_PER_SECOND / 4; // time for lock to be acquired -void SixenseManager::updateCalibration(void* controllersX) { +void SixenseManager::InputDevice::updateCalibration(void* controllersX) { auto controllers = reinterpret_cast(controllersX); const sixenseControllerData* dataLeft = controllers; const sixenseControllerData* dataRight = controllers + 1; @@ -309,26 +309,25 @@ void SixenseManager::updateCalibration(void* controllersX) { } switch (_calibrationState) { case CALIBRATION_STATE_COMPLETE: - { - // compute calibration results - _avatarPosition = - 0.5f * (_reachLeft + _reachRight); // neck is midway between right and left hands - glm::vec3 xAxis = glm::normalize(_reachRight - _reachLeft); - glm::vec3 zAxis = glm::normalize(glm::cross(xAxis, Vectors::UNIT_Y)); - xAxis = glm::normalize(glm::cross(Vectors::UNIT_Y, zAxis)); - _reachLength = glm::dot(xAxis, _reachRight - _reachLeft); - _avatarRotation = glm::inverse(glm::quat_cast(glm::mat3(xAxis, Vectors::UNIT_Y, zAxis))); - const float Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR = -0.3f; - _avatarPosition.y += Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR; - _container->requestReset(); - qCDebug(inputplugins, "succeess: sixense calibration"); - } - break; + { + // compute calibration results + _avatarPosition = - 0.5f * (_reachLeft + _reachRight); // neck is midway between right and left hands + glm::vec3 xAxis = glm::normalize(_reachRight - _reachLeft); + glm::vec3 zAxis = glm::normalize(glm::cross(xAxis, Vectors::UNIT_Y)); + xAxis = glm::normalize(glm::cross(Vectors::UNIT_Y, zAxis)); + _reachLength = glm::dot(xAxis, _reachRight - _reachLeft); + _avatarRotation = glm::inverse(glm::quat_cast(glm::mat3(xAxis, Vectors::UNIT_Y, zAxis))); + const float Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR = -0.3f; + _avatarPosition.y += Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR; + qCDebug(inputplugins, "succeess: sixense calibration"); + } + break; + default: + _calibrationState = CALIBRATION_STATE_IDLE; qCDebug(inputplugins, "failed: sixense calibration"); break; } - - _calibrationState = CALIBRATION_STATE_IDLE; return; } @@ -382,15 +381,15 @@ void SixenseManager::updateCalibration(void* controllersX) { #endif // HAVE_SIXENSE -void SixenseManager::focusOutEvent() { +void SixenseManager::InputDevice::focusOutEvent() { _axisStateMap.clear(); _buttonPressedMap.clear(); }; -void SixenseManager::handleAxisEvent(float stickX, float stickY, float trigger, bool left) { +void SixenseManager::InputDevice::handleAxisEvent(float stickX, float stickY, float trigger, bool left) { } -void SixenseManager::handleButtonEvent(unsigned int buttons, bool left) { +void SixenseManager::InputDevice::handleButtonEvent(unsigned int buttons, bool left) { using namespace controller; if (buttons & BUTTON_0) { _buttonPressedMap.insert(left ? BACK : START); @@ -415,7 +414,7 @@ void SixenseManager::handleButtonEvent(unsigned int buttons, bool left) { } } -void SixenseManager::handlePoseEvent(float deltaTime, glm::vec3 position, glm::quat rotation, bool left) { +void SixenseManager::InputDevice::handlePoseEvent(float deltaTime, glm::vec3 position, glm::quat rotation, bool left) { #ifdef HAVE_SIXENSE auto hand = left ? controller::StandardPoseChannel::LEFT_HAND : controller::StandardPoseChannel::RIGHT_HAND; @@ -521,7 +520,7 @@ static const auto R4 = controller::Y; using namespace controller; -controller::Input::NamedVector SixenseManager::getAvailableInputs() const { +controller::Input::NamedVector SixenseManager::InputDevice::getAvailableInputs() const { using namespace controller; static const Input::NamedVector availableInputs { makePair(L0, "L0"), @@ -551,7 +550,7 @@ controller::Input::NamedVector SixenseManager::getAvailableInputs() const { }; -QString SixenseManager::getDefaultMappingConfig() const { +QString SixenseManager::InputDevice::getDefaultMappingConfig() const { static const QString MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/hydra.json"; return MAPPING_JSON; } @@ -562,9 +561,9 @@ void SixenseManager::saveSettings() const { QString idString = getID(); settings.beginGroup(idString); { - settings.setVec3Value(QString("avatarPosition"), _avatarPosition); - settings.setQuatValue(QString("avatarRotation"), _avatarRotation); - settings.setValue(QString("reachLength"), QVariant(_reachLength)); + settings.setVec3Value(QString("avatarPosition"), _inputDevice->_avatarPosition); + settings.setQuatValue(QString("avatarRotation"), _inputDevice->_avatarRotation); + settings.setValue(QString("reachLength"), QVariant(_inputDevice->_reachLength)); } settings.endGroup(); } @@ -574,9 +573,9 @@ void SixenseManager::loadSettings() { QString idString = getID(); settings.beginGroup(idString); { - settings.getVec3ValueIfValid(QString("avatarPosition"), _avatarPosition); - settings.getQuatValueIfValid(QString("avatarRotation"), _avatarRotation); - settings.getFloatValueIfValid(QString("reachLength"), _reachLength); + settings.getVec3ValueIfValid(QString("avatarPosition"), _inputDevice->_avatarPosition); + settings.getQuatValueIfValid(QString("avatarRotation"), _inputDevice->_avatarRotation); + settings.getFloatValueIfValid(QString("reachLength"), _inputDevice->_reachLength); } settings.endGroup(); } diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.h b/libraries/input-plugins/src/input-plugins/SixenseManager.h index 5b5cb7ccfa..7a686dc423 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.h +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.h @@ -44,10 +44,11 @@ const unsigned int BUTTON_TRIGGER = 1U << 8; const bool DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS = false; // Handles interaction with the Sixense SDK (e.g., Razer Hydra). -class SixenseManager : public InputPlugin, public controller::InputDevice { +class SixenseManager : public InputPlugin { Q_OBJECT public: - SixenseManager(); + SixenseManager() {} + virtual ~SixenseManager() {} // Plugin functions virtual bool isSupported() const override; @@ -58,15 +59,8 @@ public: virtual void activate() override; virtual void deactivate() override; - virtual void pluginFocusOutEvent() override { focusOutEvent(); } - virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override { update(deltaTime, jointsCaptured); } - - // Device functions - virtual controller::Input::NamedVector getAvailableInputs() const override; - virtual QString getDefaultMappingConfig() const override; - - virtual void update(float deltaTime, bool jointsCaptured) override; - virtual void focusOutEvent() override; + virtual void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); } + virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override; virtual void saveSettings() const override; virtual void loadSettings() override; @@ -75,38 +69,57 @@ public slots: void setSixenseFilter(bool filter); private: - void handleButtonEvent(unsigned int buttons, bool left); - void handleAxisEvent(float x, float y, float trigger, bool left); - void handlePoseEvent(float deltaTime, glm::vec3 position, glm::quat rotation, bool left); - - void updateCalibration(void* controllers); - - int _calibrationState; - - // these are calibration results - glm::vec3 _avatarPosition; // in hydra-frame - glm::quat _avatarRotation; // in hydra-frame - float _reachLength; - - // these are measured values used to compute the calibration results - quint64 _lockExpiry; - glm::vec3 _averageLeft; - glm::vec3 _averageRight; - glm::vec3 _reachLeft; - glm::vec3 _reachRight; - float _lastDistance; - bool _useSixenseFilter = true; - - static const int MAX_NUM_AVERAGING_SAMPLES = 50; // At ~100 updates per seconds this means averaging over ~.5s + static const int CALIBRATION_STATE_IDLE = 0; + static const int CALIBRATION_STATE_IN_PROGRESS = 1; + static const int CALIBRATION_STATE_COMPLETE = 2; + static const glm::vec3 DEFAULT_AVATAR_POSITION; + static const float CONTROLLER_THRESHOLD; + static const float DEFAULT_REACH_LENGTH; + + using Samples = std::pair< MovingAverage< glm::vec3, MAX_NUM_AVERAGING_SAMPLES>, MovingAverage< glm::vec4, MAX_NUM_AVERAGING_SAMPLES> >; using MovingAverageMap = std::map< int, Samples >; - MovingAverageMap _collectedSamples; - -#ifdef __APPLE__ - QLibrary* _sixenseLibrary { nullptr }; -#endif + + class InputDevice : public controller::InputDevice { + public: + InputDevice() : controller::InputDevice("Hydra") {} + private: + // Device functions + virtual controller::Input::NamedVector getAvailableInputs() const override; + virtual QString getDefaultMappingConfig() const override; + virtual void update(float deltaTime, bool jointsCaptured) override; + virtual void focusOutEvent() override; + + void handleButtonEvent(unsigned int buttons, bool left); + void handleAxisEvent(float x, float y, float trigger, bool left); + void handlePoseEvent(float deltaTime, glm::vec3 position, glm::quat rotation, bool left); + void updateCalibration(void* controllers); + + friend class SixenseManager; + + MovingAverageMap _collectedSamples; + + int _calibrationState { CALIBRATION_STATE_IDLE }; + // these are calibration results + glm::vec3 _avatarPosition { DEFAULT_AVATAR_POSITION }; // in hydra-frame + glm::quat _avatarRotation; // in hydra-frame + float _reachLength { DEFAULT_REACH_LENGTH }; + float _lastDistance; + // these are measured values used to compute the calibration results + quint64 _lockExpiry; + glm::vec3 _averageLeft; + glm::vec3 _averageRight; + glm::vec3 _reachLeft; + glm::vec3 _reachRight; + }; + + + + bool _useSixenseFilter = true; + std::shared_ptr _inputDevice { std::make_shared() }; + static const QString NAME; static const QString HYDRA_ID_STRING; }; diff --git a/libraries/input-plugins/src/input-plugins/SpacemouseManager.cpp b/libraries/input-plugins/src/input-plugins/SpacemouseManager.cpp index 43e6ee48a8..fe90470cb4 100644 --- a/libraries/input-plugins/src/input-plugins/SpacemouseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SpacemouseManager.cpp @@ -21,11 +21,10 @@ const float MAX_AXIS = 75.0f; // max forward = 2x speed -static std::shared_ptr instance; -SpacemouseDevice::SpacemouseDevice() : -InputDevice("Spacemouse") +static std::shared_ptr instance = std::make_shared(); + +SpacemouseDevice::SpacemouseDevice() : InputDevice("Spacemouse") { - instance = std::shared_ptr(this); } void SpacemouseDevice::focusOutEvent() { @@ -118,14 +117,6 @@ void SpacemouseDevice::update(float deltaTime, bool jointsCaptured) { // for osx the api will call DeviceAddedHandler or DeviceRemoveHandler when a 3Dconnexion device is attached or detached } -SpacemouseManager& SpacemouseManager::getInstance() { - static SpacemouseManager sharedInstance; - if (instance == nullptr) { - new SpacemouseDevice(); - } - return sharedInstance; -} - void SpacemouseManager::ManagerFocusOutEvent() { instance->focusOutEvent(); } diff --git a/libraries/input-plugins/src/input-plugins/SpacemouseManager.h b/libraries/input-plugins/src/input-plugins/SpacemouseManager.h index 08ac954c94..6253fa7f9d 100644 --- a/libraries/input-plugins/src/input-plugins/SpacemouseManager.h +++ b/libraries/input-plugins/src/input-plugins/SpacemouseManager.h @@ -23,7 +23,6 @@ class SpacemouseManager : public QObject { Q_OBJECT public: - static SpacemouseManager& getInstance(); void ManagerFocusOutEvent(); void init(); void destroy() {}; @@ -92,7 +91,6 @@ class SpacemouseManager : public QObject, public QAbstractNativeEventFilter { public: SpacemouseManager() {}; - static SpacemouseManager& getInstance(); void init(); void destroy(); bool Is3dmouseAttached(); @@ -169,7 +167,6 @@ private: class SpacemouseManager : public QObject { Q_OBJECT public: - static SpacemouseManager& getInstance(); void init(); void destroy(); bool Is3dmouseAttached(); diff --git a/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp b/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp index 69b2b5b2c6..ec0c35cc96 100644 --- a/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp +++ b/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp @@ -27,12 +27,13 @@ #include #ifdef Q_OS_WIN -extern vr::IVRSystem* _hmd; -extern int hmdRefCount; extern vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount]; extern mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount]; #endif +vr::IVRSystem* acquireOpenVrSystem(); +void releaseOpenVrSystem(); + const float CONTROLLER_LENGTH_OFFSET = 0.0762f; // three inches const QString CONTROLLER_MODEL_STRING = "vr_controller_05_wireless_b"; @@ -44,28 +45,11 @@ const QString MENU_NAME = "Vive Controllers"; const QString MENU_PATH = MENU_PARENT + ">" + MENU_NAME; const QString RENDER_CONTROLLERS = "Render Hand Controllers"; -static std::shared_ptr instance; - -ViveControllerManager::ViveControllerManager() : - InputDevice("Vive"), - _trackedControllers(0), - _modelLoaded(false), - _leftHandRenderID(0), - _rightHandRenderID(0), - _renderControllers(false) -{ - instance = std::shared_ptr(this); -} - bool ViveControllerManager::isSupported() const { #ifdef Q_OS_WIN - bool success = vr::VR_IsHmdPresent(); - if (success) { - vr::HmdError eError = vr::HmdError_None; - auto hmd = vr::VR_Init(&eError); - success = (hmd != nullptr); - vr::VR_Shutdown(); - } + auto hmd = acquireOpenVrSystem(); + bool success = hmd != nullptr; + releaseOpenVrSystem(); return success; #else return false; @@ -80,11 +64,8 @@ void ViveControllerManager::activate() { [this] (bool clicked) { this->setRenderControllers(clicked); }, true, true); - hmdRefCount++; if (!_hmd) { - vr::HmdError eError = vr::HmdError_None; - _hmd = vr::VR_Init(&eError); - Q_ASSERT(eError == vr::HmdError_None); + _hmd = acquireOpenVrSystem(); } Q_ASSERT(_hmd); @@ -138,7 +119,7 @@ void ViveControllerManager::activate() { // unregister with UserInputMapper auto userInputMapper = DependencyManager::get(); - userInputMapper->registerDevice(instance); + userInputMapper->registerDevice(_inputDevice); _registeredWithInputMapper = true; } @@ -149,18 +130,17 @@ void ViveControllerManager::deactivate() { _container->removeMenuItem(MENU_NAME, RENDER_CONTROLLERS); _container->removeMenu(MENU_PATH); - hmdRefCount--; - - if (hmdRefCount == 0 && _hmd) { - vr::VR_Shutdown(); + if (_hmd) { + releaseOpenVrSystem(); _hmd = nullptr; } - _poseStateMap.clear(); + + _inputDevice->_poseStateMap.clear(); #endif // unregister with UserInputMapper auto userInputMapper = DependencyManager::get(); - userInputMapper->removeDevice(_deviceID); + userInputMapper->removeDevice(_inputDevice->_deviceID); _registeredWithInputMapper = false; } @@ -177,8 +157,8 @@ void ViveControllerManager::updateRendering(RenderArgs* args, render::ScenePoint //pendingChanges.updateItem(_leftHandRenderID, ); - controller::Pose leftHand = _poseStateMap[controller::StandardPoseChannel::LEFT_HAND]; - controller::Pose rightHand = _poseStateMap[controller::StandardPoseChannel::RIGHT_HAND]; + controller::Pose leftHand = _inputDevice->_poseStateMap[controller::StandardPoseChannel::LEFT_HAND]; + controller::Pose rightHand = _inputDevice->_poseStateMap[controller::StandardPoseChannel::RIGHT_HAND]; gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { auto geometryCache = DependencyManager::get(); @@ -223,15 +203,28 @@ void ViveControllerManager::renderHand(const controller::Pose& pose, gpu::Batch& batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0); } -void ViveControllerManager::update(float deltaTime, bool jointsCaptured) { + +void ViveControllerManager::pluginUpdate(float deltaTime, bool jointsCaptured) { + _inputDevice->update(deltaTime, jointsCaptured); + auto userInputMapper = DependencyManager::get(); + + if (_inputDevice->_trackedControllers == 0 && _registeredWithInputMapper) { + userInputMapper->removeDevice(_inputDevice->_deviceID); + _registeredWithInputMapper = false; + _inputDevice->_poseStateMap.clear(); + } + + if (!_registeredWithInputMapper && _inputDevice->_trackedControllers > 0) { + userInputMapper->registerDevice(_inputDevice); + _registeredWithInputMapper = true; + UserActivityLogger::getInstance().connectedDevice("spatial_controller", "steamVR"); + } +} + +void ViveControllerManager::InputDevice::update(float deltaTime, bool jointsCaptured) { #ifdef Q_OS_WIN _poseStateMap.clear(); - // TODO: This shouldn't be necessary - if (!_hmd) { - return; - } - _buttonPressedMap.clear(); PerformanceTimer perfTimer("ViveControllerManager::update"); @@ -279,33 +272,17 @@ void ViveControllerManager::update(float deltaTime, bool jointsCaptured) { } } - auto userInputMapper = DependencyManager::get(); - - if (numTrackedControllers == 0) { - if (_registeredWithInputMapper) { - userInputMapper->removeDevice(_deviceID); - _registeredWithInputMapper = false; - _poseStateMap.clear(); - } - } - - if (_trackedControllers == 0 && numTrackedControllers > 0) { - userInputMapper->registerDevice(instance); - _registeredWithInputMapper = true; - UserActivityLogger::getInstance().connectedDevice("spatial_controller", "steamVR"); - } - _trackedControllers = numTrackedControllers; #endif } -void ViveControllerManager::focusOutEvent() { +void ViveControllerManager::InputDevice::focusOutEvent() { _axisStateMap.clear(); _buttonPressedMap.clear(); }; // These functions do translation from the Steam IDs to the standard controller IDs -void ViveControllerManager::handleAxisEvent(uint32_t axis, float x, float y, bool left) { +void ViveControllerManager::InputDevice::handleAxisEvent(uint32_t axis, float x, float y, bool left) { #ifdef Q_OS_WIN //FIX ME? It enters here every frame: probably we want to enter only if an event occurs axis += vr::k_EButton_Axis0; @@ -320,7 +297,7 @@ void ViveControllerManager::handleAxisEvent(uint32_t axis, float x, float y, boo } // These functions do translation from the Steam IDs to the standard controller IDs -void ViveControllerManager::handleButtonEvent(uint32_t button, bool pressed, bool left) { +void ViveControllerManager::InputDevice::handleButtonEvent(uint32_t button, bool pressed, bool left) { #ifdef Q_OS_WIN if (!pressed) { return; @@ -342,7 +319,7 @@ void ViveControllerManager::handleButtonEvent(uint32_t button, bool pressed, boo #endif } -void ViveControllerManager::handlePoseEvent(const mat4& mat, bool left) { +void ViveControllerManager::InputDevice::handlePoseEvent(const mat4& mat, bool left) { glm::vec3 position = extractTranslation(mat); glm::quat rotation = glm::quat_cast(mat); @@ -409,7 +386,7 @@ void ViveControllerManager::handlePoseEvent(const mat4& mat, bool left) { _poseStateMap[left ? controller::LEFT_HAND : controller::RIGHT_HAND] = controller::Pose(position, rotation); } -controller::Input::NamedVector ViveControllerManager::getAvailableInputs() const { +controller::Input::NamedVector ViveControllerManager::InputDevice::getAvailableInputs() const { using namespace controller; QVector availableInputs{ // Trackpad analogs @@ -450,7 +427,7 @@ controller::Input::NamedVector ViveControllerManager::getAvailableInputs() const return availableInputs; } -QString ViveControllerManager::getDefaultMappingConfig() const { +QString ViveControllerManager::InputDevice::getDefaultMappingConfig() const { static const QString MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/vive.json"; return MAPPING_JSON; } diff --git a/libraries/input-plugins/src/input-plugins/ViveControllerManager.h b/libraries/input-plugins/src/input-plugins/ViveControllerManager.h index 938f2f9ba9..a925733327 100644 --- a/libraries/input-plugins/src/input-plugins/ViveControllerManager.h +++ b/libraries/input-plugins/src/input-plugins/ViveControllerManager.h @@ -24,10 +24,15 @@ #include #include -class ViveControllerManager : public InputPlugin, public controller::InputDevice { +namespace vr { + class IVRSystem; +} + +class ViveControllerManager : public InputPlugin { Q_OBJECT public: - ViveControllerManager(); + ViveControllerManager() {} + virtual ~ViveControllerManager() {} // Plugin functions virtual bool isSupported() const override; @@ -37,40 +42,51 @@ public: virtual void activate() override; virtual void deactivate() override; - virtual void pluginFocusOutEvent() override { focusOutEvent(); } - virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override { update(deltaTime, jointsCaptured); } - - // Device functions - virtual controller::Input::NamedVector getAvailableInputs() const override; - virtual QString getDefaultMappingConfig() const override; - virtual void update(float deltaTime, bool jointsCaptured) override; - virtual void focusOutEvent() override; + virtual void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); } + virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override; void updateRendering(RenderArgs* args, render::ScenePointer scene, render::PendingChanges pendingChanges); void setRenderControllers(bool renderControllers) { _renderControllers = renderControllers; } private: + class InputDevice : public controller::InputDevice { + public: + InputDevice(vr::IVRSystem*& hmd) : controller::InputDevice("Vive"), _hmd(hmd) {} + private: + // Device functions + virtual controller::Input::NamedVector getAvailableInputs() const override; + virtual QString getDefaultMappingConfig() const override; + virtual void update(float deltaTime, bool jointsCaptured) override; + virtual void focusOutEvent() override; + + void handleButtonEvent(uint32_t button, bool pressed, bool left); + void handleAxisEvent(uint32_t axis, float x, float y, bool left); + void handlePoseEvent(const mat4& mat, bool left); + + int _trackedControllers { 0 }; + vr::IVRSystem*& _hmd; + friend class ViveControllerManager; + }; + void renderHand(const controller::Pose& pose, gpu::Batch& batch, int sign); - void handleButtonEvent(uint32_t button, bool pressed, bool left); - void handleAxisEvent(uint32_t axis, float x, float y, bool left); - void handlePoseEvent(const mat4& mat, bool left); - int _trackedControllers; - bool _modelLoaded; + bool _registeredWithInputMapper { false }; + bool _modelLoaded { false }; model::Geometry _modelGeometry; gpu::TexturePointer _texture; - int _leftHandRenderID; - int _rightHandRenderID; + int _leftHandRenderID { 0 }; + int _rightHandRenderID { 0 }; - bool _renderControllers; + bool _renderControllers { false }; + vr::IVRSystem* _hmd { nullptr }; + std::shared_ptr _inputDevice { std::make_shared(_hmd) }; static const QString NAME; - bool _registeredWithInputMapper { false }; }; diff --git a/tests/controllers/src/main.cpp b/tests/controllers/src/main.cpp index 6e2732f1d8..6cc2cfc6eb 100644 --- a/tests/controllers/src/main.cpp +++ b/tests/controllers/src/main.cpp @@ -132,7 +132,7 @@ int main(int argc, char** argv) { inputPlugin->activate(); auto userInputMapper = DependencyManager::get(); if (name == KeyboardMouseDevice::NAME) { - userInputMapper->registerDevice(std::dynamic_pointer_cast(inputPlugin)); + userInputMapper->registerDevice(dynamic_cast(inputPlugin.get())->getInputDevice()); } inputPlugin->pluginUpdate(0, false); }