diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 54a600d2e7..b5687b55c0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -64,6 +64,7 @@ #include #include #include + #include #include #include @@ -74,6 +75,9 @@ #include #include #include +#include +#include // this should probably be removed +#include // this definitely should be removed #include #include #include @@ -123,9 +127,6 @@ #include "devices/Leapmotion.h" #include "devices/RealSense.h" #include "devices/MIDIManager.h" -#include -#include -#include #include "RenderDeferredTask.h" #include "scripting/AccountScriptingInterface.h" #include "scripting/AudioDeviceScriptingInterface.h" @@ -621,9 +622,19 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : auto userInputMapper = DependencyManager::get(); connect(userInputMapper.data(), &UserInputMapper::actionEvent, &_controllerScriptingInterface, &AbstractControllerScriptingInterface::actionEvent); + auto inputPlugins = getInputPlugins(); + foreach(auto inputPlugin, inputPlugins) { + QString name = inputPlugin->getName(); + if (name == KeyboardMouseDevice::NAME) { + _keyboardMouseDevice = static_cast(inputPlugin.data()); // TODO: this seems super hacky + } + } + + //updateInputModes(); // TODO: shouldn't have to call this explicitly + // Setup the keyboardMouseDevice and the user input mapper with the default bindings - _keyboardMouseDevice.registerToUserInputMapper(*userInputMapper); - _keyboardMouseDevice.assignDefaultInputMapping(*userInputMapper); + _keyboardMouseDevice->registerToUserInputMapper(*userInputMapper); + _keyboardMouseDevice->assignDefaultInputMapping(*userInputMapper); // check first run... if (_firstRun.get()) { @@ -676,11 +687,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : connect(ddeTracker.data(), &FaceTracker::muteToggled, this, &Application::faceTrackerMuteToggled); #endif - if (ViveControllerManager::getInstance().isSupported()) { - ViveControllerManager::getInstance().init(); - ViveControllerManager::getInstance().activate(NULL); - } - _oldHandMouseX[0] = -1; _oldHandMouseY[0] = -1; _oldHandMouseX[1] = -1; @@ -771,6 +777,15 @@ Application::~Application() { getActiveDisplayPlugin()->deactivate(); + auto inputPlugins = getInputPlugins(); + foreach(auto inputPlugin, inputPlugins) { + QString name = inputPlugin->getName(); + QAction* action = Menu::getInstance()->getActionForOption(name); + if (action->isChecked()) { + inputPlugin->deactivate(); + } + } + // remove avatars from physics engine DependencyManager::get()->clearOtherAvatars(); _physicsEngine.deleteObjects(DependencyManager::get()->getObjectsToDelete()); @@ -1344,7 +1359,9 @@ void Application::keyPressEvent(QKeyEvent* event) { } if (hasFocus()) { - _keyboardMouseDevice.keyPressEvent(event); + if (Menu::getInstance()->isOptionChecked(KeyboardMouseDevice::NAME)) { + _keyboardMouseDevice->keyPressEvent(event); + } bool isShifted = event->modifiers().testFlag(Qt::ShiftModifier); bool isMeta = event->modifiers().testFlag(Qt::ControlModifier); @@ -1614,7 +1631,9 @@ void Application::keyReleaseEvent(QKeyEvent* event) { return; } - _keyboardMouseDevice.keyReleaseEvent(event); + if (Menu::getInstance()->isOptionChecked(KeyboardMouseDevice::NAME)) { + _keyboardMouseDevice->keyReleaseEvent(event); + } switch (event->key()) { case Qt::Key_Space: { @@ -1641,10 +1660,14 @@ void Application::keyReleaseEvent(QKeyEvent* event) { } void Application::focusOutEvent(QFocusEvent* event) { - _keyboardMouseDevice.pluginFocusOutEvent(); - SixenseManager::getInstance().pluginFocusOutEvent(); - SDL2Manager::getInstance()->pluginFocusOutEvent(); - ViveControllerManager::getInstance().pluginFocusOutEvent(); + auto inputPlugins = getInputPlugins(); + foreach(auto inputPlugin, inputPlugins) { + QString name = inputPlugin->getName(); + QAction* action = Menu::getInstance()->getActionForOption(name); + if (action->isChecked()) { + inputPlugin->pluginFocusOutEvent(); + } + } // synthesize events for keys currently pressed, since we may not get their release events foreach (int key, _keysPressed) { @@ -1687,7 +1710,9 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { return; } - _keyboardMouseDevice.mouseMoveEvent(event, deviceID); + if (Menu::getInstance()->isOptionChecked(KeyboardMouseDevice::NAME)) { + _keyboardMouseDevice->mouseMoveEvent(event, deviceID); + } } @@ -1708,7 +1733,9 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { if (hasFocus()) { - _keyboardMouseDevice.mousePressEvent(event); + if (Menu::getInstance()->isOptionChecked(KeyboardMouseDevice::NAME)) { + _keyboardMouseDevice->mousePressEvent(event); + } if (event->button() == Qt::LeftButton) { _mouseDragStarted = getTrueMouse(); @@ -1748,7 +1775,9 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { } if (hasFocus()) { - _keyboardMouseDevice.mouseReleaseEvent(event); + if (Menu::getInstance()->isOptionChecked(KeyboardMouseDevice::NAME)) { + _keyboardMouseDevice->mouseReleaseEvent(event); + } if (event->button() == Qt::LeftButton) { _mousePressed = false; @@ -1775,7 +1804,9 @@ void Application::touchUpdateEvent(QTouchEvent* event) { return; } - _keyboardMouseDevice.touchUpdateEvent(event); + if (Menu::getInstance()->isOptionChecked(KeyboardMouseDevice::NAME)) { + _keyboardMouseDevice->touchUpdateEvent(event); + } bool validTouch = false; if (hasFocus()) { @@ -1809,7 +1840,9 @@ void Application::touchBeginEvent(QTouchEvent* event) { return; } - _keyboardMouseDevice.touchBeginEvent(event); + if (Menu::getInstance()->isOptionChecked(KeyboardMouseDevice::NAME)) { + _keyboardMouseDevice->touchBeginEvent(event); + } } @@ -1824,7 +1857,9 @@ void Application::touchEndEvent(QTouchEvent* event) { return; } - _keyboardMouseDevice.touchEndEvent(event); + if (Menu::getInstance()->isOptionChecked(KeyboardMouseDevice::NAME)) { + _keyboardMouseDevice->touchEndEvent(event); + } // put any application specific touch behavior below here.. _touchDragStartedAvg = _touchAvg; @@ -1840,8 +1875,10 @@ void Application::wheelEvent(QWheelEvent* event) { if (_controllerScriptingInterface.isWheelCaptured()) { return; } - - _keyboardMouseDevice.wheelEvent(event); + + if (Menu::getInstance()->isOptionChecked(KeyboardMouseDevice::NAME)) { + _keyboardMouseDevice->wheelEvent(event); + } } void Application::dropEvent(QDropEvent *event) { @@ -1964,6 +2001,14 @@ void Application::idle() { PerformanceTimer perfTimer("updateGL"); PerformanceWarning warn(showWarnings, "Application::idle()... updateGL()"); getActiveDisplayPlugin()->idle(); + auto inputPlugins = getInputPlugins(); + foreach(auto inputPlugin, inputPlugins) { + QString name = inputPlugin->getName(); + QAction* action = Menu::getInstance()->getActionForOption(name); + if (action->isChecked()) { + inputPlugin->idle(); + } + } } { PerformanceTimer perfTimer("rest"); @@ -2625,10 +2670,14 @@ void Application::update(float deltaTime) { userInputMapper->setSensorToWorldMat(_myAvatar->getSensorToWorldMatrix()); userInputMapper->update(deltaTime); - _keyboardMouseDevice.pluginUpdate(deltaTime); - SixenseManager::getInstance().pluginUpdate(deltaTime); - SDL2Manager::getInstance()->pluginUpdate(deltaTime); - ViveControllerManager::getInstance().pluginUpdate(deltaTime); + auto inputPlugins = getInputPlugins(); + foreach(auto inputPlugin, inputPlugins) { + QString name = inputPlugin->getName(); + QAction* action = Menu::getInstance()->getActionForOption(name); + if (action->isChecked()) { + inputPlugin->pluginUpdate(deltaTime); // add flag to prevent multiple devices from modifying joints + } + } // Dispatch input events _controllerScriptingInterface.updateInputControllers(); @@ -2826,7 +2875,7 @@ void Application::setPalmData(Hand* hand, UserInputMapper::PoseValue pose, int i palm->setActive(pose.isValid()); - // TODO: velocity filters, tip velocities, et.c + // TODO: velocity filters, tip velocities, etc. // see SixenseManager // transform from sensor space, to world space, to avatar model space. @@ -2872,8 +2921,7 @@ void Application::emulateMouse(Hand* hand, float click, float shift, int index) float yAngle = 0.5f - ((atan2f(direction.z, direction.y) + (float)M_PI_2)); auto canvasSize = qApp->getCanvasSize(); // Get the pixel range over which the xAngle and yAngle are scaled - // TODO: move this from SixenseManager - float cursorRange = canvasSize.x * SixenseManager::getInstance().getCursorPixelRangeMult(); + float cursorRange = canvasSize.x * InputDevice::getCursorPixelRangeMult(); pos.setX(canvasSize.x / 2.0f + cursorRange * xAngle); pos.setY(canvasSize.y / 2.0f + cursorRange * yAngle); @@ -5128,6 +5176,51 @@ void Application::updateDisplayMode() { Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); } +static QVector> _currentInputPluginActions; + +void Application::updateInputModes() { + auto menu = Menu::getInstance(); + auto inputPlugins = getInputPlugins(); + auto offscreenUi = DependencyManager::get(); + + InputPluginPointer newInputPlugin = InputPluginPointer(nullptr); + InputPluginPointer removedInputPlugin = InputPluginPointer(nullptr); + foreach(InputPluginPointer inputPlugin, inputPlugins) { + QString name = inputPlugin->getName(); + QAction* action = menu->getActionForOption(name); + if (action->isChecked() && !_activeInputPlugins.contains(inputPlugin)) { + _activeInputPlugins.append(inputPlugin); + newInputPlugin = inputPlugin; + break; + } else if (!action->isChecked() && _activeInputPlugins.contains(inputPlugin)) { + _activeInputPlugins.removeOne(inputPlugin); + removedInputPlugin = inputPlugin; + break; + } + } + + // A plugin was checked + if (newInputPlugin) { + newInputPlugin->activate(this); + newInputPlugin->installEventFilter(qApp); + newInputPlugin->installEventFilter(offscreenUi.data()); + } else if (removedInputPlugin) { // A plugin was unchecked + removedInputPlugin->deactivate(); + removedInputPlugin->removeEventFilter(qApp); + removedInputPlugin->removeEventFilter(offscreenUi.data()); + } + + if (newInputPlugin || removedInputPlugin) { + if (!_currentInputPluginActions.isEmpty()) { + auto menu = Menu::getInstance(); + foreach(auto itemInfo, _currentInputPluginActions) { + menu->removeMenuItem(itemInfo.first, itemInfo.second); + } + _currentInputPluginActions.clear(); + } + } +} + void Application::addMenuItem(const QString& path, const QString& name, std::function onClicked, bool checkable, bool checked, const QString& groupName) { auto menu = Menu::getInstance(); MenuWrapper* parentItem = menu->getMenu(path); @@ -5136,6 +5229,7 @@ void Application::addMenuItem(const QString& path, const QString& name, std::fun onClicked(); }); _currentDisplayPluginActions.push_back({ path, name }); + _currentInputPluginActions.push_back({ path, name }); } GlWindow* Application::getVisibleWindow() { diff --git a/interface/src/Application.h b/interface/src/Application.h index c0d6ac103c..6e0a41c404 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -54,6 +54,7 @@ #include "Stars.h" #include "avatar/Avatar.h" #include "avatar/MyAvatar.h" +#include #include "scripting/ControllerScriptingInterface.h" #include "scripting/WebWindowClass.h" #include "ui/BandwidthDialog.h" @@ -68,11 +69,11 @@ #include "ui/ApplicationCompositor.h" #include "ui/RunningScriptsWidget.h" #include "ui/ToolWindow.h" -#include "devices/KeyboardMouseDevice.h" #include "octree/OctreeFade.h" #include "octree/OctreePacketProcessor.h" #include "UndoStackScriptingInterface.h" #include "DisplayPlugins.h" +#include "InputPlugins.h" #include "render/Engine.h" class QGLWidget; @@ -385,6 +386,7 @@ public slots: void nodeKilled(SharedNodePointer node); void packetSent(quint64 length); void updateDisplayMode(); + void updateInputModes(); QVector pasteEntities(float x, float y, float z); bool exportEntities(const QString& filename, const QVector& entityIDs); @@ -513,6 +515,7 @@ private: OffscreenGlCanvas* _offscreenContext; DisplayPluginPointer _displayPlugin; + InputPluginList _activeInputPlugins; MainWindow* _window; @@ -553,10 +556,10 @@ private: OctreeQuery _octreeQuery; // NodeData derived class for querying octee cells from octree servers - KeyboardMouseDevice _keyboardMouseDevice; // Default input device, the good old keyboard mouse and maybe touchpad - MyAvatar* _myAvatar; // TODO: move this and relevant code to AvatarManager (or MyAvatar as the case may be) - Camera _myCamera; // My view onto the world - Camera _mirrorCamera; // Cammera for mirror view + KeyboardMouseDevice* _keyboardMouseDevice; // Default input device, the good old keyboard mouse and maybe touchpad + MyAvatar* _myAvatar; // TODO: move this and relevant code to AvatarManager (or MyAvatar as the case may be) + Camera _myCamera; // My view onto the world + Camera _mirrorCamera; // Cammera for mirror view QRect _mirrorViewRect; Setting::Handle _firstRun; diff --git a/interface/src/InputPlugins.cpp b/interface/src/InputPlugins.cpp new file mode 100644 index 0000000000..6774963e2d --- /dev/null +++ b/interface/src/InputPlugins.cpp @@ -0,0 +1,64 @@ +// +// Created by Bradley Austin Davis on 2015/05/30 +// 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 "InputPlugins.h" + +#include "Application.h" + +#include +#include +#include +#include +#include + + +static void addInputPluginToMenu(InputPluginPointer inputPlugin, bool active = false) { + auto menu = Menu::getInstance(); + QString name = inputPlugin->getName(); + Q_ASSERT(!menu->menuItemExists(MenuOption::InputMenu, name)); + + static QActionGroup* inputPluginGroup = nullptr; + if (!inputPluginGroup) { + inputPluginGroup = new QActionGroup(menu); + } + auto parent = menu->getMenu(MenuOption::InputMenu); + auto action = menu->addCheckableActionToQMenuAndActionHash(parent, + name, 0, true, qApp, + SLOT(updateInputModes())); + inputPluginGroup->addAction(action); + Q_ASSERT(menu->menuItemExists(MenuOption::InputMenu, name)); + + qApp->updateInputModes(); // TODO: this should be called automatically +} + +// FIXME move to a plugin manager class +const InputPluginList& getInputPlugins() { + static InputPluginList INPUT_PLUGINS; + static bool init = false; + if (!init) { + init = true; + + InputPlugin* PLUGIN_POOL[] = { + new KeyboardMouseDevice(), + new SDL2Manager(), + new SixenseManager(), + new ViveControllerManager(), + nullptr + }; + for (int i = 0; PLUGIN_POOL[i]; ++i) { + InputPlugin * plugin = PLUGIN_POOL[i]; + if (plugin->isSupported()) { + plugin->init(); + InputPluginPointer pluginPointer(plugin); + addInputPluginToMenu(pluginPointer, plugin == *PLUGIN_POOL); + INPUT_PLUGINS.push_back(pluginPointer); + } + } + } + return INPUT_PLUGINS; +} diff --git a/interface/src/InputPlugins.h b/interface/src/InputPlugins.h new file mode 100644 index 0000000000..14ed808df4 --- /dev/null +++ b/interface/src/InputPlugins.h @@ -0,0 +1,18 @@ +// +// Created by Sam Gondelman on 7/16/2015 +// 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 +// +#pragma once + +class InputPlugin; + +#include +#include + +using InputPluginPointer = QSharedPointer; +using InputPluginList = QVector; + +const InputPluginList& getInputPlugins(); \ No newline at end of file diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index db4942b7e7..c53c23f88a 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -226,6 +226,10 @@ Menu::Menu() { MenuWrapper* avatarMenu = addMenu("Avatar"); QObject* avatar = DependencyManager::get()->getMyAvatar(); + MenuWrapper* inputModeMenu = addMenu(MenuOption::InputMenu); + QActionGroup* inputModeGroup = new QActionGroup(inputModeMenu); + inputModeGroup->setExclusive(false); + MenuWrapper* avatarSizeMenu = avatarMenu->addMenu("Size"); addActionToQMenuAndActionHash(avatarSizeMenu, MenuOption::IncreaseAvatarSize, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index fee3229682..d92d1b2427 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -80,6 +80,13 @@ public: const QKeySequence& shortcut = 0, QAction::MenuRole role = QAction::NoRole, int menuItemLocation = UNSPECIFIED_POSITION); + QAction* addCheckableActionToQMenuAndActionHash(MenuWrapper* destinationMenu, + const QString& actionName, + const QKeySequence& shortcut = 0, + const bool checked = false, + const QObject* receiver = NULL, + const char* member = NULL, + int menuItemLocation = UNSPECIFIED_POSITION); void removeAction(MenuWrapper* menu, const QString& actionName); @@ -109,14 +116,6 @@ private: void addDisabledActionAndSeparator(MenuWrapper* destinationMenu, const QString& actionName, int menuItemLocation = UNSPECIFIED_POSITION); - QAction* addCheckableActionToQMenuAndActionHash(MenuWrapper* destinationMenu, - const QString& actionName, - const QKeySequence& shortcut = 0, - const bool checked = false, - const QObject* receiver = NULL, - const char* member = NULL, - int menuItemLocation = UNSPECIFIED_POSITION); - QAction* getActionFromName(const QString& menuName, MenuWrapper* menu); MenuWrapper* getSubMenuFromName(const QString& menuName, MenuWrapper* menu); MenuWrapper* getMenuParent(const QString& menuName, QString& finalMenuPart); @@ -203,6 +202,7 @@ namespace MenuOption { const QString HandLasers = "Enable Hand UI Lasers"; const QString IncreaseAvatarSize = "Increase Avatar Size"; const QString IndependentMode = "Independent Mode"; + const QString InputMenu = "Avatar>Input Devices"; const QString KeyboardMotorControl = "Enable Keyboard Motor Control"; const QString LeapMotionOnHMD = "Leap Motion on HMD"; const QString LoadScript = "Open and Run Script File..."; diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index d2ee8b4028..8febc20acf 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -22,7 +22,8 @@ #include "Tooltip.h" #include "Application.h" -#include // TODO: any references to sixense should be removed here +#include // TODO: any references to sixense should be removed here +#include // Used to animate the magnification windows @@ -506,7 +507,7 @@ void ApplicationCompositor::renderControllerPointers(gpu::Batch& batch) { float yAngle = 0.5f - ((atan2f(direction.z, direction.y) + (float)M_PI_2)); // Get the pixel range over which the xAngle and yAngle are scaled - float cursorRange = canvasSize.x * SixenseManager::getInstance().getCursorPixelRangeMult(); + float cursorRange = canvasSize.x * InputDevice::getCursorPixelRangeMult(); mouseX = (canvasSize.x / 2.0f + cursorRange * xAngle); mouseY = (canvasSize.y / 2.0f + cursorRange * yAngle); diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index e99d5d4205..8cafc152f4 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -182,7 +182,7 @@ void PreferencesDialog::loadPreferences() { #endif SixenseManager& sixense = SixenseManager::getInstance(); - ui.sixenseReticleMoveSpeedSpin->setValue(sixense.getReticleMoveSpeed()); + ui.sixenseReticleMoveSpeedSpin->setValue(InputDevice::getReticleMoveSpeed()); ui.invertSixenseButtonsCheckBox->setChecked(sixense.getInvertButtons()); // LOD items @@ -246,7 +246,7 @@ void PreferencesDialog::savePreferences() { qApp->getApplicationCompositor().setHmdUIAngularSize(ui.oculusUIAngularSizeSpin->value()); SixenseManager& sixense = SixenseManager::getInstance(); - sixense.setReticleMoveSpeed(ui.sixenseReticleMoveSpeedSpin->value()); + InputDevice::setReticleMoveSpeed(ui.sixenseReticleMoveSpeedSpin->value()); sixense.setInvertButtons(ui.invertSixenseButtonsCheckBox->isChecked()); auto audio = DependencyManager::get(); diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp index 2a41516cbb..417496bbb1 100644 --- a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp @@ -36,6 +36,7 @@ const QString & OpenVrDisplayPlugin::getName() const { } vr::IVRSystem *_hmd{ nullptr }; +int hmdRefCount = 0; static vr::IVRCompositor* _compositor{ nullptr }; vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount]; mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount]; @@ -79,6 +80,7 @@ bool OpenVrDisplayPlugin::isSupported() const { } void OpenVrDisplayPlugin::activate(PluginContainer * container) { + hmdRefCount++; vr::HmdError eError = vr::HmdError_None; if (!_hmd) { _hmd = vr::VR_Init(&eError); @@ -119,8 +121,12 @@ void OpenVrDisplayPlugin::activate(PluginContainer * container) { } void OpenVrDisplayPlugin::deactivate() { - vr::VR_Shutdown(); - _hmd = nullptr; + hmdRefCount--; + + if (hmdRefCount == 0 && _hmd) { + vr::VR_Shutdown(); + _hmd = nullptr; + } _compositor = nullptr; } diff --git a/libraries/input-plugins/src/input-plugins/InputDevice.cpp b/libraries/input-plugins/src/input-plugins/InputDevice.cpp index 9e8574c6e7..8f0f2449ca 100644 --- a/libraries/input-plugins/src/input-plugins/InputDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/InputDevice.cpp @@ -7,6 +7,20 @@ // #include "InputDevice.h" +const float DEFAULT_HAND_RETICLE_MOVE_SPEED = 37.5f; +float InputDevice::reticleMoveSpeed = DEFAULT_HAND_RETICLE_MOVE_SPEED; + +//Constants for getCursorPixelRangeMultiplier() +const float MIN_PIXEL_RANGE_MULT = 0.4f; +const float MAX_PIXEL_RANGE_MULT = 2.0f; +const float RANGE_MULT = (MAX_PIXEL_RANGE_MULT - MIN_PIXEL_RANGE_MULT) * 0.01f; + +//Returns a multiplier to be applied to the cursor range for the controllers +float InputDevice::getCursorPixelRangeMult() { + //scales (0,100) to (MINIMUM_PIXEL_RANGE_MULT, MAXIMUM_PIXEL_RANGE_MULT) + return InputDevice::reticleMoveSpeed * RANGE_MULT + MIN_PIXEL_RANGE_MULT; +} + float InputDevice::getButton(int channel) const { if (!_buttonPressedMap.empty()) { if (_buttonPressedMap.find(channel) != _buttonPressedMap.end()) { @@ -37,4 +51,4 @@ UserInputMapper::PoseValue InputDevice::getPose(int channel) const { else { return UserInputMapper::PoseValue(); } -} \ No newline at end of file +} diff --git a/libraries/input-plugins/src/input-plugins/InputDevice.h b/libraries/input-plugins/src/input-plugins/InputDevice.h index 83548a5b90..4776766312 100644 --- a/libraries/input-plugins/src/input-plugins/InputDevice.h +++ b/libraries/input-plugins/src/input-plugins/InputDevice.h @@ -40,6 +40,10 @@ public: int getDeviceID() { return _deviceID; } + static float getCursorPixelRangeMult(); + static float getReticleMoveSpeed() { return reticleMoveSpeed; } + static void setReticleMoveSpeed(float sixenseReticleMoveSpeed) { reticleMoveSpeed = sixenseReticleMoveSpeed; } + protected: int _deviceID = 0; @@ -48,4 +52,7 @@ protected: ButtonPressedMap _buttonPressedMap; AxisStateMap _axisStateMap; PoseStateMap _poseStateMap; -}; + +private: + static float reticleMoveSpeed; +}; \ No newline at end of file diff --git a/libraries/input-plugins/src/input-plugins/InputPlugin.h b/libraries/input-plugins/src/input-plugins/InputPlugin.h index c10770679d..776ece8b8a 100644 --- a/libraries/input-plugins/src/input-plugins/InputPlugin.h +++ b/libraries/input-plugins/src/input-plugins/InputPlugin.h @@ -9,11 +9,9 @@ #include -const float DEFAULT_HAND_RETICLE_MOVE_SPEED = 37.5f; - class InputPlugin : public Plugin { public: - virtual bool isHandController() const = 0; + virtual bool isJointController() const = 0; virtual void pluginFocusOutEvent() = 0; diff --git a/interface/src/devices/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp old mode 100755 new mode 100644 similarity index 99% rename from interface/src/devices/KeyboardMouseDevice.cpp rename to libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index d99b974585..66751cc542 --- a/interface/src/devices/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -11,7 +11,7 @@ // #include "KeyboardMouseDevice.h" -const QString KeyboardMouseDevice::NAME = "Keyboard"; +const QString KeyboardMouseDevice::NAME = "Keyboard/Mouse"; void KeyboardMouseDevice::update(float deltaTime) { _axisStateMap.clear(); diff --git a/interface/src/devices/KeyboardMouseDevice.h b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h old mode 100755 new mode 100644 similarity index 92% rename from interface/src/devices/KeyboardMouseDevice.h rename to libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h index c58eb0cabd..727920630b --- a/interface/src/devices/KeyboardMouseDevice.h +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h @@ -14,8 +14,8 @@ #include #include -#include -#include +#include "InputDevice.h" +#include "InputPlugin.h" class KeyboardMouseDevice : public InputPlugin, public InputDevice { Q_OBJECT @@ -58,14 +58,11 @@ public: // Plugin functions virtual bool isSupported() const override { return true; } - virtual bool isHandController() const override { return false; } + virtual bool isJointController() const override { return false; } const QString& getName() const { return NAME; } - virtual void init() override {}; - virtual void deinit() override {}; virtual void activate(PluginContainer * container) override {}; virtual void deactivate() override {}; - virtual void idle() override {}; virtual void pluginFocusOutEvent() override { focusOutEvent(); } virtual void pluginUpdate(float deltaTime) override { update(deltaTime); } @@ -96,6 +93,8 @@ public: UserInputMapper::Input makeInput(KeyboardMouseDevice::TouchAxisChannel axis); UserInputMapper::Input makeInput(KeyboardMouseDevice::TouchButtonChannel button); + static const QString NAME; + protected: QPoint _lastCursor; glm::vec2 _lastTouch; @@ -104,9 +103,6 @@ protected: glm::vec2 evalAverageTouchPoints(const QList& points) const; std::chrono::high_resolution_clock _clock; std::chrono::high_resolution_clock::time_point _lastTouchTime; - -private: - static const QString NAME; }; #endif // hifi_KeyboardMouseDevice_h diff --git a/libraries/input-plugins/src/input-plugins/SDL2Manager.cpp b/libraries/input-plugins/src/input-plugins/SDL2Manager.cpp index 40ec26bf71..c5e56457b3 100644 --- a/libraries/input-plugins/src/input-plugins/SDL2Manager.cpp +++ b/libraries/input-plugins/src/input-plugins/SDL2Manager.cpp @@ -32,15 +32,18 @@ _openJoysticks(), #endif _isInitialized(false) { +} + +void SDL2Manager::init() { #ifdef HAVE_SDL2 bool initSuccess = (SDL_Init(SDL_INIT_GAMECONTROLLER) == 0); - + if (initSuccess) { int joystickCount = SDL_NumJoysticks(); - + for (int i = 0; i < joystickCount; i++) { SDL_GameController* controller = SDL_GameControllerOpen(i); - + if (controller) { SDL_JoystickID id = getInstanceId(controller); if (!_openJoysticks.contains(id)) { @@ -53,27 +56,23 @@ _isInitialized(false) } } } - + _isInitialized = true; - } else { + } + else { qDebug() << "Error initializing SDL2 Manager"; } #endif } -SDL2Manager::~SDL2Manager() { +void SDL2Manager::deinit() { #ifdef HAVE_SDL2 qDeleteAll(_openJoysticks); - + SDL_Quit(); #endif } -SDL2Manager* SDL2Manager::getInstance() { - static SDL2Manager sharedInstance; - return &sharedInstance; -} - bool SDL2Manager::isSupported() const { #ifdef HAVE_SDL2 return true; diff --git a/libraries/input-plugins/src/input-plugins/SDL2Manager.h b/libraries/input-plugins/src/input-plugins/SDL2Manager.h index 9520cb9eab..123f8dc910 100644 --- a/libraries/input-plugins/src/input-plugins/SDL2Manager.h +++ b/libraries/input-plugins/src/input-plugins/SDL2Manager.h @@ -26,20 +26,16 @@ class SDL2Manager : public InputPlugin { public: SDL2Manager(); - ~SDL2Manager(); - - static SDL2Manager* getInstance(); - + // Plugin functions virtual bool isSupported() const override; - virtual bool isHandController() const override { return false; } + virtual bool isJointController() const override { return false; } const QString& getName() const { return NAME; } - virtual void init() override {}; - virtual void deinit() override {}; + virtual void init() override; + virtual void deinit() override; virtual void activate(PluginContainer * container) override {}; virtual void deactivate() override {}; - virtual void idle() override {}; virtual void pluginFocusOutEvent() override; virtual void pluginUpdate(float deltaTime) override; diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp index ffb9278992..3bc2d790b6 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp @@ -68,24 +68,6 @@ SixenseManager::SixenseManager() : } -SixenseManager::~SixenseManager() { -#ifdef HAVE_SIXENSE_ - - if (_isInitialized) { -#ifdef __APPLE__ - SixenseBaseFunction sixenseExit = (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseExit"); -#endif - - sixenseExit(); - } - -#ifdef __APPLE__ - delete _sixenseLibrary; -#endif - -#endif -} - bool SixenseManager::isSupported() const { #ifdef HAVE_SIXENSE return true; @@ -138,6 +120,24 @@ void SixenseManager::init() { #endif } +void SixenseManager::deinit() { +#ifdef HAVE_SIXENSE_ + + if (_isInitialized) { +#ifdef __APPLE__ + SixenseBaseFunction sixenseExit = (SixenseBaseFunction)_sixenseLibrary->resolve("sixenseExit"); +#endif + + sixenseExit(); + } + +#ifdef __APPLE__ + delete _sixenseLibrary; +#endif + +#endif +} + void SixenseManager::setFilter(bool filter) { #ifdef HAVE_SIXENSE @@ -175,12 +175,6 @@ void SixenseManager::update(float deltaTime) { userInputMapper->removeDevice(_deviceID); _deviceID = 0; _poseStateMap.clear(); -// if (_prevPalms[0]) { -// _prevPalms[0]->setActive(false); -// } -// if (_prevPalms[1]) { -// _prevPalms[1]->setActive(false); -// } } return; } @@ -296,17 +290,6 @@ void SixenseManager::update(float deltaTime) { #endif // HAVE_SIXENSE } -//Constants for getCursorPixelRangeMultiplier() -const float MIN_PIXEL_RANGE_MULT = 0.4f; -const float MAX_PIXEL_RANGE_MULT = 2.0f; -const float RANGE_MULT = (MAX_PIXEL_RANGE_MULT - MIN_PIXEL_RANGE_MULT) * 0.01f; - -//Returns a multiplier to be applied to the cursor range for the controllers -float SixenseManager::getCursorPixelRangeMult() const { - //scales (0,100) to (MINIMUM_PIXEL_RANGE_MULT, MAXIMUM_PIXEL_RANGE_MULT) - return _reticleMoveSpeed * RANGE_MULT + MIN_PIXEL_RANGE_MULT; -} - void SixenseManager::toggleSixense(bool shouldEnable) { if (shouldEnable && !isInitialized()) { init(); diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.h b/libraries/input-plugins/src/input-plugins/SixenseManager.h index 0ec0f65636..3aecb4aca5 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.h +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.h @@ -52,19 +52,20 @@ public: LEFT_HAND = 0, RIGHT_HAND, }; + + SixenseManager(); static SixenseManager& getInstance(); // Plugin functions virtual bool isSupported() const override; - virtual bool isHandController() const override { return false; } + virtual bool isJointController() const override { return true; } const QString& getName() const { return NAME; } virtual void init() override; - virtual void deinit() override {}; + virtual void deinit() override; virtual void activate(PluginContainer * container) override {}; - virtual void deactivate() override {}; - virtual void idle() override {}; + virtual void deactivate() override { _poseStateMap.clear(); }; virtual void pluginFocusOutEvent() override { focusOutEvent(); } virtual void pluginUpdate(float deltaTime) override { update(deltaTime); } @@ -79,10 +80,6 @@ public: void setIsEnabled(bool isEnabled) { _isEnabled = isEnabled; } - float getCursorPixelRangeMult() const; - - float getReticleMoveSpeed() const { return _reticleMoveSpeed; } - void setReticleMoveSpeed(float sixenseReticleMoveSpeed) { _reticleMoveSpeed = sixenseReticleMoveSpeed; } bool getInvertButtons() const { return _invertButtons; } void setInvertButtons(bool invertSixenseButtons) { _invertButtons = invertSixenseButtons; } @@ -95,10 +92,7 @@ public slots: void setFilter(bool filter); void setLowVelocityFilter(bool lowVelocityFilter) { _lowVelocityFilter = lowVelocityFilter; }; -private: - SixenseManager(); - ~SixenseManager(); - +private: void handleButtonEvent(unsigned int buttons, int index); void handleAxisEvent(float x, float y, float trigger, int index); void handlePoseEvent(glm::vec3 position, glm::quat rotation, int index); @@ -134,8 +128,7 @@ private: bool _lowVelocityFilter; bool _controllersAtBase; - - float _reticleMoveSpeed = DEFAULT_HAND_RETICLE_MOVE_SPEED; + bool _invertButtons = DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS; static const QString NAME; diff --git a/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp b/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp index 5ee3e32238..f81e058b1e 100644 --- a/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp +++ b/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp @@ -22,6 +22,7 @@ #include "UserActivityLogger.h" extern vr::IVRSystem *_hmd; +extern int hmdRefCount; extern vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount]; extern mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount]; @@ -43,15 +44,8 @@ const QString CONTROLLER_MODEL_STRING = "vr_controller_05_wireless_b"; const QString ViveControllerManager::NAME = "OpenVR"; -ViveControllerManager& ViveControllerManager::getInstance() { - static ViveControllerManager sharedInstance; - return sharedInstance; -} - ViveControllerManager::ViveControllerManager() : InputDevice("SteamVR Controller"), - _isInitialized(false), - _isEnabled(true), _trackedControllers(0), _modelLoaded(false), _leftHandRenderID(0), @@ -60,19 +54,12 @@ ViveControllerManager::ViveControllerManager() : } -ViveControllerManager::~ViveControllerManager() { - -} - bool ViveControllerManager::isSupported() const { return vr::VR_IsHmdPresent(); } -void ViveControllerManager::deinit() { - // TODO: deinit openvr? avoid conflicts with display plugin -} - -void ViveControllerManager::init() { +void ViveControllerManager::activate(PluginContainer* container) { + hmdRefCount++; if (!_hmd) { vr::HmdError eError = vr::HmdError_None; _hmd = vr::VR_Init(&eError); @@ -125,8 +112,16 @@ void ViveControllerManager::init() { _modelLoaded = true; } +} - _isInitialized = true; +void ViveControllerManager::deactivate() { + hmdRefCount--; + + if (hmdRefCount == 0 && _hmd) { + vr::VR_Shutdown(); + _hmd = nullptr; + } + _poseStateMap.clear(); } void ViveControllerManager::updateRendering(RenderArgs* args, render::ScenePointer scene, render::PendingChanges pendingChanges) { @@ -192,68 +187,68 @@ void ViveControllerManager::renderHand(UserInputMapper::PoseValue pose, gpu::Bat } void ViveControllerManager::update(float deltaTime) { + // TODO: This shouldn't be necessary if (!_hmd) { return; } + _buttonPressedMap.clear(); - if (_isInitialized && _isEnabled) { - PerformanceTimer perfTimer("ViveControllerManager::update"); + PerformanceTimer perfTimer("ViveControllerManager::update"); - int numTrackedControllers = 0; + int numTrackedControllers = 0; - for (vr::TrackedDeviceIndex_t device = vr::k_unTrackedDeviceIndex_Hmd + 1; - device < vr::k_unMaxTrackedDeviceCount && numTrackedControllers < 2; ++device) { + for (vr::TrackedDeviceIndex_t device = vr::k_unTrackedDeviceIndex_Hmd + 1; + device < vr::k_unMaxTrackedDeviceCount && numTrackedControllers < 2; ++device) { - if (!_hmd->IsTrackedDeviceConnected(device)) { - continue; - } + if (!_hmd->IsTrackedDeviceConnected(device)) { + continue; + } - if(_hmd->GetTrackedDeviceClass(device) != vr::TrackedDeviceClass_Controller) { - continue; - } + if(_hmd->GetTrackedDeviceClass(device) != vr::TrackedDeviceClass_Controller) { + continue; + } - if (!_trackedDevicePose[device].bPoseIsValid) { - continue; - } + if (!_trackedDevicePose[device].bPoseIsValid) { + continue; + } - numTrackedControllers++; + numTrackedControllers++; - const mat4& mat = _trackedDevicePoseMat4[device]; + const mat4& mat = _trackedDevicePoseMat4[device]; - handlePoseEvent(mat, numTrackedControllers - 1); + handlePoseEvent(mat, numTrackedControllers - 1); - // handle inputs - vr::VRControllerState_t controllerState = vr::VRControllerState_t(); - if (_hmd->GetControllerState(device, &controllerState)) { - //qDebug() << (numTrackedControllers == 1 ? "Left: " : "Right: "); - //qDebug() << "Trackpad: " << controllerState.rAxis[0].x << " " << controllerState.rAxis[0].y; - //qDebug() << "Trigger: " << controllerState.rAxis[1].x << " " << controllerState.rAxis[1].y; - handleButtonEvent(controllerState.ulButtonPressed, numTrackedControllers - 1); - for (int i = 0; i < vr::k_unControllerStateAxisCount; i++) { - handleAxisEvent(Axis(i), controllerState.rAxis[i].x, controllerState.rAxis[i].y, numTrackedControllers - 1); - } + // handle inputs + vr::VRControllerState_t controllerState = vr::VRControllerState_t(); + if (_hmd->GetControllerState(device, &controllerState)) { + //qDebug() << (numTrackedControllers == 1 ? "Left: " : "Right: "); + //qDebug() << "Trackpad: " << controllerState.rAxis[0].x << " " << controllerState.rAxis[0].y; + //qDebug() << "Trigger: " << controllerState.rAxis[1].x << " " << controllerState.rAxis[1].y; + handleButtonEvent(controllerState.ulButtonPressed, numTrackedControllers - 1); + for (int i = 0; i < vr::k_unControllerStateAxisCount; i++) { + handleAxisEvent(Axis(i), controllerState.rAxis[i].x, controllerState.rAxis[i].y, numTrackedControllers - 1); } } - - auto userInputMapper = DependencyManager::get(); - - if (numTrackedControllers == 0) { - if (_deviceID != 0) { - userInputMapper->removeDevice(_deviceID); - _deviceID = 0; - _poseStateMap.clear(); - } - } - - if (_trackedControllers == 0 && numTrackedControllers > 0) { - registerToUserInputMapper(*userInputMapper); - assignDefaultInputMapping(*userInputMapper); - UserActivityLogger::getInstance().connectedDevice("spatial_controller", "steamVR"); - } - - _trackedControllers = numTrackedControllers; } + + auto userInputMapper = DependencyManager::get(); + + if (numTrackedControllers == 0) { + if (_deviceID != 0) { + userInputMapper->removeDevice(_deviceID); + _deviceID = 0; + _poseStateMap.clear(); + } + } + + if (_trackedControllers == 0 && numTrackedControllers > 0) { + registerToUserInputMapper(*userInputMapper); + assignDefaultInputMapping(*userInputMapper); + UserActivityLogger::getInstance().connectedDevice("spatial_controller", "steamVR"); + } + + _trackedControllers = numTrackedControllers; } void ViveControllerManager::focusOutEvent() { diff --git a/libraries/input-plugins/src/input-plugins/ViveControllerManager.h b/libraries/input-plugins/src/input-plugins/ViveControllerManager.h index 93e0946154..81f8d0d729 100644 --- a/libraries/input-plugins/src/input-plugins/ViveControllerManager.h +++ b/libraries/input-plugins/src/input-plugins/ViveControllerManager.h @@ -48,18 +48,15 @@ public: RIGHT_HAND, }; - static ViveControllerManager& getInstance(); + ViveControllerManager(); // Plugin functions virtual bool isSupported() const override; - virtual bool isHandController() const override { return true; } + virtual bool isJointController() const override { return true; } const QString& getName() const { return NAME; } - virtual void init() override; - virtual void deinit() override; - virtual void activate(PluginContainer * container) override {}; - virtual void deactivate() override {}; - virtual void idle() override {}; + virtual void activate(PluginContainer * container) override; + virtual void deactivate() override; virtual void pluginFocusOutEvent() override { focusOutEvent(); } virtual void pluginUpdate(float deltaTime) override { update(deltaTime); } @@ -77,17 +74,12 @@ public: UserInputMapper::Input makeInput(JointChannel joint); private: - ViveControllerManager(); - ~ViveControllerManager(); - void renderHand(UserInputMapper::PoseValue pose, gpu::Batch& batch, int index); void handleButtonEvent(uint64_t buttons, int index); void handleAxisEvent(Axis axis, float x, float y, int index); void handlePoseEvent(const mat4& mat, int index); - bool _isInitialized; - bool _isEnabled; int _trackedControllers; bool _modelLoaded;