From 56e7af081efc49726b03aaf115b83a36b9336443 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 15 Jul 2015 18:50:44 -0700 Subject: [PATCH] input plugin architecture, fixed sixense --- interface/CMakeLists.txt | 2 +- interface/src/Application.cpp | 24 +++--- interface/src/Application.h | 1 - interface/src/Menu.cpp | 2 +- interface/src/devices/KeyboardMouseDevice.cpp | 28 ++----- interface/src/devices/KeyboardMouseDevice.h | 52 ++++++------ .../ControllerScriptingInterface.cpp | 4 +- interface/src/ui/ApplicationCompositor.cpp | 1 + interface/src/ui/AvatarAppearanceDialog.cpp | 1 - interface/src/ui/PreferencesDialog.cpp | 2 +- libraries/input-plugins/CMakeLists.txt | 56 ++++++++++++- .../src/input-plugins/InputDevice.cpp | 40 +++++++++ .../src/input-plugins/InputDevice.h | 51 +++++++++++ .../src/input-plugins/InputPlugin.cpp | 2 +- .../src/input-plugins/InputPlugin.h | 9 +- .../src/input-plugins/Joystick.cpp | 23 +---- .../src/input-plugins/Joystick.h | 38 +++------ .../src/input-plugins/SDL2Manager.cpp | 16 +++- .../src/input-plugins/SDL2Manager.h | 28 +++++-- .../src/input-plugins}/SixenseManager.cpp | 84 ++++++++----------- .../src/input-plugins}/SixenseManager.h | 61 ++++++-------- .../input-plugins/ViveControllerManager.cpp | 72 ++-------------- .../src/input-plugins/ViveControllerManager.h | 73 ++++++---------- 23 files changed, 344 insertions(+), 326 deletions(-) create mode 100644 libraries/input-plugins/src/input-plugins/InputDevice.cpp create mode 100644 libraries/input-plugins/src/input-plugins/InputDevice.h rename {interface/src/devices => libraries/input-plugins/src/input-plugins}/SixenseManager.cpp (93%) rename {interface/src/devices => libraries/input-plugins/src/input-plugins}/SixenseManager.h (74%) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 06a54e99be..0316226746 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -2,7 +2,7 @@ set(TARGET_NAME interface) project(${TARGET_NAME}) # set a default root dir for each of our optional externals if it was not passed -set(OPTIONAL_EXTERNALS "Faceshift" "LeapMotion" "RtMidi" "SDL2" "RSSDK") +set(OPTIONAL_EXTERNALS "Faceshift" "LeapMotion" "RtMidi" "RSSDK") foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) string(TOUPPER ${EXTERNAL} ${EXTERNAL}_UPPERCASE) if (NOT ${${EXTERNAL}_UPPERCASE}_ROOT_DIR) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 11a1f34168..c078359835 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -124,6 +124,7 @@ #include "devices/RealSense.h" #include "devices/MIDIManager.h" #include +#include #include #include "RenderDeferredTask.h" #include "scripting/AccountScriptingInterface.h" @@ -675,9 +676,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : connect(ddeTracker.data(), &FaceTracker::muteToggled, this, &Application::faceTrackerMuteToggled); #endif - ViveControllerManager::getInstance().init(); if (ViveControllerManager::getInstance().isSupported()) { - ViveControllerManager::getInstance().activate(); + ViveControllerManager::getInstance().init(); + ViveControllerManager::getInstance().activate(NULL); } _oldHandMouseX[0] = -1; @@ -1640,10 +1641,10 @@ void Application::keyReleaseEvent(QKeyEvent* event) { } void Application::focusOutEvent(QFocusEvent* event) { - _keyboardMouseDevice.focusOutEvent(event); - SixenseManager::getInstance().focusOutEvent(); - SDL2Manager::getInstance()->focusOutEvent(); - ViveControllerManager::getInstance().focusOutEvent(); + _keyboardMouseDevice.pluginFocusOutEvent(); + SixenseManager::getInstance().pluginFocusOutEvent(); + SDL2Manager::getInstance()->pluginFocusOutEvent(); + ViveControllerManager::getInstance().pluginFocusOutEvent(); // synthesize events for keys currently pressed, since we may not get their release events foreach (int key, _keysPressed) { @@ -2615,15 +2616,16 @@ void Application::update(float deltaTime) { _lastFaceTrackerUpdate = 0; } - SixenseManager::getInstance().update(deltaTime); - SDL2Manager::getInstance()->update(); - ViveControllerManager::getInstance().update(); } auto userInputMapper = DependencyManager::get(); userInputMapper->setSensorToWorldMat(_myAvatar->getSensorToWorldMatrix()); userInputMapper->update(deltaTime); - _keyboardMouseDevice.update(); + + _keyboardMouseDevice.pluginUpdate(deltaTime); + SixenseManager::getInstance().pluginUpdate(deltaTime); + SDL2Manager::getInstance()->pluginUpdate(deltaTime); + ViveControllerManager::getInstance().pluginUpdate(deltaTime); // Dispatch input events _controllerScriptingInterface.updateInputControllers(); @@ -3734,7 +3736,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se } renderArgs->_debugFlags = renderDebugFlags; _entities.render(renderArgs); - ViveControllerManager::getInstance().updateRendering(renderArgs, _main3DScene, pendingChanges); + //ViveControllerManager::getInstance().updateRendering(renderArgs, _main3DScene, pendingChanges); } // render the ambient occlusion effect if enabled diff --git a/interface/src/Application.h b/interface/src/Application.h index 226f885585..c0d6ac103c 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -54,7 +54,6 @@ #include "Stars.h" #include "avatar/Avatar.h" #include "avatar/MyAvatar.h" -#include "devices/SixenseManager.h" #include "scripting/ControllerScriptingInterface.h" #include "scripting/WebWindowClass.h" #include "ui/BandwidthDialog.h" diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 84253a21d7..db4942b7e7 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -30,7 +30,7 @@ #include "devices/DdeFaceTracker.h" #include "devices/Faceshift.h" #include "devices/RealSense.h" -//#include "devices/SixenseManager.h" +#include // TODO: should be able to remove this once input plugin architecture is finished #include "MainWindow.h" #include "scripting/MenuScriptingInterface.h" #if defined(Q_OS_MAC) || defined(Q_OS_WIN) diff --git a/interface/src/devices/KeyboardMouseDevice.cpp b/interface/src/devices/KeyboardMouseDevice.cpp index dd8de00bc7..d99b974585 100755 --- a/interface/src/devices/KeyboardMouseDevice.cpp +++ b/interface/src/devices/KeyboardMouseDevice.cpp @@ -11,7 +11,9 @@ // #include "KeyboardMouseDevice.h" -void KeyboardMouseDevice::update() { +const QString KeyboardMouseDevice::NAME = "Keyboard"; + +void KeyboardMouseDevice::update(float deltaTime) { _axisStateMap.clear(); // For touch event, we need to check that the last event is not too long ago @@ -27,7 +29,7 @@ void KeyboardMouseDevice::update() { } } -void KeyboardMouseDevice::focusOutEvent(QFocusEvent* event) { +void KeyboardMouseDevice::focusOutEvent() { _buttonPressedMap.clear(); }; @@ -159,7 +161,7 @@ void KeyboardMouseDevice::registerToUserInputMapper(UserInputMapper& mapper) { // Grab the current free device ID _deviceID = mapper.getFreeDeviceID(); - auto proxy = UserInputMapper::DeviceProxy::Pointer(new UserInputMapper::DeviceProxy("Keyboard")); + auto proxy = UserInputMapper::DeviceProxy::Pointer(new UserInputMapper::DeviceProxy(_name)); proxy->getButton = [this] (const UserInputMapper::Input& input, int timestamp) -> bool { return this->getButton(input.getChannel()); }; proxy->getAxis = [this] (const UserInputMapper::Input& input, int timestamp) -> float { return this->getAxis(input.getChannel()); }; proxy->getAvailabeInputs = [this] () -> QVector { @@ -282,23 +284,3 @@ void KeyboardMouseDevice::assignDefaultInputMapping(UserInputMapper& mapper) { mapper.addInputChannel(UserInputMapper::ACTION2, makeInput(Qt::Key_T)); } -float KeyboardMouseDevice::getButton(int channel) const { - if (!_buttonPressedMap.empty()) { - if (_buttonPressedMap.find(channel) != _buttonPressedMap.end()) { - return 1.0f; - } else { - return 0.0f; - } - } - return 0.0f; -} - -float KeyboardMouseDevice::getAxis(int channel) const { - auto axis = _axisStateMap.find(channel); - if (axis != _axisStateMap.end()) { - return (*axis).second; - } else { - return 0.0f; - } -} - diff --git a/interface/src/devices/KeyboardMouseDevice.h b/interface/src/devices/KeyboardMouseDevice.h index 3c6eefeac3..c58eb0cabd 100755 --- a/interface/src/devices/KeyboardMouseDevice.h +++ b/interface/src/devices/KeyboardMouseDevice.h @@ -14,11 +14,12 @@ #include #include -#include +#include +#include -class KeyboardMouseDevice { +class KeyboardMouseDevice : public InputPlugin, public InputDevice { + Q_OBJECT public: - enum KeyboardChannel { KEYBOARD_FIRST = 0, KEYBOARD_LAST = 255, @@ -53,10 +54,27 @@ public: TOUCH_BUTTON_PRESS = TOUCH_AXIS_Y_NEG + 1, }; - typedef std::unordered_set ButtonPressedMap; - typedef std::map AxisStateMap; // 8 axes + KeyboardMouseDevice() : InputDevice("Keyboard") {} - void focusOutEvent(QFocusEvent* event); + // Plugin functions + virtual bool isSupported() const override { return true; } + virtual bool isHandController() 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); } + + // Device functions + virtual void registerToUserInputMapper(UserInputMapper& mapper) override; + virtual void assignDefaultInputMapping(UserInputMapper& mapper) override; + virtual void update(float deltaTime) override; + virtual void focusOutEvent() override; void keyPressEvent(QKeyEvent* event); void keyReleaseEvent(QKeyEvent* event); @@ -70,32 +88,15 @@ public: void touchUpdateEvent(const QTouchEvent* event); void wheelEvent(QWheelEvent* event); - - // Get current state for each channels - float getButton(int channel) const; - float getAxis(int channel) const; - + // Let's make it easy for Qt because we assume we love Qt forever UserInputMapper::Input makeInput(Qt::Key code); UserInputMapper::Input makeInput(Qt::MouseButton code); UserInputMapper::Input makeInput(KeyboardMouseDevice::MouseAxisChannel axis); UserInputMapper::Input makeInput(KeyboardMouseDevice::TouchAxisChannel axis); UserInputMapper::Input makeInput(KeyboardMouseDevice::TouchButtonChannel button); - - KeyboardMouseDevice() {} - - void registerToUserInputMapper(UserInputMapper& mapper); - void assignDefaultInputMapping(UserInputMapper& mapper); - - // Update call MUST be called once per simulation loop - // It takes care of updating the action states and deltas - void update(); protected: - ButtonPressedMap _buttonPressedMap; - AxisStateMap _axisStateMap; - - int _deviceID = 0; QPoint _lastCursor; glm::vec2 _lastTouch; bool _isTouching = false; @@ -103,6 +104,9 @@ 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/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 736b8f31b6..e888ea1c63 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -16,9 +16,11 @@ #include "Application.h" #include "devices/MotionTracker.h" -//#include "devices/SixenseManager.h" #include "ControllerScriptingInterface.h" +// TODO: this needs to be removed, as well as any related controller-specific information +#include + ControllerScriptingInterface::ControllerScriptingInterface() : _mouseCaptured(false), diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index 5283aaf3ee..d2ee8b4028 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -22,6 +22,7 @@ #include "Tooltip.h" #include "Application.h" +#include // TODO: any references to sixense should be removed here // Used to animate the magnification windows diff --git a/interface/src/ui/AvatarAppearanceDialog.cpp b/interface/src/ui/AvatarAppearanceDialog.cpp index 3ab99c141d..54e48dca26 100644 --- a/interface/src/ui/AvatarAppearanceDialog.cpp +++ b/interface/src/ui/AvatarAppearanceDialog.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include "Application.h" diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index db6e8ce1ed..e99d5d4205 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include // TODO: This should be replaced with InputDevice/InputPlugin, or something similar #include #include "Application.h" diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index 28c17552c9..4a56dfa241 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -1,5 +1,15 @@ set(TARGET_NAME input-plugins) +# set a default root dir for each of our optional externals if it was not passed +set(OPTIONAL_EXTERNALS "SDL2" "Sixense") +foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) + string(TOUPPER ${EXTERNAL} ${EXTERNAL}_UPPERCASE) + if (NOT ${${EXTERNAL}_UPPERCASE}_ROOT_DIR) + string(TOLOWER ${EXTERNAL} ${EXTERNAL}_LOWERCASE) + set(${${EXTERNAL}_UPPERCASE}_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/${${EXTERNAL}_LOWERCASE}") + endif () +endforeach() + setup_hifi_library() # use setup_hifi_library macro to setup our project and link appropriate Qt modules @@ -16,7 +26,45 @@ find_package(OpenVR REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${OPENVR_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${OPENVR_LIBRARIES}) -add_dependency_external_projects(Sixense) -find_package(Sixense REQUIRED) -target_include_directories(${TARGET_NAME} PRIVATE ${SIXENSE_INCLUDE_DIRS}) -target_link_libraries(${TARGET_NAME} ${SIXENSE_LIBRARIES}) +#add_dependency_external_projects(Sixense) +#find_package(Sixense REQUIRED) +#target_include_directories(${TARGET_NAME} PRIVATE ${SIXENSE_INCLUDE_DIRS}) +#target_link_libraries(${TARGET_NAME} ${SIXENSE_LIBRARIES}) + +# perform standard include and linking for found externals +foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) + + if (${${EXTERNAL}_UPPERCASE}_REQUIRED) + find_package(${EXTERNAL} REQUIRED) + else () + find_package(${EXTERNAL}) + endif () + + if (${${EXTERNAL}_UPPERCASE}_FOUND AND NOT DISABLE_${${EXTERNAL}_UPPERCASE}) + add_definitions(-DHAVE_${${EXTERNAL}_UPPERCASE}) + + # include the library directories (ignoring warnings) + if (NOT ${${EXTERNAL}_UPPERCASE}_INCLUDE_DIRS) + set(${${EXTERNAL}_UPPERCASE}_INCLUDE_DIRS ${${${EXTERNAL}_UPPERCASE}_INCLUDE_DIR}) + endif () + + include_directories(SYSTEM ${${${EXTERNAL}_UPPERCASE}_INCLUDE_DIRS}) + + # perform the system include hack for OS X to ignore warnings + if (APPLE) + foreach(EXTERNAL_INCLUDE_DIR ${${${EXTERNAL}_UPPERCASE}_INCLUDE_DIRS}) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${EXTERNAL_INCLUDE_DIR}") + endforeach() + endif () + + if (NOT ${${EXTERNAL}_UPPERCASE}_LIBRARIES) + set(${${EXTERNAL}_UPPERCASE}_LIBRARIES ${${${EXTERNAL}_UPPERCASE}_LIBRARY}) + endif () + + if (NOT APPLE OR NOT ${${EXTERNAL}_UPPERCASE} MATCHES "SIXENSE") + target_link_libraries(${TARGET_NAME} ${${${EXTERNAL}_UPPERCASE}_LIBRARIES}) + elseif (APPLE AND NOT INSTALLER_BUILD) + add_definitions(-DSIXENSE_LIB_FILENAME=\"${${${EXTERNAL}_UPPERCASE}_LIBRARY_RELEASE}\") + endif () + endif () +endforeach() \ No newline at end of file diff --git a/libraries/input-plugins/src/input-plugins/InputDevice.cpp b/libraries/input-plugins/src/input-plugins/InputDevice.cpp new file mode 100644 index 0000000000..9e8574c6e7 --- /dev/null +++ b/libraries/input-plugins/src/input-plugins/InputDevice.cpp @@ -0,0 +1,40 @@ +// +// Created by Sam Gondelman on 7/15/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 +// +#include "InputDevice.h" + +float InputDevice::getButton(int channel) const { + if (!_buttonPressedMap.empty()) { + if (_buttonPressedMap.find(channel) != _buttonPressedMap.end()) { + return 1.0f; + } + else { + return 0.0f; + } + } + return 0.0f; +} + +float InputDevice::getAxis(int channel) const { + auto axis = _axisStateMap.find(channel); + if (axis != _axisStateMap.end()) { + return (*axis).second; + } + else { + return 0.0f; + } +} + +UserInputMapper::PoseValue InputDevice::getPose(int channel) const { + auto pose = _poseStateMap.find(channel); + if (pose != _poseStateMap.end()) { + return (*pose).second; + } + 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 new file mode 100644 index 0000000000..83548a5b90 --- /dev/null +++ b/libraries/input-plugins/src/input-plugins/InputDevice.h @@ -0,0 +1,51 @@ +// +// Created by Sam Gondelman on 7/15/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 + +#include "UserInputMapper.h" + +// Event types for each controller +const unsigned int CONTROLLER_0_EVENT = 1500U; +const unsigned int CONTROLLER_1_EVENT = 1501U; + +// NOTE: If something inherits from both InputDevice and InputPlugin, InputPlugin must go first. +// e.g. class Example : public InputPlugin, public InputDevice +// instead of class Example : public InputDevice, public InputPlugin +class InputDevice { +public: + InputDevice::InputDevice(const QString& name) : _name(name) {} + + typedef std::unordered_set ButtonPressedMap; + typedef std::map AxisStateMap; + typedef std::map PoseStateMap; + + // Get current state for each channel + float getButton(int channel) const; + float getAxis(int channel) const; + UserInputMapper::PoseValue getPose(int channel) const; + + virtual void registerToUserInputMapper(UserInputMapper& mapper) = 0; + virtual void assignDefaultInputMapping(UserInputMapper& mapper) = 0; + + // Update call MUST be called once per simulation loop + // It takes care of updating the action states and deltas + virtual void update(float deltaTime) = 0; + + virtual void focusOutEvent() = 0; + + int getDeviceID() { return _deviceID; } + +protected: + int _deviceID = 0; + + QString _name; + + ButtonPressedMap _buttonPressedMap; + AxisStateMap _axisStateMap; + PoseStateMap _poseStateMap; +}; diff --git a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp index 1da0dce891..0543c3547f 100644 --- a/libraries/input-plugins/src/input-plugins/InputPlugin.cpp +++ b/libraries/input-plugins/src/input-plugins/InputPlugin.cpp @@ -5,4 +5,4 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "InputPlugin.h" +#include "InputPlugin.h" \ 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 1b3eca4049..c10770679d 100644 --- a/libraries/input-plugins/src/input-plugins/InputPlugin.h +++ b/libraries/input-plugins/src/input-plugins/InputPlugin.h @@ -9,9 +9,14 @@ #include +const float DEFAULT_HAND_RETICLE_MOVE_SPEED = 37.5f; + class InputPlugin : public Plugin { - Q_OBJECT public: - virtual bool isHandController() = 0; + virtual bool isHandController() const = 0; + + virtual void pluginFocusOutEvent() = 0; + + virtual void pluginUpdate(float deltaTime) = 0; }; diff --git a/libraries/input-plugins/src/input-plugins/Joystick.cpp b/libraries/input-plugins/src/input-plugins/Joystick.cpp index 5eaf7f02bb..a652bee227 100644 --- a/libraries/input-plugins/src/input-plugins/Joystick.cpp +++ b/libraries/input-plugins/src/input-plugins/Joystick.cpp @@ -21,6 +21,7 @@ const float CONTROLLER_THRESHOLD = 0.3f; const float MAX_AXIS = 32768.0f; Joystick::Joystick(SDL_JoystickID instanceId, const QString& name, SDL_GameController* sdlGameController) : + InputDevice(name), _sdlGameController(sdlGameController), _sdlJoystick(SDL_GameControllerGetJoystick(_sdlGameController)), _instanceId(instanceId) @@ -40,7 +41,7 @@ void Joystick::closeJoystick() { #endif } -void Joystick::update() { +void Joystick::update(float deltaTime) { for (auto axisState : _axisStateMap) { if (fabsf(axisState.second) < CONTROLLER_THRESHOLD) { _axisStateMap[axisState.first] = 0.0f; @@ -212,26 +213,6 @@ void Joystick::assignDefaultInputMapping(UserInputMapper& mapper) { #endif } -float Joystick::getButton(int channel) const { - if (!_buttonPressedMap.empty()) { - if (_buttonPressedMap.find(channel) != _buttonPressedMap.end()) { - return 1.0f; - } else { - return 0.0f; - } - } - return 0.0f; -} - -float Joystick::getAxis(int channel) const { - auto axis = _axisStateMap.find(channel); - if (axis != _axisStateMap.end()) { - return (*axis).second; - } else { - return 0.0f; - } -} - #ifdef HAVE_SDL2 UserInputMapper::Input Joystick::makeInput(SDL_GameControllerButton button) { return UserInputMapper::Input(_deviceID, button, UserInputMapper::ChannelType::BUTTON); diff --git a/libraries/input-plugins/src/input-plugins/Joystick.h b/libraries/input-plugins/src/input-plugins/Joystick.h index f6f62efdf6..131a8ced11 100644 --- a/libraries/input-plugins/src/input-plugins/Joystick.h +++ b/libraries/input-plugins/src/input-plugins/Joystick.h @@ -20,11 +20,10 @@ #undef main #endif -#include "UserInputMapper.h" +#include "InputDevice.h" -class Joystick : public QObject { +class Joystick : public QObject, InputDevice { Q_OBJECT - Q_PROPERTY(QString name READ getName) #ifdef HAVE_SDL2 @@ -44,27 +43,23 @@ public: RIGHT_SHOULDER, LEFT_SHOULDER, }; + + const QString& getName() const { return _name; } + + // Device functions + virtual void registerToUserInputMapper(UserInputMapper& mapper) override; + virtual void assignDefaultInputMapping(UserInputMapper& mapper) override; + virtual void update(float deltaTime) override; + virtual void focusOutEvent() override; - Joystick(); + Joystick() : InputDevice("Joystick") {} ~Joystick(); - typedef std::unordered_set ButtonPressedMap; - typedef std::map AxisStateMap; - - float getButton(int channel) const; - float getAxis(int channel) const; - #ifdef HAVE_SDL2 UserInputMapper::Input makeInput(SDL_GameControllerButton button); #endif UserInputMapper::Input makeInput(Joystick::JoystickAxisChannel axis); - void registerToUserInputMapper(UserInputMapper& mapper); - void assignDefaultInputMapping(UserInputMapper& mapper); - - void update(); - void focusOutEvent(); - #ifdef HAVE_SDL2 Joystick(SDL_JoystickID instanceId, const QString& name, SDL_GameController* sdlGameController); #endif @@ -76,27 +71,16 @@ public: void handleButtonEvent(const SDL_ControllerButtonEvent& event); #endif - const QString& getName() const { return _name; } #ifdef HAVE_SDL2 int getInstanceId() const { return _instanceId; } #endif - int getDeviceID() { return _deviceID; } - private: #ifdef HAVE_SDL2 SDL_GameController* _sdlGameController; SDL_Joystick* _sdlJoystick; SDL_JoystickID _instanceId; #endif - - QString _name; - -protected: - int _deviceID = 0; - - ButtonPressedMap _buttonPressedMap; - AxisStateMap _axisStateMap; }; #endif // hifi_Joystick_h diff --git a/libraries/input-plugins/src/input-plugins/SDL2Manager.cpp b/libraries/input-plugins/src/input-plugins/SDL2Manager.cpp index b6a1fab951..8756006491 100644 --- a/libraries/input-plugins/src/input-plugins/SDL2Manager.cpp +++ b/libraries/input-plugins/src/input-plugins/SDL2Manager.cpp @@ -17,6 +17,8 @@ #include "SDL2Manager.h" +const QString SDL2Manager::NAME = "SDL2"; + #ifdef HAVE_SDL2 SDL_JoystickID SDL2Manager::getInstanceId(SDL_GameController* controller) { SDL_Joystick* joystick = SDL_GameControllerGetJoystick(controller); @@ -72,7 +74,15 @@ SDL2Manager* SDL2Manager::getInstance() { return &sharedInstance; } -void SDL2Manager::focusOutEvent() { +bool SDL2Manager::isSupported() const { +#ifdef HAVE_SDL2 + return true; +#else + return false; +#endif +} + +void SDL2Manager::pluginFocusOutEvent() { #ifdef HAVE_SDL2 for (auto joystick : _openJoysticks) { joystick->focusOutEvent(); @@ -80,12 +90,12 @@ void SDL2Manager::focusOutEvent() { #endif } -void SDL2Manager::update() { +void SDL2Manager::pluginUpdate(float deltaTime) { #ifdef HAVE_SDL2 if (_isInitialized) { auto userInputMapper = DependencyManager::get(); for (auto joystick : _openJoysticks) { - joystick->update(); + joystick->update(deltaTime); } PerformanceTimer perfTimer("SDL2Manager::update"); diff --git a/libraries/input-plugins/src/input-plugins/SDL2Manager.h b/libraries/input-plugins/src/input-plugins/SDL2Manager.h index 3ae1b43c5d..9520cb9eab 100644 --- a/libraries/input-plugins/src/input-plugins/SDL2Manager.h +++ b/libraries/input-plugins/src/input-plugins/SDL2Manager.h @@ -16,22 +16,33 @@ #include #endif +#include "InputPlugin.h" #include "UserInputMapper.h" #include "Joystick.h" -class SDL2Manager : public QObject { +class SDL2Manager : public InputPlugin { Q_OBJECT public: SDL2Manager(); ~SDL2Manager(); - - void focusOutEvent(); - - void update(); - + static SDL2Manager* getInstance(); + + // Plugin functions + virtual bool isSupported() const override; + virtual bool isHandController() 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; + virtual void pluginUpdate(float deltaTime) override; signals: void joystickAdded(Joystick* joystick); @@ -70,12 +81,11 @@ private: int buttonPressed() const { return SDL_PRESSED; } int buttonRelease() const { return SDL_RELEASED; } -#endif - -#ifdef HAVE_SDL2 + QMap _openJoysticks; #endif bool _isInitialized; + static const QString NAME; }; #endif // hifi__SDL2Manager_h diff --git a/interface/src/devices/SixenseManager.cpp b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp similarity index 93% rename from interface/src/devices/SixenseManager.cpp rename to libraries/input-plugins/src/input-plugins/SixenseManager.cpp index 7b33861270..ffb9278992 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp @@ -11,13 +11,16 @@ #include -#include #include -#include "Application.h" +#include "NumericalConstants.h" #include "SixenseManager.h" #include "UserActivityLogger.h" -#include "InterfaceLogging.h" + +// TODO: This should not be here +#include +Q_DECLARE_LOGGING_CATEGORY(inputplugins) +Q_LOGGING_CATEGORY(inputplugins, "hifi.inputplugins") // These bits aren't used for buttons, so they can be used as masks: const unsigned int LEFT_MASK = 0; @@ -46,12 +49,15 @@ typedef int (*SixenseTakeIntAndSixenseControllerData)(int, sixenseControllerData #endif +const QString SixenseManager::NAME = "Sixense"; + SixenseManager& SixenseManager::getInstance() { static SixenseManager sharedInstance; return sharedInstance; } SixenseManager::SixenseManager() : + InputDevice("Hydra"), #if defined(HAVE_SIXENSE) && defined(__APPLE__) _sixenseLibrary(NULL), #endif @@ -80,7 +86,15 @@ SixenseManager::~SixenseManager() { #endif } -void SixenseManager::initialize() { +bool SixenseManager::isSupported() const { +#ifdef HAVE_SIXENSE + return true; +#else + return false; +#endif +} + +void SixenseManager::init() { #ifdef HAVE_SIXENSE if (!_isInitialized) { @@ -144,18 +158,21 @@ void SixenseManager::setFilter(bool filter) { void SixenseManager::update(float deltaTime) { #ifdef HAVE_SIXENSE - Hand* hand = DependencyManager::get()->getMyAvatar()->getHand(); + //Hand* hand = DependencyManager::get()->getMyAvatar()->getHand(); if (_isInitialized && _isEnabled) { _buttonPressedMap.clear(); + #ifdef __APPLE__ SixenseBaseFunction sixenseGetNumActiveControllers = (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseGetNumActiveControllers"); #endif + auto userInputMapper = DependencyManager::get(); + if (sixenseGetNumActiveControllers() == 0) { _hydrasConnected = false; if (_deviceID != 0) { - Application::getUserInputMapper()->removeDevice(_deviceID); + userInputMapper->removeDevice(_deviceID); _deviceID = 0; _poseStateMap.clear(); // if (_prevPalms[0]) { @@ -171,8 +188,8 @@ void SixenseManager::update(float deltaTime) { PerformanceTimer perfTimer("sixense"); if (!_hydrasConnected) { _hydrasConnected = true; - registerToUserInputMapper(*Application::getUserInputMapper()); - getInstance().assignDefaultInputMapping(*Application::getUserInputMapper()); + registerToUserInputMapper(*userInputMapper); + getInstance().assignDefaultInputMapping(*userInputMapper); UserActivityLogger::getInstance().connectedDevice("spatial_controller", "hydra"); } @@ -240,7 +257,7 @@ void SixenseManager::update(float deltaTime) { glm::quat rotation(data->rot_quat[3], -data->rot_quat[0], data->rot_quat[1], -data->rot_quat[2]); rotation = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)) * _orbRotation * rotation; - handlePoseEvent(position, rotation, numActiveControlers - 1); + handlePoseEvent(position, rotation, numActiveControllers - 1); } else { _poseStateMap.clear(); } @@ -292,9 +309,9 @@ float SixenseManager::getCursorPixelRangeMult() const { void SixenseManager::toggleSixense(bool shouldEnable) { if (shouldEnable && !isInitialized()) { - initialize(); - setFilter(Menu::getInstance()->isOptionChecked(MenuOption::FilterSixense)); - setLowVelocityFilter(Menu::getInstance()->isOptionChecked(MenuOption::LowVelocityFilter)); + init(); + //setFilter(Menu::getInstance()->isOptionChecked(MenuOption::FilterSixense)); + //setLowVelocityFilter(Menu::getInstance()->isOptionChecked(MenuOption::LowVelocityFilter)); } setIsEnabled(shouldEnable); } @@ -337,11 +354,11 @@ void SixenseManager::updateCalibration(const sixenseControllerData* controllers) glm::vec3 zAxis = glm::normalize(glm::cross(xAxis, yAxis)); xAxis = glm::normalize(glm::cross(yAxis, zAxis)); _orbRotation = glm::inverse(glm::quat_cast(glm::mat3(xAxis, yAxis, zAxis))); - qCDebug(interfaceapp, "succeess: sixense calibration"); + qCDebug(inputplugins, "succeess: sixense calibration"); } break; default: - qCDebug(interfaceapp, "failed: sixense calibration"); + qCDebug(inputplugins, "failed: sixense calibration"); break; } @@ -360,7 +377,7 @@ void SixenseManager::updateCalibration(const sixenseControllerData* controllers) if (_calibrationState == CALIBRATION_STATE_IDLE) { float reach = glm::distance(positionLeft, positionRight); if (reach > 2.0f * MINIMUM_ARM_REACH) { - qCDebug(interfaceapp, "started: sixense calibration"); + qCDebug(inputplugins, "started: sixense calibration"); _averageLeft = positionLeft; _averageRight = positionRight; _reachLeft = _averageLeft; @@ -393,7 +410,7 @@ void SixenseManager::updateCalibration(const sixenseControllerData* controllers) _lastDistance = 0.0f; _reachUp = 0.5f * (_reachLeft + _reachRight); _calibrationState = CALIBRATION_STATE_Y; - qCDebug(interfaceapp, "success: sixense calibration: left"); + qCDebug(inputplugins, "success: sixense calibration: left"); } } else if (_calibrationState == CALIBRATION_STATE_Y) { @@ -412,7 +429,7 @@ void SixenseManager::updateCalibration(const sixenseControllerData* controllers) _lastDistance = 0.0f; _lockExpiry = now + LOCK_DURATION; _calibrationState = CALIBRATION_STATE_Z; - qCDebug(interfaceapp, "success: sixense calibration: up"); + qCDebug(inputplugins, "success: sixense calibration: up"); } } } @@ -434,7 +451,7 @@ void SixenseManager::updateCalibration(const sixenseControllerData* controllers) if (fabsf(_lastDistance) > 0.05f * MINIMUM_ARM_REACH) { // lock has expired so clamp the data and move on _calibrationState = CALIBRATION_STATE_COMPLETE; - qCDebug(interfaceapp, "success: sixense calibration: forward"); + qCDebug(inputplugins, "success: sixense calibration: forward"); // TODO: it is theoretically possible to detect that the controllers have been // accidentally switched (left hand is holding right controller) and to swap the order. } @@ -547,7 +564,7 @@ void SixenseManager::registerToUserInputMapper(UserInputMapper& mapper) { // Grab the current free device ID _deviceID = mapper.getFreeDeviceID(); - auto proxy = UserInputMapper::DeviceProxy::Pointer(new UserInputMapper::DeviceProxy("Hydra")); + auto proxy = UserInputMapper::DeviceProxy::Pointer(new UserInputMapper::DeviceProxy(_name)); proxy->getButton = [this] (const UserInputMapper::Input& input, int timestamp) -> bool { return this->getButton(input.getChannel()); }; proxy->getAxis = [this] (const UserInputMapper::Input& input, int timestamp) -> float { return this->getAxis(input.getChannel()); }; proxy->getPose = [this](const UserInputMapper::Input& input, int timestamp) -> UserInputMapper::PoseValue { return this->getPose(input.getChannel()); }; @@ -633,35 +650,6 @@ void SixenseManager::assignDefaultInputMapping(UserInputMapper& mapper) { } -float SixenseManager::getButton(int channel) const { - if (!_buttonPressedMap.empty()) { - if (_buttonPressedMap.find(channel) != _buttonPressedMap.end()) { - return 1.0f; - } else { - return 0.0f; - } - } - return 0.0f; -} - -float SixenseManager::getAxis(int channel) const { - auto axis = _axisStateMap.find(channel); - if (axis != _axisStateMap.end()) { - return (*axis).second; - } else { - return 0.0f; - } -} - -UserInputMapper::PoseValue SixenseManager::getPose(int channel) const { - auto pose = _poseStateMap.find(channel); - if (pose != _poseStateMap.end()) { - return (*pose).second; - } else { - return UserInputMapper::PoseValue(); - } -} - UserInputMapper::Input SixenseManager::makeInput(unsigned int button, int index) { return UserInputMapper::Input(_deviceID, button | (index == 0 ? LEFT_MASK : RIGHT_MASK), UserInputMapper::ChannelType::BUTTON); } diff --git a/interface/src/devices/SixenseManager.h b/libraries/input-plugins/src/input-plugins/SixenseManager.h similarity index 74% rename from interface/src/devices/SixenseManager.h rename to libraries/input-plugins/src/input-plugins/SixenseManager.h index 9dd60c5d27..0ec0f65636 100644 --- a/interface/src/devices/SixenseManager.h +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.h @@ -12,9 +12,6 @@ #ifndef hifi_SixenseManager_h #define hifi_SixenseManager_h -#include -#include - #ifdef HAVE_SIXENSE #include #include @@ -26,7 +23,8 @@ #endif -#include +#include "InputPlugin.h" +#include "InputDevice.h" const unsigned int BUTTON_0 = 1U << 0; // the skinny button between 1 and 2 const unsigned int BUTTON_1 = 1U << 5; @@ -36,15 +34,10 @@ const unsigned int BUTTON_4 = 1U << 4; const unsigned int BUTTON_FWD = 1U << 7; const unsigned int BUTTON_TRIGGER = 1U << 8; -// Event type that represents using the controller -const unsigned int CONTROLLER_0_EVENT = 1500U; -const unsigned int CONTROLLER_1_EVENT = 1501U; - -const float DEFAULT_SIXENSE_RETICLE_MOVE_SPEED = 37.5f; const bool DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS = false; -/// Handles interaction with the Sixense SDK (e.g., Razer Hydra). -class SixenseManager : public QObject { +// Handles interaction with the Sixense SDK (e.g., Razer Hydra). +class SixenseManager : public InputPlugin, public InputDevice { Q_OBJECT public: enum JoystickAxisChannel { @@ -61,13 +54,31 @@ public: }; static SixenseManager& getInstance(); - - void initialize(); + + // Plugin functions + virtual bool isSupported() const override; + virtual bool isHandController() 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); } + + // Device functions + virtual void registerToUserInputMapper(UserInputMapper& mapper) override; + virtual void assignDefaultInputMapping(UserInputMapper& mapper) override; + virtual void update(float deltaTime) override; + virtual void focusOutEvent() override; + bool isInitialized() const { return _isInitialized; } void setIsEnabled(bool isEnabled) { _isEnabled = isEnabled; } - void update(float deltaTime); float getCursorPixelRangeMult() const; float getReticleMoveSpeed() const { return _reticleMoveSpeed; } @@ -75,23 +86,10 @@ public: bool getInvertButtons() const { return _invertButtons; } void setInvertButtons(bool invertSixenseButtons) { _invertButtons = invertSixenseButtons; } - typedef std::unordered_set ButtonPressedMap; - typedef std::map AxisStateMap; - typedef std::map PoseStateMap; - - float getButton(int channel) const; - float getAxis(int channel) const; - UserInputMapper::PoseValue getPose(int channel) const; - UserInputMapper::Input makeInput(unsigned int button, int index); UserInputMapper::Input makeInput(JoystickAxisChannel axis, int index); UserInputMapper::Input makeInput(JointChannel joint); - void registerToUserInputMapper(UserInputMapper& mapper); - void assignDefaultInputMapping(UserInputMapper& mapper); - - void focusOutEvent(); - public slots: void toggleSixense(bool shouldEnable); void setFilter(bool filter); @@ -137,15 +135,10 @@ private: bool _lowVelocityFilter; bool _controllersAtBase; - float _reticleMoveSpeed = DEFAULT_SIXENSE_RETICLE_MOVE_SPEED; + float _reticleMoveSpeed = DEFAULT_HAND_RETICLE_MOVE_SPEED; bool _invertButtons = DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS; -protected: - int _deviceID = 0; - - ButtonPressedMap _buttonPressedMap; - AxisStateMap _axisStateMap; - PoseStateMap _poseStateMap; + static const QString NAME; }; #endif // hifi_SixenseManager_h diff --git a/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp b/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp index fdf735940b..5ee3e32238 100644 --- a/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp +++ b/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp @@ -21,12 +21,6 @@ #include "NumericalConstants.h" #include "UserActivityLogger.h" -#include -Q_DECLARE_LOGGING_CATEGORY(inputplugins) -Q_LOGGING_CATEGORY(inputplugins, "hifi.inputplugins") - -const QString ViveControllerManager::NAME("OpenVR (Vive) Hand Controllers"); - extern vr::IVRSystem *_hmd; extern vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount]; extern mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount]; @@ -47,12 +41,15 @@ const unsigned int TRIGGER_BUTTON = 1U << 4; const float CONTROLLER_LENGTH_OFFSET = 0.175f; 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), @@ -67,41 +64,15 @@ ViveControllerManager::~ViveControllerManager() { } -const QString& ViveControllerManager::getName() const { - return NAME; -} - bool ViveControllerManager::isSupported() const { return vr::VR_IsHmdPresent(); } -void ViveControllerManager::init() { - ; -} - void ViveControllerManager::deinit() { - ; + // TODO: deinit openvr? avoid conflicts with display plugin } -void ViveControllerManager::activate(PluginContainer * container) { - activate(); -} - -/// Called when a plugin is no longer being used. May be called multiple times. -void ViveControllerManager::deactivate() { - ; -} - -/** - * Called by the application during it's idle phase. If the plugin needs to do - * CPU intensive work, it should launch a thread for that, rather than trying to - * do long operations in the idle call - */ -void ViveControllerManager::idle() { - update(); -} - -void ViveControllerManager::activate() { +void ViveControllerManager::init() { if (!_hmd) { vr::HmdError eError = vr::HmdError_None; _hmd = vr::VR_Init(&eError); @@ -220,7 +191,7 @@ void ViveControllerManager::renderHand(UserInputMapper::PoseValue pose, gpu::Bat batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0); } -void ViveControllerManager::update() { +void ViveControllerManager::update(float deltaTime) { if (!_hmd) { return; } @@ -333,7 +304,7 @@ void ViveControllerManager::registerToUserInputMapper(UserInputMapper& mapper) { // Grab the current free device ID _deviceID = mapper.getFreeDeviceID(); - auto proxy = UserInputMapper::DeviceProxy::Pointer(new UserInputMapper::DeviceProxy("SteamVR Controller")); + auto proxy = UserInputMapper::DeviceProxy::Pointer(new UserInputMapper::DeviceProxy(_name)); proxy->getButton = [this] (const UserInputMapper::Input& input, int timestamp) -> bool { return this->getButton(input.getChannel()); }; proxy->getAxis = [this] (const UserInputMapper::Input& input, int timestamp) -> float { return this->getAxis(input.getChannel()); }; proxy->getPose = [this](const UserInputMapper::Input& input, int timestamp) -> UserInputMapper::PoseValue { return this->getPose(input.getChannel()); }; @@ -405,35 +376,6 @@ void ViveControllerManager::assignDefaultInputMapping(UserInputMapper& mapper) { mapper.addInputChannel(UserInputMapper::RIGHT_HAND, makeInput(RIGHT_HAND)); } -float ViveControllerManager::getButton(int channel) const { - if (!_buttonPressedMap.empty()) { - if (_buttonPressedMap.find(channel) != _buttonPressedMap.end()) { - return 1.0f; - } else { - return 0.0f; - } - } - return 0.0f; -} - -float ViveControllerManager::getAxis(int channel) const { - auto axis = _axisStateMap.find(channel); - if (axis != _axisStateMap.end()) { - return (*axis).second; - } else { - return 0.0f; - } -} - -UserInputMapper::PoseValue ViveControllerManager::getPose(int channel) const { - auto pose = _poseStateMap.find(channel); - if (pose != _poseStateMap.end()) { - return (*pose).second; - } else { - return UserInputMapper::PoseValue(); - } -} - UserInputMapper::Input ViveControllerManager::makeInput(unsigned int button, int index) { return UserInputMapper::Input(_deviceID, button | (index == 0 ? LEFT_MASK : RIGHT_MASK), UserInputMapper::ChannelType::BUTTON); } diff --git a/libraries/input-plugins/src/input-plugins/ViveControllerManager.h b/libraries/input-plugins/src/input-plugins/ViveControllerManager.h index a1a44db6fc..93e0946154 100644 --- a/libraries/input-plugins/src/input-plugins/ViveControllerManager.h +++ b/libraries/input-plugins/src/input-plugins/ViveControllerManager.h @@ -19,34 +19,14 @@ #include #include +#include "InputDevice.h" #include "InputPlugin.h" #include #include -#include "UserInputMapper.h" -class ViveControllerManager : public InputPlugin { +class ViveControllerManager : public InputPlugin, public InputDevice { + Q_OBJECT public: - virtual const QString& getName() const override; - virtual bool isSupported() const override; - virtual bool isHandController() { return true; } - - /// Called when plugin is initially loaded, typically at application start - virtual void init() override; - /// Called when application is shutting down - virtual void deinit() override ; - - /// Called when a plugin is being activated for use. May be called multiple times. - virtual void activate(PluginContainer * container) override; - /// Called when a plugin is no longer being used. May be called multiple times. - virtual void deactivate() override; - - /** - * Called by the application during it's idle phase. If the plugin needs to do - * CPU intensive work, it should launch a thread for that, rather than trying to - * do long operations in the idle call - */ - virtual void idle() override; - enum JoystickAxisChannel { AXIS_Y_POS = 1U << 1, AXIS_Y_NEG = 1U << 2, @@ -67,31 +47,35 @@ public: LEFT_HAND = 0, RIGHT_HAND, }; - - void focusOutEvent(); + + static ViveControllerManager& getInstance(); + + // Plugin functions + virtual bool isSupported() const override; + virtual bool isHandController() 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 pluginFocusOutEvent() override { focusOutEvent(); } + virtual void pluginUpdate(float deltaTime) override { update(deltaTime); } + + // Device functions + virtual void registerToUserInputMapper(UserInputMapper& mapper) override; + virtual void assignDefaultInputMapping(UserInputMapper& mapper) override; + virtual void update(float deltaTime) override; + virtual void focusOutEvent() override; void updateRendering(RenderArgs* args, render::ScenePointer scene, render::PendingChanges pendingChanges); - void update(); - - static ViveControllerManager& getInstance(); - - typedef std::unordered_set ButtonPressedMap; - typedef std::map AxisStateMap; - typedef std::map PoseStateMap; - - float getButton(int channel) const; - float getAxis(int channel) const; - UserInputMapper::PoseValue getPose(int channel) const; UserInputMapper::Input makeInput(unsigned int button, int index); UserInputMapper::Input makeInput(JoystickAxisChannel axis, int index); UserInputMapper::Input makeInput(JointChannel joint); - void registerToUserInputMapper(UserInputMapper& mapper); - void assignDefaultInputMapping(UserInputMapper& mapper); - - void activate(); - private: ViveControllerManager(); ~ViveControllerManager(); @@ -114,13 +98,6 @@ private: int _rightHandRenderID; static const QString NAME; - -protected: - int _deviceID = 0; - - ButtonPressedMap _buttonPressedMap; - AxisStateMap _axisStateMap; - PoseStateMap _poseStateMap; };