From 603405ad61d8009fa81e0c6c2e791dc2d3731af4 Mon Sep 17 00:00:00 2001 From: EdgarPironti Date: Mon, 2 Nov 2015 23:29:15 -0800 Subject: [PATCH] Do not merge - Spacemouse --- interface/src/Application.cpp | 13 +- interface/src/Menu.cpp | 12 +- interface/src/devices/3DConnexionClient.cpp | 972 -------------------- interface/src/devices/3DConnexionClient.h | 223 ----- 4 files changed, 10 insertions(+), 1210 deletions(-) delete mode 100755 interface/src/devices/3DConnexionClient.cpp delete mode 100755 interface/src/devices/3DConnexionClient.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6d41679bea..dc166e729b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -100,7 +100,7 @@ #include "audio/AudioScope.h" #include "avatar/AvatarManager.h" #include "CrashHandler.h" -#include "devices/3DConnexionClient.h" +#include "input-plugins/SpacemouseManager.h" #include "devices/DdeFaceTracker.h" #include "devices/EyeTracker.h" #include "devices/Faceshift.h" @@ -729,10 +729,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : // Now that menu is initalized we can sync myAvatar with it's state. getMyAvatar()->updateMotionBehaviorFromMenu(); -#if 0 // the 3Dconnexion device wants to be initiliazed after a window is displayed. - ConnexionClient::getInstance().init(); -#endif + SpacemouseManager::getInstance().init(); auto& packetReceiver = nodeList->getPacketReceiver(); packetReceiver.registerListener(PacketType::DomainConnectionDenied, this, "handleDomainConnectionDeniedPacket"); @@ -1839,9 +1837,10 @@ void Application::focusOutEvent(QFocusEvent* event) { inputPlugin->pluginFocusOutEvent(); } } -#if 0 - ConnexionData::getInstance().focusOutEvent(); -#endif + + //SpacemouseDevice::getInstance().focusOutEvent(); + //SpacemouseManager::getInstance().getDevice()->focusOutEvent(); + SpacemouseManager::getInstance().ManagerFocusOutEvent(); // 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 1565db2905..c15ce4a066 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/3DConnexionClient.h" +#include "input-plugins/SpacemouseManager.h" #include "MainWindow.h" #include "scripting/MenuScriptingInterface.h" #include "ui/AssetUploadDialogFactory.h" @@ -464,13 +464,9 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::MeshVisible, 0, true, avatar, SLOT(setEnableMeshVisible(bool))); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::DisableEyelidAdjustment, 0, false); -#if 0 - addCheckableActionToQMenuAndActionHash(avatarDebugMenu, - MenuOption::Connexion, - 0, false, - &ConnexionClient::getInstance(), - SLOT(toggleConnexion(bool))); -#endif + + addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::Connexion, 0, false, &SpacemouseManager::getInstance(), SLOT(toggleConnexion(bool))); + addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ComfortMode, 0, true); MenuWrapper* handOptionsMenu = developerMenu->addMenu("Hands"); diff --git a/interface/src/devices/3DConnexionClient.cpp b/interface/src/devices/3DConnexionClient.cpp deleted file mode 100755 index 38a9b4cb29..0000000000 --- a/interface/src/devices/3DConnexionClient.cpp +++ /dev/null @@ -1,972 +0,0 @@ -// -// 3DConnexionClient.cpp -// interface/src/devices -// -// Created by MarcelEdward Verhagen on 09-06-15. -// 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 "3DConnexionClient.h" - -#if 0 -#include -#include - -#include "Menu.h" - -const float MAX_AXIS = 75.0f; // max forward = 2x speed - -void ConnexionData::focusOutEvent() { - _axisStateMap.clear(); - _buttonPressedMap.clear(); -}; - -ConnexionData& ConnexionData::getInstance() { - static ConnexionData sharedInstance; - return sharedInstance; -} - - -ConnexionData::ConnexionData() : InputDevice("ConnexionClient") {} - - -void ConnexionData::handleAxisEvent() { - auto rotation = cc_rotation / MAX_AXIS; - _axisStateMap[ROTATE_X] = rotation.x; - _axisStateMap[ROTATE_Y] = rotation.y; - _axisStateMap[ROTATE_Z] = rotation.z; - auto position = cc_rotation / MAX_AXIS; - _axisStateMap[TRANSLATE_X] = position.x; - _axisStateMap[TRANSLATE_Y] = position.y; - _axisStateMap[TRANSLATE_Z] = position.z; -} - -void ConnexionData::setButton(int lastButtonState) { - _buttonPressedMap.clear(); - _buttonPressedMap.insert(lastButtonState); -} - -void ConnexionData::buildDeviceProxy(controller::DeviceProxy::Pointer proxy) { - proxy->_name = _name = "ConnexionClient"; - proxy->getButton = [this](const controller::Input& input, int timestamp) -> bool { return this->getButton(input.getChannel()); }; - proxy->getAxis = [this](const controller::Input& input, int timestamp) -> float { return this->getAxis(input.getChannel()); }; - proxy->getAvailabeInputs = [this]() -> QVector { - using namespace controller; - static QVector availableInputs { - Input::NamedPair(makeInput(BUTTON_1), "LeftButton"), - Input::NamedPair(makeInput(BUTTON_2), "RightButton"), - Input::NamedPair(makeInput(BUTTON_3), "BothButtons"), - Input::NamedPair(makeInput(TRANSLATE_X), "TranslateX"), - Input::NamedPair(makeInput(TRANSLATE_Y), "TranslateY"), - Input::NamedPair(makeInput(TRANSLATE_Z), "TranslateZ"), - Input::NamedPair(makeInput(ROTATE_X), "RotateX"), - Input::NamedPair(makeInput(ROTATE_Y), "RotateY"), - Input::NamedPair(makeInput(ROTATE_Z), "RotateZ"), - }; - return availableInputs; - }; -} - -QString ConnexionData::getDefaultMappingConfig() { - static const QString MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/vive.json"; - return MAPPING_JSON; -} - -//void ConnexionData::assignDefaultInputMapping(UserInputMapper& mapper) { -// const float JOYSTICK_MOVE_SPEED = 1.0f; -// //const float DPAD_MOVE_SPEED = 0.5f; -// const float JOYSTICK_YAW_SPEED = 0.5f; -// const float JOYSTICK_PITCH_SPEED = 0.25f; -// const float BOOM_SPEED = 0.1f; -// -// // Y axes are flipped (up is negative) -// // postion: Movement, strafing -// mapper.addInputChannel(UserInputMapper::LONGITUDINAL_FORWARD, makeInput(POSITION_AXIS_Y_NEG), JOYSTICK_MOVE_SPEED); -// mapper.addInputChannel(UserInputMapper::LONGITUDINAL_BACKWARD, makeInput(POSITION_AXIS_Y_POS), JOYSTICK_MOVE_SPEED); -// mapper.addInputChannel(UserInputMapper::LATERAL_RIGHT, makeInput(POSITION_AXIS_X_POS), JOYSTICK_MOVE_SPEED); -// mapper.addInputChannel(UserInputMapper::LATERAL_LEFT, makeInput(POSITION_AXIS_X_NEG), JOYSTICK_MOVE_SPEED); -// mapper.addInputChannel(UserInputMapper::VERTICAL_UP, makeInput(POSITION_AXIS_Z_NEG), JOYSTICK_MOVE_SPEED); -// mapper.addInputChannel(UserInputMapper::VERTICAL_DOWN, makeInput(POSITION_AXIS_Z_POS), JOYSTICK_MOVE_SPEED); -// -// // Rotation: Camera orientation with button 1 -// mapper.addInputChannel(UserInputMapper::YAW_RIGHT, makeInput(ROTATION_AXIS_Z_POS), JOYSTICK_YAW_SPEED); -// mapper.addInputChannel(UserInputMapper::YAW_LEFT, makeInput(ROTATION_AXIS_Z_NEG), JOYSTICK_YAW_SPEED); -// mapper.addInputChannel(UserInputMapper::PITCH_DOWN, makeInput(ROTATION_AXIS_Y_NEG), JOYSTICK_PITCH_SPEED); -// mapper.addInputChannel(UserInputMapper::PITCH_UP, makeInput(ROTATION_AXIS_Y_POS), JOYSTICK_PITCH_SPEED); -// -// // Button controls -// // Zoom -// mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(BUTTON_1), BOOM_SPEED); -// mapper.addInputChannel(UserInputMapper::BOOM_OUT, makeInput(BUTTON_2), BOOM_SPEED); -// -// // Zoom -// // mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(ROTATION_AXIS_Z_NEG), BOOM_SPEED); -// // mapper.addInputChannel(UserInputMapper::BOOM_OUT, makeInput(ROTATION_AXIS_Z_POS), BOOM_SPEED); -// -//} - -float ConnexionData::getButton(int channel) const { - if (!_buttonPressedMap.empty()) { - if (_buttonPressedMap.find(channel) != _buttonPressedMap.end()) { - return 1.0f; - } else { - return 0.0f; - } - } - return 0.0f; -} - -float ConnexionData::getAxis(int channel) const { - auto axis = _axisStateMap.find(channel); - if (axis != _axisStateMap.end()) { - return (*axis).second; - } else { - return 0.0f; - } -} - -controller::Input ConnexionData::makeInput(ConnexionData::ButtonChannel button) { - return controller::Input(_deviceID, button, controller::ChannelType::BUTTON); -} - -controller::Input ConnexionData::makeInput(ConnexionData::PositionChannel axis) { - return controller::Input(_deviceID, axis, controller::ChannelType::AXIS); -} - -void ConnexionData::update(float deltaTime, bool jointsCaptured) { - // the update is done in the ConnexionClient class. - // for windows in the nativeEventFilter the inputmapper is connected or registed or removed when an 3Dconnnexion device is attached or detached - // for osx the api will call DeviceAddedHandler or DeviceRemoveHandler when a 3Dconnexion device is attached or detached -} - -ConnexionClient& ConnexionClient::getInstance() { - static ConnexionClient sharedInstance; - return sharedInstance; -} - -#ifdef HAVE_3DCONNEXIONCLIENT - -#ifdef Q_OS_WIN - -#include - -void ConnexionClient::toggleConnexion(bool shouldEnable) { - ConnexionData& connexiondata = ConnexionData::getInstance(); - if (shouldEnable && connexiondata.getDeviceID() == 0) { - init(); - } - if (!shouldEnable && connexiondata.getDeviceID() != 0) { - destroy(); - } -} - -void ConnexionClient::init() { - if (Menu::getInstance()->isOptionChecked(MenuOption::Connexion)) { - fLast3dmouseInputTime = 0; - - InitializeRawInput(GetActiveWindow()); - - QAbstractEventDispatcher::instance()->installNativeEventFilter(this); - } -} - -void ConnexionClient::destroy() { - QAbstractEventDispatcher::instance()->removeNativeEventFilter(this); - ConnexionData& connexiondata = ConnexionData::getInstance(); - int deviceid = connexiondata.getDeviceID(); - auto userInputMapper = DependencyManager::get(); - userInputMapper->removeDevice(deviceid); -} - -#define LOGITECH_VENDOR_ID 0x46d - -#ifndef RIDEV_DEVNOTIFY -#define RIDEV_DEVNOTIFY 0x00002000 -#endif - -const int TRACE_RIDI_DEVICENAME = 0; -const int TRACE_RIDI_DEVICEINFO = 0; - -#ifdef _WIN64 -typedef unsigned __int64 QWORD; -#endif - -// object angular velocity per mouse tick 0.008 milliradians per second per count -static const double k3dmouseAngularVelocity = 8.0e-6; // radians per second per count - -static const int kTimeToLive = 5; - -enum ConnexionPid { - CONNEXIONPID_SPACEPILOT = 0xc625, - CONNEXIONPID_SPACENAVIGATOR = 0xc626, - CONNEXIONPID_SPACEEXPLORER = 0xc627, - CONNEXIONPID_SPACENAVIGATORFORNOTEBOOKS = 0xc628, - CONNEXIONPID_SPACEPILOTPRO = 0xc629 -}; - -// e3dmouse_virtual_key -enum V3dk { - V3DK_INVALID = 0, - V3DK_MENU = 1, V3DK_FIT, - V3DK_TOP, V3DK_LEFT, V3DK_RIGHT, V3DK_FRONT, V3DK_BOTTOM, V3DK_BACK, - V3DK_CW, V3DK_CCW, - V3DK_ISO1, V3DK_ISO2, - V3DK_1, V3DK_2, V3DK_3, V3DK_4, V3DK_5, V3DK_6, V3DK_7, V3DK_8, V3DK_9, V3DK_10, - V3DK_ESC, V3DK_ALT, V3DK_SHIFT, V3DK_CTRL, - V3DK_ROTATE, V3DK_PANZOOM, V3DK_DOMINANT, - V3DK_PLUS, V3DK_MINUS -}; - -struct tag_VirtualKeys { - ConnexionPid pid; - size_t nKeys; - V3dk *vkeys; -}; - -// e3dmouse_virtual_key -static const V3dk SpaceExplorerKeys[] = { - V3DK_INVALID, // there is no button 0 - V3DK_1, V3DK_2, - V3DK_TOP, V3DK_LEFT, V3DK_RIGHT, V3DK_FRONT, - V3DK_ESC, V3DK_ALT, V3DK_SHIFT, V3DK_CTRL, - V3DK_FIT, V3DK_MENU, - V3DK_PLUS, V3DK_MINUS, - V3DK_ROTATE -}; - -//e3dmouse_virtual_key -static const V3dk SpacePilotKeys[] = { - V3DK_INVALID, - V3DK_1, V3DK_2, V3DK_3, V3DK_4, V3DK_5, V3DK_6, - V3DK_TOP, V3DK_LEFT, V3DK_RIGHT, V3DK_FRONT, - V3DK_ESC, V3DK_ALT, V3DK_SHIFT, V3DK_CTRL, - V3DK_FIT, V3DK_MENU, - V3DK_PLUS, V3DK_MINUS, - V3DK_DOMINANT, V3DK_ROTATE, -}; - -static const struct tag_VirtualKeys _3dmouseVirtualKeys[] = { - CONNEXIONPID_SPACEPILOT, - sizeof(SpacePilotKeys) / sizeof(SpacePilotKeys[0]), - const_cast(SpacePilotKeys), - CONNEXIONPID_SPACEEXPLORER, - sizeof(SpaceExplorerKeys) / sizeof(SpaceExplorerKeys[0]), - const_cast(SpaceExplorerKeys) -}; - -// Converts a hid device keycode (button identifier) of a pre-2009 3Dconnexion USB device to the standard 3d mouse virtual key definition. -// pid USB Product ID (PID) of 3D mouse device -// hidKeyCode Hid keycode as retrieved from a Raw Input packet -// return The standard 3d mouse virtual key (button identifier) or zero if an error occurs. - -// Converts a hid device keycode (button identifier) of a pre-2009 3Dconnexion USB device -// to the standard 3d mouse virtual key definition. -unsigned short HidToVirtualKey(unsigned long pid, unsigned short hidKeyCode) { - unsigned short virtualkey = hidKeyCode; - for (size_t i = 0; i(); - if (Is3dmouseAttached() && connexiondata.getDeviceID() == 0) { - userInputMapper->registerDevice(&connexiondata); - UserActivityLogger::getInstance().connectedDevice("controller", "3Dconnexion"); - } else if (!Is3dmouseAttached() && connexiondata.getDeviceID() != 0) { - userInputMapper->removeDevice(connexiondata.getDeviceID()); - } - - if (!Is3dmouseAttached()) { - return false; - } - - MSG* message = (MSG*)(msg); - - if (message->message == WM_INPUT) { - HRAWINPUT hRawInput = reinterpret_cast(message->lParam); - OnRawInput(RIM_INPUT, hRawInput); - if (result != 0) { - result = 0; - } - return true; - } - return false; -} - -// Access the mouse parameters structure -I3dMouseParam& ConnexionClient::MouseParams() { - return f3dMouseParams; -} - -// Access the mouse parameters structure -const I3dMouseParam& ConnexionClient::MouseParams() const { - return f3dMouseParams; -} - -//Called with the processed motion data when a 3D mouse event is received -void ConnexionClient::Move3d(HANDLE device, std::vector& motionData) { - Q_UNUSED(device); - ConnexionData& connexiondata = ConnexionData::getInstance(); - connexiondata.cc_position = { motionData[0] * 1000, motionData[1] * 1000, motionData[2] * 1000 }; - connexiondata.cc_rotation = { motionData[3] * 1500, motionData[4] * 1500, motionData[5] * 1500 }; - connexiondata.handleAxisEvent(); -} - -//Called when a 3D mouse key is pressed -void ConnexionClient::On3dmouseKeyDown(HANDLE device, int virtualKeyCode) { - Q_UNUSED(device); - ConnexionData& connexiondata = ConnexionData::getInstance(); - connexiondata.setButton(virtualKeyCode); -} - -//Called when a 3D mouse key is released -void ConnexionClient::On3dmouseKeyUp(HANDLE device, int virtualKeyCode) { - Q_UNUSED(device); - ConnexionData& connexiondata = ConnexionData::getInstance(); - connexiondata.setButton(0); -} - -//Get an initialized array of PRAWINPUTDEVICE for the 3D devices -//pNumDevices returns the number of devices to register. Currently this is always 1. -static PRAWINPUTDEVICE GetDevicesToRegister(unsigned int* pNumDevices) { - // Array of raw input devices to register - static RAWINPUTDEVICE sRawInputDevices[] = { - { 0x01, 0x08, 0x00, 0x00 } // Usage Page = 0x01 Generic Desktop Page, Usage Id= 0x08 Multi-axis Controller - }; - - if (pNumDevices) { - *pNumDevices = sizeof(sRawInputDevices) / sizeof(sRawInputDevices[0]); - } - - return sRawInputDevices; -} - -//Detect the 3D mouse -bool ConnexionClient::Is3dmouseAttached() { - unsigned int numDevicesOfInterest = 0; - PRAWINPUTDEVICE devicesToRegister = GetDevicesToRegister(&numDevicesOfInterest); - - unsigned int nDevices = 0; - - if (::GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST)) != 0) { - return false; - } - - if (nDevices == 0) { - return false; - } - - std::vector rawInputDeviceList(nDevices); - if (::GetRawInputDeviceList(&rawInputDeviceList[0], &nDevices, sizeof(RAWINPUTDEVICELIST)) == static_cast(-1)) { - return false; - } - - for (unsigned int i = 0; i < nDevices; ++i) { - RID_DEVICE_INFO rdi = { sizeof(rdi) }; - unsigned int cbSize = sizeof(rdi); - - if (GetRawInputDeviceInfo(rawInputDeviceList[i].hDevice, RIDI_DEVICEINFO, &rdi, &cbSize) > 0) { - //skip non HID and non logitec (3DConnexion) devices - if (rdi.dwType != RIM_TYPEHID || rdi.hid.dwVendorId != LOGITECH_VENDOR_ID) { - continue; - } - - //check if devices matches Multi-axis Controller - for (unsigned int j = 0; j < numDevicesOfInterest; ++j) { - if (devicesToRegister[j].usUsage == rdi.hid.usUsage - && devicesToRegister[j].usUsagePage == rdi.hid.usUsagePage) { - return true; - } - } - } - } - return false; -} - -// Initialize the window to recieve raw-input messages -// This needs to be called initially so that Windows will send the messages from the 3D mouse to the window. -bool ConnexionClient::InitializeRawInput(HWND hwndTarget) { - fWindow = hwndTarget; - - // Simply fail if there is no window - if (!hwndTarget) { - return false; - } - - unsigned int numDevices = 0; - PRAWINPUTDEVICE devicesToRegister = GetDevicesToRegister(&numDevices); - - if (numDevices == 0) { - return false; - } - - unsigned int cbSize = sizeof(devicesToRegister[0]); - for (size_t i = 0; i < numDevices; i++) { - // Set the target window to use - //devicesToRegister[i].hwndTarget = hwndTarget; - - // If Vista or newer, enable receiving the WM_INPUT_DEVICE_CHANGE message. - if (IsWindowsVistaOrGreater()) { - devicesToRegister[i].dwFlags |= RIDEV_DEVNOTIFY; - } - } - return (::RegisterRawInputDevices(devicesToRegister, numDevices, cbSize) != FALSE); -} - -//Get the raw input data from Windows -UINT ConnexionClient::GetRawInputBuffer(PRAWINPUT pData, PUINT pcbSize, UINT cbSizeHeader) { - //Includes workaround for incorrect alignment of the RAWINPUT structure on x64 os - //when running as Wow64 (copied directly from 3DConnexion code) -#ifdef _WIN64 - return ::GetRawInputBuffer(pData, pcbSize, cbSizeHeader); -#else - BOOL bIsWow64 = FALSE; - ::IsWow64Process(GetCurrentProcess(), &bIsWow64); - if (!bIsWow64 || pData == NULL) { - return ::GetRawInputBuffer(pData, pcbSize, cbSizeHeader); - } else { - HWND hwndTarget = fWindow; - - size_t cbDataSize = 0; - UINT nCount = 0; - PRAWINPUT pri = pData; - - MSG msg; - while (PeekMessage(&msg, hwndTarget, WM_INPUT, WM_INPUT, PM_NOREMOVE)) { - HRAWINPUT hRawInput = reinterpret_cast(msg.lParam); - size_t cbSize = *pcbSize - cbDataSize; - if (::GetRawInputData(hRawInput, RID_INPUT, pri, &cbSize, cbSizeHeader) == static_cast(-1)) { - if (nCount == 0) { - return static_cast(-1); - } else { - break; - } - } - ++nCount; - - // Remove the message for the data just read - PeekMessage(&msg, hwndTarget, WM_INPUT, WM_INPUT, PM_REMOVE); - - pri = NEXTRAWINPUTBLOCK(pri); - cbDataSize = reinterpret_cast(pri)-reinterpret_cast(pData); - if (cbDataSize >= *pcbSize) { - cbDataSize = *pcbSize; - break; - } - } - return nCount; - } -#endif -} - -// Process the raw input device data -// On3dmouseInput() does all the preprocessing of the rawinput device data before -// finally calling the Move3d method. -void ConnexionClient::On3dmouseInput() { - // Don't do any data processing in background - bool bIsForeground = (::GetActiveWindow() != NULL); - if (!bIsForeground) { - // set all cached data to zero so that a zero event is seen and the cached data deleted - for (std::map::iterator it = fDevice2Data.begin(); it != fDevice2Data.end(); it++) { - it->second.fAxes.assign(6, .0); - it->second.fIsDirty = true; - } - } - - DWORD dwNow = ::GetTickCount(); // Current time; - DWORD dwElapsedTime; // Elapsed time since we were last here - - if (0 == fLast3dmouseInputTime) { - dwElapsedTime = 10; // System timer resolution - } else { - dwElapsedTime = dwNow - fLast3dmouseInputTime; - if (fLast3dmouseInputTime > dwNow) { - dwElapsedTime = ~dwElapsedTime + 1; - } - if (dwElapsedTime<1) { - dwElapsedTime = 1; - } else if (dwElapsedTime > 500) { - // Check for wild numbers because the device was removed while sending data - dwElapsedTime = 10; - } - } - - //qDebug("On3DmouseInput() period is %dms\n", dwElapsedTime); - - float mouseData2Rotation = k3dmouseAngularVelocity; - // v = w * r, we don't know r yet so lets assume r=1.) - float mouseData2PanZoom = k3dmouseAngularVelocity; - - // Grab the I3dmouseParam interface - I3dMouseParam& i3dmouseParam = f3dMouseParams; - // Take a look at the users preferred speed setting and adjust the sensitivity accordingly - I3dMouseSensor::Speed speedSetting = i3dmouseParam.GetSpeed(); - // See "Programming for the 3D Mouse", Section 5.1.3 - float speed = (speedSetting == I3dMouseSensor::SPEED_LOW ? 0.25f : speedSetting == I3dMouseSensor::SPEED_HIGH ? 4.f : 1.f); - - // Multiplying by the following will convert the 3d mouse data to real world units - mouseData2PanZoom *= speed; - mouseData2Rotation *= speed; - - std::map::iterator iterator = fDevice2Data.begin(); - while (iterator != fDevice2Data.end()) { - - // If we have not received data for a while send a zero event - if ((--(iterator->second.fTimeToLive)) == 0) { - iterator->second.fAxes.assign(6, .0); - } else if ( !iterator->second.fIsDirty) { //!t_bPoll3dmouse && - // If we are not polling then only handle the data that was actually received - ++iterator; - continue; - } - iterator->second.fIsDirty = false; - - // get a copy of the device - HANDLE hdevice = iterator->first; - - // get a copy of the motion vectors and apply the user filters - std::vector motionData = iterator->second.fAxes; - - // apply the user filters - - // Pan Zoom filter - // See "Programming for the 3D Mouse", Section 5.1.2 - if (!i3dmouseParam.IsPanZoom()) { - // Pan zoom is switched off so set the translation vector values to zero - motionData[0] = motionData[1] = motionData[2] = 0.; - } - - // Rotate filter - // See "Programming for the 3D Mouse", Section 5.1.1 - if (!i3dmouseParam.IsRotate()) { - // Rotate is switched off so set the rotation vector values to zero - motionData[3] = motionData[4] = motionData[5] = 0.; - } - - // convert the translation vector into physical data - for (int axis = 0; axis < 3; axis++) { - motionData[axis] *= mouseData2PanZoom; - } - - // convert the directed Rotate vector into physical data - // See "Programming for the 3D Mouse", Section 7.2.2 - for (int axis = 3; axis < 6; axis++) { - motionData[axis] *= mouseData2Rotation; - } - - // Now that the data has had the filters and sensitivty settings applied - // calculate the displacements since the last view update - for (int axis = 0; axis < 6; axis++) { - motionData[axis] *= dwElapsedTime; - } - - // Now a bit of book keeping before passing on the data - if (iterator->second.IsZero()) { - iterator = fDevice2Data.erase(iterator); - } else { - ++iterator; - } - - // Work out which will be the next device - HANDLE hNextDevice = 0; - if (iterator != fDevice2Data.end()) { - hNextDevice = iterator->first; - } - - // Pass the 3dmouse input to the view controller - Move3d(hdevice, motionData); - - // Because we don't know what happened in the previous call, the cache might have - // changed so reload the iterator - iterator = fDevice2Data.find(hNextDevice); - } - - if (!fDevice2Data.empty()) { - fLast3dmouseInputTime = dwNow; - } else { - fLast3dmouseInputTime = 0; - } -} - -//Called when new raw input data is available -void ConnexionClient::OnRawInput(UINT nInputCode, HRAWINPUT hRawInput) { - const size_t cbSizeOfBuffer = 1024; - BYTE pBuffer[cbSizeOfBuffer]; - - PRAWINPUT pRawInput = reinterpret_cast(pBuffer); - UINT cbSize = cbSizeOfBuffer; - - if (::GetRawInputData(hRawInput, RID_INPUT, pRawInput, &cbSize, sizeof(RAWINPUTHEADER)) == static_cast(-1)) { - return; - } - - bool b3dmouseInput = TranslateRawInputData(nInputCode, pRawInput); - ::DefRawInputProc(&pRawInput, 1, sizeof(RAWINPUTHEADER)); - - // Check for any buffered messages - cbSize = cbSizeOfBuffer; - UINT nCount = this->GetRawInputBuffer(pRawInput, &cbSize, sizeof(RAWINPUTHEADER)); - if (nCount == (UINT)-1) { - qDebug("GetRawInputBuffer returned error %d\n", GetLastError()); - } - - while (nCount>0 && nCount != static_cast(-1)) { - PRAWINPUT pri = pRawInput; - UINT nInput; - for (nInput = 0; nInputGetRawInputBuffer(pRawInput, &cbSize, sizeof(RAWINPUTHEADER)); - } - - // If we have mouse input data for the app then tell tha app about it - if (b3dmouseInput) { - On3dmouseInput(); - } -} - -bool ConnexionClient::TranslateRawInputData(UINT nInputCode, PRAWINPUT pRawInput) { - bool bIsForeground = (nInputCode == RIM_INPUT); - - // We are not interested in keyboard or mouse data received via raw input - if (pRawInput->header.dwType != RIM_TYPEHID) { - return false; - } - - if (TRACE_RIDI_DEVICENAME == 1) { - UINT dwSize = 0; - if (::GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_DEVICENAME, NULL, &dwSize) == 0) { - std::vector szDeviceName(dwSize + 1); - if (::GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_DEVICENAME, &szDeviceName[0], &dwSize) > 0) { - qDebug("Device Name = %s\nDevice handle = 0x%x\n", &szDeviceName[0], pRawInput->header.hDevice); - } - } - } - - RID_DEVICE_INFO sRidDeviceInfo; - sRidDeviceInfo.cbSize = sizeof(RID_DEVICE_INFO); - UINT cbSize = sizeof(RID_DEVICE_INFO); - - if (::GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_DEVICEINFO, &sRidDeviceInfo, &cbSize) == cbSize) { - if (TRACE_RIDI_DEVICEINFO == 1) { - switch (sRidDeviceInfo.dwType) { - case RIM_TYPEMOUSE: - qDebug("\tsRidDeviceInfo.dwType=RIM_TYPEMOUSE\n"); - break; - case RIM_TYPEKEYBOARD: - qDebug("\tsRidDeviceInfo.dwType=RIM_TYPEKEYBOARD\n"); - break; - case RIM_TYPEHID: - qDebug("\tsRidDeviceInfo.dwType=RIM_TYPEHID\n"); - qDebug("\tVendor=0x%x\n\tProduct=0x%x\n\tUsagePage=0x%x\n\tUsage=0x%x\n", - sRidDeviceInfo.hid.dwVendorId, - sRidDeviceInfo.hid.dwProductId, - sRidDeviceInfo.hid.usUsagePage, - sRidDeviceInfo.hid.usUsage); - break; - } - } - - if (sRidDeviceInfo.hid.dwVendorId == LOGITECH_VENDOR_ID) { - if (pRawInput->data.hid.bRawData[0] == 0x01) { // Translation vector - TInputData& deviceData = fDevice2Data[pRawInput->header.hDevice]; - deviceData.fTimeToLive = kTimeToLive; - if (bIsForeground) { - short* pnRawData = reinterpret_cast(&pRawInput->data.hid.bRawData[1]); - // Cache the pan zoom data - deviceData.fAxes[0] = static_cast(pnRawData[0]); - deviceData.fAxes[1] = static_cast(pnRawData[1]); - deviceData.fAxes[2] = static_cast(pnRawData[2]); - - //qDebug("Pan/Zoom RI Data =\t0x%x,\t0x%x,\t0x%x\n", pnRawData[0], pnRawData[1], pnRawData[2]); - - if (pRawInput->data.hid.dwSizeHid >= 13) { // Highspeed package - // Cache the rotation data - deviceData.fAxes[3] = static_cast(pnRawData[3]); - deviceData.fAxes[4] = static_cast(pnRawData[4]); - deviceData.fAxes[5] = static_cast(pnRawData[5]); - deviceData.fIsDirty = true; - - //qDebug("Rotation RI Data =\t0x%x,\t0x%x,\t0x%x\n", pnRawData[3], pnRawData[4], pnRawData[5]); - return true; - } - } else { // Zero out the data if the app is not in forground - deviceData.fAxes.assign(6, 0.f); - } - } else if (pRawInput->data.hid.bRawData[0] == 0x02) { // Rotation vector - // If we are not in foreground do nothing - // The rotation vector was zeroed out with the translation vector in the previous message - if (bIsForeground) { - TInputData& deviceData = fDevice2Data[pRawInput->header.hDevice]; - deviceData.fTimeToLive = kTimeToLive; - - short* pnRawData = reinterpret_cast(&pRawInput->data.hid.bRawData[1]); - // Cache the rotation data - deviceData.fAxes[3] = static_cast(pnRawData[0]); - deviceData.fAxes[4] = static_cast(pnRawData[1]); - deviceData.fAxes[5] = static_cast(pnRawData[2]); - deviceData.fIsDirty = true; - - //qDebug("Rotation RI Data =\t0x%x,\t0x%x,\t0x%x\n", pnRawData[0], pnRawData[1], pnRawData[2]); - - return true; - } - } else if (pRawInput->data.hid.bRawData[0] == 0x03) { // Keystate change - // this is a package that contains 3d mouse keystate information - // bit0=key1, bit=key2 etc. - - unsigned long dwKeystate = *reinterpret_cast(&pRawInput->data.hid.bRawData[1]); - - //qDebug("ButtonData =0x%x\n", dwKeystate); - - // Log the keystate changes - unsigned long dwOldKeystate = fDevice2Keystate[pRawInput->header.hDevice]; - if (dwKeystate != 0) { - fDevice2Keystate[pRawInput->header.hDevice] = dwKeystate; - } else { - fDevice2Keystate.erase(pRawInput->header.hDevice); - } - - // Only call the keystate change handlers if the app is in foreground - if (bIsForeground) { - unsigned long dwChange = dwKeystate ^ dwOldKeystate; - - for (int nKeycode = 1; nKeycode<33; nKeycode++) { - if (dwChange & 0x01) { - int nVirtualKeyCode = HidToVirtualKey(sRidDeviceInfo.hid.dwProductId, nKeycode); - if (nVirtualKeyCode) { - if (dwKeystate & 0x01) { - On3dmouseKeyDown(pRawInput->header.hDevice, nVirtualKeyCode); - } else { - On3dmouseKeyUp(pRawInput->header.hDevice, nVirtualKeyCode); - } - } - } - dwChange >>= 1; - dwKeystate >>= 1; - } - } - } - } - } - return false; -} - -MouseParameters::MouseParameters() : - fNavigation(NAVIGATION_OBJECT_MODE), - fPivot(PIVOT_AUTO), - fPivotVisibility(PIVOT_SHOW), - fIsLockHorizon(true), - fIsPanZoom(true), - fIsRotate(true), - fSpeed(SPEED_LOW) -{ -} - -bool MouseParameters::IsPanZoom() const { - return fIsPanZoom; -} - -bool MouseParameters::IsRotate() const { - return fIsRotate; -} - -MouseParameters::Speed MouseParameters::GetSpeed() const { - return fSpeed; -} - -void MouseParameters::SetPanZoom(bool isPanZoom) { - fIsPanZoom = isPanZoom; -} - -void MouseParameters::SetRotate(bool isRotate) { - fIsRotate = isRotate; -} - -void MouseParameters::SetSpeed(Speed speed) { - fSpeed = speed; -} - -MouseParameters::Navigation MouseParameters::GetNavigationMode() const { - return fNavigation; -} - -MouseParameters::Pivot MouseParameters::GetPivotMode() const { - return fPivot; -} - -MouseParameters::PivotVisibility MouseParameters::GetPivotVisibility() const { - return fPivotVisibility; -} - -bool MouseParameters::IsLockHorizon() const { - return fIsLockHorizon; -} - -void MouseParameters::SetLockHorizon(bool bOn) { - fIsLockHorizon=bOn; -} - -void MouseParameters::SetNavigationMode(Navigation navigation) { - fNavigation=navigation; -} - -void MouseParameters::SetPivotMode(Pivot pivot) { - if (fPivot!=PIVOT_MANUAL || pivot!=PIVOT_AUTO_OVERRIDE) { - fPivot = pivot; - } -} - -void MouseParameters::SetPivotVisibility(PivotVisibility visibility) { - fPivotVisibility = visibility; -} - -#else - -int fConnexionClientID; - -static ConnexionDeviceState lastState; - -static void DeviceAddedHandler(unsigned int connection); -static void DeviceRemovedHandler(unsigned int connection); -static void MessageHandler(unsigned int connection, unsigned int messageType, void *messageArgument); - -void ConnexionClient::toggleConnexion(bool shouldEnable) { - if (shouldEnable && !Is3dmouseAttached()) { - init(); - } - if (!shouldEnable && Is3dmouseAttached()) { - destroy(); - } -} - -void ConnexionClient::init() { - // Make sure the framework is installed - if (Menu::getInstance()->isOptionChecked(MenuOption::Connexion)) { - // Install message handler and register our client - InstallConnexionHandlers(MessageHandler, DeviceAddedHandler, DeviceRemovedHandler); - // Either use this to take over in our application only... does not work - // fConnexionClientID = RegisterConnexionClient('MCTt', "\pConnexion Client Test", kConnexionClientModeTakeOver, kConnexionMaskAll); - - // ...or use this to take over system-wide - fConnexionClientID = RegisterConnexionClient(kConnexionClientWildcard, NULL, kConnexionClientModeTakeOver, kConnexionMaskAll); - ConnexionData& connexiondata = ConnexionData::getInstance(); - memcpy(&connexiondata.clientId, &fConnexionClientID, (long)sizeof(int)); - - // A separate API call is required to capture buttons beyond the first 8 - SetConnexionClientButtonMask(fConnexionClientID, kConnexionMaskAllButtons); - - // use default switches - ConnexionClientControl(fConnexionClientID, kConnexionCtlSetSwitches, kConnexionSwitchesDisabled, NULL); - - if (Is3dmouseAttached() && connexiondata.getDeviceID() == 0) { - auto userInputMapper = DependencyManager::get(); - userInputMapper->registerDevice(&connexiondata); - UserActivityLogger::getInstance().connectedDevice("controller", "3Dconnexion"); - } - //let one axis be dominant - //ConnexionClientControl(fConnexionClientID, kConnexionCtlSetSwitches, kConnexionSwitchDominant | kConnexionSwitchEnableAll, NULL); - } -} - -void ConnexionClient::destroy() { - // Make sure the framework is installed - if (&InstallConnexionHandlers != NULL) { - // Unregister our client and clean up all handlers - if (fConnexionClientID) { - UnregisterConnexionClient(fConnexionClientID); - } - CleanupConnexionHandlers(); - fConnexionClientID = 0; - ConnexionData& connexiondata = ConnexionData::getInstance(); - if (connexiondata.getDeviceID()!=0) { - auto userInputMapper = DependencyManager::get(); - userInputMapper->removeDevice(connexiondata.getDeviceID()); - connexiondata.setDeviceID(0); - } - } -} - -void DeviceAddedHandler(unsigned int connection) { - ConnexionData& connexiondata = ConnexionData::getInstance(); - if (connexiondata.getDeviceID() == 0) { - qCWarning(interfaceapp) << "3Dconnexion device added "; - auto userInputMapper = DependencyManager::get(); - userInputMapper->registerDevice(&connexiondata); - UserActivityLogger::getInstance().connectedDevice("controller", "3Dconnexion"); - } -} - -void DeviceRemovedHandler(unsigned int connection) { - ConnexionData& connexiondata = ConnexionData::getInstance(); - if (connexiondata.getDeviceID() != 0) { - qCWarning(interfaceapp) << "3Dconnexion device removed"; - auto userInputMapper = DependencyManager::get(); - userInputMapper->removeDevice(connexiondata.getDeviceID()); - connexiondata.setDeviceID(0); - } -} - -bool ConnexionClient::Is3dmouseAttached() { - int result; - if (fConnexionClientID) { - if (ConnexionControl(kConnexionCtlGetDeviceID, 0, &result)) { - return false; - } - return true; - } - return false; -} - -void MessageHandler(unsigned int connection, unsigned int messageType, void *messageArgument) { - ConnexionDeviceState *state; - - switch (messageType) { - case kConnexionMsgDeviceState: - state = (ConnexionDeviceState*)messageArgument; - if (state->client == fConnexionClientID) { - ConnexionData& connexiondata = ConnexionData::getInstance(); - connexiondata.cc_position = { state->axis[0], state->axis[1], state->axis[2] }; - connexiondata.cc_rotation = { state->axis[3], state->axis[4], state->axis[5] }; - - connexiondata.handleAxisEvent(); - if (state->buttons != lastState.buttons) { - connexiondata.setButton(state->buttons); - } - memmove(&lastState, state, (long)sizeof(ConnexionDeviceState)); - } - break; - case kConnexionMsgPrefsChanged: - // the prefs have changed, do something - break; - default: - // other messageTypes can happen and should be ignored - break; - } - -} - -#endif // __APPLE__ - -#endif // HAVE_3DCONNEXIONCLIENT -#endif \ No newline at end of file diff --git a/interface/src/devices/3DConnexionClient.h b/interface/src/devices/3DConnexionClient.h deleted file mode 100755 index 03a43d4c64..0000000000 --- a/interface/src/devices/3DConnexionClient.h +++ /dev/null @@ -1,223 +0,0 @@ -// 3DConnexionClient.h -// interface/src/devices -// -// Created by Marcel Verhagen on 09-06-15. -// 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 -// - -#ifndef hifi_3DConnexionClient_h -#define hifi_3DConnexionClient_h - -#if 0 -#include -#include -#include - -#include "InterfaceLogging.h" - -#ifndef HAVE_3DCONNEXIONCLIENT -class ConnexionClient : public QObject { - Q_OBJECT -public: - static ConnexionClient& getInstance(); - void init() {}; - void destroy() {}; - bool Is3dmouseAttached() { return false; }; -public slots: - void toggleConnexion(bool shouldEnable) {}; -}; -#endif // NOT_HAVE_3DCONNEXIONCLIENT - -#ifdef HAVE_3DCONNEXIONCLIENT -// the windows connexion rawinput -#ifdef Q_OS_WIN - -#include "I3dMouseParams.h" -#include -#include -#include -#include - -// windows rawinput parameters -class MouseParameters : public I3dMouseParam { -public: - MouseParameters(); - - // I3dmouseSensor interface - bool IsPanZoom() const; - bool IsRotate() const; - Speed GetSpeed() const; - - void SetPanZoom(bool isPanZoom); - void SetRotate(bool isRotate); - void SetSpeed(Speed speed); - - // I3dmouseNavigation interface - Navigation GetNavigationMode() const; - Pivot GetPivotMode() const; - PivotVisibility GetPivotVisibility() const; - bool IsLockHorizon() const; - - void SetLockHorizon(bool bOn); - void SetNavigationMode(Navigation navigation); - void SetPivotMode(Pivot pivot); - void SetPivotVisibility(PivotVisibility visibility); - - static bool Is3dmouseAttached(); - -private: - MouseParameters(const MouseParameters&); - const MouseParameters& operator = (const MouseParameters&); - - Navigation fNavigation; - Pivot fPivot; - PivotVisibility fPivotVisibility; - bool fIsLockHorizon; - - bool fIsPanZoom; - bool fIsRotate; - Speed fSpeed; -}; - -class ConnexionClient : public QObject, public QAbstractNativeEventFilter { - Q_OBJECT -public: - ConnexionClient() {}; - - static ConnexionClient& getInstance(); - void init(); - void destroy(); - bool Is3dmouseAttached(); - - ConnexionClient* client; - - I3dMouseParam& MouseParams(); - const I3dMouseParam& MouseParams() const; - - virtual void Move3d(HANDLE device, std::vector& motionData); - virtual void On3dmouseKeyDown(HANDLE device, int virtualKeyCode); - virtual void On3dmouseKeyUp(HANDLE device, int virtualKeyCode); - - virtual bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) Q_DECL_OVERRIDE - { - MSG* msg = static_cast< MSG * >(message); - return RawInputEventFilter(message, result); - } - -public slots: - void toggleConnexion(bool shouldEnable); - -signals: - void Move3d(std::vector& motionData); - void On3dmouseKeyDown(int virtualKeyCode); - void On3dmouseKeyUp(int virtualKeyCode); - -private: - bool InitializeRawInput(HWND hwndTarget); - - bool RawInputEventFilter(void* msg, long* result); - - void OnRawInput(UINT nInputCode, HRAWINPUT hRawInput); - UINT GetRawInputBuffer(PRAWINPUT pData, PUINT pcbSize, UINT cbSizeHeader); - bool TranslateRawInputData(UINT nInputCode, PRAWINPUT pRawInput); - void On3dmouseInput(); - - class TInputData { - public: - TInputData() : fAxes(6) {} - - bool IsZero() { - return (0.0f == fAxes[0] && 0.0f == fAxes[1] && 0.0f == fAxes[2] && - 0.0f == fAxes[3] && 0.0f == fAxes[4] && 0.0f == fAxes[5]); - } - - int fTimeToLive; // For telling if the device was unplugged while sending data - bool fIsDirty; - std::vector fAxes; - - }; - - HWND fWindow; - - // Data cache to handle multiple rawinput devices - std::map< HANDLE, TInputData> fDevice2Data; - std::map< HANDLE, unsigned long> fDevice2Keystate; - - // 3dmouse parameters - MouseParameters f3dMouseParams; // Rotate, Pan Zoom etc. - - // use to calculate distance traveled since last event - DWORD fLast3dmouseInputTime; -}; - -// the osx connexion api -#else - -#include -#include "ConnexionClientAPI.h" - -class ConnexionClient : public QObject { - Q_OBJECT -public: - static ConnexionClient& getInstance(); - void init(); - void destroy(); - bool Is3dmouseAttached(); -public slots: - void toggleConnexion(bool shouldEnable); -}; - -#endif // __APPLE__ - -#endif // HAVE_3DCONNEXIONCLIENT - - -// connnects to the userinputmapper -class ConnexionData : public QObject, public controller::InputDevice { - Q_OBJECT - -public: - static ConnexionData& getInstance(); - ConnexionData(); - enum PositionChannel { - TRANSLATE_X, - TRANSLATE_Y, - TRANSLATE_Z, - ROTATE_X, - ROTATE_Y, - ROTATE_Z, - }; - - enum ButtonChannel { - BUTTON_1 = 1, - BUTTON_2 = 2, - BUTTON_3 = 3 - }; - - typedef std::unordered_set ButtonPressedMap; - typedef std::map AxisStateMap; - - float getButton(int channel) const; - float getAxis(int channel) const; - - controller::Input makeInput(ConnexionData::PositionChannel axis); - controller::Input makeInput(ConnexionData::ButtonChannel button); - virtual void buildDeviceProxy(controller::DeviceProxy::Pointer proxy) override; - virtual QString getDefaultMappingConfig() override; - virtual void update(float deltaTime, bool jointsCaptured) override; - virtual void focusOutEvent() override; - - glm::vec3 cc_position; - glm::vec3 cc_rotation; - int clientId; - - void setButton(int lastButtonState); - void handleAxisEvent(); -}; - -#endif - -#endif // defined(hifi_3DConnexionClient_h)