From 603405ad61d8009fa81e0c6c2e791dc2d3731af4 Mon Sep 17 00:00:00 2001 From: EdgarPironti Date: Mon, 2 Nov 2015 23:29:15 -0800 Subject: [PATCH 01/11] 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) From 5d695da630dbdabfd9fdcd72d188ce15fbaec674 Mon Sep 17 00:00:00 2001 From: EdgarPironti Date: Mon, 2 Nov 2015 23:31:10 -0800 Subject: [PATCH 02/11] Do not merge - Spacemouse --- .../Spacemouse/spacemouseExample.js | 72 ++ .../resources/controllers/spacemouse.json | 15 + .../src/input-plugins/SpacemouseManager.cpp | 1022 +++++++++++++++++ .../src/input-plugins/SpacemouseManager.h | 236 ++++ 4 files changed, 1345 insertions(+) create mode 100644 examples/controllers/Spacemouse/spacemouseExample.js create mode 100644 interface/resources/controllers/spacemouse.json create mode 100644 libraries/input-plugins/src/input-plugins/SpacemouseManager.cpp create mode 100644 libraries/input-plugins/src/input-plugins/SpacemouseManager.h diff --git a/examples/controllers/Spacemouse/spacemouseExample.js b/examples/controllers/Spacemouse/spacemouseExample.js new file mode 100644 index 0000000000..904f29cd75 --- /dev/null +++ b/examples/controllers/Spacemouse/spacemouseExample.js @@ -0,0 +1,72 @@ +// +// spaceMouseDebug.js +// examples +// +// 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 +// + + + +var firstmove = 1; +var position = { + x: 0, + y: 0, + z: 0 + }; +var rotation = { + x: 0, + y: 0, + z: 0 + }; + +function toggleFirstMove() { + if(firstmove){ + print("____________________________________"); + firstmove = 0; + } +} + +function spacemouseCheck() { + return Controller.Hardware.Spacemouse !== undefined; +} + +function update(deltaTime) { + if(spacemouseCheck){ + if(Controller.getValue(Controller.Standard.LY) != 0){ + toggleFirstMove(); + print("Controller TX: " + Controller.getValue(Controller.Standard.LY)); + } + + if(Controller.getValue(Controller.Standard.LX) != 0){ + toggleFirstMove(); + print("Controller TZ: " + Controller.getValue(Controller.Standard.LX)); + } + + if(Controller.getValue(Controller.Standard.LT) != 0){ + toggleFirstMove(); + print("Controller TY: " + Controller.getValue(Controller.Standard.LT)); + } + + if(Controller.getValue(Controller.Standard.RY) != 0){ + toggleFirstMove(); + print("Controller RX: " + Controller.getValue(Controller.Standard.RY)); + } + + if(Controller.getValue(Controller.Standard.RX) != 0){ + toggleFirstMove(); + print("Controller RZ: " + Controller.getValue(Controller.Standard.RX)); + } + + if(Controller.getValue(Controller.Standard.RT) != 0){ + toggleFirstMove(); + print("Controller RY: " + Controller.getValue(Controller.Standard.RT)); + } + + firstmove = 1; + } +} + +Script.update.connect(update); \ No newline at end of file diff --git a/interface/resources/controllers/spacemouse.json b/interface/resources/controllers/spacemouse.json new file mode 100644 index 0000000000..61af605512 --- /dev/null +++ b/interface/resources/controllers/spacemouse.json @@ -0,0 +1,15 @@ +{ + "name": "Spacemouse to Standard", + "channels": [ + { "from": "Spacemouse.TranslateX", "to": "Standard.LY" }, + { "from": "Spacemouse.TranslateZ", "filters": "invert", "to": "Standard.LX" }, + + { "from": "Spacemouse.RotateX", "to": "Standard.RY" }, + { "from": "Spacemouse.RotateZ", "to": "Standard.RX" }, + + { "from": "Spacemouse.LeftButton", "to": "Standard.Back" }, + { "from": "Spacemouse.RightButton", "to": "Standard.Start" } + + ] +} + diff --git a/libraries/input-plugins/src/input-plugins/SpacemouseManager.cpp b/libraries/input-plugins/src/input-plugins/SpacemouseManager.cpp new file mode 100644 index 0000000000..3078f99a23 --- /dev/null +++ b/libraries/input-plugins/src/input-plugins/SpacemouseManager.cpp @@ -0,0 +1,1022 @@ +// +// SpacemouseManager.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 "SpacemouseManager.h" + +#include +#include + +#include +#include + +#include "../../../interface/src/Menu.h" + +const float MAX_AXIS = 75.0f; // max forward = 2x speed + +static std::shared_ptr instance = NULL; +SpacemouseDevice::SpacemouseDevice() : +InputDevice("Spacemouse") +{ + instance = std::shared_ptr(this); +} + +void SpacemouseDevice::focusOutEvent() { + _axisStateMap.clear(); + _buttonPressedMap.clear(); +}; + + +//SpacemouseDevice& SpacemouseDevice::getInstance() { +// static SpacemouseDevice sharedInstance; +// return sharedInstance; +//} + + + +//std::shared_ptr SpacemouseManager::getDevice(){ +// return instance; +//} + +//SpacemouseDevice::SpacemouseDevice() : InputDevice("Spacemouse") {} + + +void SpacemouseDevice::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 SpacemouseDevice::setButton(int lastButtonState) { + _buttonPressedMap.clear(); + _buttonPressedMap.insert(lastButtonState); +} + + +controller::Input::NamedVector SpacemouseDevice::getAvailableInputs() const { + using namespace controller; + + + static const Input::NamedVector availableInputs{ + + makePair(BUTTON_1, "LeftButton"), + makePair(BUTTON_2, "RightButton"), + //makePair(BUTTON_3, "BothButtons"), + makePair(TRANSLATE_X, "TranslateX"), + //makePair(TRANSLATE_Y, "TranslateY"), + makePair(TRANSLATE_Z, "TranslateZ"), + makePair(ROTATE_X, "RotateX"), + //makePair(ROTATE_Y, "RotateY"), + makePair(ROTATE_Z, "RotateZ"), + + }; + return availableInputs; +} + +QString SpacemouseDevice::getDefaultMappingConfig() const { + static const QString MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/spacemouse.json"; + return MAPPING_JSON; +} + +//void SpacemouseDevice::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 SpacemouseDevice::getButton(int channel) const { + if (!_buttonPressedMap.empty()) { + if (_buttonPressedMap.find(channel) != _buttonPressedMap.end()) { + return 1.0f; + } + else { + return 0.0f; + } + } + return 0.0f; +} + +float SpacemouseDevice::getAxis(int channel) const { + auto axis = _axisStateMap.find(channel); + if (axis != _axisStateMap.end()) { + return (*axis).second; + } + else { + return 0.0f; + } +} + +controller::Input SpacemouseDevice::makeInput(SpacemouseDevice::ButtonChannel button) const { + return controller::Input(_deviceID, button, controller::ChannelType::BUTTON); +} + +controller::Input SpacemouseDevice::makeInput(SpacemouseDevice::PositionChannel axis) const { + return controller::Input(_deviceID, axis, controller::ChannelType::AXIS); +} + +controller::Input::NamedPair SpacemouseDevice::makePair(SpacemouseDevice::ButtonChannel button, const QString& name) const { + return controller::Input::NamedPair(makeInput(button), name); +} + +controller::Input::NamedPair SpacemouseDevice::makePair(SpacemouseDevice::PositionChannel axis, const QString& name) const { + return controller::Input::NamedPair(makeInput(axis), name); +} + +void SpacemouseDevice::update(float deltaTime, bool jointsCaptured) { + // the update is done in the SpacemouseManager 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 +} + +SpacemouseManager& SpacemouseManager::getInstance() { + static SpacemouseManager sharedInstance; + if (instance == NULL){ + new SpacemouseDevice(); + } + return sharedInstance; +} + +void SpacemouseManager::ManagerFocusOutEvent() { + instance->focusOutEvent(); +} + +#ifdef HAVE_SPACEMOUSE + +#ifdef Q_OS_WIN + +#include + + + +void SpacemouseManager::toggleSpacemouse(bool shouldEnable) { + //SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); + //if (shouldEnable && spacemousedevice.getDeviceID() == controller::Input::INVALID_DEVICE) { + if (shouldEnable && instance->getDeviceID() == controller::Input::INVALID_DEVICE) { + init(); + } + if (!shouldEnable && instance->getDeviceID() != controller::Input::INVALID_DEVICE) { + destroy(); + } +} + +void SpacemouseManager::init() { + if (Menu::getInstance()->isOptionChecked(MenuOption::Connexion)) { + fLast3dmouseInputTime = 0; + + InitializeRawInput(GetActiveWindow()); + + QAbstractEventDispatcher::instance()->installNativeEventFilter(this); + } +} + +void SpacemouseManager::destroy() { + QAbstractEventDispatcher::instance()->removeNativeEventFilter(this); + //SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); + //int deviceid = spacemousedevice.getDeviceID(); + int deviceid = instance->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() && spacemousedevice.getDeviceID() == controller::Input::INVALID_DEVICE) { + if (Is3dmouseAttached() && instance->getDeviceID() == controller::Input::INVALID_DEVICE) { + userInputMapper->registerDevice(instance); + UserActivityLogger::getInstance().connectedDevice("controller", "Spacemouse"); + } + //else if (!Is3dmouseAttached() && spacemousedevice.getDeviceID() != controller::Input::INVALID_DEVICE) { + else if (!Is3dmouseAttached() && instance->getDeviceID() != controller::Input::INVALID_DEVICE) { + userInputMapper->removeDevice(instance->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& SpacemouseManager::MouseParams() { + return f3dMouseParams; +} + +// Access the mouse parameters structure +const I3dMouseParam& SpacemouseManager::MouseParams() const { + return f3dMouseParams; +} + +//Called with the processed motion data when a 3D mouse event is received +void SpacemouseManager::Move3d(HANDLE device, std::vector& motionData) { + Q_UNUSED(device); + instance->cc_position = { motionData[0] * 1000, motionData[1] * 1000, motionData[2] * 1000 }; + instance->cc_rotation = { motionData[3] * 1500, motionData[4] * 1500, motionData[5] * 1500 }; + instance->handleAxisEvent(); +} + +//Called when a 3D mouse key is pressed +void SpacemouseManager::On3dmouseKeyDown(HANDLE device, int virtualKeyCode) { + Q_UNUSED(device); + //SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); + instance->setButton(virtualKeyCode); +} + +//Called when a 3D mouse key is released +void SpacemouseManager::On3dmouseKeyUp(HANDLE device, int virtualKeyCode) { + Q_UNUSED(device); + //SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); + instance->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 SpacemouseManager::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 SpacemouseManager::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 SpacemouseManager::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 SpacemouseManager::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 SpacemouseManager::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 SpacemouseManager::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 SpacemouseDeviceState 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 SpacemouseManager::toggleSpacemouse(bool shouldEnable) { + if (shouldEnable && !Is3dmouseAttached()) { + init(); + } + if (!shouldEnable && Is3dmouseAttached()) { + destroy(); + } +} + +void SpacemouseManager::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); + SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); + memcpy(&spacemousedevice.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() && spacemousedevice.getDeviceID() == controller::Input::INVALID_DEVICE) { + auto userInputMapper = DependencyManager::get(); + userInputMapper->registerDevice(&spacemousedevice); + UserActivityLogger::getInstance().connectedDevice("controller", "Spacemouse"); + } + //let one axis be dominant + //ConnexionClientControl(fConnexionClientID, kConnexionCtlSetSwitches, kConnexionSwitchDominant | kConnexionSwitchEnableAll, NULL); + } +} + +void SpacemouseManager::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; + SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); + if (spacemousedevice.getDeviceID() != controller::Input::INVALID_DEVICE) { + auto userInputMapper = DependencyManager::get(); + userInputMapper->removeDevice(spacemousedevice.getDeviceID()); + spacemousedevice.setDeviceID(0); + } + } +} + +void DeviceAddedHandler(unsigned int connection) { + SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); + if (spacemousedevice.getDeviceID() == controller::Input::INVALID_DEVICE) { + qCWarning(interfaceapp) << "Spacemouse device added "; + auto userInputMapper = DependencyManager::get(); + userInputMapper->registerDevice(&spacemousedevice); + UserActivityLogger::getInstance().connectedDevice("controller", "Spacemouse"); + } +} + +void DeviceRemovedHandler(unsigned int connection) { + SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); + if (spacemousedevice.getDeviceID() != controller::Input::INVALID_DEVICE) { + qCWarning(interfaceapp) << "Spacemouse device removed"; + auto userInputMapper = DependencyManager::get(); + userInputMapper->removeDevice(spacemousedevice.getDeviceID()); + spacemousedevice.setDeviceID(controller::Input::INVALID_DEVICE); + } +} + +bool SpacemouseManager::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) { + SpacemouseDeviceState *state; + + switch (messageType) { + case kConnexionMsgDeviceState: + state = (SpacemouseDeviceState*)messageArgument; + if (state->client == fConnexionClientID) { + //SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); + instance->cc_position = { state->axis[0], state->axis[1], state->axis[2] }; + instance->cc_rotation = { state->axis[3], state->axis[4], state->axis[5] }; + + instance->handleAxisEvent(); + if (state->buttons != lastState.buttons) { + instance->setButton(state->buttons); + } + memmove(&lastState, state, (long)sizeof(SpacemouseDeviceState)); + } + break; + case kConnexionMsgPrefsChanged: + // the prefs have changed, do something + break; + default: + // other messageTypes can happen and should be ignored + break; + } + +} + +#endif // __APPLE__ + +#endif diff --git a/libraries/input-plugins/src/input-plugins/SpacemouseManager.h b/libraries/input-plugins/src/input-plugins/SpacemouseManager.h new file mode 100644 index 0000000000..5379af9991 --- /dev/null +++ b/libraries/input-plugins/src/input-plugins/SpacemouseManager.h @@ -0,0 +1,236 @@ +// SpacemouseManager.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_SpacemouseManager_h +#define hifi_SpacemouseManager_h + +#include +#include +#include +#include +#include + +#include "InputPlugin.h" + +#ifndef HAVE_SPACEMOUSE +class SpacemouseManager : public QObject { + Q_OBJECT +public: + static SpacemouseManager& getInstance(); + void ManagerFocusOutEvent(); + void init() {}; + void destroy() {}; + bool Is3dmouseAttached() { return false; }; + public slots: + void toggleConnexion(bool shouldEnable) {}; +}; +#endif + +#ifdef HAVE_SPACEMOUSE +// the windows connexion rawinput +#ifdef Q_OS_WIN + +#include "../../../interface/external/3dconnexionclient/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 SpacemouseManager : public QObject, public QAbstractNativeEventFilter { +//class SpacemouseManager : public InputPlugin, public controller::InputDevice { + + Q_OBJECT +public: + SpacemouseManager() {}; + + static SpacemouseManager& getInstance(); + void init(); + void destroy(); + bool Is3dmouseAttached(); + + SpacemouseManager* client; + + void ManagerFocusOutEvent(); + + 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 toggleSpacemouse(bool shouldEnable); + + //std::shared_ptr getDevice(); + + +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 "../../../interface/external/3dconnexionclient/include/ConnexionClientAPI.h" + +class SpacemouseManager : public QObject { + Q_OBJECT +public: + static SpacemouseManager& getInstance(); + void init(); + void destroy(); + bool Is3dmouseAttached(); + public slots: + void toggleSpacemouse(bool shouldEnable); +}; + +#endif // __APPLE__ + +#endif + + +// connnects to the userinputmapper +class SpacemouseDevice : public QObject, public controller::InputDevice { + Q_OBJECT + +public: + //static SpacemouseDevice& getInstance(); + SpacemouseDevice(); + 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(SpacemouseDevice::PositionChannel axis) const; + controller::Input makeInput(SpacemouseDevice::ButtonChannel button) const; + + controller::Input::NamedPair makePair(SpacemouseDevice::PositionChannel axis, const QString& name) const; + controller::Input::NamedPair makePair(SpacemouseDevice::ButtonChannel button, const QString& name) const; + + virtual controller::Input::NamedVector getAvailableInputs() const override; + virtual QString getDefaultMappingConfig() const 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 // defined(hifi_SpacemouseManager_h) \ No newline at end of file From 7adf38f7812ded2f4a03b2f178da5f00e2b68ca7 Mon Sep 17 00:00:00 2001 From: EdgarPironti Date: Tue, 3 Nov 2015 18:22:55 -0800 Subject: [PATCH 03/11] Spacemouse migration --- .../Spacemouse/spacemouseExample.js | 12 +- .../resources/controllers/spacemouse.json | 16 +- interface/src/Menu.cpp | 2 +- .../src/input-plugins/SpacemouseManager.cpp | 186 ++++++------------ .../src/input-plugins/SpacemouseManager.h | 8 +- 5 files changed, 82 insertions(+), 142 deletions(-) diff --git a/examples/controllers/Spacemouse/spacemouseExample.js b/examples/controllers/Spacemouse/spacemouseExample.js index 904f29cd75..46ccd80fa7 100644 --- a/examples/controllers/Spacemouse/spacemouseExample.js +++ b/examples/controllers/Spacemouse/spacemouseExample.js @@ -37,32 +37,32 @@ function update(deltaTime) { if(spacemouseCheck){ if(Controller.getValue(Controller.Standard.LY) != 0){ toggleFirstMove(); - print("Controller TX: " + Controller.getValue(Controller.Standard.LY)); + print("- Controller TY: " + Controller.getValue(Controller.Standard.LY)); } if(Controller.getValue(Controller.Standard.LX) != 0){ toggleFirstMove(); - print("Controller TZ: " + Controller.getValue(Controller.Standard.LX)); + print("- Controller RZ: " + Controller.getValue(Controller.Standard.LX)); } if(Controller.getValue(Controller.Standard.LT) != 0){ toggleFirstMove(); - print("Controller TY: " + Controller.getValue(Controller.Standard.LT)); + print("- Controller LEFTB: " + Controller.getValue(Controller.Standard.LT)); } if(Controller.getValue(Controller.Standard.RY) != 0){ toggleFirstMove(); - print("Controller RX: " + Controller.getValue(Controller.Standard.RY)); + print("- Controller TZ: " + Controller.getValue(Controller.Standard.RY)); } if(Controller.getValue(Controller.Standard.RX) != 0){ toggleFirstMove(); - print("Controller RZ: " + Controller.getValue(Controller.Standard.RX)); + print("- Controller TX: " + Controller.getValue(Controller.Standard.RX)); } if(Controller.getValue(Controller.Standard.RT) != 0){ toggleFirstMove(); - print("Controller RY: " + Controller.getValue(Controller.Standard.RT)); + print("- Controller RIGHTB: " + Controller.getValue(Controller.Standard.RT)); } firstmove = 1; diff --git a/interface/resources/controllers/spacemouse.json b/interface/resources/controllers/spacemouse.json index 61af605512..e02d0d4101 100644 --- a/interface/resources/controllers/spacemouse.json +++ b/interface/resources/controllers/spacemouse.json @@ -1,15 +1,15 @@ { "name": "Spacemouse to Standard", "channels": [ - { "from": "Spacemouse.TranslateX", "to": "Standard.LY" }, - { "from": "Spacemouse.TranslateZ", "filters": "invert", "to": "Standard.LX" }, - - { "from": "Spacemouse.RotateX", "to": "Standard.RY" }, - { "from": "Spacemouse.RotateZ", "to": "Standard.RX" }, - - { "from": "Spacemouse.LeftButton", "to": "Standard.Back" }, - { "from": "Spacemouse.RightButton", "to": "Standard.Start" } + { "from": "Spacemouse.TranslateX", "to": "Standard.RX" }, + { "from": "Spacemouse.TranslateY", "to": "Standard.LY" }, + { "from": "Spacemouse.TranslateZ", "to": "Standard.RY" }, + + { "from": "Spacemouse.RotateZ", "to": "Standard.LX" }, + + { "from": "Spacemouse.LeftButton", "to": "Standard.LT" }, + { "from": "Spacemouse.RightButton", "to": "Standard.RT" } ] } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index c15ce4a066..162b713948 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -465,7 +465,7 @@ Menu::Menu() { avatar, SLOT(setEnableMeshVisible(bool))); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::DisableEyelidAdjustment, 0, false); - addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::Connexion, 0, false, &SpacemouseManager::getInstance(), SLOT(toggleConnexion(bool))); + addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::Connexion, 0, false, &SpacemouseManager::getInstance(), SLOT(toggleSpacemouse(bool))); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ComfortMode, 0, true); diff --git a/libraries/input-plugins/src/input-plugins/SpacemouseManager.cpp b/libraries/input-plugins/src/input-plugins/SpacemouseManager.cpp index 3078f99a23..3f68be8039 100644 --- a/libraries/input-plugins/src/input-plugins/SpacemouseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SpacemouseManager.cpp @@ -34,26 +34,12 @@ void SpacemouseDevice::focusOutEvent() { }; -//SpacemouseDevice& SpacemouseDevice::getInstance() { -// static SpacemouseDevice sharedInstance; -// return sharedInstance; -//} - - - -//std::shared_ptr SpacemouseManager::getDevice(){ -// return instance; -//} - -//SpacemouseDevice::SpacemouseDevice() : InputDevice("Spacemouse") {} - - void SpacemouseDevice::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; + auto position = cc_position / MAX_AXIS; _axisStateMap[TRANSLATE_X] = position.x; _axisStateMap[TRANSLATE_Y] = position.y; _axisStateMap[TRANSLATE_Z] = position.z; @@ -75,9 +61,9 @@ controller::Input::NamedVector SpacemouseDevice::getAvailableInputs() const { makePair(BUTTON_2, "RightButton"), //makePair(BUTTON_3, "BothButtons"), makePair(TRANSLATE_X, "TranslateX"), - //makePair(TRANSLATE_Y, "TranslateY"), + makePair(TRANSLATE_Y, "TranslateY"), makePair(TRANSLATE_Z, "TranslateZ"), - makePair(ROTATE_X, "RotateX"), + //makePair(ROTATE_X, "RotateX"), //makePair(ROTATE_Y, "RotateY"), makePair(ROTATE_Z, "RotateZ"), @@ -90,45 +76,11 @@ QString SpacemouseDevice::getDefaultMappingConfig() const { return MAPPING_JSON; } -//void SpacemouseDevice::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 SpacemouseDevice::getButton(int channel) const { if (!_buttonPressedMap.empty()) { if (_buttonPressedMap.find(channel) != _buttonPressedMap.end()) { return 1.0f; - } - else { + } else { return 0.0f; } } @@ -139,8 +91,7 @@ float SpacemouseDevice::getAxis(int channel) const { auto axis = _axisStateMap.find(channel); if (axis != _axisStateMap.end()) { return (*axis).second; - } - else { + } else { return 0.0f; } } @@ -179,18 +130,14 @@ void SpacemouseManager::ManagerFocusOutEvent() { instance->focusOutEvent(); } -#ifdef HAVE_SPACEMOUSE +#ifdef HAVE_3DCONNEXIONCLIENT #ifdef Q_OS_WIN #include - - void SpacemouseManager::toggleSpacemouse(bool shouldEnable) { - //SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); - //if (shouldEnable && spacemousedevice.getDeviceID() == controller::Input::INVALID_DEVICE) { - if (shouldEnable && instance->getDeviceID() == controller::Input::INVALID_DEVICE) { + if (shouldEnable) { init(); } if (!shouldEnable && instance->getDeviceID() != controller::Input::INVALID_DEVICE) { @@ -205,13 +152,18 @@ void SpacemouseManager::init() { InitializeRawInput(GetActiveWindow()); QAbstractEventDispatcher::instance()->installNativeEventFilter(this); + + if (instance->getDeviceID() != controller::Input::INVALID_DEVICE) { + auto userInputMapper = DependencyManager::get(); + userInputMapper->registerDevice(instance); + UserActivityLogger::getInstance().connectedDevice("controller", "Spacemouse"); + } + } } void SpacemouseManager::destroy() { QAbstractEventDispatcher::instance()->removeNativeEventFilter(this); - //SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); - //int deviceid = spacemousedevice.getDeviceID(); int deviceid = instance->getDeviceID(); auto userInputMapper = DependencyManager::get(); userInputMapper->removeDevice(deviceid); @@ -306,8 +258,7 @@ unsigned short HidToVirtualKey(unsigned long pid, unsigned short hidKeyCode) { if (pid == _3dmouseVirtualKeys[i].pid) { if (hidKeyCode < _3dmouseVirtualKeys[i].nKeys) { virtualkey = _3dmouseVirtualKeys[i].vkeys[hidKeyCode]; - } - else { + } else { virtualkey = V3DK_INVALID; } break; @@ -318,15 +269,12 @@ unsigned short HidToVirtualKey(unsigned long pid, unsigned short hidKeyCode) { } bool SpacemouseManager::RawInputEventFilter(void* msg, long* result) { - //SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); auto userInputMapper = DependencyManager::get(); - //if (Is3dmouseAttached() && spacemousedevice.getDeviceID() == controller::Input::INVALID_DEVICE) { if (Is3dmouseAttached() && instance->getDeviceID() == controller::Input::INVALID_DEVICE) { userInputMapper->registerDevice(instance); UserActivityLogger::getInstance().connectedDevice("controller", "Spacemouse"); } - //else if (!Is3dmouseAttached() && spacemousedevice.getDeviceID() != controller::Input::INVALID_DEVICE) { else if (!Is3dmouseAttached() && instance->getDeviceID() != controller::Input::INVALID_DEVICE) { userInputMapper->removeDevice(instance->getDeviceID()); } @@ -361,6 +309,7 @@ const I3dMouseParam& SpacemouseManager::MouseParams() const { //Called with the processed motion data when a 3D mouse event is received void SpacemouseManager::Move3d(HANDLE device, std::vector& motionData) { Q_UNUSED(device); + instance->cc_position = { motionData[0] * 1000, motionData[1] * 1000, motionData[2] * 1000 }; instance->cc_rotation = { motionData[3] * 1500, motionData[4] * 1500, motionData[5] * 1500 }; instance->handleAxisEvent(); @@ -478,8 +427,7 @@ UINT SpacemouseManager::GetRawInputBuffer(PRAWINPUT pData, PUINT pcbSize, UINT c ::IsWow64Process(GetCurrentProcess(), &bIsWow64); if (!bIsWow64 || pData == NULL) { return ::GetRawInputBuffer(pData, pcbSize, cbSizeHeader); - } - else { + } else { HWND hwndTarget = fWindow; size_t cbDataSize = 0; @@ -493,8 +441,7 @@ UINT SpacemouseManager::GetRawInputBuffer(PRAWINPUT pData, PUINT pcbSize, UINT c if (::GetRawInputData(hRawInput, RID_INPUT, pri, &cbSize, cbSizeHeader) == static_cast(-1)) { if (nCount == 0) { return static_cast(-1); - } - else { + } else { break; } } @@ -534,16 +481,14 @@ void SpacemouseManager::On3dmouseInput() { if (0 == fLast3dmouseInputTime) { dwElapsedTime = 10; // System timer resolution - } - else { + } else { dwElapsedTime = dwNow - fLast3dmouseInputTime; if (fLast3dmouseInputTime > dwNow) { dwElapsedTime = ~dwElapsedTime + 1; } if (dwElapsedTime<1) { dwElapsedTime = 1; - } - else if (dwElapsedTime > 500) { + } else if (dwElapsedTime > 500) { // Check for wild numbers because the device was removed while sending data dwElapsedTime = 10; } @@ -572,8 +517,7 @@ void SpacemouseManager::On3dmouseInput() { // 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 && + } else if (!iterator->second.fIsDirty) { //!t_bPoll3dmouse && // If we are not polling then only handle the data that was actually received ++iterator; continue; @@ -591,14 +535,14 @@ void SpacemouseManager::On3dmouseInput() { // 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 + // 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 + // Rotate is switched off so set the rotation vector values to zero motionData[3] = motionData[4] = motionData[5] = 0.; } @@ -622,8 +566,7 @@ void SpacemouseManager::On3dmouseInput() { // Now a bit of book keeping before passing on the data if (iterator->second.IsZero()) { iterator = fDevice2Data.erase(iterator); - } - else { + } else { ++iterator; } @@ -643,8 +586,7 @@ void SpacemouseManager::On3dmouseInput() { if (!fDevice2Data.empty()) { fLast3dmouseInputTime = dwNow; - } - else { + } else { fLast3dmouseInputTime = 0; } } @@ -746,22 +688,20 @@ bool SpacemouseManager::TranslateRawInputData(UINT nInputCode, PRAWINPUT pRawInp //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; + //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 + // 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 + } 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) { @@ -779,8 +719,7 @@ bool SpacemouseManager::TranslateRawInputData(UINT nInputCode, PRAWINPUT pRawInp return true; } - } - else if (pRawInput->data.hid.bRawData[0] == 0x03) { // Keystate change + } 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. @@ -792,8 +731,7 @@ bool SpacemouseManager::TranslateRawInputData(UINT nInputCode, PRAWINPUT pRawInp unsigned long dwOldKeystate = fDevice2Keystate[pRawInput->header.hDevice]; if (dwKeystate != 0) { fDevice2Keystate[pRawInput->header.hDevice] = dwKeystate; - } - else { + } else { fDevice2Keystate.erase(pRawInput->header.hDevice); } @@ -807,8 +745,7 @@ bool SpacemouseManager::TranslateRawInputData(UINT nInputCode, PRAWINPUT pRawInp if (nVirtualKeyCode) { if (dwKeystate & 0x01) { On3dmouseKeyDown(pRawInput->header.hDevice, nVirtualKeyCode); - } - else { + } else { On3dmouseKeyUp(pRawInput->header.hDevice, nVirtualKeyCode); } } @@ -824,13 +761,13 @@ bool SpacemouseManager::TranslateRawInputData(UINT nInputCode, PRAWINPUT pRawInp } MouseParameters::MouseParameters() : -fNavigation(NAVIGATION_OBJECT_MODE), -fPivot(PIVOT_AUTO), -fPivotVisibility(PIVOT_SHOW), -fIsLockHorizon(true), -fIsPanZoom(true), -fIsRotate(true), -fSpeed(SPEED_LOW) + fNavigation(NAVIGATION_OBJECT_MODE), + fPivot(PIVOT_AUTO), + fPivotVisibility(PIVOT_SHOW), + fIsLockHorizon(true), + fIsPanZoom(true), + fIsRotate(true), + fSpeed(SPEED_LOW) { } @@ -921,8 +858,9 @@ void SpacemouseManager::init() { // ...or use this to take over system-wide fConnexionClientID = RegisterConnexionClient(kConnexionClientWildcard, NULL, kConnexionClientModeTakeOver, kConnexionMaskAll); - SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); - memcpy(&spacemousedevice.clientId, &fConnexionClientID, (long)sizeof(int)); + //SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); + //memcpy(&spacemousedevice.clientId, &fConnexionClientID, (long)sizeof(int)); + memcpy(&instance->clientId, &fConnexionClientID, (long)sizeof(int)); // A separate API call is required to capture buttons beyond the first 8 SetConnexionClientButtonMask(fConnexionClientID, kConnexionMaskAllButtons); @@ -930,9 +868,9 @@ void SpacemouseManager::init() { // use default switches ConnexionClientControl(fConnexionClientID, kConnexionCtlSetSwitches, kConnexionSwitchesDisabled, NULL); - if (Is3dmouseAttached() && spacemousedevice.getDeviceID() == controller::Input::INVALID_DEVICE) { + if (Is3dmouseAttached() && instance->getDeviceID() == controller::Input::INVALID_DEVICE) { auto userInputMapper = DependencyManager::get(); - userInputMapper->registerDevice(&spacemousedevice); + userInputMapper->registerDevice(instance); UserActivityLogger::getInstance().connectedDevice("controller", "Spacemouse"); } //let one axis be dominant @@ -949,32 +887,32 @@ void SpacemouseManager::destroy() { } CleanupConnexionHandlers(); fConnexionClientID = 0; - SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); - if (spacemousedevice.getDeviceID() != controller::Input::INVALID_DEVICE) { + //SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); + if (instance->getDeviceID() != controller::Input::INVALID_DEVICE) { auto userInputMapper = DependencyManager::get(); - userInputMapper->removeDevice(spacemousedevice.getDeviceID()); - spacemousedevice.setDeviceID(0); + userInputMapper->removeDevice(instance->getDeviceID()); + instance->setDeviceID(controller::Input::INVALID_DEVICE); } } } void DeviceAddedHandler(unsigned int connection) { - SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); - if (spacemousedevice.getDeviceID() == controller::Input::INVALID_DEVICE) { + //SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); + if (instance->getDeviceID() == controller::Input::INVALID_DEVICE) { qCWarning(interfaceapp) << "Spacemouse device added "; auto userInputMapper = DependencyManager::get(); - userInputMapper->registerDevice(&spacemousedevice); + userInputMapper->registerDevice(instance); UserActivityLogger::getInstance().connectedDevice("controller", "Spacemouse"); } } void DeviceRemovedHandler(unsigned int connection) { - SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); - if (spacemousedevice.getDeviceID() != controller::Input::INVALID_DEVICE) { + //SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); + if (instance->getDeviceID() != controller::Input::INVALID_DEVICE) { qCWarning(interfaceapp) << "Spacemouse device removed"; auto userInputMapper = DependencyManager::get(); - userInputMapper->removeDevice(spacemousedevice.getDeviceID()); - spacemousedevice.setDeviceID(controller::Input::INVALID_DEVICE); + userInputMapper->removeDevice(instance->getDeviceID()); + instance->setDeviceID(controller::Input::INVALID_DEVICE); } } diff --git a/libraries/input-plugins/src/input-plugins/SpacemouseManager.h b/libraries/input-plugins/src/input-plugins/SpacemouseManager.h index 5379af9991..0d6556d059 100644 --- a/libraries/input-plugins/src/input-plugins/SpacemouseManager.h +++ b/libraries/input-plugins/src/input-plugins/SpacemouseManager.h @@ -11,6 +11,8 @@ #ifndef hifi_SpacemouseManager_h #define hifi_SpacemouseManager_h +#define HAVE_3DCONNEXIONCLIENT + #include #include #include @@ -19,7 +21,7 @@ #include "InputPlugin.h" -#ifndef HAVE_SPACEMOUSE +#ifndef HAVE_3DCONNEXIONCLIENT class SpacemouseManager : public QObject { Q_OBJECT public: @@ -29,11 +31,11 @@ public: void destroy() {}; bool Is3dmouseAttached() { return false; }; public slots: - void toggleConnexion(bool shouldEnable) {}; + void toggleSpacemouse(bool shouldEnable) {}; }; #endif -#ifdef HAVE_SPACEMOUSE +#ifdef HAVE_3DCONNEXIONCLIENT // the windows connexion rawinput #ifdef Q_OS_WIN From ade0862948ae8d010d8450b6d4056716348e388d Mon Sep 17 00:00:00 2001 From: EdgarPironti Date: Wed, 4 Nov 2015 00:49:40 -0800 Subject: [PATCH 04/11] Spacemouse fixes --- .../controllers/Spacemouse/spacemouseExample.js | 8 ++++---- interface/resources/controllers/spacemouse.json | 4 ++-- .../src/input-plugins/SpacemouseManager.cpp | 14 +++----------- .../src/input-plugins/SpacemouseManager.h | 9 ++------- 4 files changed, 11 insertions(+), 24 deletions(-) diff --git a/examples/controllers/Spacemouse/spacemouseExample.js b/examples/controllers/Spacemouse/spacemouseExample.js index 46ccd80fa7..92e89055b7 100644 --- a/examples/controllers/Spacemouse/spacemouseExample.js +++ b/examples/controllers/Spacemouse/spacemouseExample.js @@ -45,9 +45,9 @@ function update(deltaTime) { print("- Controller RZ: " + Controller.getValue(Controller.Standard.LX)); } - if(Controller.getValue(Controller.Standard.LT) != 0){ + if(Controller.getValue(Controller.Standard.LB) != 0){ toggleFirstMove(); - print("- Controller LEFTB: " + Controller.getValue(Controller.Standard.LT)); + print("- Controller LEFTB: " + Controller.getValue(Controller.Standard.LB)); } if(Controller.getValue(Controller.Standard.RY) != 0){ @@ -60,9 +60,9 @@ function update(deltaTime) { print("- Controller TX: " + Controller.getValue(Controller.Standard.RX)); } - if(Controller.getValue(Controller.Standard.RT) != 0){ + if(Controller.getValue(Controller.Standard.RB) != 0){ toggleFirstMove(); - print("- Controller RIGHTB: " + Controller.getValue(Controller.Standard.RT)); + print("- Controller RIGHTB: " + Controller.getValue(Controller.Standard.RB)); } firstmove = 1; diff --git a/interface/resources/controllers/spacemouse.json b/interface/resources/controllers/spacemouse.json index e02d0d4101..adcfef71a6 100644 --- a/interface/resources/controllers/spacemouse.json +++ b/interface/resources/controllers/spacemouse.json @@ -8,8 +8,8 @@ { "from": "Spacemouse.RotateZ", "to": "Standard.LX" }, - { "from": "Spacemouse.LeftButton", "to": "Standard.LT" }, - { "from": "Spacemouse.RightButton", "to": "Standard.RT" } + { "from": "Spacemouse.LeftButton", "to": "Standard.LB" }, + { "from": "Spacemouse.RightButton", "to": "Standard.RB" } ] } diff --git a/libraries/input-plugins/src/input-plugins/SpacemouseManager.cpp b/libraries/input-plugins/src/input-plugins/SpacemouseManager.cpp index 3f68be8039..9c1307a18e 100644 --- a/libraries/input-plugins/src/input-plugins/SpacemouseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SpacemouseManager.cpp @@ -21,7 +21,7 @@ const float MAX_AXIS = 75.0f; // max forward = 2x speed -static std::shared_ptr instance = NULL; +static std::shared_ptr instance; SpacemouseDevice::SpacemouseDevice() : InputDevice("Spacemouse") { @@ -120,9 +120,9 @@ void SpacemouseDevice::update(float deltaTime, bool jointsCaptured) { SpacemouseManager& SpacemouseManager::getInstance() { static SpacemouseManager sharedInstance; - if (instance == NULL){ + if (instance == nullptr) { new SpacemouseDevice(); - } + } return sharedInstance; } @@ -318,14 +318,12 @@ void SpacemouseManager::Move3d(HANDLE device, std::vector& motionData) { //Called when a 3D mouse key is pressed void SpacemouseManager::On3dmouseKeyDown(HANDLE device, int virtualKeyCode) { Q_UNUSED(device); - //SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); instance->setButton(virtualKeyCode); } //Called when a 3D mouse key is released void SpacemouseManager::On3dmouseKeyUp(HANDLE device, int virtualKeyCode) { Q_UNUSED(device); - //SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); instance->setButton(0); } @@ -858,8 +856,6 @@ void SpacemouseManager::init() { // ...or use this to take over system-wide fConnexionClientID = RegisterConnexionClient(kConnexionClientWildcard, NULL, kConnexionClientModeTakeOver, kConnexionMaskAll); - //SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); - //memcpy(&spacemousedevice.clientId, &fConnexionClientID, (long)sizeof(int)); memcpy(&instance->clientId, &fConnexionClientID, (long)sizeof(int)); // A separate API call is required to capture buttons beyond the first 8 @@ -887,7 +883,6 @@ void SpacemouseManager::destroy() { } CleanupConnexionHandlers(); fConnexionClientID = 0; - //SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); if (instance->getDeviceID() != controller::Input::INVALID_DEVICE) { auto userInputMapper = DependencyManager::get(); userInputMapper->removeDevice(instance->getDeviceID()); @@ -897,7 +892,6 @@ void SpacemouseManager::destroy() { } void DeviceAddedHandler(unsigned int connection) { - //SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); if (instance->getDeviceID() == controller::Input::INVALID_DEVICE) { qCWarning(interfaceapp) << "Spacemouse device added "; auto userInputMapper = DependencyManager::get(); @@ -907,7 +901,6 @@ void DeviceAddedHandler(unsigned int connection) { } void DeviceRemovedHandler(unsigned int connection) { - //SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); if (instance->getDeviceID() != controller::Input::INVALID_DEVICE) { qCWarning(interfaceapp) << "Spacemouse device removed"; auto userInputMapper = DependencyManager::get(); @@ -934,7 +927,6 @@ void MessageHandler(unsigned int connection, unsigned int messageType, void *mes case kConnexionMsgDeviceState: state = (SpacemouseDeviceState*)messageArgument; if (state->client == fConnexionClientID) { - //SpacemouseDevice& spacemousedevice = SpacemouseDevice::getInstance(); instance->cc_position = { state->axis[0], state->axis[1], state->axis[2] }; instance->cc_rotation = { state->axis[3], state->axis[4], state->axis[5] }; diff --git a/libraries/input-plugins/src/input-plugins/SpacemouseManager.h b/libraries/input-plugins/src/input-plugins/SpacemouseManager.h index 0d6556d059..26e0155825 100644 --- a/libraries/input-plugins/src/input-plugins/SpacemouseManager.h +++ b/libraries/input-plugins/src/input-plugins/SpacemouseManager.h @@ -89,8 +89,7 @@ private: }; class SpacemouseManager : public QObject, public QAbstractNativeEventFilter { -//class SpacemouseManager : public InputPlugin, public controller::InputDevice { - + Q_OBJECT public: SpacemouseManager() {}; @@ -118,10 +117,7 @@ public: } public slots: - void toggleSpacemouse(bool shouldEnable); - - //std::shared_ptr getDevice(); - + void toggleSpacemouse(bool shouldEnable); signals: void Move3d(std::vector& motionData); @@ -193,7 +189,6 @@ class SpacemouseDevice : public QObject, public controller::InputDevice { Q_OBJECT public: - //static SpacemouseDevice& getInstance(); SpacemouseDevice(); enum PositionChannel { TRANSLATE_X, From 18d2b184dcf32d2d52dcbe91f7d0c8548edb80f9 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 4 Nov 2015 11:39:34 -0800 Subject: [PATCH 05/11] Fix ability to enable mappings parsed from JSON in JS --- libraries/controllers/src/controllers/UserInputMapper.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index ec32024b91..fae7a2aaa8 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -1029,6 +1029,7 @@ Mapping::Pointer UserInputMapper::parseMapping(const QJsonValue& json) { } mapping->routes.push_back(route); } + _mappingsByName[mapping->name] = mapping; return mapping; } From 4dec31d524a2d835f05e54111785bca47e08de91 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 4 Nov 2015 13:20:47 -0800 Subject: [PATCH 06/11] Fix crash in Oculus simulator --- plugins/oculus/src/OculusDebugDisplayPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/oculus/src/OculusDebugDisplayPlugin.cpp b/plugins/oculus/src/OculusDebugDisplayPlugin.cpp index 2021ce1c5a..7a8b355ddd 100644 --- a/plugins/oculus/src/OculusDebugDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDebugDisplayPlugin.cpp @@ -25,7 +25,7 @@ bool OculusDebugDisplayPlugin::isSupported() const { } void OculusDebugDisplayPlugin::customizeContext() { - WindowOpenGLDisplayPlugin::customizeContext(); + OculusBaseDisplayPlugin::customizeContext(); enableVsync(false); } From 1cbe6c446301c5208a37b985ba9752a1a19c1e98 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 4 Nov 2015 13:59:37 -0800 Subject: [PATCH 07/11] don't attempt to grab particles or zones --- examples/controllers/handControllerGrab.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 2d82896e26..afe72b530a 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -452,6 +452,14 @@ function MyController(hand) { continue; } + if (propsForCandidate.type == 'ParticleEffect') { + continue; + } + + if (propsForCandidate.type == 'Zone') { + continue; + } + if (propsForCandidate.locked && !grabbableDataForCandidate.wantsTrigger) { continue; } From 20d1035821b83b5d4d29bbf3ca94d4db09a15498 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 4 Nov 2015 15:50:21 -0800 Subject: [PATCH 08/11] Fixing step yaw to move by consistent amounts, be 'tappable' --- .../resources/controllers/keyboardMouse.json | 35 +++++++++++++++---- interface/src/Application.cpp | 2 +- .../controllers/impl/filters/PulseFilter.cpp | 15 ++++++-- .../controllers/impl/filters/PulseFilter.h | 7 ++-- 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/interface/resources/controllers/keyboardMouse.json b/interface/resources/controllers/keyboardMouse.json index f99472b0e9..4a68ca0d20 100644 --- a/interface/resources/controllers/keyboardMouse.json +++ b/interface/resources/controllers/keyboardMouse.json @@ -12,28 +12,49 @@ { "from": "Keyboard.W", "when": "Keyboard.Shift", "to": "Actions.PITCH_UP" }, - { "from": { "makeAxis" : ["Keyboard.MouseMoveLeft", "Keyboard.MouseMoveRight"] }, + { "comment" : "Mouse turn need to be small continuous increments", + "from": { "makeAxis" : [ + [ "Keyboard.MouseMoveLeft" ], + [ "Keyboard.MouseMoveRight" ] + ] + }, "when": [ "Application.InHMD", "Application.ComfortMode", "Keyboard.RightMouseButton" ], "to": "Actions.StepYaw", "filters": [ "constrainToInteger", - { "type": "pulse", "interval": 0.5 }, - { "type": "scale", "scale": 15 } + { "type": "pulse", "interval": 0.2 }, + { "type": "scale", "scale": 22.5 } + ] + }, + + { "comment" : "Touchpad turn need to be small continuous increments, but without the RMB constraint", + "from": { "makeAxis" : [ + [ "Keyboard.TouchpadLeft" ], + [ "Keyboard.TouchpadRight" ] + ] + }, + "when": [ "Application.InHMD", "Application.ComfortMode" ], + "to": "Actions.StepYaw", + "filters": + [ + "constrainToInteger", + { "type": "pulse", "interval": 0.2 }, + { "type": "scale", "scale": 22.5 } ] }, { "from": { "makeAxis" : [ - ["Keyboard.A", "Keyboard.Left", "Keyboard.TouchpadLeft"], - ["Keyboard.D", "Keyboard.Right", "Keyboard.TouchpadRight"] + ["Keyboard.A", "Keyboard.Left" ], + ["Keyboard.D", "Keyboard.Right"] ] }, "when": [ "Application.InHMD", "Application.ComfortMode" ], "to": "Actions.StepYaw", "filters": [ - { "type": "pulse", "interval": 0.5 }, - { "type": "scale", "scale": 15 } + { "type": "pulse", "interval": 0.5, "resetOnZero": true }, + { "type": "scale", "scale": 22.5 } ] }, diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d31d9de4a0..da92605cb8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2795,7 +2795,7 @@ void Application::update(float deltaTime) { float timeFactor = EXPECTED_FRAME_RATE * deltaTime; myAvatar->setDriveKeys(PITCH, -1.0f * userInputMapper->getActionState(controller::Action::PITCH) / timeFactor); myAvatar->setDriveKeys(YAW, -1.0f * userInputMapper->getActionState(controller::Action::YAW) / timeFactor); - myAvatar->setDriveKeys(STEP_YAW, -1.0f * userInputMapper->getActionState(controller::Action::STEP_YAW) / timeFactor); + myAvatar->setDriveKeys(STEP_YAW, -1.0f * userInputMapper->getActionState(controller::Action::STEP_YAW)); } } myAvatar->setDriveKeys(ZOOM, userInputMapper->getActionState(controller::Action::TRANSLATE_CAMERA_Z)); diff --git a/libraries/controllers/src/controllers/impl/filters/PulseFilter.cpp b/libraries/controllers/src/controllers/impl/filters/PulseFilter.cpp index f4e1f04791..6ef9d40802 100644 --- a/libraries/controllers/src/controllers/impl/filters/PulseFilter.cpp +++ b/libraries/controllers/src/controllers/impl/filters/PulseFilter.cpp @@ -13,7 +13,7 @@ using namespace controller; - +const float PulseFilter::DEFAULT_LAST_EMIT_TIME = -::std::numeric_limits::max(); float PulseFilter::apply(float value) const { float result = 0.0f; @@ -25,13 +25,22 @@ float PulseFilter::apply(float value) const { _lastEmitTime = now; result = value; } + } else if (_resetOnZero) { + _lastEmitTime = DEFAULT_LAST_EMIT_TIME; } return result; } bool PulseFilter::parseParameters(const QJsonValue& parameters) { - static const QString JSON_MIN = QStringLiteral("interval"); - return parseSingleFloatParameter(parameters, JSON_MIN, _interval); + static const QString JSON_INTERVAL = QStringLiteral("interval"); + static const QString JSON_RESET = QStringLiteral("resetOnZero"); + if (parameters.isObject()) { + auto obj = parameters.toObject(); + if (obj.contains(JSON_RESET)) { + _resetOnZero = obj[JSON_RESET].toBool(); + } + } + return parseSingleFloatParameter(parameters, JSON_INTERVAL, _interval); } diff --git a/libraries/controllers/src/controllers/impl/filters/PulseFilter.h b/libraries/controllers/src/controllers/impl/filters/PulseFilter.h index 2512b479cf..dbe2eba81b 100644 --- a/libraries/controllers/src/controllers/impl/filters/PulseFilter.h +++ b/libraries/controllers/src/controllers/impl/filters/PulseFilter.h @@ -21,14 +21,15 @@ public: PulseFilter() {} PulseFilter(float interval) : _interval(interval) {} - virtual float apply(float value) const override; virtual bool parseParameters(const QJsonValue& parameters); private: - mutable float _lastEmitTime { -::std::numeric_limits::max() }; - float _interval = 1.0f; + static const float DEFAULT_LAST_EMIT_TIME; + mutable float _lastEmitTime { DEFAULT_LAST_EMIT_TIME }; + bool _resetOnZero { false }; + float _interval { 1.0f }; }; } From 69d29bbbbb921eebe8dc481d997e3aa0e7d54d6b Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 4 Nov 2015 16:18:55 -0800 Subject: [PATCH 09/11] Creating recording library --- libraries/recording/CMakeLists.txt | 9 +++++++ libraries/recording/src/recording/Forward.h | 28 +++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 libraries/recording/CMakeLists.txt create mode 100644 libraries/recording/src/recording/Forward.h diff --git a/libraries/recording/CMakeLists.txt b/libraries/recording/CMakeLists.txt new file mode 100644 index 0000000000..a0beae4496 --- /dev/null +++ b/libraries/recording/CMakeLists.txt @@ -0,0 +1,9 @@ +set(TARGET_NAME recording) + +# set a default root dir for each of our optional externals if it was not passed +setup_hifi_library(Script) + +# use setup_hifi_library macro to setup our project and link appropriate Qt modules +link_hifi_libraries(shared) + +GroupSources("src/recording") diff --git a/libraries/recording/src/recording/Forward.h b/libraries/recording/src/recording/Forward.h new file mode 100644 index 0000000000..83a89da847 --- /dev/null +++ b/libraries/recording/src/recording/Forward.h @@ -0,0 +1,28 @@ +// +// Created by Bradley Austin Davis 2015/11/04 +// 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 +#ifndef hifi_Recording_Forward_h +#define hifi_Recording_Forward_h + +#include +#include + +namespace recording { + +// A recording of some set of state from the application, usually avatar +// data + audio for a single person +class Clip; + +// An interface for interacting with clips, creating them by recording or +// playing them back. Also serialization to and from files / network sources +class Deck; + +} + +#endif From adb9118dc1df77517a591f8170f6c91f77142b9b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 4 Nov 2015 16:21:02 -0800 Subject: [PATCH 10/11] don't set release velocity --- examples/controllers/handControllerGrab.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index afe72b530a..1a5b28b82c 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -903,9 +903,9 @@ function MyController(hand) { // the action will tend to quickly bring an object's velocity to zero. now that // the action is gone, set the objects velocity to something the holder might expect. - Entities.editEntity(this.grabbedEntity, { - velocity: this.grabbedVelocity - }); + // Entities.editEntity(this.grabbedEntity, { + // velocity: this.grabbedVelocity + // }); this.grabbedVelocity = ZERO_VEC; this.grabbedEntity = null; From 05a977e31bc87ea96190c1fd0f359d08e587f3ee Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 4 Nov 2015 16:26:30 -0800 Subject: [PATCH 11/11] get rid of code that computes release velocity --- examples/controllers/handControllerGrab.js | 29 +--------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 1a5b28b82c..b0721de119 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -178,12 +178,11 @@ function MyController(hand) { this.actionID = null; // action this script created... this.grabbedEntity = null; // on this entity. - this.grabbedVelocity = ZERO_VEC; // rolling average of held object's velocity this.state = STATE_OFF; this.pointer = null; // entity-id of line object this.triggerValue = 0; // rolling average of trigger value this.rawTriggerValue = 0; - + this.offsetPosition = { x: 0.0, y: 0.0, z: 0.0 }; this.offsetRotation = { x: 0.0, y: 0.0, z: 0.0, w: 1.0 }; @@ -595,7 +594,6 @@ function MyController(hand) { var deltaPosition = Vec3.subtract(newObjectPosition, this.currentObjectPosition); // meters var now = Date.now(); var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds - this.computeReleaseVelocity(deltaPosition, deltaTime, false); this.currentObjectPosition = newObjectPosition; this.currentObjectTime = now; @@ -715,7 +713,6 @@ function MyController(hand) { var deltaPosition = Vec3.subtract(handControllerPosition, this.currentHandControllerTipPosition); // meters var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds - this.computeReleaseVelocity(deltaPosition, deltaTime, true); this.currentHandControllerTipPosition = handControllerPosition; this.currentObjectTime = now; @@ -867,23 +864,6 @@ function MyController(hand) { Entities.callEntityMethod(entityID, "stopTouch"); }; - this.computeReleaseVelocity = function(deltaPosition, deltaTime, useMultiplier) { - if (deltaTime > 0.0 && !vec3equal(deltaPosition, ZERO_VEC)) { - var grabbedVelocity = Vec3.multiply(deltaPosition, 1.0 / deltaTime); - // don't update grabbedVelocity if the trigger is off. the smoothing of the trigger - // value would otherwise give the held object time to slow down. - if (this.triggerSqueezed()) { - this.grabbedVelocity = - Vec3.sum(Vec3.multiply(this.grabbedVelocity, (1.0 - NEAR_GRABBING_VELOCITY_SMOOTH_RATIO)), - Vec3.multiply(grabbedVelocity, NEAR_GRABBING_VELOCITY_SMOOTH_RATIO)); - } - - if (useMultiplier) { - this.grabbedVelocity = Vec3.multiply(this.grabbedVelocity, RELEASE_VELOCITY_MULTIPLIER); - } - } - }; - this.release = function() { if(this.hand !== disabledHand){ @@ -901,13 +881,6 @@ function MyController(hand) { this.deactivateEntity(this.grabbedEntity); - // the action will tend to quickly bring an object's velocity to zero. now that - // the action is gone, set the objects velocity to something the holder might expect. - // Entities.editEntity(this.grabbedEntity, { - // velocity: this.grabbedVelocity - // }); - - this.grabbedVelocity = ZERO_VEC; this.grabbedEntity = null; this.actionID = null; this.setState(STATE_OFF);