├── .gitignore ├── .gitmodules ├── LICENSE ├── Readme.md ├── VRInputEmulator.sln ├── client_commandline ├── client_commandline.vcxproj └── src │ ├── client_commandline.cpp │ ├── client_commandline.h │ └── main.cpp ├── client_leapmotion ├── client_leapmotion.vcxproj └── src │ ├── LeapMotionClient.cpp │ ├── LeapMotionClient.h │ ├── main.cpp │ └── utils │ └── Matrix.h ├── client_overlay ├── bin │ ├── logging.conf.installer │ ├── logging.conf.standalone │ ├── win64 │ │ ├── LICENSE │ │ ├── logging.conf │ │ ├── manifest.vrmanifest │ │ ├── openvr_api.dll │ │ ├── qt.conf │ │ ├── res │ │ │ ├── qml │ │ │ │ ├── DeviceAnalogAxisEntry.qml │ │ │ │ ├── DeviceAnalogInputRemappingPage.qml │ │ │ │ ├── DeviceDigitalBindingPage.qml │ │ │ │ ├── DeviceDigitalButtonEntry.qml │ │ │ │ ├── DeviceDigitalInputRemappingPage.qml │ │ │ │ ├── DeviceInputRemappingPage.qml │ │ │ │ ├── DeviceManipulationPage.qml │ │ │ │ ├── DeviceOffsetsPage.qml │ │ │ │ ├── DeviceRenderModelPage.qml │ │ │ │ ├── MotionCompensationPage.qml │ │ │ │ ├── MyComboBox.qml │ │ │ │ ├── MyDialogOkCancelPopup.qml │ │ │ │ ├── MyDialogOkPopup.qml │ │ │ │ ├── MyOffsetGroupBox.qml │ │ │ │ ├── MyPushButton.qml │ │ │ │ ├── MyPushButton2.qml │ │ │ │ ├── MyRangeSlider.qml │ │ │ │ ├── MyResources.qml │ │ │ │ ├── MySlider.qml │ │ │ │ ├── MyStackViewPage.qml │ │ │ │ ├── MyText.qml │ │ │ │ ├── MyTextField.qml │ │ │ │ ├── MyToggleButton.qml │ │ │ │ ├── backarrow.svg │ │ │ │ ├── mainwidget.qml │ │ │ │ └── qmldir │ │ │ ├── thumbicon.png │ │ │ └── transparent.png │ │ └── startdesktopmode.bat │ └── windeployqt.bat ├── client_overlay.pro ├── client_overlay.vcxproj └── src │ ├── logging.h │ ├── main.cpp │ ├── overlaycontroller.cpp │ ├── overlaycontroller.h │ └── tabcontrollers │ ├── AnalogInputRemappingController.cpp │ ├── AnalogInputRemappingController.h │ ├── DeviceManipulationTabController.cpp │ ├── DeviceManipulationTabController.h │ ├── DigitalInputRemappingController.cpp │ └── DigitalInputRemappingController.h ├── docs └── screenshots │ ├── AnalogBindingOpenVRPage.png │ ├── AnalogBindingPage.png │ ├── DeviceManipulationPage.png │ ├── DeviceOffsetsPage.png │ ├── DigitalBindingKeyboardPage.png │ ├── DigitalBindingOpenVRPage.png │ ├── DigitalBindingPage.png │ ├── DigitalInputPage.png │ ├── InVRScreenshot.png │ ├── InputRemappingPage.png │ └── MotionCompensationPage.png ├── driver_vrinputemulator ├── driver.vrdrivermanifest ├── driver_vrinputemulator.vcxproj ├── resources │ ├── driver.vrresources │ ├── settings │ │ └── default.vrsettings │ └── sounds │ │ ├── License.txt │ │ └── audiocue.wav └── src │ ├── com │ └── shm │ │ ├── driver_ipc_shm.cpp │ │ └── driver_ipc_shm.h │ ├── devicemanipulation │ ├── DeviceManipulationHandle.cpp │ ├── DeviceManipulationHandle.h │ ├── MotionCompensationManager.cpp │ ├── MotionCompensationManager.h │ └── utils │ │ ├── KalmanFilter.cpp │ │ ├── KalmanFilter.h │ │ └── MovingAverageRingBuffer.h │ ├── dllmain.cpp │ ├── driver │ ├── ServerDriver.cpp │ ├── ServerDriver.h │ ├── VirtualDeviceDriver.cpp │ ├── VirtualDeviceDriver.h │ ├── WatchdogProvider.cpp │ ├── WatchdogProvider.h │ └── utils │ │ └── DevicePropertyValueVisitor.h │ ├── driver_vrinputemulator.cpp │ ├── hooks │ ├── ITrackedDeviceServerDriver005Hooks.cpp │ ├── ITrackedDeviceServerDriver005Hooks.h │ ├── IVRControllerComponent001Hooks.cpp │ ├── IVRControllerComponent001Hooks.h │ ├── IVRDriverContextHooks.cpp │ ├── IVRDriverContextHooks.h │ ├── IVRDriverInput001Hooks.cpp │ ├── IVRDriverInput001Hooks.h │ ├── IVRProperties001Hooks.cpp │ ├── IVRProperties001Hooks.h │ ├── IVRServerDriverHost004Hooks.cpp │ ├── IVRServerDriverHost004Hooks.h │ ├── IVRServerDriverHost005Hooks.cpp │ ├── IVRServerDriverHost005Hooks.h │ ├── common.cpp │ └── common.h │ └── logging.h ├── installer ├── installer.nsi ├── listUninstallFiles.sh └── uninstallFiles.list ├── lib_vrinputemulator ├── include │ ├── config.h │ ├── ipc_protocol.h │ ├── openvr_math.h │ ├── vrinputemulator.h │ └── vrinputemulator_types.h ├── lib_vrinputemulator.vcxproj └── src │ ├── logging.h │ └── vrinputemulator.cpp ├── scripts └── create_virtual_controller.bat └── third-party ├── MinHook ├── include │ └── MinHook.h ├── lib │ ├── libMinHook-x64-v100-md.lib │ ├── libMinHook-x64-v100-mdd.lib │ ├── libMinHook-x64-v100-mt.lib │ ├── libMinHook-x64-v100-mtd.lib │ ├── libMinHook-x64-v110-md.lib │ ├── libMinHook-x64-v110-mdd.lib │ ├── libMinHook-x64-v110-mt.lib │ ├── libMinHook-x64-v110-mtd.lib │ ├── libMinHook-x64-v120-md.lib │ ├── libMinHook-x64-v120-mdd.lib │ ├── libMinHook-x64-v120-mt.lib │ ├── libMinHook-x64-v120-mtd.lib │ ├── libMinHook-x64-v140-md.lib │ ├── libMinHook-x64-v140-mdd.lib │ ├── libMinHook-x64-v140-mt.lib │ ├── libMinHook-x64-v140-mtd.lib │ ├── libMinHook-x64-v141-md.lib │ ├── libMinHook-x64-v141-mdd.lib │ ├── libMinHook-x64-v141-mt.lib │ ├── libMinHook-x64-v141-mtd.lib │ ├── libMinHook-x64-v90-md.lib │ ├── libMinHook-x64-v90-mdd.lib │ ├── libMinHook-x64-v90-mt.lib │ ├── libMinHook-x64-v90-mtd.lib │ ├── libMinHook-x86-v100-md.lib │ ├── libMinHook-x86-v100-mdd.lib │ ├── libMinHook-x86-v100-mt.lib │ ├── libMinHook-x86-v100-mtd.lib │ ├── libMinHook-x86-v110-md.lib │ ├── libMinHook-x86-v110-mdd.lib │ ├── libMinHook-x86-v110-mt.lib │ ├── libMinHook-x86-v110-mtd.lib │ ├── libMinHook-x86-v120-md.lib │ ├── libMinHook-x86-v120-mdd.lib │ ├── libMinHook-x86-v120-mt.lib │ ├── libMinHook-x86-v120-mtd.lib │ ├── libMinHook-x86-v140-md.lib │ ├── libMinHook-x86-v140-mdd.lib │ ├── libMinHook-x86-v140-mt.lib │ ├── libMinHook-x86-v140-mtd.lib │ ├── libMinHook-x86-v141-md.lib │ ├── libMinHook-x86-v141-mdd.lib │ ├── libMinHook-x86-v141-mt.lib │ ├── libMinHook-x86-v141-mtd.lib │ ├── libMinHook-x86-v90-md.lib │ ├── libMinHook-x86-v90-mdd.lib │ ├── libMinHook-x86-v90-mt.lib │ └── libMinHook-x86-v90-mtd.lib └── readme.txt └── easylogging++ ├── LICENSE └── easylogging++.h /.gitignore: -------------------------------------------------------------------------------- 1 | /third-party/LeapSDK/* 2 | /third-party/boost_1_63_0/* 3 | /build/* 4 | /Release/* 5 | /Debug/* 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "openvr"] 2 | path = openvr 3 | url = https://github.com/ValveSoftware/openvr.git 4 | -------------------------------------------------------------------------------- /VRInputEmulator.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.24720.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib_vrinputemulator", "lib_vrinputemulator\lib_vrinputemulator.vcxproj", "{05AC9994-2B63-4DE5-ABF3-95CE346F3A64}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "driver_vrinputemulator", "driver_vrinputemulator\driver_vrinputemulator.vcxproj", "{AF6FBE95-527D-499B-9ABD-3A47E9E84C8A}" 9 | ProjectSection(ProjectDependencies) = postProject 10 | {05AC9994-2B63-4DE5-ABF3-95CE346F3A64} = {05AC9994-2B63-4DE5-ABF3-95CE346F3A64} 11 | EndProjectSection 12 | EndProject 13 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "client_leapmotion", "client_leapmotion\client_leapmotion.vcxproj", "{329C6147-E62D-456F-8860-A2DD91B113B5}" 14 | EndProject 15 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "client_commandline", "client_commandline\client_commandline.vcxproj", "{C4680CF3-74B7-4A1C-9762-1124E7B10634}" 16 | EndProject 17 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "client_overlay", "client_overlay\client_overlay.vcxproj", "{33E075DB-922D-3252-976E-46B5721DC3DE}" 18 | EndProject 19 | Global 20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 21 | Debug|x64 = Debug|x64 22 | Debug|x86 = Debug|x86 23 | Release|x64 = Release|x64 24 | Release|x86 = Release|x86 25 | EndGlobalSection 26 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 27 | {05AC9994-2B63-4DE5-ABF3-95CE346F3A64}.Debug|x64.ActiveCfg = Debug|x64 28 | {05AC9994-2B63-4DE5-ABF3-95CE346F3A64}.Debug|x64.Build.0 = Debug|x64 29 | {05AC9994-2B63-4DE5-ABF3-95CE346F3A64}.Debug|x86.ActiveCfg = Debug|Win32 30 | {05AC9994-2B63-4DE5-ABF3-95CE346F3A64}.Debug|x86.Build.0 = Debug|Win32 31 | {05AC9994-2B63-4DE5-ABF3-95CE346F3A64}.Release|x64.ActiveCfg = Release|x64 32 | {05AC9994-2B63-4DE5-ABF3-95CE346F3A64}.Release|x64.Build.0 = Release|x64 33 | {05AC9994-2B63-4DE5-ABF3-95CE346F3A64}.Release|x86.ActiveCfg = Release|Win32 34 | {05AC9994-2B63-4DE5-ABF3-95CE346F3A64}.Release|x86.Build.0 = Release|Win32 35 | {AF6FBE95-527D-499B-9ABD-3A47E9E84C8A}.Debug|x64.ActiveCfg = Debug|x64 36 | {AF6FBE95-527D-499B-9ABD-3A47E9E84C8A}.Debug|x64.Build.0 = Debug|x64 37 | {AF6FBE95-527D-499B-9ABD-3A47E9E84C8A}.Debug|x86.ActiveCfg = Debug|Win32 38 | {AF6FBE95-527D-499B-9ABD-3A47E9E84C8A}.Debug|x86.Build.0 = Debug|Win32 39 | {AF6FBE95-527D-499B-9ABD-3A47E9E84C8A}.Release|x64.ActiveCfg = Release|x64 40 | {AF6FBE95-527D-499B-9ABD-3A47E9E84C8A}.Release|x64.Build.0 = Release|x64 41 | {AF6FBE95-527D-499B-9ABD-3A47E9E84C8A}.Release|x86.ActiveCfg = Release|Win32 42 | {AF6FBE95-527D-499B-9ABD-3A47E9E84C8A}.Release|x86.Build.0 = Release|Win32 43 | {329C6147-E62D-456F-8860-A2DD91B113B5}.Debug|x64.ActiveCfg = Debug|x64 44 | {329C6147-E62D-456F-8860-A2DD91B113B5}.Debug|x64.Build.0 = Debug|x64 45 | {329C6147-E62D-456F-8860-A2DD91B113B5}.Debug|x86.ActiveCfg = Debug|Win32 46 | {329C6147-E62D-456F-8860-A2DD91B113B5}.Debug|x86.Build.0 = Debug|Win32 47 | {329C6147-E62D-456F-8860-A2DD91B113B5}.Release|x64.ActiveCfg = Release|x64 48 | {329C6147-E62D-456F-8860-A2DD91B113B5}.Release|x64.Build.0 = Release|x64 49 | {329C6147-E62D-456F-8860-A2DD91B113B5}.Release|x86.ActiveCfg = Release|Win32 50 | {329C6147-E62D-456F-8860-A2DD91B113B5}.Release|x86.Build.0 = Release|Win32 51 | {C4680CF3-74B7-4A1C-9762-1124E7B10634}.Debug|x64.ActiveCfg = Debug|x64 52 | {C4680CF3-74B7-4A1C-9762-1124E7B10634}.Debug|x64.Build.0 = Debug|x64 53 | {C4680CF3-74B7-4A1C-9762-1124E7B10634}.Debug|x86.ActiveCfg = Debug|Win32 54 | {C4680CF3-74B7-4A1C-9762-1124E7B10634}.Debug|x86.Build.0 = Debug|Win32 55 | {C4680CF3-74B7-4A1C-9762-1124E7B10634}.Release|x64.ActiveCfg = Release|x64 56 | {C4680CF3-74B7-4A1C-9762-1124E7B10634}.Release|x64.Build.0 = Release|x64 57 | {C4680CF3-74B7-4A1C-9762-1124E7B10634}.Release|x86.ActiveCfg = Release|Win32 58 | {C4680CF3-74B7-4A1C-9762-1124E7B10634}.Release|x86.Build.0 = Release|Win32 59 | {33E075DB-922D-3252-976E-46B5721DC3DE}.Debug|x64.ActiveCfg = Debug|x64 60 | {33E075DB-922D-3252-976E-46B5721DC3DE}.Debug|x64.Build.0 = Debug|x64 61 | {33E075DB-922D-3252-976E-46B5721DC3DE}.Debug|x86.ActiveCfg = Debug|x64 62 | {33E075DB-922D-3252-976E-46B5721DC3DE}.Release|x64.ActiveCfg = Release|x64 63 | {33E075DB-922D-3252-976E-46B5721DC3DE}.Release|x64.Build.0 = Release|x64 64 | {33E075DB-922D-3252-976E-46B5721DC3DE}.Release|x86.ActiveCfg = Release|x64 65 | EndGlobalSection 66 | GlobalSection(SolutionProperties) = preSolution 67 | HideSolutionNode = FALSE 68 | EndGlobalSection 69 | EndGlobal 70 | -------------------------------------------------------------------------------- /client_commandline/src/client_commandline.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | void listDevices(int argc, const char* argv[]); 5 | 6 | void buttonEvent(int argc, const char* argv[]); 7 | 8 | void axisEvent(int argc, const char* argv[]); 9 | 10 | void proximitySensorEvent(int argc, const char* argv[]); 11 | 12 | void listVirtual(int argc, const char* argv[]); 13 | 14 | void addTrackedController(int argc, const char* argv[]); 15 | 16 | void publishTrackedDevice(int argc, const char* argv[]); 17 | 18 | void setDeviceProperty(int argc, const char* argv[]); 19 | 20 | void getDeviceProperty(int argc, const char* argv[]); 21 | 22 | void removeDeviceProperty(int argc, const char* argv[]); 23 | 24 | void setDeviceConnection(int argc, const char* argv[]); 25 | 26 | void setDevicePosition(int argc, const char* argv[]); 27 | 28 | void setDeviceRotation(int argc, const char* argv[]); 29 | 30 | void deviceOffsets(int argc, const char* argv[]); 31 | 32 | void benchmarkIPC(int argc, const char* argv[]); 33 | -------------------------------------------------------------------------------- /client_commandline/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "client_commandline.h" 4 | 5 | #include 6 | 7 | 8 | void printHelp(int argc, const char* argv[]) { 9 | std::cout << "Usage: client_commandline.exe ..." << std::endl << std::endl 10 | << "Available commands (enter \" help\" for help):" << std::endl << std::endl 11 | << " listdevices\t\t\tLists all openvr devices" << std::endl 12 | << " buttonevent\t\t\tSends button event" << std::endl 13 | << " axisevent\t\t\tSends axis event" << std::endl 14 | << " proximitysensor\t\tSends proximity sensor event" << std::endl 15 | << " getdeviceproperty\t\tReturns a device property" << std::endl 16 | << " listvirtual\t\t\tLists all virtual devices" << std::endl 17 | << " addcontroller\t\t\tCreates a new virtual controller" << std::endl 18 | << " publishdevice\t\t\tAdds a virtual controller to openvr" << std::endl 19 | << " setdeviceproperty\t\tSets a device property" << std::endl 20 | << " removedeviceproperty\t\tRemoves a device property" << std::endl 21 | << " setdeviceconnection\t\tSets the connection state of a virtual device" << std::endl 22 | << " setdeviceposition\t\tSets the position of a virtual device" << std::endl 23 | << " setdevicerotation\t\tSets the rotation of a virtual device" << std::endl 24 | << " deviceoffsets\t\t\tConfigure the device translation/rotation offsets" << std::endl 25 | << " benchmarkipc\t\t\tipc benchmarks" << std::endl; 26 | } 27 | 28 | 29 | int main(int argc, const char* argv[]) { 30 | int retval = 0; 31 | if (argc <= 1) { 32 | std::cout << "Error: No Arguments given." << std::endl; 33 | printHelp(argc, argv); 34 | exit(1); 35 | } 36 | 37 | try { 38 | if (argc == 1 || std::strcmp(argv[1], "help") == 0) { 39 | printHelp(argc, argv); 40 | } else if (std::strcmp(argv[1], "listdevices") == 0) { 41 | listDevices(argc, argv); 42 | } else if (std::strcmp(argv[1], "buttonevent") == 0) { 43 | buttonEvent(argc, argv); 44 | } else if (std::strcmp(argv[1], "axisevent") == 0) { 45 | axisEvent(argc, argv); 46 | } else if (std::strcmp(argv[1], "proximitysensor") == 0) { 47 | proximitySensorEvent(argc, argv); 48 | } else if (std::strcmp(argv[1], "listvirtual") == 0) { 49 | listVirtual(argc, argv); 50 | } else if (std::strcmp(argv[1], "addcontroller") == 0) { 51 | addTrackedController(argc, argv); 52 | } else if (std::strcmp(argv[1], "publishdevice") == 0) { 53 | publishTrackedDevice(argc, argv); 54 | } else if (std::strcmp(argv[1], "setdeviceproperty") == 0) { 55 | setDeviceProperty(argc, argv); 56 | } else if (std::strcmp(argv[1], "getdeviceproperty") == 0) { 57 | getDeviceProperty(argc, argv); 58 | } else if (std::strcmp(argv[1], "removedeviceproperty") == 0) { 59 | removeDeviceProperty(argc, argv); 60 | } else if (std::strcmp(argv[1], "setdeviceconnection") == 0) { 61 | setDeviceConnection(argc, argv); 62 | } else if (std::strcmp(argv[1], "setdeviceposition") == 0) { 63 | setDevicePosition(argc, argv); 64 | } else if (std::strcmp(argv[1], "setdevicerotation") == 0) { 65 | setDeviceRotation(argc, argv); 66 | } else if (std::strcmp(argv[1], "deviceoffsets") == 0) { 67 | deviceOffsets(argc, argv); 68 | } else if (std::strcmp(argv[1], "benchmarkipc") == 0) { 69 | benchmarkIPC(argc, argv); 70 | } else { 71 | throw std::runtime_error("Error: Unknown command."); 72 | } 73 | } catch (const std::exception& e) { 74 | std::cout << e.what() << std::endl; 75 | retval = 3; 76 | } 77 | 78 | return retval; 79 | } 80 | 81 | -------------------------------------------------------------------------------- /client_leapmotion/src/LeapMotionClient.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | class LeapMotionClient : public Leap::Listener { 9 | private: 10 | Leap::Controller* leapController; 11 | vrinputemulator::VRInputEmulator* inputEmulator; 12 | 13 | 14 | uint32_t virtualIdLeft; 15 | bool leftReadyFlag = false; 16 | vr::DriverPose_t leftPose; 17 | vr::VRControllerState_t leftState; 18 | double leftTranslationOffset[3] = {0.0, 0.0, -0.15}; 19 | vr::HmdQuaternion_t leftRotationOffset = vrmath::quaternionFromYawPitchRoll(0.0f, -0.1f, 0.0f); 20 | 21 | uint32_t virtualIdRight; 22 | bool rightReadyFlag = false; 23 | vr::DriverPose_t rightPose; 24 | vr::VRControllerState_t rightState; 25 | double rightTranslationOffset[3] = { 0.0, 0.0, -0.15 }; 26 | vr::HmdQuaternion_t rightRotationOffset = vrmath::quaternionFromYawPitchRoll(0.0f, -0.1f, 0.0f); 27 | 28 | public: 29 | LeapMotionClient(Leap::Controller* leapController, vrinputemulator::VRInputEmulator* inputEmulator); 30 | ~LeapMotionClient(); 31 | 32 | virtual void onFrame(const Leap::Controller &) override; 33 | }; 34 | 35 | -------------------------------------------------------------------------------- /client_leapmotion/src/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "LeapMotionClient.h" 8 | 9 | 10 | int main() { 11 | 12 | Leap::Controller leapController; 13 | leapController.setPolicy(Leap::Controller::POLICY_OPTIMIZE_HMD); 14 | leapController.setPolicy(Leap::Controller::POLICY_BACKGROUND_FRAMES); 15 | if (leapController.isServiceConnected()) { 16 | std::cout << "Leap Motion Service not running." << std::endl; 17 | exit(-1); 18 | } 19 | 20 | vr::EVRInitError peError; 21 | vr::VR_Init(&peError, vr::VRApplication_Overlay); 22 | if (peError != vr::VRInitError_None) { 23 | std::cout << "OpenVR Error: " << vr::VR_GetVRInitErrorAsEnglishDescription(peError) << std::endl; 24 | exit(-2); 25 | } 26 | 27 | vrinputemulator::VRInputEmulator inputEmulator; 28 | try { 29 | inputEmulator.connect(); 30 | } catch (std::exception& e) { 31 | std::cout << "Caught exception: " << e.what() << std::endl; 32 | exit(-3); 33 | } 34 | 35 | LeapMotionClient leapClient(&leapController, &inputEmulator); 36 | leapController.addListener(leapClient); 37 | 38 | vr::VREvent_t vrevent; 39 | bool stopLoop = false; 40 | while(!stopLoop) { 41 | if (vr::VRSystem()->PollNextEvent(&vrevent, sizeof(vr::VREvent_t))) { 42 | if (vrevent.eventType == vr::VREvent_Quit) { 43 | stopLoop = true; 44 | } 45 | } else { 46 | std::this_thread::sleep_for(std::chrono::milliseconds(10)); 47 | } 48 | } 49 | 50 | leapController.removeListener(leapClient); 51 | vr::VR_Shutdown(); 52 | 53 | return 0; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /client_leapmotion/src/utils/Matrix.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | namespace utils { 8 | 9 | inline vr::HmdMatrix34_t& initRotationMatrix(vr::HmdMatrix34_t& matrix, unsigned axisId, float angle) { 10 | switch (axisId) { 11 | case 0: // x-axis 12 | matrix.m[0][0] = 1.0f; 13 | matrix.m[0][1] = 0.0f; 14 | matrix.m[0][2] = 0.0f; 15 | matrix.m[0][3] = 0.0f; 16 | matrix.m[1][0] = 0.0f; 17 | matrix.m[1][1] = std::cos(angle); 18 | matrix.m[1][2] = -std::sin(angle); 19 | matrix.m[1][3] = 0.0f; 20 | matrix.m[2][0] = 0.0f; 21 | matrix.m[2][1] = std::sin(angle); 22 | matrix.m[2][2] = std::cos(angle); 23 | matrix.m[2][3] = 0.0f; 24 | break; 25 | case 1: // y-axis 26 | matrix.m[0][0] = std::cos(angle); 27 | matrix.m[0][1] = 0.0f; 28 | matrix.m[0][2] = std::sin(angle); 29 | matrix.m[0][3] = 0.0f; 30 | matrix.m[1][0] = 0.0f; 31 | matrix.m[1][1] = 1.0f; 32 | matrix.m[1][2] = 0.0f; 33 | matrix.m[1][3] = 0.0f; 34 | matrix.m[2][0] = -std::sin(angle); 35 | matrix.m[2][1] = 0.0f; 36 | matrix.m[2][2] = std::cos(angle); 37 | matrix.m[2][3] = 0.0f; 38 | break; 39 | case 2: // z-axis 40 | matrix.m[0][0] = std::cos(angle); 41 | matrix.m[0][1] = -std::sin(angle); 42 | matrix.m[0][2] = 0.0f; 43 | matrix.m[0][3] = 0.0f; 44 | matrix.m[1][0] = std::sin(angle); 45 | matrix.m[1][1] = std::cos(angle); 46 | matrix.m[1][2] = 0.0f; 47 | matrix.m[1][3] = 0.0f; 48 | matrix.m[2][0] = 0.0f; 49 | matrix.m[2][1] = 0.0f; 50 | matrix.m[2][2] = 1.0f; 51 | matrix.m[2][3] = 0.0f; 52 | break; 53 | default: 54 | break; 55 | } 56 | return matrix; 57 | } 58 | 59 | 60 | inline vr::HmdMatrix34_t& matMul33(vr::HmdMatrix34_t& result, const vr::HmdMatrix34_t& a, const vr::HmdMatrix34_t& b) { 61 | for (unsigned i = 0; i < 3; i++) { 62 | for (unsigned j = 0; j < 3; j++) { 63 | result.m[i][j] = 0.0f; 64 | for (unsigned k = 0; k < 3; k++) { 65 | result.m[i][j] += a.m[i][k] * b.m[k][j]; 66 | } 67 | } 68 | } 69 | return result; 70 | } 71 | 72 | 73 | inline vr::HmdVector3_t& matMul33(vr::HmdVector3_t& result, const vr::HmdMatrix34_t& a, const vr::HmdVector3_t& b) { 74 | for (unsigned i = 0; i < 3; i++) { 75 | result.v[i] = 0.0f; 76 | for (unsigned k = 0; k < 3; k++) { 77 | result.v[i] += a.m[i][k] * b.v[k]; 78 | }; 79 | } 80 | return result; 81 | } 82 | 83 | 84 | inline vr::HmdVector3_t& matMul33(vr::HmdVector3_t& result, const vr::HmdVector3_t& a, const vr::HmdMatrix34_t& b) { 85 | for (unsigned i = 0; i < 3; i++) { 86 | result.v[i] = 0.0f; 87 | for (unsigned k = 0; k < 3; k++) { 88 | result.v[i] += a.v[k] * b.m[k][i]; 89 | }; 90 | } 91 | return result; 92 | } 93 | 94 | 95 | 96 | } // end namespace utils 97 | 98 | -------------------------------------------------------------------------------- /client_overlay/bin/logging.conf.installer: -------------------------------------------------------------------------------- 1 | * GLOBAL: 2 | FORMAT = "[%level] %datetime{%Y-%M-%d %H:%m:%s}: %msg" 3 | ENABLED = true 4 | TO_FILE = true 5 | TO_STANDARD_OUTPUT = true 6 | MAX_LOG_FILE_SIZE = 2097152 ## 2MB 7 | * DEBUG: 8 | ENABLED = false 9 | * TRACE: 10 | ENABLED = false 11 | -------------------------------------------------------------------------------- /client_overlay/bin/logging.conf.standalone: -------------------------------------------------------------------------------- 1 | * GLOBAL: 2 | FORMAT = "[%level] %datetime{%Y-%M-%d %H:%m:%s}: %msg" 3 | FILENAME = "OpenVR-InputEmulatorOverlay.log" 4 | ENABLED = true 5 | TO_FILE = true 6 | TO_STANDARD_OUTPUT = true 7 | MAX_LOG_FILE_SIZE = 2097152 ## 2MB 8 | * DEBUG: 9 | ENABLED = false 10 | * TRACE: 11 | ENABLED = false 12 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/logging.conf: -------------------------------------------------------------------------------- 1 | * GLOBAL: 2 | FORMAT = "[%level] %datetime{%Y-%M-%d %H:%m:%s}: %msg" 3 | ENABLED = true 4 | TO_FILE = true 5 | TO_STANDARD_OUTPUT = true 6 | MAX_LOG_FILE_SIZE = 2097152 ## 2MB 7 | * DEBUG: 8 | ENABLED = false 9 | * TRACE: 10 | ENABLED = false 11 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/manifest.vrmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "source" : "builtin", 3 | "applications": [{ 4 | "app_key": "matzman666.VRInputEmulator", 5 | "launch_type": "binary", 6 | "binary_path_windows": "OpenVR-InputEmulatorOverlay.exe", 7 | "is_dashboard_overlay": true, 8 | 9 | "strings": { 10 | "en_us": { 11 | "name": "VR Input Emulator", 12 | "description": "OpenVR Input Emulator Overlay" 13 | } 14 | } 15 | }] 16 | } -------------------------------------------------------------------------------- /client_overlay/bin/win64/openvr_api.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/client_overlay/bin/win64/openvr_api.dll -------------------------------------------------------------------------------- /client_overlay/bin/win64/qt.conf: -------------------------------------------------------------------------------- 1 | [Paths] 2 | Prefix = qtdata 3 | Qml2Imports = . 4 | Imports = . 5 | [Platforms] 6 | WindowsArguments = dpiawareness=0 7 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/qml/DeviceAnalogAxisEntry.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9; 2 | import QtQuick.Controls 2.2; 3 | import QtQuick.Layouts 1.3; 4 | import matzman666.inputemulator 1.0 5 | 6 | RowLayout { 7 | 8 | property string axisName: "" 9 | property string axisStatus: "" 10 | property int deviceIndex: -1 11 | property int axisId: -1 12 | 13 | MyText { 14 | Layout.preferredWidth: 270 15 | text: axisName 16 | } 17 | MyPushButton { 18 | id: configButton 19 | Layout.preferredWidth: 840 20 | text: axisStatus 21 | onClicked: { 22 | DeviceManipulationTabController.startConfigureAnalogInputRemapping(deviceIndex, axisId) 23 | deviceAnalogInputRemappingPage.setDeviceIndex(deviceIndex, axisId) 24 | MyResources.playFocusChangedSound() 25 | var res = mainView.push(deviceAnalogInputRemappingPage) 26 | } 27 | } 28 | 29 | Connections { 30 | target: DeviceManipulationTabController 31 | onConfigureAnalogInputRemappingFinished: { 32 | axisStatus = DeviceManipulationTabController.getAnalogAxisStatus(deviceIndex, axisId); 33 | configButton.text = axisStatus 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/qml/DeviceDigitalButtonEntry.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9; 2 | import QtQuick.Controls 2.2; 3 | import QtQuick.Layouts 1.3; 4 | import matzman666.inputemulator 1.0 5 | 6 | RowLayout { 7 | 8 | property string buttonName: "" 9 | property string buttonStatus: "" 10 | property int deviceIndex: -1 11 | property int buttonId: -1 12 | 13 | MyText { 14 | Layout.preferredWidth: 270 15 | text: buttonName 16 | } 17 | MyPushButton { 18 | id: configButton 19 | Layout.preferredWidth: 840 20 | text: buttonStatus 21 | onClicked: { 22 | DeviceManipulationTabController.startConfigureDigitalInputRemapping(deviceIndex, buttonId) 23 | deviceDigitalInputRemappingPage.setDeviceIndex(deviceIndex, buttonId) 24 | MyResources.playFocusChangedSound() 25 | var res = mainView.push(deviceDigitalInputRemappingPage) 26 | } 27 | } 28 | 29 | Connections { 30 | target: DeviceManipulationTabController 31 | onConfigureDigitalInputRemappingFinished: { 32 | buttonStatus = DeviceManipulationTabController.getDigitalButtonStatus(deviceIndex, buttonId); 33 | configButton.text = buttonStatus 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/qml/DeviceInputRemappingPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Controls 2.2 3 | import QtQuick.Layouts 1.3 4 | import QtQuick.Dialogs 1.2 5 | import matzman666.inputemulator 1.0 6 | 7 | MyStackViewPage { 8 | id: deviceInputRemappingPage 9 | 10 | headerText: "Input Remapping Settings " 11 | 12 | property int deviceIndex: -1 13 | 14 | property var objects: [] 15 | 16 | property var _digitalButtonComponent: Qt.createComponent("DeviceDigitalButtonEntry.qml") 17 | property var _analogAxisComponent: Qt.createComponent("DeviceAnalogAxisEntry.qml") 18 | 19 | function createDigitalButton(i, buttonId) { 20 | var buttonName = DeviceManipulationTabController.getDigitalButtonName(deviceIndex, buttonId); 21 | var buttonStatus = DeviceManipulationTabController.getDigitalButtonStatus(deviceIndex, buttonId); 22 | var obj = _digitalButtonComponent.createObject(digitalButtonContainer, { 23 | "buttonName": buttonName, 24 | "buttonStatus": buttonStatus, 25 | "deviceIndex": deviceIndex, 26 | "buttonId": buttonId 27 | }); 28 | if (obj == null) { 29 | console.log("Error creating object"); 30 | } 31 | objects.push(obj) 32 | } 33 | 34 | function createAnalogAxis(i, axisId) { 35 | var axisName = DeviceManipulationTabController.getAnalogAxisName(deviceIndex, axisId); 36 | var axisStatus = DeviceManipulationTabController.getAnalogAxisStatus(deviceIndex, axisId); 37 | var obj = _analogAxisComponent.createObject(analogAxisContainer, { 38 | "axisName": axisName, 39 | "axisStatus": axisStatus, 40 | "deviceIndex": deviceIndex, 41 | "axisId": axisId 42 | }); 43 | if (obj == null) { 44 | console.log("Error creating object"); 45 | } 46 | objects.push(obj) 47 | } 48 | 49 | function deleteObjects() { 50 | for (var i = 0; i < objects.length; i++) { 51 | objects[i].destroy() 52 | } 53 | objects = [] 54 | } 55 | 56 | function setDeviceIndex(index) { 57 | deviceIndex = index 58 | deleteObjects() 59 | var buttonCount = DeviceManipulationTabController.getDigitalButtonCount(index); 60 | if (buttonCount > 0) { 61 | digitalInputHeader.visible = true 62 | for (var i = 0; i < buttonCount; i++) { 63 | var buttonId = DeviceManipulationTabController.getDigitalButtonId(index, i); 64 | createDigitalButton(i, buttonId) 65 | } 66 | } else { 67 | digitalInputHeader.visible = false 68 | } 69 | var axisCount = DeviceManipulationTabController.getAnalogAxisCount(index); 70 | if (axisCount > 0) { 71 | analogInputHeader.visible = true 72 | for (var i = 0; i < axisCount; i++) { 73 | var axisId = DeviceManipulationTabController.getAnalogAxisId(index, i); 74 | createAnalogAxis(i, axisId) 75 | } 76 | } else { 77 | analogInputHeader.visible = false 78 | } 79 | if (buttonCount == 0 && axisCount == 0) { 80 | noInputsLabel.visible = true 81 | } else { 82 | noInputsLabel.visible = false 83 | } 84 | } 85 | 86 | function updateRemappingStatus() { 87 | 88 | } 89 | 90 | content: ColumnLayout { 91 | spacing: 18 92 | 93 | MyText { 94 | id: noInputsLabel 95 | visible: false 96 | text: "No Inputs" 97 | } 98 | 99 | ScrollView { 100 | ScrollBar.vertical.policy: ScrollBar.AsNeeded 101 | ScrollBar.vertical.width: 25 102 | Layout.fillWidth: true 103 | Layout.fillHeight: true 104 | clip: true 105 | ColumnLayout { 106 | spacing: 24 107 | 108 | RowLayout { 109 | id: digitalInputHeader 110 | visible: false 111 | Layout.topMargin: 32 112 | Layout.leftMargin: 250 113 | Rectangle { 114 | Layout.rightMargin: 10 115 | color: "#ffffff" 116 | height: 1 117 | width: 200 118 | } 119 | MyText { 120 | text: "Digital Inputs" 121 | } 122 | Rectangle { 123 | Layout.leftMargin: 10 124 | color: "#ffffff" 125 | height: 1 126 | width: 200 127 | } 128 | } 129 | 130 | ColumnLayout { 131 | id: digitalButtonContainer 132 | spacing: 18 133 | } 134 | 135 | RowLayout { 136 | id: analogInputHeader 137 | visible: false 138 | Layout.topMargin: 32 139 | Layout.leftMargin: 250 140 | Rectangle { 141 | Layout.rightMargin: 10 142 | color: "#ffffff" 143 | height: 1 144 | width: 200 145 | } 146 | MyText { 147 | text: "Analog Inputs" 148 | } 149 | Rectangle { 150 | Layout.leftMargin: 10 151 | color: "#ffffff" 152 | height: 1 153 | width: 200 154 | } 155 | } 156 | 157 | ColumnLayout { 158 | id: analogAxisContainer 159 | spacing: 24 160 | } 161 | } 162 | } 163 | 164 | 165 | Item { 166 | Layout.fillWidth: true 167 | Layout.fillHeight: true 168 | } 169 | 170 | Component.onCompleted: { 171 | } 172 | 173 | } 174 | 175 | } 176 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/qml/DeviceRenderModelPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Controls 2.0 3 | import QtQuick.Layouts 1.3 4 | import QtQuick.Dialogs 1.2 5 | import matzman666.inputemulator 1.0 6 | 7 | MyStackViewPage { 8 | id: deviceRenderModelPage 9 | 10 | headerText: "Render Model Settings" 11 | 12 | property int deviceIndex: -1 13 | 14 | function setDeviceIndex(index) { 15 | deviceIndex = index 16 | var renderModelCount = DeviceManipulationTabController.getRenderModelCount() 17 | var renderModels = [""] 18 | for (var i = 0; i < renderModelCount; i++) { 19 | renderModels.push(DeviceManipulationTabController.getRenderModelName(i)) 20 | deviceRenderModelComboBox.model = renderModels 21 | } 22 | } 23 | 24 | content: ColumnLayout { 25 | spacing: 18 26 | 27 | RowLayout { 28 | spacing: 18 29 | 30 | MyText { 31 | text: "Render Model:" 32 | } 33 | 34 | MyComboBox { 35 | id: deviceRenderModelComboBox 36 | Layout.maximumWidth: 910 37 | Layout.minimumWidth: 910 38 | Layout.preferredWidth: 910 39 | Layout.fillWidth: true 40 | model: [""] 41 | onCurrentIndexChanged: { 42 | } 43 | } 44 | } 45 | 46 | Item { 47 | Layout.fillWidth: true 48 | Layout.fillHeight: true 49 | } 50 | 51 | RowLayout { 52 | spacing: 18 53 | 54 | Item { 55 | Layout.fillWidth: true 56 | } 57 | 58 | MyPushButton { 59 | id: deviceRenderModelButton 60 | Layout.preferredWidth: 194 61 | Layout.rightMargin: 32 62 | text: "Save" 63 | onClicked: { 64 | DeviceManipulationTabController.setDeviceRenderModel(deviceIndex, deviceRenderModelComboBox.currentIndex) 65 | } 66 | } 67 | } 68 | 69 | 70 | Component.onCompleted: { 71 | } 72 | 73 | Connections { 74 | target: DeviceManipulationTabController 75 | } 76 | 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/qml/MyComboBox.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Controls 2.0 3 | import "." // QTBUG-34418, singletons require explicit import to load qmldir file 4 | 5 | 6 | ComboBox { 7 | id: myComboBox 8 | hoverEnabled: true 9 | 10 | background: Rectangle { 11 | color: parent.pressed ? "#406288" : (parent.activeFocus ? "#365473" : "#2c435d") 12 | } 13 | 14 | contentItem: MyText { 15 | leftPadding: 0 16 | rightPadding: parent.indicator.width + parent.spacing 17 | text: parent.displayText 18 | horizontalAlignment: Text.AlignLeft 19 | verticalAlignment: Text.AlignVCenter 20 | elide: Text.ElideRight 21 | } 22 | 23 | delegate: ItemDelegate { 24 | width: myComboBox.width 25 | text: modelData 26 | hoverEnabled: true 27 | contentItem: MyText { 28 | horizontalAlignment: Text.AlignLeft 29 | verticalAlignment: Text.AlignVCenter 30 | text: parent.text 31 | color: parent.enabled ? "#ffffff" : "#909090" 32 | } 33 | background: Rectangle { 34 | color: parent.pressed ? "#406288" : (parent.hovered ? "#365473" : "#2c435d") 35 | } 36 | } 37 | 38 | indicator: Canvas { 39 | x: parent.width - width - parent.rightPadding 40 | y: parent.topPadding + (parent.availableHeight - height) / 2 41 | width: 13 42 | height: 7 43 | contextType: "2d" 44 | 45 | onPaint: { 46 | if (!context) { 47 | getContext("2d") 48 | } 49 | context.reset(); 50 | context.lineWidth = 2 51 | context.moveTo(1, 1); 52 | context.lineTo(Math.ceil(width / 2), height - 1); 53 | context.lineTo(width - 1, 1); 54 | context.strokeStyle = "#ffffff" 55 | context.stroke() 56 | } 57 | } 58 | 59 | onHoveredChanged: { 60 | if (hovered) { 61 | forceActiveFocus() 62 | } 63 | } 64 | 65 | onActivated: { 66 | if (activeFocus) { 67 | MyResources.playActivationSound() 68 | } 69 | } 70 | 71 | Component.onCompleted: { 72 | popup.background.color = "#2c435d" 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/qml/MyDialogOkCancelPopup.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Controls 2.0 3 | import QtQuick.Layouts 1.3 4 | 5 | Popup { 6 | id: myDialogPopup 7 | 8 | implicitHeight: parent.height 9 | implicitWidth: parent.width 10 | 11 | property string dialogTitle: "" 12 | property string dialogText: "" 13 | property int dialogWidth: 600 14 | property int dialogHeight: 300 15 | 16 | property Item dialogContentItem: MyText { 17 | text: dialogText 18 | horizontalAlignment: Text.AlignHCenter 19 | verticalAlignment: Text.AlignVCenter 20 | Layout.fillWidth: true 21 | } 22 | 23 | property bool okClicked: false 24 | 25 | closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent 26 | 27 | background: Rectangle { 28 | color: "black" 29 | opacity: 0.8 30 | } 31 | 32 | contentItem: Item { 33 | Rectangle { 34 | implicitWidth: dialogWidth 35 | implicitHeight: dialogHeight 36 | anchors.centerIn: parent 37 | radius: 24 38 | color: "#1b2939" 39 | border.color: "#cccccc" 40 | border.width: 2 41 | ColumnLayout { 42 | anchors.fill: parent 43 | anchors.margins: 12 44 | MyText { 45 | Layout.leftMargin: 16 46 | Layout.rightMargin: 16 47 | text: dialogTitle 48 | } 49 | Rectangle { 50 | color: "#cccccc" 51 | height: 1 52 | Layout.fillWidth: true 53 | } 54 | Item { 55 | Layout.fillHeight: true 56 | Layout.fillWidth: true 57 | } 58 | ColumnLayout { 59 | id: dialogContent 60 | } 61 | Item { 62 | Layout.fillHeight: true 63 | Layout.fillWidth: true 64 | } 65 | RowLayout { 66 | Layout.fillWidth: true 67 | Layout.leftMargin: 24 68 | Layout.rightMargin: 24 69 | Layout.bottomMargin: 12 70 | MyPushButton { 71 | implicitWidth: 200 72 | text: "Ok" 73 | onClicked: { 74 | okClicked = true 75 | myDialogPopup.close() 76 | } 77 | } 78 | Item { 79 | Layout.fillWidth: true 80 | } 81 | MyPushButton { 82 | implicitWidth: 200 83 | text: "Cancel" 84 | onClicked: { 85 | okClicked = false 86 | myDialogPopup.close() 87 | } 88 | } 89 | } 90 | } 91 | } 92 | } 93 | 94 | Component.onCompleted: { 95 | dialogContentItem.parent = dialogContent 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/qml/MyDialogOkPopup.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Controls 2.0 3 | import QtQuick.Layouts 1.3 4 | 5 | Popup { 6 | id: myDialogPopup 7 | 8 | implicitHeight: parent.height 9 | implicitWidth: parent.width 10 | 11 | property string dialogTitle: "" 12 | property string dialogText: "" 13 | property int dialogWidth: 600 14 | property int dialogHeight: 300 15 | 16 | property Item dialogContentItem: MyText { 17 | text: dialogText 18 | horizontalAlignment: Text.AlignHCenter 19 | verticalAlignment: Text.AlignVCenter 20 | Layout.fillWidth: true 21 | } 22 | 23 | property bool okClicked: false 24 | 25 | closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent 26 | 27 | background: Rectangle { 28 | color: "black" 29 | opacity: 0.8 30 | } 31 | 32 | contentItem: Item { 33 | Rectangle { 34 | implicitWidth: dialogWidth 35 | implicitHeight: dialogHeight 36 | anchors.centerIn: parent 37 | radius: 24 38 | color: "#1b2939" 39 | border.color: "#cccccc" 40 | border.width: 2 41 | ColumnLayout { 42 | anchors.fill: parent 43 | anchors.margins: 12 44 | MyText { 45 | Layout.leftMargin: 16 46 | Layout.rightMargin: 16 47 | text: dialogTitle 48 | } 49 | Rectangle { 50 | color: "#cccccc" 51 | height: 1 52 | Layout.fillWidth: true 53 | } 54 | Item { 55 | Layout.fillHeight: true 56 | Layout.fillWidth: true 57 | } 58 | ColumnLayout { 59 | id: dialogContent 60 | } 61 | Item { 62 | Layout.fillHeight: true 63 | Layout.fillWidth: true 64 | } 65 | RowLayout { 66 | Layout.fillWidth: true 67 | Layout.leftMargin: 24 68 | Layout.rightMargin: 24 69 | Layout.bottomMargin: 12 70 | Item { 71 | Layout.fillWidth: true 72 | } 73 | MyPushButton { 74 | implicitWidth: 200 75 | text: "Ok" 76 | onClicked: { 77 | okClicked = true 78 | myDialogPopup.close() 79 | } 80 | } 81 | Item { 82 | Layout.fillWidth: true 83 | } 84 | } 85 | } 86 | } 87 | } 88 | 89 | Component.onCompleted: { 90 | dialogContentItem.parent = dialogContent 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/qml/MyPushButton.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Controls 2.0 3 | import "." // QTBUG-34418, singletons require explicit import to load qmldir file 4 | 5 | Button { 6 | property bool activationSoundEnabled: true 7 | hoverEnabled: true 8 | contentItem: MyText { 9 | horizontalAlignment: Text.AlignHCenter 10 | verticalAlignment: Text.AlignVCenter 11 | text: parent.text 12 | color: parent.enabled ? "#ffffff" : "#909090" 13 | } 14 | background: Rectangle { 15 | color: parent.down ? "#406288" : (parent.activeFocus ? "#365473" : "#2c435d") 16 | } 17 | 18 | onHoveredChanged: { 19 | if (hovered) { 20 | forceActiveFocus() 21 | } else { 22 | focus = false 23 | } 24 | } 25 | 26 | onClicked: { 27 | if (activationSoundEnabled) { 28 | MyResources.playActivationSound() 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/qml/MyPushButton2.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Controls 2.0 3 | import "." // QTBUG-34418, singletons require explicit import to load qmldir file 4 | 5 | Button { 6 | hoverEnabled: true 7 | contentItem: MyText { 8 | horizontalAlignment: Text.AlignHCenter 9 | verticalAlignment: Text.AlignVCenter 10 | text: parent.text 11 | color: parent.enabled ? "#ffffff" : "#909090" 12 | } 13 | background: Rectangle { 14 | color: parent.down ? "#406288" : (parent.activeFocus ? "#365473" : "transparent") 15 | border.color: parent.enabled ? "#ffffff" : "#909090" 16 | radius: 8 17 | } 18 | onHoveredChanged: { 19 | if (hovered) { 20 | forceActiveFocus() 21 | } else { 22 | focus = false 23 | } 24 | } 25 | 26 | onClicked: { 27 | MyResources.playActivationSound() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/qml/MyRangeSlider.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Controls 2.2 3 | import "." // QTBUG-34418, singletons require explicit import to load qmldir file 4 | 5 | 6 | RangeSlider { 7 | id: rangeSlider 8 | snapMode: Slider.SnapAlways 9 | wheelEnabled: true 10 | hoverEnabled: true 11 | 12 | background: Rectangle { 13 | x: rangeSlider.leftPadding 14 | y: rangeSlider.topPadding + rangeSlider.availableHeight / 2 - height / 2 15 | implicitWidth: 200 16 | implicitHeight: 8 17 | width: rangeSlider.availableWidth 18 | height: implicitHeight 19 | color: "#cccccc" 20 | radius: 8 21 | 22 | Rectangle { 23 | x: rangeSlider.first.visualPosition * parent.width 24 | width: rangeSlider.second.visualPosition * parent.width - x 25 | height: parent.height 26 | color: "#2c435d" 27 | radius: 8 28 | } 29 | } 30 | 31 | first.handle: Rectangle { 32 | x: rangeSlider.leftPadding + rangeSlider.first.visualPosition * (rangeSlider.availableWidth - width) 33 | y: rangeSlider.topPadding + rangeSlider.availableHeight / 2 - height / 2 34 | implicitWidth: 20 35 | implicitHeight: 40 36 | radius: 2 37 | color: rangeSlider.first.pressed ? "#ffffff" : "#eeeeee" 38 | border.color: "#bdbebf" 39 | } 40 | 41 | second.handle: Rectangle { 42 | x: rangeSlider.leftPadding + rangeSlider.second.visualPosition * (rangeSlider.availableWidth - width) 43 | y: rangeSlider.topPadding + rangeSlider.availableHeight / 2 - height / 2 44 | implicitWidth: 20 45 | implicitHeight: 40 46 | radius: 4 47 | color: rangeSlider.second.pressed ? "#ffffff" : "#eeeeee" 48 | border.color: "#bdbebf" 49 | } 50 | 51 | onHoveredChanged: { 52 | if (hovered) { 53 | forceActiveFocus() 54 | } else { 55 | focus = false 56 | } 57 | } 58 | 59 | first.onValueChanged: { 60 | if (activeFocus) { 61 | MyResources.playActivationSound() 62 | } 63 | } 64 | 65 | second.onValueChanged: { 66 | if (activeFocus) { 67 | MyResources.playActivationSound() 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/qml/MyResources.qml: -------------------------------------------------------------------------------- 1 | pragma Singleton 2 | import QtQuick 2.9 3 | import QtMultimedia 5.6 4 | import matzman666.inputemulator 1.0 5 | 6 | QtObject { 7 | function playActivationSound() { 8 | OverlayController.playActivationSound() 9 | } 10 | function playFocusChangedSound() { 11 | OverlayController.playFocusChangedSound() 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/qml/MySlider.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Controls 2.0 3 | import "." // QTBUG-34418, singletons require explicit import to load qmldir file 4 | 5 | 6 | 7 | Slider { 8 | snapMode: Slider.SnapAlways 9 | wheelEnabled: true 10 | hoverEnabled: true 11 | 12 | background: Rectangle { 13 | x: parent.leftPadding 14 | y: parent.topPadding + parent.availableHeight / 2 - height / 2 15 | width: parent.availableWidth 16 | height: parent.availableHeight 17 | radius: 2 18 | color: parent.activeFocus ? "#2c435d" : "#1b2939" 19 | Rectangle { 20 | y: parent.height / 2 - height / 2 21 | implicitHeight: 4 22 | width: parent.width 23 | height: implicitHeight 24 | radius: 2 25 | color: parent.enabled ? "#bdbebf" : "#8b8c8c" 26 | } 27 | } 28 | 29 | handle: Rectangle { 30 | x: parent.leftPadding + parent.visualPosition * (parent.availableWidth - width) 31 | y: parent.topPadding + parent.availableHeight / 2 - height / 2 32 | implicitWidth: 20 33 | implicitHeight: 40 34 | radius: 4 35 | color: parent.pressed ? "#ffffff" : (parent.enabled ? "#eeeeee" : "#8b8c8c") 36 | border.color: parent.enabled ? "#bdbebf" : "#8b8c8c" 37 | } 38 | 39 | onHoveredChanged: { 40 | if (hovered) { 41 | forceActiveFocus() 42 | } else { 43 | focus = false 44 | } 45 | } 46 | 47 | onValueChanged: { 48 | if (activeFocus) { 49 | MyResources.playActivationSound() 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/qml/MyStackViewPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Controls 2.0 3 | import QtQuick.Layouts 1.2 4 | import "." // QTBUG-34418, singletons require explicit import to load qmldir file 5 | 6 | Rectangle { 7 | id: myStackViewPage 8 | 9 | color: "#1b2939" 10 | width: 1200 11 | height: 800 12 | 13 | signal pageBackButtonClicked 14 | 15 | property StackView stackView 16 | 17 | property string headerText: "Header Title" 18 | 19 | property bool headerShowBackButton: true 20 | 21 | property Item header: ColumnLayout { 22 | RowLayout { 23 | Button { 24 | id: headerBackButton 25 | Layout.preferredHeight: 50 26 | Layout.preferredWidth: 50 27 | hoverEnabled: true 28 | enabled: headerShowBackButton 29 | opacity: headerShowBackButton ? 1.0 : 0.0 30 | contentItem: Image { 31 | source: "backarrow.svg" 32 | sourceSize.width: 50 33 | sourceSize.height: 50 34 | anchors.fill: parent 35 | } 36 | background: Rectangle { 37 | opacity: parent.down ? 1.0 : (parent.activeFocus ? 0.5 : 0.0) 38 | color: "#406288" 39 | radius: 4 40 | anchors.fill: parent 41 | } 42 | onHoveredChanged: { 43 | if (hovered) { 44 | forceActiveFocus() 45 | } else { 46 | focus = false 47 | } 48 | } 49 | onClicked: { 50 | myStackViewPage.pageBackButtonClicked() 51 | goBack() 52 | } 53 | } 54 | MyText { 55 | id: headerTitle 56 | text: headerText 57 | font.pointSize: 30 58 | anchors.verticalCenter: headerBackButton.verticalCenter 59 | Layout.leftMargin: 32 60 | } 61 | } 62 | 63 | Rectangle { 64 | color: "#cccccc" 65 | height: 1 66 | Layout.topMargin: 10 67 | Layout.fillWidth: true 68 | } 69 | } 70 | 71 | property Item content: Frame { 72 | MyText { 73 | text: "Content" 74 | } 75 | } 76 | 77 | function goBack() { 78 | MyResources.playFocusChangedSound() 79 | stackView.pop() 80 | } 81 | 82 | ColumnLayout { 83 | id: mainLayout 84 | spacing: 12 85 | anchors.fill: parent 86 | } 87 | 88 | Component.onCompleted: { 89 | header.parent = mainLayout 90 | header.Layout.leftMargin = 40 91 | header.Layout.topMargin = 30 92 | header.Layout.rightMargin = 40 93 | content.parent = mainLayout 94 | content.Layout.fillHeight = true 95 | content.Layout.fillWidth = true 96 | content.Layout.topMargin = 10 97 | content.Layout.leftMargin = 40 98 | content.Layout.rightMargin = 40 99 | content.Layout.bottomMargin = 40 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/qml/MyText.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Controls 2.0 3 | 4 | 5 | Text { 6 | color: enabled ? "#ffffff" : "#8b8c8c" 7 | font.pointSize: 20 8 | } 9 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/qml/MyTextField.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Controls 2.0 3 | import matzman666.inputemulator 1.0 4 | 5 | TextField { 6 | property int _keyBoardUID: -1 7 | property string savedText: "" 8 | id: myTextField 9 | color: "#cccccc" 10 | text: "" 11 | font.pointSize: 20 12 | background: Button { 13 | hoverEnabled: true 14 | background: Rectangle { 15 | color: parent.hovered ? "#2c435d" : "#1b2939" 16 | border.color: "#cccccc" 17 | border.width: 2 18 | } 19 | onClicked: { 20 | myTextField.forceActiveFocus() 21 | } 22 | } 23 | onActiveFocusChanged: { 24 | if (activeFocus) { 25 | if (!OverlayController.desktopMode) { 26 | if (_keyBoardUID < 0) { 27 | _keyBoardUID = OverlayController.getNewUniqueNumber() 28 | } 29 | OverlayController.showKeyboard(text, _keyBoardUID) 30 | } else { 31 | savedText = text 32 | } 33 | } 34 | } 35 | onEditingFinished: { 36 | if (OverlayController.desktopMode && savedText !== text) { 37 | myTextField.onInputEvent(text) 38 | } 39 | } 40 | function onInputEvent(input) { 41 | text = input 42 | } 43 | Connections { 44 | target: OverlayController 45 | onKeyBoardInputSignal: { 46 | if (_keyBoardUID >= 0 && userValue == _keyBoardUID) { 47 | if (myTextField.text !== input) { 48 | myTextField.onInputEvent(input) 49 | } 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/qml/MyToggleButton.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Controls 2.0 3 | import "." // QTBUG-34418, singletons require explicit import to load qmldir file 4 | 5 | 6 | CheckBox { 7 | hoverEnabled: true 8 | spacing: 12 9 | 10 | indicator: Rectangle { 11 | implicitWidth: 28 12 | implicitHeight: 28 13 | x: parent.leftPadding 14 | y: parent.height / 2 - height / 2 15 | color: parent.enabled ? (parent.down ? "#e0e0e0" : "#ffffff") : "#a0a0a0" 16 | border.width: 0 17 | Image { 18 | width: 38 19 | height: 38 20 | x: (parent.width - width) / 2 21 | y: (parent.height - height) / 2 22 | source: "image://default/check/#2c435d" 23 | sourceSize.width: width 24 | sourceSize.height: height 25 | visible: parent.parent.checked 26 | } 27 | } 28 | 29 | contentItem: MyText { 30 | text: parent.text 31 | horizontalAlignment: Text.AlignLeft 32 | verticalAlignment: Text.AlignVCenter 33 | leftPadding: parent.indicator.width + parent.spacing 34 | color: parent.enabled ? "#ffffff" : "#909090" 35 | } 36 | 37 | background: Rectangle { 38 | color: "#2c435d" 39 | opacity: parent.activeFocus ? 1.0 : 0.0 40 | } 41 | 42 | onHoveredChanged: { 43 | if (hovered) { 44 | forceActiveFocus() 45 | } else { 46 | focus = false 47 | } 48 | } 49 | 50 | onClicked: { 51 | MyResources.playActivationSound() 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/qml/backarrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 16 | 18 | 19 | 21 | image/svg+xml 22 | 24 | 25 | 26 | 27 | 28 | 30 | 32 | 36 | 40 | 41 | 42 | 62 | 65 | 66 | 70 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/qml/mainwidget.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.9 2 | import QtQuick.Controls 2.2 3 | import QtQuick.Layouts 1.0 4 | import "." // QTBUG-34418, singletons require explicit import to load qmldir file 5 | 6 | 7 | Rectangle { 8 | id: root 9 | color: "#1b2939" 10 | width: 1200 11 | height: 800 12 | 13 | property DeviceManipulationPage devicePage: DeviceManipulationPage { 14 | stackView: mainView 15 | } 16 | 17 | property DeviceOffsetsPage deviceOffsetsPage: DeviceOffsetsPage { 18 | stackView: mainView 19 | } 20 | 21 | property MotionCompensationPage motionCompensationPage: MotionCompensationPage { 22 | stackView: mainView 23 | } 24 | 25 | property DeviceRenderModelPage deviceRenderModelPage: DeviceRenderModelPage { 26 | stackView: mainView 27 | } 28 | 29 | property DeviceInputRemappingPage deviceInputRemappingPage: DeviceInputRemappingPage { 30 | stackView: mainView 31 | } 32 | 33 | property DeviceDigitalInputRemappingPage deviceDigitalInputRemappingPage: DeviceDigitalInputRemappingPage { 34 | stackView: mainView 35 | } 36 | 37 | property DeviceDigitalBindingPage deviceDigitalBindingPage: DeviceDigitalBindingPage { 38 | stackView: mainView 39 | } 40 | 41 | property DeviceAnalogInputRemappingPage deviceAnalogInputRemappingPage: DeviceAnalogInputRemappingPage { 42 | stackView: mainView 43 | } 44 | 45 | 46 | StackView { 47 | id: mainView 48 | anchors.fill: parent 49 | 50 | pushEnter: Transition { 51 | PropertyAnimation { 52 | property: "x" 53 | from: mainView.width 54 | to: 0 55 | duration: 200 56 | } 57 | } 58 | pushExit: Transition { 59 | PropertyAnimation { 60 | property: "x" 61 | from: 0 62 | to: -mainView.width 63 | duration: 200 64 | } 65 | } 66 | popEnter: Transition { 67 | PropertyAnimation { 68 | property: "x" 69 | from: -mainView.width 70 | to: 0 71 | duration: 200 72 | } 73 | } 74 | popExit: Transition { 75 | PropertyAnimation { 76 | property: "x" 77 | from: 0 78 | to: mainView.width 79 | duration: 200 80 | } 81 | } 82 | 83 | initialItem: devicePage 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/qml/qmldir: -------------------------------------------------------------------------------- 1 | singleton MyResources 1.0 MyResources.qml -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/thumbicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/client_overlay/bin/win64/res/thumbicon.png -------------------------------------------------------------------------------- /client_overlay/bin/win64/res/transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/client_overlay/bin/win64/res/transparent.png -------------------------------------------------------------------------------- /client_overlay/bin/win64/startdesktopmode.bat: -------------------------------------------------------------------------------- 1 | start OpenVR-InputEmulatorOverlay.exe -desktop -nosound -------------------------------------------------------------------------------- /client_overlay/bin/windeployqt.bat: -------------------------------------------------------------------------------- 1 | 2 | cd win64 3 | 4 | windeployqt.exe --dir qtdata --libdir . --plugindir qtdata/plugins --no-system-d3d-compiler --no-opengl-sw --release --qmldir res/qml OpenVR-InputEmulatorOverlay.exe 5 | 6 | @REM Debug: 7 | @REM windeployqt.exe --dir qtdata --libdir . --plugindir qtdata/plugins --no-system-d3d-compiler --compiler-runtime --no-opengl-sw --debug --qmldir res/qml OpenVR-InputEmulatorOverlay.exe 8 | -------------------------------------------------------------------------------- /client_overlay/client_overlay.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2015-06-10T16:57:45 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui qml quick multimedia 8 | 9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 10 | 11 | TARGET = OpenVR-InputEmulatorOverlay 12 | TEMPLATE = app 13 | 14 | 15 | SOURCES += src/main.cpp\ 16 | src/overlaycontroller.cpp \ 17 | src/tabcontrollers/DeviceManipulationTabController.cpp 18 | 19 | HEADERS += src/overlaycontroller.h \ 20 | src/logging.h \ 21 | src/tabcontrollers/DeviceManipulationTabController.h 22 | 23 | INCLUDEPATH += ../openvr/headers \ 24 | ../third-party/easylogging++ 25 | 26 | LIBS += -L../openvr/lib/win64 -lopenvr_api 27 | 28 | DESTDIR = bin/win64 29 | -------------------------------------------------------------------------------- /client_overlay/src/logging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // easylogging includes 4 | #ifndef _DEBUG 5 | #define _DEBUG 6 | #define ELPP_THREAD_SAFE 7 | #define ELPP_QT_LOGGING 8 | #define ELPP_NO_DEFAULT_LOG_FILE 9 | #include 10 | #undef _DEBUG 11 | #else 12 | #define ELPP_THREAD_SAFE 13 | #define ELPP_QT_LOGGING 14 | #define ELPP_NO_DEFAULT_LOG_FILE 15 | #include 16 | #endif 17 | -------------------------------------------------------------------------------- /client_overlay/src/overlaycontroller.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | // because of incompatibilities with QtOpenGL and GLEW we need to cherry pick includes 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include "logging.h" 26 | 27 | #include "tabcontrollers/DeviceManipulationTabController.h" 28 | #include "tabcontrollers/DigitalInputRemappingController.h" 29 | #include "tabcontrollers/AnalogInputRemappingController.h" 30 | 31 | 32 | 33 | // application namespace 34 | namespace inputemulator { 35 | 36 | class OverlayController : public QObject { 37 | Q_OBJECT 38 | Q_PROPERTY(bool desktopMode READ isDesktopMode) 39 | 40 | public: 41 | static constexpr const char* applicationKey = "matzman666.VRInputEmulator"; 42 | static constexpr const char* applicationName = "OpenVR Input Emulator"; 43 | static constexpr const char* applicationVersionString = "v1.3"; 44 | 45 | private: 46 | vr::VROverlayHandle_t m_ulOverlayHandle = vr::k_ulOverlayHandleInvalid; 47 | vr::VROverlayHandle_t m_ulOverlayThumbnailHandle = vr::k_ulOverlayHandleInvalid; 48 | 49 | std::unique_ptr m_pRenderControl; 50 | std::unique_ptr m_pWindow; 51 | std::unique_ptr m_pFbo; 52 | std::unique_ptr m_pOpenGLContext; 53 | std::unique_ptr m_pOffscreenSurface; 54 | 55 | std::unique_ptr m_pPumpEventsTimer; 56 | std::unique_ptr m_pRenderTimer; 57 | bool dashboardVisible = false; 58 | 59 | QPoint m_ptLastMouse; 60 | Qt::MouseButtons m_lastMouseButtons = 0; 61 | 62 | vrinputemulator::VRInputEmulator m_vrInputEmulator; 63 | 64 | bool desktopMode; 65 | bool noSound; 66 | 67 | QUrl m_runtimePathUrl; 68 | 69 | std::atomic_uint32_t m_uniqueNumber = 0; 70 | 71 | QSoundEffect activationSoundEffect; 72 | QSoundEffect focusChangedSoundEffect; 73 | 74 | static std::map _openVRButtonNames; 75 | static std::vector> _keyboardVirtualCodes; 76 | static std::vector _keyboardVaryingVirtualCodes; 77 | 78 | public: // I know it's an ugly hack to make them public to enable external access, but I am too lazy to implement getters. 79 | DeviceManipulationTabController deviceManipulationTabController; 80 | DigitalInputRemappingController digitalInputRemappingController; 81 | AnalogInputRemappingController analogInputRemappingController; 82 | 83 | private: 84 | OverlayController(bool desktopMode, bool noSound) : QObject(), desktopMode(desktopMode), noSound(noSound) {} 85 | 86 | public: 87 | virtual ~OverlayController(); 88 | 89 | void Init(QQmlEngine* qmlEngine); 90 | void Shutdown(); 91 | 92 | vrinputemulator::VRInputEmulator& vrInputEmulator() { return m_vrInputEmulator; } 93 | 94 | bool isDashboardVisible() { 95 | return dashboardVisible; 96 | } 97 | 98 | void SetWidget(QQuickItem* quickItem, const std::string& name, const std::string& key = ""); 99 | 100 | bool isDesktopMode() { return desktopMode; }; 101 | 102 | Q_INVOKABLE QString getVersionString(); 103 | Q_INVOKABLE QUrl getVRRuntimePathUrl(); 104 | 105 | Q_INVOKABLE bool soundDisabled(); 106 | 107 | Q_INVOKABLE unsigned getNewUniqueNumber(); 108 | 109 | const vr::VROverlayHandle_t& overlayHandle(); 110 | const vr::VROverlayHandle_t& overlayThumbnailHandle(); 111 | bool getOverlayTexture(vr::Texture_t& texture); 112 | 113 | 114 | QString digitalBindingToString(const vrinputemulator::DigitalBinding& binding, bool printOptController); 115 | QString analogBindingToString(const vrinputemulator::AnalogBinding& binding, bool printOptController); 116 | QString openvrButtonToString(unsigned deviceId, unsigned buttonId); 117 | QString openvrAxisToString(unsigned deviceId, unsigned axisId); 118 | 119 | Q_INVOKABLE unsigned keyboardVirtualCodeCount(); 120 | Q_INVOKABLE QString keyboardVirtualCodeNameFromIndex(unsigned index); 121 | Q_INVOKABLE unsigned keyboardVirtualCodeIdFromIndex(unsigned index); 122 | Q_INVOKABLE unsigned keyboardVirtualCodeIndexFromId(unsigned id); 123 | 124 | public slots: 125 | void renderOverlay(); 126 | void OnRenderRequest(); 127 | void OnTimeoutPumpEvents(); 128 | 129 | void showKeyboard(QString existingText, unsigned long userValue = 0); 130 | 131 | void playActivationSound(); 132 | void playFocusChangedSound(); 133 | 134 | signals: 135 | void keyBoardInputSignal(QString input, unsigned long userValue = 0); 136 | 137 | private: 138 | static QSettings* _appSettings; 139 | static std::unique_ptr singleton; 140 | 141 | public: 142 | static OverlayController* getInstance() { 143 | return singleton.get(); 144 | } 145 | 146 | static OverlayController* createInstance(bool desktopMode, bool noSound) { 147 | singleton.reset(new inputemulator::OverlayController(desktopMode, noSound)); 148 | return singleton.get(); 149 | } 150 | 151 | static QSettings* appSettings() { return _appSettings; } 152 | 153 | static void setAppSettings(QSettings* settings) { _appSettings = settings; } 154 | }; 155 | 156 | } // namespace inputemulator 157 | -------------------------------------------------------------------------------- /client_overlay/src/tabcontrollers/AnalogInputRemappingController.cpp: -------------------------------------------------------------------------------- 1 | #include "AnalogInputRemappingController.h" 2 | #include "../overlaycontroller.h" 3 | 4 | // application namespace 5 | namespace inputemulator { 6 | 7 | AnalogInputRemappingController::~AnalogInputRemappingController() { 8 | } 9 | 10 | void AnalogInputRemappingController::initStage1() { 11 | } 12 | 13 | 14 | void AnalogInputRemappingController::initStage2(OverlayController * parent, QQuickWindow * widget) { 15 | this->parent = parent; 16 | this->widget = widget; 17 | } 18 | 19 | 20 | void AnalogInputRemappingController::eventLoopTick(vr::TrackedDevicePose_t* /*devicePoses*/) { 21 | if (settingsUpdateCounter >= 50) { 22 | settingsUpdateCounter = 0; 23 | } else { 24 | settingsUpdateCounter++; 25 | } 26 | } 27 | 28 | void AnalogInputRemappingController::handleEvent(const vr::VREvent_t&) { 29 | /*switch (vrEvent.eventType) { 30 | default: 31 | break; 32 | }*/ 33 | } 34 | 35 | void AnalogInputRemappingController::startConfigureRemapping(vrinputemulator::AnalogInputRemapping remapping, uint32_t deviceIndex, uint32_t deviceId, uint32_t axisId) { 36 | m_currentDeviceIndex = deviceIndex; 37 | m_currentDeviceId = deviceId; 38 | m_currentAxisId = axisId; 39 | m_currentRemapping = remapping; 40 | } 41 | 42 | int AnalogInputRemappingController::getAxisMaxCount() { 43 | return vr::k_unControllerStateAxisCount; 44 | } 45 | 46 | QString AnalogInputRemappingController::getAxisName(int id, bool withDefaults) { 47 | QString name("Axis"); 48 | name.append(QString::number(id)); 49 | if (withDefaults) { 50 | switch (id) { 51 | case 0: 52 | name.append(" (TrackPad)"); 53 | break; 54 | case 1: 55 | name.append(" (Trigger)"); 56 | break; 57 | default: 58 | break; 59 | } 60 | } 61 | return name; 62 | } 63 | 64 | 65 | 66 | int AnalogInputRemappingController::getBindingType() { 67 | if (m_currentRemapping.valid) { 68 | return (int)m_currentRemapping.binding.type; 69 | } else { 70 | return 0; 71 | } 72 | } 73 | 74 | int AnalogInputRemappingController::getBindingOpenVRControllerId() { 75 | if (m_currentRemapping.valid) { 76 | return m_currentRemapping.binding.data.openvr.controllerId; 77 | } else { 78 | return -1; 79 | } 80 | } 81 | 82 | int AnalogInputRemappingController::getBindingOpenVRAxisId() { 83 | if (m_currentRemapping.valid) { 84 | return m_currentRemapping.binding.data.openvr.axisId; 85 | } else { 86 | return -1; 87 | } 88 | } 89 | 90 | bool AnalogInputRemappingController::isBindingOpenVRXInverted() { 91 | if (m_currentRemapping.valid) { 92 | return m_currentRemapping.binding.invertXAxis; 93 | } else { 94 | return false; 95 | } 96 | } 97 | 98 | bool AnalogInputRemappingController::isBindingOpenVRYInverted() { 99 | if (m_currentRemapping.valid) { 100 | return m_currentRemapping.binding.invertYAxis; 101 | } else { 102 | return false; 103 | } 104 | } 105 | 106 | bool AnalogInputRemappingController::isBindingOpenVRAxesSwapped() { 107 | if (m_currentRemapping.valid) { 108 | return m_currentRemapping.binding.swapAxes; 109 | } else { 110 | return false; 111 | } 112 | } 113 | 114 | float AnalogInputRemappingController::getBindingDeadzoneLower() { 115 | if (m_currentRemapping.valid) { 116 | return m_currentRemapping.binding.lowerDeadzone; 117 | } else { 118 | return false; 119 | } 120 | } 121 | 122 | float AnalogInputRemappingController::getBindingDeadzoneUpper() { 123 | if (m_currentRemapping.valid) { 124 | return m_currentRemapping.binding.upperDeadzone; 125 | } else { 126 | return false; 127 | } 128 | } 129 | 130 | unsigned AnalogInputRemappingController::getBindingTouchpadEmulationMode() { 131 | if (m_currentRemapping.valid) { 132 | return m_currentRemapping.binding.touchpadEmulationMode; 133 | } else { 134 | return false; 135 | } 136 | } 137 | 138 | bool AnalogInputRemappingController::getBindingButtonPressDeadzoneFix() { 139 | if (m_currentRemapping.valid) { 140 | return m_currentRemapping.binding.buttonPressDeadzoneFix; 141 | } else { 142 | return false; 143 | } 144 | } 145 | 146 | void AnalogInputRemappingController::finishConfigure_Original(unsigned touchpadEmulationMode, bool updateOnButtonEvent) { 147 | m_currentRemapping.binding.type = vrinputemulator::AnalogBindingType::NoRemapping; 148 | m_currentRemapping.binding.touchpadEmulationMode = touchpadEmulationMode; 149 | m_currentRemapping.binding.buttonPressDeadzoneFix = updateOnButtonEvent; 150 | parent->deviceManipulationTabController.finishConfigureAnalogInputRemapping(m_currentDeviceIndex, m_currentAxisId); 151 | } 152 | 153 | void AnalogInputRemappingController::finishConfigure_Disabled() { 154 | m_currentRemapping.binding.type = vrinputemulator::AnalogBindingType::Disabled; 155 | parent->deviceManipulationTabController.finishConfigureAnalogInputRemapping(m_currentDeviceIndex, m_currentAxisId); 156 | } 157 | 158 | void AnalogInputRemappingController::finishConfigure_OpenVR(int controllerId, int axisId, bool invertXAxis, bool invertYAxis, bool swapAxes, float lowerDeadzone, float upperDeadzone, unsigned touchpadEmulationMode, bool updateOnButtonEvent) { 159 | m_currentRemapping.binding.type = vrinputemulator::AnalogBindingType::OpenVR; 160 | if (controllerId < 0) { 161 | m_currentRemapping.binding.data.openvr.controllerId = vr::k_unTrackedDeviceIndexInvalid; 162 | } else { 163 | m_currentRemapping.binding.data.openvr.controllerId = controllerId; 164 | } 165 | m_currentRemapping.binding.data.openvr.axisId = axisId; 166 | m_currentRemapping.binding.invertXAxis = invertXAxis; 167 | m_currentRemapping.binding.invertYAxis = invertYAxis; 168 | m_currentRemapping.binding.swapAxes = swapAxes; 169 | m_currentRemapping.binding.lowerDeadzone = lowerDeadzone; 170 | m_currentRemapping.binding.upperDeadzone = upperDeadzone; 171 | m_currentRemapping.binding.touchpadEmulationMode = touchpadEmulationMode; 172 | m_currentRemapping.binding.buttonPressDeadzoneFix = updateOnButtonEvent; 173 | parent->deviceManipulationTabController.finishConfigureAnalogInputRemapping(m_currentDeviceIndex, m_currentAxisId); 174 | } 175 | 176 | 177 | } // namespace inputemulator 178 | -------------------------------------------------------------------------------- /client_overlay/src/tabcontrollers/AnalogInputRemappingController.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | class QQuickWindow; 9 | // application namespace 10 | namespace inputemulator { 11 | 12 | // forward declaration 13 | class OverlayController; 14 | 15 | 16 | class AnalogInputRemappingController : public QObject { 17 | Q_OBJECT 18 | 19 | public: 20 | ~AnalogInputRemappingController(); 21 | void initStage1(); 22 | void initStage2(OverlayController* parent, QQuickWindow* widget); 23 | 24 | void eventLoopTick(vr::TrackedDevicePose_t* devicePoses); 25 | void handleEvent(const vr::VREvent_t& vrEvent); 26 | 27 | void startConfigureRemapping(vrinputemulator::AnalogInputRemapping remapping, uint32_t deviceIndex, uint32_t deviceId, uint32_t axisId); 28 | 29 | Q_INVOKABLE int getAxisMaxCount(); 30 | Q_INVOKABLE QString getAxisName(int id, bool withDefaults = true); 31 | 32 | Q_INVOKABLE int getBindingType(); 33 | 34 | Q_INVOKABLE int getBindingOpenVRControllerId(); 35 | Q_INVOKABLE int getBindingOpenVRAxisId(); 36 | 37 | Q_INVOKABLE bool isBindingOpenVRXInverted(); 38 | Q_INVOKABLE bool isBindingOpenVRYInverted(); 39 | Q_INVOKABLE bool isBindingOpenVRAxesSwapped(); 40 | 41 | Q_INVOKABLE float getBindingDeadzoneLower(); 42 | Q_INVOKABLE float getBindingDeadzoneUpper(); 43 | 44 | Q_INVOKABLE unsigned getBindingTouchpadEmulationMode(); 45 | Q_INVOKABLE bool getBindingButtonPressDeadzoneFix(); 46 | 47 | const vrinputemulator::AnalogInputRemapping& currentRemapping() { return m_currentRemapping; } 48 | 49 | public slots: 50 | void finishConfigure_Original(unsigned touchpadEmulationMode, bool updateOnButtonEvent); 51 | void finishConfigure_Disabled(); 52 | void finishConfigure_OpenVR(int controllerId, int axisId, bool invertXAxis, bool invertYAxis, bool swapAxes, float lowerDeadzone, float upperDeadzone, unsigned touchpadEmulationMode, bool updateOnButtonEvent); 53 | 54 | private: 55 | OverlayController* parent; 56 | QQuickWindow* widget; 57 | 58 | unsigned settingsUpdateCounter = 0; 59 | 60 | vrinputemulator::AnalogInputRemapping m_currentRemapping; 61 | uint32_t m_currentDeviceIndex; 62 | uint32_t m_currentDeviceId; 63 | uint32_t m_currentAxisId; 64 | }; 65 | 66 | 67 | } // namespace inputemulator 68 | -------------------------------------------------------------------------------- /client_overlay/src/tabcontrollers/DeviceManipulationTabController.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class QQuickWindow; 10 | // application namespace 11 | namespace inputemulator { 12 | 13 | // forward declaration 14 | class OverlayController; 15 | 16 | 17 | struct DigitalInputRemappingProfile { 18 | QString normalBindingControllerSerial; 19 | QString longBindingControllerSerial; 20 | QString doubleBindingControllerSerial; 21 | vrinputemulator::DigitalInputRemapping remapping; 22 | 23 | DigitalInputRemappingProfile() : remapping(true) {} 24 | }; 25 | 26 | struct AnalogInputRemappingProfile { 27 | QString controllerSerial; 28 | vrinputemulator::AnalogInputRemapping remapping; 29 | 30 | AnalogInputRemappingProfile() : remapping(true) {} 31 | }; 32 | 33 | struct DeviceManipulationProfile { 34 | std::string profileName; 35 | 36 | bool includesDeviceOffsets = false; 37 | bool deviceOffsetsEnabled = false; 38 | vr::HmdVector3d_t worldFromDriverTranslationOffset; 39 | vr::HmdVector3d_t worldFromDriverRotationOffset; 40 | vr::HmdVector3d_t driverFromHeadTranslationOffset; 41 | vr::HmdVector3d_t driverFromHeadRotationOffset; 42 | vr::HmdVector3d_t driverTranslationOffset; 43 | vr::HmdVector3d_t driverRotationOffset; 44 | bool includesInputRemapping = false; 45 | std::map digitalRemappingProfiles; 46 | AnalogInputRemappingProfile analogRemappingProfiles[5]; 47 | }; 48 | 49 | 50 | struct DeviceInfo { 51 | std::string serial; 52 | vr::ETrackedDeviceClass deviceClass = vr::TrackedDeviceClass_Invalid; 53 | uint32_t openvrId = 0; 54 | int deviceStatus = 0; // 0 .. Normal, 1 .. Disconnected/Suspended 55 | int deviceMode = 0; // 0 .. Default, 1 .. Fake Disconnected, 2 .. Redirect Source, 3 .. Redirect Target, 4 .. Motion Compensation 56 | uint32_t refDeviceId = 0; 57 | bool deviceOffsetsEnabled; 58 | vr::HmdVector3d_t worldFromDriverRotationOffset; 59 | vr::HmdVector3d_t worldFromDriverTranslationOffset; 60 | vr::HmdVector3d_t driverFromHeadRotationOffset; 61 | vr::HmdVector3d_t driverFromHeadTranslationOffset; 62 | vr::HmdVector3d_t deviceRotationOffset; 63 | vr::HmdVector3d_t deviceTranslationOffset; 64 | uint32_t renderModelIndex = 0; 65 | vr::VROverlayHandle_t renderModelOverlay = vr::k_ulOverlayHandleInvalid; 66 | std::string renderModelOverlayName; 67 | }; 68 | 69 | 70 | class DeviceManipulationTabController : public QObject { 71 | Q_OBJECT 72 | 73 | private: 74 | OverlayController* parent; 75 | QQuickWindow* widget; 76 | 77 | std::vector> deviceInfos; 78 | uint32_t maxValidDeviceId = 0; 79 | 80 | std::vector deviceManipulationProfiles; 81 | 82 | vrinputemulator::MotionCompensationVelAccMode motionCompensationVelAccMode = vrinputemulator::MotionCompensationVelAccMode::Disabled; 83 | double motionCompensationKalmanProcessNoise = 0.1; 84 | double motionCompensationKalmanObservationNoise = 0.1; 85 | unsigned motionCompensationMovingAverageWindow = 3; 86 | 87 | QString m_deviceModeErrorString; 88 | 89 | unsigned settingsUpdateCounter = 0; 90 | 91 | std::thread identifyThread; 92 | 93 | public: 94 | ~DeviceManipulationTabController(); 95 | void initStage1(); 96 | void initStage2(OverlayController* parent, QQuickWindow* widget); 97 | 98 | void eventLoopTick(vr::TrackedDevicePose_t* devicePoses); 99 | void handleEvent(const vr::VREvent_t& vrEvent); 100 | 101 | Q_INVOKABLE unsigned getDeviceCount(); 102 | Q_INVOKABLE QString getDeviceSerial(unsigned index); 103 | Q_INVOKABLE unsigned getDeviceId(unsigned index); 104 | Q_INVOKABLE int getDeviceClass(unsigned index); 105 | Q_INVOKABLE int getDeviceState(unsigned index); 106 | Q_INVOKABLE int getDeviceMode(unsigned index); 107 | Q_INVOKABLE int getDeviceModeRefDeviceIndex(unsigned index); 108 | Q_INVOKABLE bool deviceOffsetsEnabled(unsigned index); 109 | Q_INVOKABLE double getWorldFromDriverRotationOffset(unsigned index, unsigned axis); 110 | Q_INVOKABLE double getWorldFromDriverTranslationOffset(unsigned index, unsigned axis); 111 | Q_INVOKABLE double getDriverFromHeadRotationOffset(unsigned index, unsigned axis); 112 | Q_INVOKABLE double getDriverFromHeadTranslationOffset(unsigned index, unsigned axis); 113 | Q_INVOKABLE double getDriverRotationOffset(unsigned index, unsigned axis); 114 | Q_INVOKABLE double getDriverTranslationOffset(unsigned index, unsigned axis); 115 | Q_INVOKABLE unsigned getMotionCompensationVelAccMode(); 116 | Q_INVOKABLE double getMotionCompensationKalmanProcessNoise(); 117 | Q_INVOKABLE double getMotionCompensationKalmanObservationNoise(); 118 | Q_INVOKABLE unsigned getMotionCompensationMovingAverageWindow(); 119 | 120 | void reloadDeviceManipulationSettings(); 121 | void reloadDeviceManipulationProfiles(); 122 | void saveDeviceManipulationSettings(); 123 | void saveDeviceManipulationProfiles(); 124 | 125 | Q_INVOKABLE unsigned getDeviceManipulationProfileCount(); 126 | Q_INVOKABLE QString getDeviceManipulationProfileName(unsigned index); 127 | 128 | Q_INVOKABLE unsigned getRenderModelCount(); 129 | Q_INVOKABLE QString getRenderModelName(unsigned index); 130 | Q_INVOKABLE bool updateDeviceInfo(unsigned index); 131 | 132 | Q_INVOKABLE unsigned getDigitalButtonCount(unsigned deviceIndex); 133 | Q_INVOKABLE int getDigitalButtonId(unsigned deviceIndex, unsigned buttonIndex); 134 | Q_INVOKABLE QString getDigitalButtonName(unsigned deviceIndex, unsigned buttonId); 135 | Q_INVOKABLE QString getDigitalButtonStatus(unsigned deviceIndex, unsigned buttonId); 136 | 137 | Q_INVOKABLE unsigned getAnalogAxisCount(unsigned deviceIndex); 138 | Q_INVOKABLE int getAnalogAxisId(unsigned deviceIndex, unsigned axisIndex); 139 | Q_INVOKABLE QString getAnalogAxisName(unsigned deviceIndex, unsigned axisId); 140 | Q_INVOKABLE QString getAnalogAxisStatus(unsigned deviceIndex, unsigned axisId); 141 | 142 | Q_INVOKABLE void startConfigureDigitalInputRemapping(unsigned deviceIndex, unsigned buttonId); 143 | Q_INVOKABLE void finishConfigureDigitalInputRemapping(unsigned deviceIndex, unsigned buttonId, bool touchAsClick, 144 | bool longPress, int longPressThreshold, bool longPressImmediateRelease, bool doublePress, int doublePressThreshold, bool doublePressImmediateRelease); 145 | 146 | Q_INVOKABLE void startConfigureAnalogInputRemapping(unsigned deviceIndex, unsigned axisId); 147 | Q_INVOKABLE void finishConfigureAnalogInputRemapping(unsigned deviceIndex, unsigned axisId); 148 | 149 | Q_INVOKABLE bool setDeviceMode(unsigned index, unsigned mode, unsigned targedIndex, bool notify = true); 150 | Q_INVOKABLE QString getDeviceModeErrorString(); 151 | 152 | 153 | public slots: 154 | void enableDeviceOffsets(unsigned index, bool enable, bool notify = true); 155 | void setWorldFromDriverRotationOffset(unsigned index, double x, double y, double z, bool notify = true); 156 | void setWorldFromDriverTranslationOffset(unsigned index, double yaw, double pitch, double roll, bool notify = true); 157 | void setDriverFromHeadRotationOffset(unsigned index, double x, double y, double z, bool notify = true); 158 | void setDriverFromHeadTranslationOffset(unsigned index, double yaw, double pitch, double roll, bool notify = true); 159 | void setDriverRotationOffset(unsigned index, double x, double y, double z, bool notify = true); 160 | void setDriverTranslationOffset(unsigned index, double yaw, double pitch, double roll, bool notify = true); 161 | void triggerHapticPulse(unsigned index); 162 | void setDeviceRenderModel(unsigned deviceIndex, unsigned renderModelIndex); 163 | 164 | void addDeviceManipulationProfile(QString name, unsigned deviceIndex, bool includesDeviceOffsets, bool includesInputRemapping); 165 | void applyDeviceManipulationProfile(unsigned index, unsigned deviceIndex); 166 | void deleteDeviceManipulationProfile(unsigned index); 167 | 168 | void setMotionCompensationVelAccMode(unsigned mode, bool notify = true); 169 | void setMotionCompensationKalmanProcessNoise(double variance, bool notify = true); 170 | void setMotionCompensationKalmanObservationNoise(double variance, bool notify = true); 171 | void setMotionCompensationMovingAverageWindow(unsigned window, bool notify = true); 172 | 173 | signals: 174 | void deviceCountChanged(unsigned deviceCount); 175 | void deviceInfoChanged(unsigned index); 176 | void motionCompensationSettingsChanged(); 177 | void deviceManipulationProfilesChanged(); 178 | void motionCompensationVelAccModeChanged(unsigned mode); 179 | void motionCompensationKalmanProcessNoiseChanged(double variance); 180 | void motionCompensationKalmanObservationNoiseChanged(double variance); 181 | void motionCompensationMovingAverageWindowChanged(unsigned window); 182 | 183 | void configureDigitalInputRemappingFinished(); 184 | void configureAnalogInputRemappingFinished(); 185 | }; 186 | 187 | } // namespace inputemulator 188 | -------------------------------------------------------------------------------- /client_overlay/src/tabcontrollers/DigitalInputRemappingController.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | class QQuickWindow; 10 | // application namespace 11 | namespace inputemulator { 12 | 13 | // forward declaration 14 | class OverlayController; 15 | 16 | class DigitalInputRemappingController : public QObject { 17 | Q_OBJECT 18 | 19 | public: 20 | ~DigitalInputRemappingController(); 21 | void initStage1(); 22 | void initStage2(OverlayController* parent, QQuickWindow* widget); 23 | 24 | void eventLoopTick(vr::TrackedDevicePose_t* devicePoses); 25 | void handleEvent(const vr::VREvent_t& vrEvent); 26 | 27 | void startConfigureRemapping(vrinputemulator::DigitalInputRemapping remapping, uint32_t deviceIndex, uint32_t deviceId, uint32_t buttonId); 28 | Q_INVOKABLE void startConfigureNormalBinding(); 29 | Q_INVOKABLE void startConfigureLongPressBinding(); 30 | Q_INVOKABLE void startConfigureDoublePressBinding(); 31 | 32 | Q_INVOKABLE QString getNormalBindingStatus(); 33 | Q_INVOKABLE bool isLongPressEnabled(); 34 | Q_INVOKABLE unsigned getLongPressThreshold(); 35 | Q_INVOKABLE QString getLongPressBindingStatus(); 36 | Q_INVOKABLE bool isLongPressImmediateRelease(); 37 | 38 | Q_INVOKABLE bool isDoublePressEnabled(); 39 | Q_INVOKABLE unsigned getDoublePressThreshold(); 40 | Q_INVOKABLE QString getDoublePressBindingStatus(); 41 | Q_INVOKABLE bool isDoublePressImmediateRelease(); 42 | 43 | Q_INVOKABLE int getButtonMaxCount(); 44 | Q_INVOKABLE QString getButtonName(int id, bool withDefaults = true); 45 | 46 | Q_INVOKABLE int getBindingType(); 47 | 48 | Q_INVOKABLE int getBindingOpenVRControllerId(); 49 | Q_INVOKABLE int getBindingOpenVRButtonId(); 50 | 51 | Q_INVOKABLE bool touchAsClickEnabled(); 52 | 53 | Q_INVOKABLE bool isToggleModeEnabled(); 54 | Q_INVOKABLE int toggleModeThreshold(); 55 | Q_INVOKABLE bool isAutoTriggerEnabled(); 56 | Q_INVOKABLE int autoTriggerFrequency(); 57 | 58 | Q_INVOKABLE bool keyboardShiftEnabled(); 59 | Q_INVOKABLE bool keyboardCtrlEnabled(); 60 | Q_INVOKABLE bool keyboardAltEnabled(); 61 | Q_INVOKABLE unsigned keyboardKeyIndex(); 62 | Q_INVOKABLE bool keyboardUseScanCode(); 63 | 64 | const vrinputemulator::DigitalInputRemapping& currentRemapping() { return m_currentRemapping; } 65 | 66 | 67 | public slots: 68 | /*void enableLongPress(bool enable, bool notify = true); 69 | void setLongPressThreshold(unsigned value, bool notify = true); 70 | void setLongPressImmediateRelease(unsigned value, bool notify = true); 71 | void enableDoublePress(bool enable, bool notify = true); 72 | void setDoublePressThreshold(unsigned value, bool notify = true); 73 | void setDoublePressImmediateRelease(unsigned value, bool notify = true); 74 | 75 | void enableTouchAsClick(bool enable, bool notify = true);*/ 76 | 77 | void finishConfigureBinding_Original(); 78 | void finishConfigureBinding_Disabled(); 79 | void finishConfigureBinding_OpenVR(int controllerId, int ButtonId, bool toggleMode, int toggleThreshold, bool autoTrigger, int triggerFrequency); 80 | void finishConfigureBinding_keyboard(bool shiftPressed, bool ctrlPressed, bool altPressed, unsigned long keyIndex, bool useScanCode, bool toggleMode, int toggleThreshold, bool autoTrigger, int triggerFrequency); 81 | void finishConfigureBinding_suspendRedirectMode(); 82 | void finishConfigureBinding_toggleTouchpadEmulationFix(); 83 | 84 | signals: 85 | /*void longPressEnabledChanged(bool enable); 86 | void longPressThresholdChanged(unsigned value); 87 | void longPressImmediateReleaseChanged(unsigned value); 88 | void doublePressEnabledChanged(bool enable); 89 | void doublePressThresholdChanged(unsigned value); 90 | void doublePressImmediateReleaseChanged(unsigned value); 91 | 92 | void touchAsClickChanged(bool value);*/ 93 | 94 | void configureDigitalBindingFinished(); 95 | 96 | private: 97 | OverlayController* parent; 98 | QQuickWindow* widget; 99 | 100 | unsigned settingsUpdateCounter = 0; 101 | 102 | vrinputemulator::DigitalInputRemapping m_currentRemapping; 103 | uint32_t m_currentDeviceIndex; 104 | uint32_t m_currentDeviceId; 105 | uint32_t m_currentButtonId; 106 | vrinputemulator::DigitalBinding* m_currentBinding = nullptr; 107 | }; 108 | 109 | 110 | } // namespace inputemulator 111 | -------------------------------------------------------------------------------- /docs/screenshots/AnalogBindingOpenVRPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/docs/screenshots/AnalogBindingOpenVRPage.png -------------------------------------------------------------------------------- /docs/screenshots/AnalogBindingPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/docs/screenshots/AnalogBindingPage.png -------------------------------------------------------------------------------- /docs/screenshots/DeviceManipulationPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/docs/screenshots/DeviceManipulationPage.png -------------------------------------------------------------------------------- /docs/screenshots/DeviceOffsetsPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/docs/screenshots/DeviceOffsetsPage.png -------------------------------------------------------------------------------- /docs/screenshots/DigitalBindingKeyboardPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/docs/screenshots/DigitalBindingKeyboardPage.png -------------------------------------------------------------------------------- /docs/screenshots/DigitalBindingOpenVRPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/docs/screenshots/DigitalBindingOpenVRPage.png -------------------------------------------------------------------------------- /docs/screenshots/DigitalBindingPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/docs/screenshots/DigitalBindingPage.png -------------------------------------------------------------------------------- /docs/screenshots/DigitalInputPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/docs/screenshots/DigitalInputPage.png -------------------------------------------------------------------------------- /docs/screenshots/InVRScreenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/docs/screenshots/InVRScreenshot.png -------------------------------------------------------------------------------- /docs/screenshots/InputRemappingPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/docs/screenshots/InputRemappingPage.png -------------------------------------------------------------------------------- /docs/screenshots/MotionCompensationPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/docs/screenshots/MotionCompensationPage.png -------------------------------------------------------------------------------- /driver_vrinputemulator/driver.vrdrivermanifest: -------------------------------------------------------------------------------- 1 | { 2 | "alwaysActivate": true, 3 | "name" : "00vrinputemulator", 4 | "directory" : "", 5 | "resourceOnly" : false 6 | } 7 | -------------------------------------------------------------------------------- /driver_vrinputemulator/resources/driver.vrresources: -------------------------------------------------------------------------------- 1 | { 2 | "jsonid" : "vrresources", 3 | "statusicons" : { 4 | } 5 | } -------------------------------------------------------------------------------- /driver_vrinputemulator/resources/settings/default.vrsettings: -------------------------------------------------------------------------------- 1 | { 2 | "driver_00vrinputemulator" : { 3 | } 4 | } -------------------------------------------------------------------------------- /driver_vrinputemulator/resources/sounds/License.txt: -------------------------------------------------------------------------------- 1 | audiocue.wav is licensed under the Creative Commons Attribution license (Find out more under https://creativecommons.org/licenses/by/4.0/legalcode). 2 | It has been downloaded from https://notificationsounds.com/notification-sounds/plucky-550, and the only changes done to it was the removal of silence. -------------------------------------------------------------------------------- /driver_vrinputemulator/resources/sounds/audiocue.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/driver_vrinputemulator/resources/sounds/audiocue.wav -------------------------------------------------------------------------------- /driver_vrinputemulator/src/com/shm/driver_ipc_shm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | // driver namespace 12 | namespace vrinputemulator { 13 | 14 | // forward declarations 15 | namespace ipc { struct Reply; } 16 | 17 | namespace driver { 18 | 19 | // forward declarations 20 | class ServerDriver; 21 | 22 | 23 | class IpcShmCommunicator { 24 | public: 25 | void init(ServerDriver* driver); 26 | void shutdown(); 27 | 28 | void sendReplySetMotionCompensationMode(bool success); 29 | 30 | private: 31 | static void _ipcThreadFunc(IpcShmCommunicator* _this, ServerDriver* driver); 32 | 33 | void sendReply(uint32_t clientId, const ipc::Reply& reply); 34 | 35 | std::mutex _sendMutex; 36 | ServerDriver* _driver = nullptr; 37 | std::thread _ipcThread; 38 | volatile bool _ipcThreadRunning = false; 39 | volatile bool _ipcThreadStopFlag = false; 40 | std::string _ipcQueueName = "driver_vrinputemulator.server_queue"; 41 | uint32_t _ipcClientIdNext = 1; 42 | std::map> _ipcEndpoints; 43 | 44 | // This is not exactly multi-user safe, maybe I fix it in the future 45 | uint32_t _setMotionCompensationClientId = 0; 46 | uint32_t _setMotionCompensationMessageId = 0; 47 | }; 48 | 49 | 50 | } // end namespace driver 51 | } // end namespace vrinputemulator 52 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/devicemanipulation/MotionCompensationManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "../logging.h" 7 | 8 | 9 | 10 | // driver namespace 11 | namespace vrinputemulator { 12 | namespace driver { 13 | 14 | 15 | // forward declarations 16 | class ServerDriver; 17 | class DeviceManipulationHandle; 18 | 19 | 20 | enum class MotionCompensationStatus : uint32_t { 21 | WaitingForZeroRef = 0, 22 | Running = 1, 23 | MotionRefNotTracking = 2 24 | }; 25 | 26 | 27 | class MotionCompensationManager { 28 | public: 29 | MotionCompensationManager(ServerDriver* parent) : m_parent(parent) {} 30 | 31 | void enableMotionCompensation(bool enable); 32 | MotionCompensationStatus motionCompensationStatus() { return _motionCompensationStatus; } 33 | void _setMotionCompensationStatus(MotionCompensationStatus status) { _motionCompensationStatus = status; } 34 | void setMotionCompensationRefDevice(DeviceManipulationHandle* device); 35 | DeviceManipulationHandle* getMotionCompensationRefDevice(); 36 | void setMotionCompensationVelAccMode(MotionCompensationVelAccMode velAccMode); 37 | double motionCompensationKalmanProcessVariance() { return m_motionCompensationKalmanProcessVariance; } 38 | void setMotionCompensationKalmanProcessVariance(double variance); 39 | double motionCompensationKalmanObservationVariance() { return m_motionCompensationKalmanObservationVariance; } 40 | void setMotionCompensationKalmanObservationVariance(double variance); 41 | double motionCompensationMovingAverageWindow() { return m_motionCompensationMovingAverageWindow; } 42 | void setMotionCompensationMovingAverageWindow(unsigned window); 43 | void _disableMotionCompensationOnAllDevices(); 44 | bool _isMotionCompensationZeroPoseValid(); 45 | void _setMotionCompensationZeroPose(const vr::DriverPose_t& pose); 46 | void _updateMotionCompensationRefPose(const vr::DriverPose_t& pose); 47 | bool _applyMotionCompensation(vr::DriverPose_t& pose, DeviceManipulationHandle* deviceInfo); 48 | 49 | void runFrame(); 50 | 51 | private: 52 | ServerDriver* m_parent; 53 | 54 | bool _motionCompensationEnabled = false; 55 | DeviceManipulationHandle* _motionCompensationRefDevice = nullptr; 56 | MotionCompensationStatus _motionCompensationStatus = MotionCompensationStatus::WaitingForZeroRef; 57 | constexpr static uint32_t _motionCompensationZeroRefTimeoutMax = 20; 58 | uint32_t _motionCompensationZeroRefTimeout = 0; 59 | MotionCompensationVelAccMode _motionCompensationVelAccMode = MotionCompensationVelAccMode::Disabled; 60 | double m_motionCompensationKalmanProcessVariance = 0.1; 61 | double m_motionCompensationKalmanObservationVariance = 0.1; 62 | unsigned m_motionCompensationMovingAverageWindow = 3; 63 | 64 | bool _motionCompensationZeroPoseValid = false; 65 | vr::HmdVector3d_t _motionCompensationZeroPos; 66 | vr::HmdQuaternion_t _motionCompensationZeroRot; 67 | 68 | bool _motionCompensationRefPoseValid = false; 69 | vr::HmdVector3d_t _motionCompensationRefPos; 70 | vr::HmdQuaternion_t _motionCompensationRotDiff; 71 | vr::HmdQuaternion_t _motionCompensationRotDiffInv; 72 | 73 | bool _motionCompensationRefVelAccValid = false; 74 | vr::HmdVector3d_t _motionCompensationRefPosVel; 75 | vr::HmdVector3d_t _motionCompensationRefPosAcc; 76 | vr::HmdVector3d_t _motionCompensationRefRotVel; 77 | vr::HmdVector3d_t _motionCompensationRefRotAcc; 78 | }; 79 | 80 | } 81 | } -------------------------------------------------------------------------------- /driver_vrinputemulator/src/devicemanipulation/utils/KalmanFilter.cpp: -------------------------------------------------------------------------------- 1 | #include "KalmanFilter.h" 2 | 3 | #include 4 | 5 | 6 | namespace vrinputemulator { 7 | namespace driver { 8 | 9 | void PosKalmanFilter::init(const vr::HmdVector3d_t& initPos, const vr::HmdVector3d_t& initVel, const double(&initCovariance)[2][2]) { 10 | lastPos = initPos; 11 | lastVel = initVel; 12 | lastCovariance[0][0] = initCovariance[0][0]; 13 | lastCovariance[0][1] = initCovariance[0][1]; 14 | lastCovariance[1][0] = initCovariance[1][0]; 15 | lastCovariance[1][1] = initCovariance[1][1]; 16 | } 17 | 18 | void PosKalmanFilter::update(const vr::HmdVector3d_t& devicePos, double dt) { 19 | // predict new position 20 | vr::HmdVector3d_t predictedPos = { 21 | lastPos.v[0] + dt * lastVel.v[0], 22 | lastPos.v[1] + dt * lastVel.v[1], 23 | lastPos.v[2] + dt * lastVel.v[2] 24 | }; 25 | // no need to predict new velocity: is equal to lastVel 26 | // predict new covariance matrix 27 | double newCovariance[2][2] = { 28 | lastCovariance[0][0] + dt * (lastCovariance[0][1] + lastCovariance[1][0]) + dt*dt* lastCovariance[1][1] + 1.0 / 4.0 * pow(dt, 4.0) * processNoise, 29 | lastCovariance[0][1] + dt * lastCovariance[1][1] + 1.0 / 2.0 * pow(dt, 3.0) * processNoise, 30 | lastCovariance[1][0] + dt * lastCovariance[1][1] + 1.0 / 2.0 * pow(dt, 3.0) * processNoise, 31 | lastCovariance[1][1] + dt*dt * processNoise 32 | }; 33 | // calculate innovation 34 | vr::HmdVector3d_t innovation = devicePos - predictedPos; 35 | // calculate innovation variance 36 | double innovationVariance = newCovariance[0][0] + observationNoise; 37 | // calculate kalman gain 38 | double gain[2]; 39 | if (innovationVariance == 0.0) { 40 | gain[0] = 1; 41 | gain[1] = 1; 42 | } else { 43 | gain[0] = newCovariance[0][0] / innovationVariance; 44 | gain[1] = newCovariance[1][0] / innovationVariance; 45 | } 46 | // calculate new a posteriori position 47 | lastPos = lastPos + innovation * gain[0]; 48 | // calculate new a posteriori velocity 49 | lastVel = lastVel + innovation * gain[1]; 50 | // calculate new a posteriori covariance matrix 51 | lastCovariance[0][0] = (1 - gain[0]) * newCovariance[0][0]; 52 | lastCovariance[0][1] = (1 - gain[0]) * newCovariance[0][1]; 53 | lastCovariance[1][0] = newCovariance[1][0] - gain[1] * newCovariance[0][0]; 54 | lastCovariance[1][1] = newCovariance[1][1] - gain[1] * newCovariance[0][1]; 55 | } 56 | 57 | } 58 | } // end namespace vrinputemulator 59 | 60 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/devicemanipulation/utils/KalmanFilter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // driver namespace 6 | namespace vrinputemulator { 7 | namespace driver { 8 | 9 | // Kalman filter to filter device positions (and get their velocity at the same time) 10 | class PosKalmanFilter { 11 | private: 12 | // last a posteriori state estimate 13 | vr::HmdVector3d_t lastPos = { 0.0, 0.0, 0.0 }; 14 | vr::HmdVector3d_t lastVel = { 0.0, 0.0, 0.0 }; 15 | // last a posteriori estimate covariance matrix 16 | double lastCovariance[2][2] = { 0.0, 0.0, 0.0, 0.0 }; 17 | // process noise variance 18 | double processNoise = 0.0; 19 | // observation noise variance 20 | double observationNoise = 0.0; 21 | public: 22 | void init(const vr::HmdVector3d_t& initPos = { 0, 0, 0 }, const vr::HmdVector3d_t& initVel = { 0, 0, 0 }, const double(&initCovariance)[2][2] = { { 100.0, 0.0 },{ 0.0, 100.0 } }); 23 | void setProcessNoise(double variance) { processNoise = variance; } 24 | void setObservationNoise(double variance) { observationNoise = variance; } 25 | 26 | void update(const vr::HmdVector3d_t& devicePos, double dt); 27 | 28 | const vr::HmdVector3d_t& getUpdatedPositionEstimate() { return lastPos; } 29 | const vr::HmdVector3d_t& getUpdatedVelocityEstimate() { return lastVel; } 30 | }; 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/devicemanipulation/utils/MovingAverageRingBuffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | // driver namespace 8 | namespace vrinputemulator { 9 | namespace driver { 10 | 11 | 12 | class MovingAverageRingBuffer { 13 | public: 14 | MovingAverageRingBuffer() noexcept : _buffer(new vr::HmdVector3d_t[1]), _bufferSize(1) {} 15 | MovingAverageRingBuffer(unsigned size) noexcept : _buffer(new vr::HmdVector3d_t[size > 0 ? size : 1]), _bufferSize(size > 0 ? size : 1) {} 16 | ~MovingAverageRingBuffer() noexcept { 17 | std::lock_guard lock(_mutex); 18 | if (_buffer) { 19 | delete[] _buffer; 20 | _buffer = nullptr; 21 | _bufferSize = _dataStart = _dataSize = 0; 22 | } 23 | } 24 | 25 | void resize(unsigned size) noexcept { 26 | std::lock_guard lock(_mutex); 27 | if (size == 0) { 28 | size = 1; 29 | } 30 | if (_buffer) { 31 | delete[] _buffer; 32 | } 33 | _buffer = new vr::HmdVector3d_t[size]; 34 | _bufferSize = size; 35 | _dataSize = _dataStart = 0; 36 | } 37 | 38 | unsigned bufferSize() noexcept { return _bufferSize; } 39 | 40 | unsigned dataSize() noexcept { return _dataSize; } 41 | 42 | void push(const vr::HmdVector3d_t& value) { 43 | if (_dataSize < _bufferSize) { 44 | _buffer[(_dataStart + _dataSize) % _bufferSize] = value; 45 | _dataSize++; 46 | } else { 47 | _buffer[_dataStart] = value; 48 | _dataStart = (_dataStart + 1) % _bufferSize; 49 | } 50 | } 51 | 52 | vr::HmdVector3d_t average() { 53 | if (_dataSize > 0) { 54 | vr::HmdVector3d_t sum = { 0.0, 0.0, 0.0 }; 55 | for (unsigned i = 0; i < _dataSize; i++) { 56 | sum = sum + _buffer[(_dataStart + i) % _bufferSize]; 57 | } 58 | return sum / _dataSize; 59 | } else { 60 | return vr::HmdVector3d_t(); 61 | } 62 | } 63 | 64 | private: 65 | std::mutex _mutex; 66 | vr::HmdVector3d_t* _buffer; 67 | unsigned _bufferSize; 68 | unsigned _dataStart = 0; 69 | unsigned _dataSize = 0; 70 | }; 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/dllmain.cpp: -------------------------------------------------------------------------------- 1 | #include "logging.h" 2 | 3 | const char* logConfigFileName = "logging.conf"; 4 | 5 | const char* logConfigDefault = 6 | "* GLOBAL:\n" 7 | " FORMAT = \"[%level] %datetime{%Y-%M-%d %H:%m:%s}: %msg\"\n" 8 | " FILENAME = \"driver_vrinputemulator.log\"\n" 9 | " ENABLED = true\n" 10 | " TO_FILE = true\n" 11 | " TO_STANDARD_OUTPUT = true\n" 12 | " MAX_LOG_FILE_SIZE = 2097152 ## 2MB\n" 13 | "* TRACE:\n" 14 | " ENABLED = false\n" 15 | "* DEBUG:\n" 16 | " ENABLED = false\n"; 17 | 18 | INITIALIZE_EASYLOGGINGPP 19 | 20 | void init_logging() { 21 | el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog); 22 | el::Configurations conf(logConfigFileName); 23 | conf.parseFromText(logConfigDefault); 24 | conf.parseFromFile(logConfigFileName); 25 | conf.setRemainingToDefault(); 26 | el::Loggers::reconfigureAllLoggers(conf); 27 | } 28 | 29 | BOOL APIENTRY DllMain( HMODULE hModule, 30 | DWORD ul_reason_for_call, 31 | LPVOID lpReserved 32 | ) { 33 | switch (ul_reason_for_call) { 34 | case DLL_PROCESS_ATTACH: 35 | init_logging(); 36 | LOG(INFO) << "VRInputEmulator dll loaded..."; 37 | break; 38 | case DLL_THREAD_ATTACH: 39 | case DLL_THREAD_DETACH: 40 | case DLL_PROCESS_DETACH: 41 | break; 42 | } 43 | return TRUE; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/driver/ServerDriver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../hooks/common.h" 10 | #include "../logging.h" 11 | #include "../com/shm/driver_ipc_shm.h" 12 | #include "../devicemanipulation/MotionCompensationManager.h" 13 | 14 | 15 | 16 | // driver namespace 17 | namespace vrinputemulator { 18 | namespace driver { 19 | 20 | 21 | // forward declarations 22 | class ServerDriver; 23 | class InterfaceHooks; 24 | class VirtualDeviceDriver; 25 | class DeviceManipulationHandle; 26 | 27 | 28 | /** 29 | * Implements the IServerTrackedDeviceProvider interface. 30 | * 31 | * Its the main entry point of the driver. It's a singleton which manages all devices owned by this driver, 32 | * and also handles the whole "hacking into OpenVR" stuff. 33 | */ 34 | class ServerDriver : public vr::IServerTrackedDeviceProvider { 35 | public: 36 | ServerDriver(); 37 | virtual ~ServerDriver(); 38 | 39 | //// from IServerTrackedDeviceProvider //// 40 | 41 | /** initializes the driver. This will be called before any other methods are called. */ 42 | virtual vr::EVRInitError Init(vr::IVRDriverContext *pDriverContext) override; 43 | 44 | /** cleans up the driver right before it is unloaded */ 45 | virtual void Cleanup() override; 46 | 47 | /** Returns the version of the ITrackedDeviceServerDriver interface used by this driver */ 48 | virtual const char * const *GetInterfaceVersions() { return vr::k_InterfaceVersions; } 49 | 50 | /** Allows the driver do to some work in the main loop of the server. Call frequency seems to be around 90Hz. */ 51 | virtual void RunFrame() override; 52 | 53 | /** Returns true if the driver wants to block Standby mode. */ 54 | virtual bool ShouldBlockStandbyMode() override { return false; } 55 | 56 | /** Called when the system is entering Standby mode */ 57 | virtual void EnterStandby() override {} 58 | 59 | /** Called when the system is leaving Standby mode */ 60 | virtual void LeaveStandby() override {} 61 | 62 | 63 | //// self //// 64 | 65 | static ServerDriver* getInstance() { return singleton; } 66 | 67 | static std::string getInstallDirectory() { return installDir; } 68 | 69 | uint32_t virtualDevices_getDeviceCount(); 70 | 71 | VirtualDeviceDriver* virtualDevices_getDevice(uint32_t unWhichDevice); 72 | 73 | VirtualDeviceDriver* virtualDevices_findDevice(const std::string& serial); 74 | 75 | int32_t virtualDevices_addDevice(VirtualDeviceType type, const std::string& serial); 76 | 77 | int32_t virtualDevices_publishDevice(uint32_t virtualDeviceId, bool notify = true); 78 | 79 | 80 | void openvr_buttonEvent(uint32_t unWhichDevice, ButtonEventType eventType, vr::EVRButtonId eButtonId, double eventTimeOffset); 81 | 82 | void openvr_axisEvent(uint32_t unWhichDevice, uint32_t unWhichAxis, const vr::VRControllerAxis_t& axisState); 83 | 84 | void openvr_poseUpdate(uint32_t unWhichDevice, vr::DriverPose_t& newPose, int64_t timestamp); 85 | 86 | void openvr_proximityEvent(uint32_t unWhichDevice, bool bProximitySensorTriggered); 87 | 88 | void openvr_vendorSpecificEvent(uint32_t unWhichDevice, vr::EVREventType eventType, vr::VREvent_Data_t & eventData, double eventTimeOffset); 89 | 90 | DeviceManipulationHandle* getDeviceManipulationHandleById(uint32_t unWhichDevice); 91 | DeviceManipulationHandle* getDeviceManipulationHandleByPropertyContainer(vr::PropertyContainerHandle_t container); 92 | 93 | 94 | // internal API 95 | 96 | void executeCodeForEachDeviceManipulationHandle(std::function code) { 97 | for (auto d : _deviceManipulationHandles) { 98 | code(d.second.get()); 99 | } 100 | } 101 | 102 | /** Called by virtual devices when they are activated */ 103 | void _trackedDeviceActivated(uint32_t deviceId, VirtualDeviceDriver* device); 104 | 105 | /** Called by virtual devices when they are deactivated */ 106 | void _trackedDeviceDeactivated(uint32_t deviceId); 107 | 108 | /* Motion Compensation related */ 109 | MotionCompensationManager& motionCompensation() { return m_motionCompensation; } 110 | void sendReplySetMotionCompensationMode(bool success); 111 | 112 | //// function hooks related //// 113 | void hooksTrackedDeviceAdded(void* serverDriverHost, int version, const char *pchDeviceSerialNumber, vr::ETrackedDeviceClass& eDeviceClass, void* pDriver); 114 | void hooksTrackedDeviceActivated(void* serverDriver, int version, uint32_t unObjectId); 115 | bool hooksTrackedDevicePoseUpdated(void* serverDriverHost, int version, uint32_t& unWhichDevice, vr::DriverPose_t& newPose, uint32_t& unPoseStructSize); 116 | bool hooksTrackedDeviceButtonPressed(void* serverDriverHost, int version, uint32_t& unWhichDevice, vr::EVRButtonId& eButtonId, double& eventTimeOffset); 117 | bool hooksTrackedDeviceButtonUnpressed(void* serverDriverHost, int version, uint32_t& unWhichDevice, vr::EVRButtonId& eButtonId, double& eventTimeOffset); 118 | bool hooksTrackedDeviceButtonTouched(void* serverDriverHost, int version, uint32_t& unWhichDevice, vr::EVRButtonId& eButtonId, double& eventTimeOffset); 119 | bool hooksTrackedDeviceButtonUntouched(void* serverDriverHost, int version, uint32_t& unWhichDevice, vr::EVRButtonId& eButtonId, double& eventTimeOffset); 120 | bool hooksTrackedDeviceAxisUpdated(void* serverDriverHost, int version, uint32_t& unWhichDevice, uint32_t& unWhichAxis, vr::VRControllerAxis_t& axisState); 121 | bool hooksPollNextEvent(void* serverDriverHost, int version, void* pEvent, uint32_t uncbVREvent); 122 | 123 | bool hooksControllerTriggerHapticPulse(void* controllerComponent, int version, uint32_t& unAxisId, uint16_t& usPulseDurationMicroseconds); 124 | 125 | void hooksPropertiesReadPropertyBatch(void* properties, int version, vr::PropertyContainerHandle_t ulContainer, void* pBatch, uint32_t unBatchEntryCount); 126 | void hooksPropertiesWritePropertyBatch(void* properties, int version, vr::PropertyContainerHandle_t ulContainer, void* pBatch, uint32_t unBatchEntryCount); 127 | 128 | void hooksCreateBooleanComponent(void* driverInput, int version, vr::PropertyContainerHandle_t ulContainer, const char *pchName, void* pHandle); 129 | void hooksCreateScalarComponent(void* driverInput, int version, vr::PropertyContainerHandle_t ulContainer, const char *pchName, void* pHandle, vr::EVRScalarType eType, vr::EVRScalarUnits eUnits); 130 | void hooksCreateHapticComponent(void* driverInput, int version, vr::PropertyContainerHandle_t ulContainer, const char *pchName, void* pHandle); 131 | bool hooksUpdateBooleanComponent(void* driverInput, int version, vr::VRInputComponentHandle_t& ulComponent, bool& bNewValue, double& fTimeOffset); 132 | bool hooksUpdateScalarComponent(void* driverInput, int version, vr::VRInputComponentHandle_t& ulComponent, float& fNewValue, double& fTimeOffset); 133 | 134 | // driver events injection 135 | void addDriverEventForInjection(void* serverDriverHost, std::shared_ptr event, uint32_t size); 136 | std::pair, uint32_t> getDriverEventForInjection(void* serverDriverHost); 137 | 138 | 139 | private: 140 | static ServerDriver* singleton; 141 | 142 | static std::string installDir; 143 | 144 | //// virtual devices related //// 145 | std::recursive_mutex _virtualDevicesMutex; 146 | uint32_t m_virtualDeviceCount = 0; 147 | std::shared_ptr m_virtualDevices[vr::k_unMaxTrackedDeviceCount]; 148 | VirtualDeviceDriver* m_openvrIdToVirtualDeviceMap[vr::k_unMaxTrackedDeviceCount]; 149 | 150 | //// ipc shm related //// 151 | IpcShmCommunicator shmCommunicator; 152 | 153 | //// device manipulation related //// 154 | std::recursive_mutex _deviceManipulationHandlesMutex; 155 | std::map> _deviceManipulationHandles; 156 | DeviceManipulationHandle* _openvrIdToDeviceManipulationHandleMap[vr::k_unMaxTrackedDeviceCount]; 157 | std::map _propertyContainerToDeviceManipulationHandleMap; 158 | std::map _ptrToDeviceManipulationHandleMap; 159 | std::map _inputComponentToDeviceManipulationHandleMap; 160 | 161 | //// motion compensation related //// 162 | MotionCompensationManager m_motionCompensation; 163 | 164 | //// function hooks related //// 165 | std::shared_ptr _driverContextHooks; 166 | 167 | // driver events injection 168 | std::mutex _driverEventInjectionMutex; 169 | std::map, uint32_t>>> m_eventsToInjectQueues; 170 | 171 | // Device Property Overrides 172 | std::string _propertiesOverrideHmdManufacturer; 173 | std::string _propertiesOverrideHmdModel; 174 | std::string _propertiesOverrideHmdTrackingSystem; 175 | bool _propertiesOverrideGenericTrackerFakeController; 176 | }; 177 | 178 | 179 | } // end namespace driver 180 | } // end namespace vrinputemulator 181 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/driver/VirtualDeviceDriver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "utils/DevicePropertyValueVisitor.h" 8 | 9 | 10 | 11 | // driver namespace 12 | namespace vrinputemulator { 13 | namespace driver { 14 | 15 | 16 | // forward declarations 17 | class ServerDriver; 18 | 19 | 20 | /** 21 | * Implements the ITrackedDeviceServerDriver interface. 22 | * 23 | * Represents a single virtual device managed by this driver. It has a serial number, a device type, device properties, a pose and components. 24 | **/ 25 | class VirtualDeviceDriver : public vr::ITrackedDeviceServerDriver, public vr::IVRControllerComponent { 26 | protected: 27 | std::recursive_mutex _mutex; 28 | 29 | ServerDriver* m_serverDriver; 30 | VirtualDeviceType m_deviceType; 31 | std::string m_serialNumber; 32 | uint32_t m_virtualDeviceId; 33 | uint32_t m_openvrId = vr::k_unTrackedDeviceIndexInvalid; 34 | bool m_published = false; 35 | bool m_periodicPoseUpdates = true; 36 | vr::PropertyContainerHandle_t m_propertyContainer = vr::k_ulInvalidPropertyContainer; 37 | 38 | vr::DriverPose_t m_pose; 39 | typedef boost::variant _devicePropertyType_t; 40 | std::map _deviceProperties; 41 | 42 | vr::VRControllerState_t m_ControllerState; 43 | 44 | public: 45 | VirtualDeviceDriver(ServerDriver* parent, VirtualDeviceType type, const std::string& serial, uint32_t virtualId = vr::k_unTrackedDeviceIndexInvalid); 46 | 47 | // from ITrackedDeviceServerDriver 48 | 49 | virtual vr::EVRInitError Activate(uint32_t unObjectId) override; 50 | virtual void Deactivate() override; 51 | virtual void EnterStandby() override {} 52 | virtual void *GetComponent(const char *pchComponentNameAndVersion) override; 53 | virtual void DebugRequest(const char *pchRequest, char *pchResponseBuffer, uint32_t unResponseBufferSize) override {} 54 | virtual vr::DriverPose_t GetPose() override; 55 | 56 | // from IVRControllerComponent 57 | 58 | virtual vr::VRControllerState_t GetControllerState() override; 59 | virtual bool TriggerHapticPulse(uint32_t unAxisId, uint16_t usPulseDurationMicroseconds) override; 60 | 61 | // from self 62 | 63 | const std::string& serialNumber() { return m_serialNumber; } 64 | VirtualDeviceType deviceType() { return m_deviceType; } 65 | bool published() { return m_published; } 66 | bool periodicPoseUpdates() { return m_periodicPoseUpdates; } 67 | 68 | ServerDriver* serverDriver() { return m_serverDriver; } 69 | uint32_t openvrDeviceId() { return m_openvrId; } 70 | uint32_t virtualDeviceId() { return m_virtualDeviceId; } 71 | 72 | vr::DriverPose_t& driverPose() { return m_pose; } 73 | 74 | bool enablePeriodicPoseUpdates(bool enabled) { return m_periodicPoseUpdates; } 75 | void publish(); 76 | 77 | void updatePose(const vr::DriverPose_t& newPose, double timeOffset, bool notify = true); 78 | void sendPoseUpdate(double timeOffset = 0.0, bool onlyWhenConnected = true); 79 | 80 | template 81 | T getTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError * pError) { 82 | std::lock_guard lock(_mutex); 83 | if (pError) { 84 | *pError = vr::TrackedProp_Success; 85 | } 86 | auto p = _deviceProperties.find((int)prop); 87 | if (p != _deviceProperties.end()) { 88 | try { 89 | T retval = boost::get(p->second); 90 | return retval; 91 | } catch (std::exception&) { 92 | if (pError) { 93 | *pError = vr::TrackedProp_WrongDataType; 94 | } 95 | return T(); 96 | } 97 | } else { 98 | if (pError) { 99 | *pError = vr::TrackedProp_ValueNotProvidedByDevice; 100 | } 101 | return T(); 102 | } 103 | } 104 | 105 | template 106 | void setTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, const T& value, bool notify = true) { 107 | std::lock_guard lock(_mutex); 108 | _deviceProperties[prop] = value; 109 | if (notify && m_openvrId != vr::k_unTrackedDeviceIndexInvalid) { 110 | auto errorMessage = boost::apply_visitor(DevicePropertyValueVisitor(m_propertyContainer, prop), _deviceProperties[prop]); 111 | if (!errorMessage.empty()) { 112 | LOG(ERROR) << "Could not set tracked device property: " << errorMessage; 113 | } 114 | } 115 | } 116 | 117 | void removeTrackedDeviceProperty(vr::ETrackedDeviceProperty prop, bool notify = true) { 118 | std::lock_guard lock(_mutex); 119 | auto i = _deviceProperties.find(prop); 120 | if (i != _deviceProperties.end()) { 121 | _deviceProperties.erase(i); 122 | if (notify && m_openvrId != vr::k_unTrackedDeviceIndexInvalid) { 123 | vr::VRProperties()->EraseProperty(m_propertyContainer, prop); 124 | } 125 | } 126 | } 127 | 128 | vr::VRControllerState_t& controllerState() { return m_ControllerState; } 129 | 130 | void updateControllerState(const vr::VRControllerState_t& newState, double timeOffset, bool notify = true); 131 | void buttonEvent(ButtonEventType eventType, uint32_t buttonId, double timeOffset, bool notify = true); 132 | void axisEvent(uint32_t axisId, const vr::VRControllerAxis_t& axisState, bool notify = true); 133 | }; 134 | 135 | 136 | } // end namespace driver 137 | } // end namespace vrinputemulator 138 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/driver/WatchdogProvider.cpp: -------------------------------------------------------------------------------- 1 | #include "WatchdogProvider.h" 2 | 3 | #include "../logging.h" 4 | 5 | 6 | // driver namespace 7 | namespace vrinputemulator { 8 | namespace driver { 9 | 10 | 11 | vr::EVRInitError WatchdogProvider::Init(vr::IVRDriverContext * pDriverContext) { 12 | LOG(TRACE) << "WatchdogProvider::Init()"; 13 | VR_INIT_WATCHDOG_DRIVER_CONTEXT(pDriverContext); 14 | return vr::VRInitError_None; 15 | } 16 | 17 | 18 | void WatchdogProvider::Cleanup() { 19 | LOG(TRACE) << "WatchdogProvider::Cleanup()"; 20 | VR_CLEANUP_WATCHDOG_DRIVER_CONTEXT(); 21 | } 22 | 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/driver/WatchdogProvider.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | 6 | // driver namespace 7 | namespace vrinputemulator { 8 | namespace driver { 9 | 10 | 11 | /** 12 | * Implements the IVRWatchdogProvider interface. 13 | * 14 | * Its only purpose seems to be to start SteamVR by calling WatchdogWakeUp() from the IVRWatchdogHost interface. 15 | * Valve probably uses this interface to start SteamVR whenever a button is pressed on the controller or hmd. 16 | * We must implement it but currently we don't use it for anything. 17 | */ 18 | class WatchdogProvider : public vr::IVRWatchdogProvider { 19 | public: 20 | /** initializes the driver in watchdog mode. */ 21 | virtual vr::EVRInitError Init(vr::IVRDriverContext *pDriverContext) override; 22 | 23 | /** cleans up the driver right before it is unloaded */ 24 | virtual void Cleanup() override; 25 | }; 26 | 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/driver/utils/DevicePropertyValueVisitor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | namespace vrinputemulator { 8 | namespace driver { 9 | 10 | 11 | class DevicePropertyValueVisitor : public boost::static_visitor { 12 | private: 13 | vr::PropertyContainerHandle_t propertyContainer; 14 | vr::ETrackedDeviceProperty deviceProperty; 15 | public: 16 | DevicePropertyValueVisitor() = delete; 17 | DevicePropertyValueVisitor(vr::PropertyContainerHandle_t& propertyContainer, vr::ETrackedDeviceProperty deviceProperty) 18 | : propertyContainer(propertyContainer), deviceProperty(deviceProperty) {} 19 | template 20 | std::string operator()(T& i) const { 21 | return "Unknown value type"; 22 | } 23 | template<> 24 | std::string operator()(int32_t& val) const { 25 | auto pError = vr::VRProperties()->SetInt32Property(propertyContainer, deviceProperty, val); 26 | if (pError == vr::TrackedProp_Success) { 27 | return ""; 28 | } else { 29 | return std::string("OpenVR returned an error: ") + std::to_string((int)pError); 30 | } 31 | } 32 | template<> 33 | std::string operator()(uint64_t& val) const { 34 | auto pError = vr::VRProperties()->SetUint64Property(propertyContainer, deviceProperty, val); 35 | if (pError == vr::TrackedProp_Success) { 36 | return ""; 37 | } else { 38 | return std::string("OpenVR returned an error: ") + std::to_string((int)pError); 39 | } 40 | } 41 | template<> 42 | std::string operator()(float& val) const { 43 | auto pError = vr::VRProperties()->SetFloatProperty(propertyContainer, deviceProperty, val); 44 | if (pError == vr::TrackedProp_Success) { 45 | return ""; 46 | } else { 47 | return std::string("OpenVR returned an error: ") + std::to_string((int)pError); 48 | } 49 | } 50 | template<> 51 | std::string operator()(bool& val) const { 52 | auto pError = vr::VRProperties()->SetBoolProperty(propertyContainer, deviceProperty, val); 53 | if (pError == vr::TrackedProp_Success) { 54 | return ""; 55 | } else { 56 | return std::string("OpenVR returned an error: ") + std::to_string((int)pError); 57 | } 58 | } 59 | template<> 60 | std::string operator()(std::string& val) const { 61 | auto pError = vr::VRProperties()->SetStringProperty(propertyContainer, deviceProperty, val.c_str()); 62 | if (pError == vr::TrackedProp_Success) { 63 | return ""; 64 | } else { 65 | return std::string("OpenVR returned an error: ") + std::to_string((int)pError); 66 | } 67 | } 68 | template<> 69 | std::string operator()(vr::HmdMatrix34_t& val) const { 70 | auto pError = vr::VRProperties()->SetProperty(propertyContainer, deviceProperty, &val, sizeof(vr::HmdMatrix34_t), vr::k_unHmdMatrix34PropertyTag); 71 | if (pError == vr::TrackedProp_Success) { 72 | return ""; 73 | } else { 74 | return std::string("OpenVR returned an error: ") + std::to_string((int)pError); 75 | } 76 | } 77 | template<> 78 | std::string operator()(vr::HmdMatrix44_t& val) const { 79 | auto pError = vr::VRProperties()->SetProperty(propertyContainer, deviceProperty, &val, sizeof(vr::HmdMatrix44_t), vr::k_unHmdMatrix44PropertyTag); 80 | if (pError == vr::TrackedProp_Success) { 81 | return ""; 82 | } else { 83 | return std::string("OpenVR returned an error: ") + std::to_string((int)pError); 84 | } 85 | } 86 | template<> 87 | std::string operator()(vr::HmdVector3_t& val) const { 88 | auto pError = vr::VRProperties()->SetProperty(propertyContainer, deviceProperty, &val, sizeof(vr::HmdVector3_t), vr::k_unHmdVector3PropertyTag); 89 | if (pError == vr::TrackedProp_Success) { 90 | return ""; 91 | } else { 92 | return std::string("OpenVR returned an error: ") + std::to_string((int)pError); 93 | } 94 | } 95 | template<> 96 | std::string operator()(vr::HmdVector4_t& val) const { 97 | auto pError = vr::VRProperties()->SetProperty(propertyContainer, deviceProperty, &val, sizeof(vr::HmdVector4_t), vr::k_unHmdVector4PropertyTag); 98 | if (pError == vr::TrackedProp_Success) { 99 | return ""; 100 | } else { 101 | return std::string("OpenVR returned an error: ") + std::to_string((int)pError); 102 | } 103 | } 104 | }; 105 | 106 | 107 | } // end namespace driver 108 | } // end namespace vrinputemulator 109 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/driver_vrinputemulator.cpp: -------------------------------------------------------------------------------- 1 | #include "driver/ServerDriver.h" 2 | #include "driver/WatchdogProvider.h" 3 | 4 | 5 | vrinputemulator::driver::ServerDriver serverDriver; 6 | vrinputemulator::driver::WatchdogProvider watchdogProvider; 7 | 8 | 9 | #define HMD_DLL_EXPORT extern "C" __declspec( dllexport ) 10 | 11 | 12 | HMD_DLL_EXPORT void *HmdDriverFactory(const char *pInterfaceName, int *pReturnCode) { 13 | LOG(TRACE) << "HmdDriverFactory( " << pInterfaceName << " )"; 14 | if (std::strcmp(vr::IServerTrackedDeviceProvider_Version, pInterfaceName) == 0){ 15 | return &serverDriver; 16 | } else if (std::strcmp(vr::IVRWatchdogProvider_Version, pInterfaceName) == 0) { 17 | return &watchdogProvider; 18 | } 19 | if (pReturnCode) { 20 | *pReturnCode = vr::VRInitError_Init_InterfaceNotFound; 21 | } 22 | return nullptr; 23 | } 24 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/hooks/ITrackedDeviceServerDriver005Hooks.cpp: -------------------------------------------------------------------------------- 1 | #include "ITrackedDeviceServerDriver005Hooks.h" 2 | 3 | #include "../driver/ServerDriver.h" 4 | 5 | 6 | namespace vrinputemulator { 7 | namespace driver { 8 | 9 | 10 | std::map> ITrackedDeviceServerDriver005Hooks::_hookedActivateAdressMap; 11 | 12 | 13 | ITrackedDeviceServerDriver005Hooks::ITrackedDeviceServerDriver005Hooks(void* iptr) { 14 | LOG(TRACE) << "ITrackedDeviceServerDriver005Hooks::ctr(" << iptr << ")"; 15 | auto vtable = (*((void***)iptr)); 16 | activateAddress = vtable[0]; 17 | auto it = _hookedActivateAdressMap.find(activateAddress); 18 | if (it == _hookedActivateAdressMap.end()) { 19 | CREATE_MH_HOOK(activateHook, _activate, "ITrackedDeviceServerDriver005::Activate", iptr, 0); 20 | _hookedActivateAdressMap[activateAddress].useCount = 1; 21 | _hookedActivateAdressMap[activateAddress].hookData = activateHook; 22 | } else { 23 | activateHook = it->second.hookData; 24 | it->second.useCount += 1; 25 | } 26 | } 27 | 28 | 29 | std::shared_ptr ITrackedDeviceServerDriver005Hooks::createHooks(void * iptr) { 30 | std::shared_ptr retval = std::shared_ptr(new ITrackedDeviceServerDriver005Hooks(iptr)); 31 | return retval; 32 | } 33 | 34 | ITrackedDeviceServerDriver005Hooks::~ITrackedDeviceServerDriver005Hooks() { 35 | auto it = _hookedActivateAdressMap.find(activateAddress); 36 | if (it != _hookedActivateAdressMap.end()) { 37 | if (it->second.useCount <= 1) { 38 | REMOVE_MH_HOOK(activateHook); 39 | _hookedActivateAdressMap.erase(it); 40 | } else { 41 | it->second.useCount -= 1; 42 | } 43 | } 44 | } 45 | 46 | 47 | vr::EVRInitError ITrackedDeviceServerDriver005Hooks::_activate(void* _this, uint32_t unObjectId) { 48 | LOG(TRACE) << "ITrackedDeviceServerDriver005Hooks::_activate(" << _this << ", " << unObjectId << ")"; 49 | auto vtable = (*((void***)_this)); 50 | auto activateAddress = vtable[0]; 51 | auto it = _hookedActivateAdressMap.find(activateAddress); 52 | if (it != _hookedActivateAdressMap.end()) { 53 | serverDriver->hooksTrackedDeviceActivated(_this, 5, unObjectId); 54 | return it->second.hookData.origFunc(_this, unObjectId); 55 | } else { 56 | LOG(ERROR) << "this pointer not in ITrackedDeviceServerDriver005Hooks::_hookedActivateAdressMap."; 57 | return vr::VRInitError_Unknown; 58 | } 59 | } 60 | 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/hooks/ITrackedDeviceServerDriver005Hooks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common.h" 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | namespace vrinputemulator { 10 | namespace driver { 11 | 12 | // forward declarations 13 | class ServerDriver; 14 | 15 | 16 | class ITrackedDeviceServerDriver005Hooks : public InterfaceHooks { 17 | public: 18 | typedef vr::EVRInitError (*activate_t)(void*, uint32_t unObjectId); 19 | 20 | static std::shared_ptr createHooks(void* iptr); 21 | virtual ~ITrackedDeviceServerDriver005Hooks(); 22 | 23 | private: 24 | HookData activateHook; 25 | void* activateAddress = nullptr; 26 | 27 | ITrackedDeviceServerDriver005Hooks(void* iptr); 28 | 29 | template 30 | struct _hookedAdressMapEntry { 31 | unsigned useCount = 0; 32 | HookData hookData; 33 | }; 34 | static std::map> _hookedActivateAdressMap; 35 | 36 | static vr::EVRInitError _activate(void*, uint32_t unObjectId); 37 | 38 | }; 39 | 40 | } 41 | } 42 | 43 | 44 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/hooks/IVRControllerComponent001Hooks.cpp: -------------------------------------------------------------------------------- 1 | #include "IVRControllerComponent001Hooks.h" 2 | 3 | #include "../driver/ServerDriver.h" 4 | 5 | 6 | namespace vrinputemulator { 7 | namespace driver { 8 | 9 | 10 | std::map> IVRControllerComponent001Hooks::_hookedTriggerHapticPulseAdressMap; 11 | 12 | 13 | IVRControllerComponent001Hooks::IVRControllerComponent001Hooks(void* iptr) : controllerComponent(iptr) { 14 | LOG(TRACE) << "IVRControllerComponent001Hooks::ctr(" << iptr << ")"; 15 | auto vtable = (*((void***)iptr)); 16 | triggerHapicPulseAddress = vtable[1]; 17 | auto it = _hookedTriggerHapticPulseAdressMap.find(triggerHapicPulseAddress); 18 | if (it == _hookedTriggerHapticPulseAdressMap.end()) { 19 | CREATE_MH_HOOK(triggerHapicPulseHook, _triggerHapticPulse, "IVRControllerComponent001Hooks::TriggerHapticPulse", iptr, 1); 20 | _hookedTriggerHapticPulseAdressMap[triggerHapicPulseAddress].useCount = 1; 21 | _hookedTriggerHapticPulseAdressMap[triggerHapicPulseAddress].hookData = triggerHapicPulseHook; 22 | } else { 23 | triggerHapicPulseHook = it->second.hookData; 24 | it->second.useCount += 1; 25 | } 26 | } 27 | 28 | 29 | std::shared_ptr IVRControllerComponent001Hooks::createHooks(void * iptr) { 30 | std::shared_ptr retval = std::shared_ptr(new IVRControllerComponent001Hooks(iptr)); 31 | return retval; 32 | } 33 | 34 | 35 | IVRControllerComponent001Hooks::~IVRControllerComponent001Hooks() { 36 | auto it = _hookedTriggerHapticPulseAdressMap.find(triggerHapicPulseAddress); 37 | if (it != _hookedTriggerHapticPulseAdressMap.end()) { 38 | if (it->second.useCount <= 1) { 39 | REMOVE_MH_HOOK(triggerHapicPulseHook); 40 | _hookedTriggerHapticPulseAdressMap.erase(it); 41 | } else { 42 | it->second.useCount -= 1; 43 | } 44 | } 45 | } 46 | 47 | bool IVRControllerComponent001Hooks::triggerHapticPulseOrig(uint32_t unAxisId, uint16_t usPulseDurationMicroseconds) { 48 | return triggerHapicPulseHook.origFunc(controllerComponent, unAxisId, usPulseDurationMicroseconds); 49 | } 50 | 51 | 52 | bool IVRControllerComponent001Hooks::_triggerHapticPulse(void* _this, uint32_t unAxisId, uint16_t usPulseDurationMicroseconds) { 53 | LOG(TRACE) << "IVRControllerComponent001Hooks::_triggerHapticPulse(" << _this << ", " << unAxisId << ", " << usPulseDurationMicroseconds << ")"; 54 | if (serverDriver->hooksControllerTriggerHapticPulse(_this, 1, unAxisId, usPulseDurationMicroseconds)) { 55 | auto vtable = (*((void***)_this)); 56 | auto triggerHapticAddress = vtable[1]; 57 | auto it = _hookedTriggerHapticPulseAdressMap.find(triggerHapticAddress); 58 | if (it != _hookedTriggerHapticPulseAdressMap.end()) { 59 | return it->second.hookData.origFunc(_this, unAxisId, usPulseDurationMicroseconds); 60 | } else { 61 | LOG(ERROR) << "this pointer not in IVRControllerComponent001Hooks::_hookedTriggerHapticPulseAdressMap."; 62 | } 63 | } 64 | return true; 65 | } 66 | 67 | 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/hooks/IVRControllerComponent001Hooks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common.h" 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | namespace vrinputemulator { 10 | namespace driver { 11 | 12 | // forward declarations 13 | class ServerDriver; 14 | 15 | 16 | class IVRControllerComponent001Hooks : public InterfaceHooks { 17 | public: 18 | typedef bool(*triggerHapticPulse_t)(void*, uint32_t unAxisId, uint16_t usPulseDurationMicroseconds); 19 | 20 | static std::shared_ptr createHooks(void* iptr); 21 | virtual ~IVRControllerComponent001Hooks(); 22 | 23 | bool triggerHapticPulseOrig(uint32_t unAxisId, uint16_t usPulseDurationMicroseconds); 24 | 25 | private: 26 | HookData triggerHapicPulseHook; 27 | void* triggerHapicPulseAddress; 28 | void* controllerComponent; 29 | 30 | IVRControllerComponent001Hooks(void* iptr); 31 | 32 | template 33 | struct _hookedAdressMapEntry { 34 | unsigned useCount = 0; 35 | HookData hookData; 36 | }; 37 | static std::map> _hookedTriggerHapticPulseAdressMap; 38 | 39 | static bool _triggerHapticPulse(void* _this, uint32_t unAxisId, uint16_t usPulseDurationMicroseconds); 40 | 41 | }; 42 | 43 | 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/hooks/IVRDriverContextHooks.cpp: -------------------------------------------------------------------------------- 1 | #include "IVRDriverContextHooks.h" 2 | 3 | 4 | namespace vrinputemulator { 5 | namespace driver { 6 | 7 | 8 | HookData IVRDriverContextHooks::getGenericInterfaceHook; 9 | std::map> IVRDriverContextHooks::_hookedInterfaces; 10 | 11 | 12 | IVRDriverContextHooks::IVRDriverContextHooks(void* iptr) { 13 | if (!_isHooked) { 14 | CREATE_MH_HOOK(getGenericInterfaceHook, _getGenericInterface, "IVRDriverContext::GetGenericInterface", iptr, 0); 15 | _isHooked = true; 16 | } 17 | } 18 | 19 | 20 | IVRDriverContextHooks::~IVRDriverContextHooks() { 21 | if (_isHooked) { 22 | REMOVE_MH_HOOK(getGenericInterfaceHook); 23 | _isHooked = false; 24 | } 25 | } 26 | 27 | 28 | std::shared_ptr IVRDriverContextHooks::createHooks(void * iptr) { 29 | std::shared_ptr retval = std::shared_ptr(new IVRDriverContextHooks(iptr)); 30 | return retval; 31 | } 32 | 33 | std::shared_ptr IVRDriverContextHooks::getInterfaceHook(std::string interfaceVersion) { 34 | auto it = _hookedInterfaces.find(interfaceVersion); 35 | if (it != _hookedInterfaces.end()){ 36 | return it->second; 37 | } 38 | return nullptr; 39 | } 40 | 41 | 42 | void* IVRDriverContextHooks::_getGenericInterface(vr::IVRDriverContext* _this, const char *pchInterfaceVersion, vr::EVRInitError *peError) { 43 | auto retval = getGenericInterfaceHook.origFunc(_this, pchInterfaceVersion, peError); 44 | if (_hookedInterfaces.find(pchInterfaceVersion) == _hookedInterfaces.end()) { 45 | auto hooks = InterfaceHooks::hookInterface(retval, pchInterfaceVersion); 46 | if (hooks != nullptr) { 47 | _hookedInterfaces.insert({ std::string(pchInterfaceVersion), hooks }); 48 | } 49 | } 50 | LOG(TRACE) << "IVRDriverContextHooks::_getGenericInterface(" << _this << ", " << pchInterfaceVersion << ") = " << retval; 51 | return retval; 52 | } 53 | 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/hooks/IVRDriverContextHooks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common.h" 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | namespace vrinputemulator { 10 | namespace driver { 11 | 12 | // forward declarations 13 | class ServerDriver; 14 | 15 | 16 | class IVRDriverContextHooks : public InterfaceHooks { 17 | public: 18 | typedef void*(*getGenericInterface_t)(vr::IVRDriverContext*, const char *pchInterfaceVersion, vr::EVRInitError *peError); 19 | 20 | static std::shared_ptr getInterfaceHook(std::string interfaceVersion); 21 | 22 | static std::shared_ptr createHooks(void* iptr); 23 | virtual ~IVRDriverContextHooks(); 24 | 25 | private: 26 | bool _isHooked = false; 27 | 28 | IVRDriverContextHooks(void* iptr); 29 | 30 | static HookData getGenericInterfaceHook; 31 | 32 | static std::map> _hookedInterfaces; 33 | static void* _getGenericInterface(vr::IVRDriverContext*, const char *pchInterfaceVersion, vr::EVRInitError *peError); 34 | 35 | }; 36 | 37 | } 38 | } 39 | 40 | 41 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/hooks/IVRDriverInput001Hooks.cpp: -------------------------------------------------------------------------------- 1 | #include "IVRDriverInput001Hooks.h" 2 | 3 | #include "../driver/ServerDriver.h" 4 | 5 | 6 | namespace vrinputemulator { 7 | namespace driver { 8 | 9 | 10 | HookData IVRDriverInput001Hooks::createBooleanComponentHook; 11 | HookData IVRDriverInput001Hooks::updateBooleanComponentHook; 12 | HookData IVRDriverInput001Hooks::createScalarComponentHook; 13 | HookData IVRDriverInput001Hooks::updateScalarComponentHook; 14 | HookData IVRDriverInput001Hooks::createHapticComponentHook; 15 | 16 | 17 | IVRDriverInput001Hooks::IVRDriverInput001Hooks(void* iptr) { 18 | if (!_isHooked) { 19 | CREATE_MH_HOOK(createBooleanComponentHook, _createBooleanComponent, "IVRDriverInput001Hooks::CreateBooleanComponent", iptr, 0); 20 | CREATE_MH_HOOK(updateBooleanComponentHook, _updateBooleanComponent, "IVRDriverInput001Hooks::UpdateBooleanComponent", iptr, 1); 21 | CREATE_MH_HOOK(createScalarComponentHook, _createScalarComponent, "IVRDriverInput001Hooks::CreateScalarComponent", iptr, 2); 22 | CREATE_MH_HOOK(updateScalarComponentHook, _updateScalarComponent, "IVRDriverInput001Hooks::UpdateScalarComponent", iptr, 3); 23 | CREATE_MH_HOOK(createHapticComponentHook, _createHapticComponent, "IVRDriverInput001Hooks::CreateHapticComponent", iptr, 4); 24 | _isHooked = true; 25 | } 26 | } 27 | 28 | 29 | IVRDriverInput001Hooks::~IVRDriverInput001Hooks() { 30 | if (_isHooked) { 31 | REMOVE_MH_HOOK(createBooleanComponentHook); 32 | REMOVE_MH_HOOK(updateBooleanComponentHook); 33 | REMOVE_MH_HOOK(createScalarComponentHook); 34 | REMOVE_MH_HOOK(updateScalarComponentHook); 35 | REMOVE_MH_HOOK(createHapticComponentHook); 36 | _isHooked = false; 37 | } 38 | } 39 | 40 | 41 | std::shared_ptr IVRDriverInput001Hooks::createHooks(void * iptr) { 42 | std::shared_ptr retval = std::shared_ptr(new IVRDriverInput001Hooks(iptr)); 43 | return retval; 44 | } 45 | 46 | vr::EVRInputError IVRDriverInput001Hooks::updateBooleanComponentOrig(void* _this, vr::VRInputComponentHandle_t ulComponent, bool bNewValue, double fTimeOffset) { 47 | return updateBooleanComponentHook.origFunc(_this, ulComponent, bNewValue, fTimeOffset); 48 | } 49 | 50 | vr::EVRInputError IVRDriverInput001Hooks::updateScalarComponentOrig(void* _this, vr::VRInputComponentHandle_t ulComponent, float fNewValue, double fTimeOffset) { 51 | return updateScalarComponentHook.origFunc(_this, ulComponent, fNewValue, fTimeOffset); 52 | } 53 | 54 | 55 | vr::EVRInputError IVRDriverInput001Hooks::_createBooleanComponent(void* _this, vr::PropertyContainerHandle_t ulContainer, const char *pchName, void* pHandle) { 56 | auto retval = createBooleanComponentHook.origFunc(_this, ulContainer, pchName, pHandle); 57 | if (retval == 0) { 58 | serverDriver->hooksCreateBooleanComponent(_this, 1, ulContainer, pchName, pHandle); 59 | } 60 | LOG(TRACE) << "IVRDriverInput001Hooks::_createBooleanComponent(" << _this << ", " << ulContainer << ", " << pchName << ", " << pHandle << ") = " << (int)retval; 61 | return retval; 62 | } 63 | 64 | vr::EVRInputError IVRDriverInput001Hooks::_updateBooleanComponent(void* _this, vr::VRInputComponentHandle_t ulComponent, bool bNewValue, double fTimeOffset) { 65 | LOG(TRACE) << "IVRDriverInput001Hooks::_updateBooleanComponent(" << _this << ", " << ulComponent << ", " << bNewValue << ", " << fTimeOffset << ")"; 66 | if (serverDriver->hooksUpdateBooleanComponent(_this, 1, ulComponent, bNewValue, fTimeOffset)) { 67 | return updateBooleanComponentHook.origFunc(_this, ulComponent, bNewValue, fTimeOffset); 68 | } 69 | return (vr::EVRInputError)0; 70 | } 71 | 72 | vr::EVRInputError IVRDriverInput001Hooks::_createScalarComponent(void* _this, vr::PropertyContainerHandle_t ulContainer, const char *pchName, void* pHandle, vr::EVRScalarType eType, vr::EVRScalarUnits eUnits) { 73 | auto retval = createScalarComponentHook.origFunc(_this, ulContainer, pchName, pHandle, eType, eUnits); 74 | if (retval == 0) { 75 | serverDriver->hooksCreateScalarComponent(_this, 1, ulContainer, pchName, pHandle, eType, eUnits); 76 | } 77 | LOG(TRACE) << "IVRDriverInput001Hooks::_createScalarComponent(" << _this << ", " << ulContainer << ", " << pchName << ", " << pHandle << ", " << (int)eType << ", " << (int)eUnits << ") = " << (int)retval; 78 | return retval; 79 | } 80 | 81 | vr::EVRInputError IVRDriverInput001Hooks::_updateScalarComponent(void* _this, vr::VRInputComponentHandle_t ulComponent, float fNewValue, double fTimeOffset) { 82 | LOG(TRACE) << "IVRDriverInput001Hooks::_updateScalarComponent(" << _this << ", " << ulComponent << ", " << fNewValue << ", " << fTimeOffset << ")"; 83 | if (serverDriver->hooksUpdateScalarComponent(_this, 1, ulComponent, fNewValue, fTimeOffset)) { 84 | return updateScalarComponentHook.origFunc(_this, ulComponent, fNewValue, fTimeOffset); 85 | } 86 | return (vr::EVRInputError)0; 87 | } 88 | 89 | vr::EVRInputError IVRDriverInput001Hooks::_createHapticComponent(void* _this, vr::PropertyContainerHandle_t ulContainer, const char *pchName, void* pHandle) { 90 | auto retval = createHapticComponentHook.origFunc(_this, ulContainer, pchName, pHandle); 91 | if (retval == 0) { 92 | serverDriver->hooksCreateHapticComponent(_this, 1, ulContainer, pchName, pHandle); 93 | } 94 | LOG(TRACE) << "IVRDriverInput001Hooks::_createHapticComponent(" << _this << ", " << ulContainer << ", " << pchName << ", " << pHandle << ") = " << (int)retval; 95 | return retval; 96 | } 97 | 98 | 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/hooks/IVRDriverInput001Hooks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common.h" 4 | #include 5 | #include 6 | 7 | 8 | namespace vrinputemulator { 9 | namespace driver { 10 | 11 | 12 | class IVRDriverInput001Hooks : public InterfaceHooks { 13 | public: 14 | typedef vr::EVRInputError(*createBooleanComponent_t)(void*, vr::PropertyContainerHandle_t, const char*, void*); 15 | typedef vr::EVRInputError(*updateBooleanComponent_t)(void*, vr::VRInputComponentHandle_t, bool, double); 16 | typedef vr::EVRInputError(*createScalarComponent_t)(void*, vr::PropertyContainerHandle_t, const char*, void*, vr::EVRScalarType, vr::EVRScalarUnits); 17 | typedef vr::EVRInputError(*updateScalarComponent_t)(void*, vr::VRInputComponentHandle_t, float, double); 18 | typedef vr::EVRInputError(*createHapticComponent_t)(void*, vr::PropertyContainerHandle_t, const char*, void*); 19 | 20 | static std::shared_ptr createHooks(void* iptr); 21 | virtual ~IVRDriverInput001Hooks(); 22 | 23 | static vr::EVRInputError updateBooleanComponentOrig(void* _this, vr::VRInputComponentHandle_t ulComponent, bool bNewValue, double fTimeOffset); 24 | static vr::EVRInputError updateScalarComponentOrig(void* _this, vr::VRInputComponentHandle_t ulComponent, float fNewValue, double fTimeOffset); 25 | 26 | private: 27 | bool _isHooked = false; 28 | 29 | IVRDriverInput001Hooks(void* iptr); 30 | 31 | static HookData createBooleanComponentHook; 32 | static HookData updateBooleanComponentHook; 33 | static HookData createScalarComponentHook; 34 | static HookData updateScalarComponentHook; 35 | static HookData createHapticComponentHook; 36 | 37 | static vr::EVRInputError _createBooleanComponent(void* _this, vr::PropertyContainerHandle_t ulContainer, const char *pchName, void* pHandle); 38 | static vr::EVRInputError _updateBooleanComponent(void* _this, vr::VRInputComponentHandle_t ulComponent, bool bNewValue, double fTimeOffset); 39 | static vr::EVRInputError _createScalarComponent(void* _this, vr::PropertyContainerHandle_t ulContainer, const char *pchName, void* pHandle, vr::EVRScalarType eType, vr::EVRScalarUnits eUnits); 40 | static vr::EVRInputError _updateScalarComponent(void* _this, vr::VRInputComponentHandle_t ulComponent, float fNewValue, double fTimeOffset); 41 | static vr::EVRInputError _createHapticComponent(void* _this, vr::PropertyContainerHandle_t ulContainer, const char *pchName, void* pHandle); 42 | 43 | }; 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/hooks/IVRProperties001Hooks.cpp: -------------------------------------------------------------------------------- 1 | #include "IVRProperties001Hooks.h" 2 | 3 | #include "../driver/ServerDriver.h" 4 | 5 | 6 | namespace vrinputemulator { 7 | namespace driver { 8 | 9 | 10 | HookData IVRProperties001Hooks::readPropertyBatchHook; 11 | HookData IVRProperties001Hooks::writePropertyBatchHook; 12 | 13 | 14 | IVRProperties001Hooks::IVRProperties001Hooks(void* iptr) { 15 | if (!_isHooked) { 16 | CREATE_MH_HOOK(readPropertyBatchHook, _readPropertyBatch, "IVRproperties001Hooks::ReadPropertyBatch", iptr, 0); 17 | CREATE_MH_HOOK(writePropertyBatchHook, _writePropertyBatch, "IVRproperties001Hooks::WritePropertyBatch", iptr, 1); 18 | _isHooked = true; 19 | } 20 | } 21 | 22 | 23 | IVRProperties001Hooks::~IVRProperties001Hooks() { 24 | if (_isHooked) { 25 | REMOVE_MH_HOOK(readPropertyBatchHook); 26 | REMOVE_MH_HOOK(writePropertyBatchHook); 27 | _isHooked = false; 28 | } 29 | } 30 | 31 | 32 | std::shared_ptr IVRProperties001Hooks::createHooks(void * iptr) { 33 | std::shared_ptr retval = std::shared_ptr(new IVRProperties001Hooks(iptr)); 34 | return retval; 35 | } 36 | 37 | 38 | vr::ETrackedPropertyError IVRProperties001Hooks::_readPropertyBatch(void* _this, vr::PropertyContainerHandle_t ulContainer, void* pBatch, uint32_t unBatchEntryCount) { 39 | auto retval = readPropertyBatchHook.origFunc(_this, ulContainer, pBatch, unBatchEntryCount); 40 | serverDriver->hooksPropertiesReadPropertyBatch(_this, 1, ulContainer, pBatch, unBatchEntryCount); 41 | //LOG(TRACE) << "IVRproperties001Hooks::_readPropertyBatch(" << _this << ", " << ulContainer << ", " << pBatch << ", " << unBatchEntryCount << ") = " << (int)retval; 42 | return retval; 43 | } 44 | 45 | vr::ETrackedPropertyError IVRProperties001Hooks::_writePropertyBatch(void* _this, vr::PropertyContainerHandle_t ulContainer, void* pBatch, uint32_t unBatchEntryCount) { 46 | serverDriver->hooksPropertiesWritePropertyBatch(_this, 1, ulContainer, pBatch, unBatchEntryCount); 47 | auto retval = writePropertyBatchHook.origFunc(_this, ulContainer, pBatch, unBatchEntryCount); 48 | //LOG(TRACE) << "IVRproperties001Hooks::_writePropertyBatch(" << _this << ", " << ulContainer << ", " << pBatch << ", " << unBatchEntryCount << ") = " << (int)retval; 49 | return retval; 50 | } 51 | 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/hooks/IVRProperties001Hooks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common.h" 4 | #include 5 | #include 6 | 7 | 8 | namespace vrinputemulator { 9 | namespace driver { 10 | 11 | 12 | class IVRProperties001Hooks : public InterfaceHooks { 13 | public: 14 | typedef vr::ETrackedPropertyError(*readPropertyBatch_t)(void*, vr::PropertyContainerHandle_t, void*, uint32_t); 15 | typedef vr::ETrackedPropertyError(*writePropertyBatch_t)(void*, vr::PropertyContainerHandle_t, void*, uint32_t); 16 | 17 | static std::shared_ptr createHooks(void* iptr); 18 | virtual ~IVRProperties001Hooks(); 19 | 20 | private: 21 | bool _isHooked = false; 22 | 23 | IVRProperties001Hooks(void* iptr); 24 | 25 | static HookData readPropertyBatchHook; 26 | static HookData writePropertyBatchHook; 27 | 28 | static vr::ETrackedPropertyError _readPropertyBatch(void* _this, vr::PropertyContainerHandle_t ulContainer, void* pBatch, uint32_t unBatchEntryCount); 29 | static vr::ETrackedPropertyError _writePropertyBatch(void* _this, vr::PropertyContainerHandle_t ulContainer, void* pBatch, uint32_t unBatchEntryCount); 30 | 31 | }; 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/hooks/IVRServerDriverHost004Hooks.cpp: -------------------------------------------------------------------------------- 1 | #include "IVRServerDriverHost004Hooks.h" 2 | 3 | #include "../driver/ServerDriver.h" 4 | 5 | 6 | namespace vrinputemulator { 7 | namespace driver { 8 | 9 | 10 | HookData IVRServerDriverHost004Hooks::trackedDeviceAddedHook; 11 | HookData IVRServerDriverHost004Hooks::trackedDevicePoseUpdatedHook; 12 | HookData IVRServerDriverHost004Hooks::trackedDeviceButtonPressedHook; 13 | HookData IVRServerDriverHost004Hooks::trackedDeviceButtonUnpressedHook; 14 | HookData IVRServerDriverHost004Hooks::trackedDeviceButtonTouchedHook; 15 | HookData IVRServerDriverHost004Hooks::trackedDeviceButtonUntouchedHook; 16 | HookData IVRServerDriverHost004Hooks::trackedDeviceAxisUpdatedHook; 17 | 18 | 19 | IVRServerDriverHost004Hooks::IVRServerDriverHost004Hooks(void* iptr) { 20 | if (!_isHooked) { 21 | CREATE_MH_HOOK(trackedDeviceAddedHook, _trackedDeviceAdded, "IVRServerDriverHost004::TrackedDeviceAdded", iptr, 0); 22 | CREATE_MH_HOOK(trackedDevicePoseUpdatedHook, _trackedDevicePoseUpdated, "IVRServerDriverHost004::TrackedDevicePoseUpdated", iptr, 1); 23 | CREATE_MH_HOOK(trackedDeviceButtonPressedHook, _trackedDeviceButtonPressed, "IVRServerDriverHost004::TrackedDeviceButtonPressed", iptr, 3); 24 | CREATE_MH_HOOK(trackedDeviceButtonUnpressedHook, _trackedDeviceButtonUnpressed, "IVRServerDriverHost004::TrackedDeviceButtonUnpressed", iptr, 4); 25 | CREATE_MH_HOOK(trackedDeviceButtonTouchedHook, _trackedDeviceButtonTouched, "IVRServerDriverHost004::TrackedDeviceButtonTouched", iptr, 5); 26 | CREATE_MH_HOOK(trackedDeviceButtonUntouchedHook, _trackedDeviceButtonUntouched, "IVRServerDriverHost004::TrackedDeviceButtonUntouched", iptr, 6); 27 | CREATE_MH_HOOK(trackedDeviceAxisUpdatedHook, _trackedDeviceAxisUpdated, "IVRServerDriverHost004::TrackedDeviceAxisUpdated", iptr, 7); 28 | _isHooked = true; 29 | } 30 | } 31 | 32 | 33 | IVRServerDriverHost004Hooks::~IVRServerDriverHost004Hooks() { 34 | if (_isHooked) { 35 | REMOVE_MH_HOOK(trackedDeviceAddedHook); 36 | REMOVE_MH_HOOK(trackedDevicePoseUpdatedHook); 37 | REMOVE_MH_HOOK(trackedDeviceButtonPressedHook); 38 | REMOVE_MH_HOOK(trackedDeviceButtonUnpressedHook); 39 | REMOVE_MH_HOOK(trackedDeviceButtonTouchedHook); 40 | REMOVE_MH_HOOK(trackedDeviceButtonUntouchedHook); 41 | REMOVE_MH_HOOK(trackedDeviceAxisUpdatedHook); 42 | _isHooked = false; 43 | } 44 | } 45 | 46 | 47 | std::shared_ptr IVRServerDriverHost004Hooks::createHooks(void * iptr) { 48 | std::shared_ptr retval = std::shared_ptr(new IVRServerDriverHost004Hooks(iptr)); 49 | return retval; 50 | } 51 | 52 | void IVRServerDriverHost004Hooks::trackedDevicePoseUpdatedOrig(void * _this, uint32_t unWhichDevice, const vr::DriverPose_t& newPose, uint32_t unPoseStructSize) { 53 | trackedDevicePoseUpdatedHook.origFunc(_this, unWhichDevice, newPose, unPoseStructSize); 54 | } 55 | 56 | void IVRServerDriverHost004Hooks::trackedDeviceButtonPressedOrig(void * _this, uint32_t unWhichDevice, vr::EVRButtonId eButtonId, double eventTimeOffset) { 57 | trackedDeviceButtonPressedHook.origFunc(_this, unWhichDevice, eButtonId, eventTimeOffset); 58 | } 59 | 60 | void IVRServerDriverHost004Hooks::trackedDeviceButtonUnpressedOrig(void * _this, uint32_t unWhichDevice, vr::EVRButtonId eButtonId, double eventTimeOffset) { 61 | trackedDeviceButtonUnpressedHook.origFunc(_this, unWhichDevice, eButtonId, eventTimeOffset); 62 | } 63 | 64 | void IVRServerDriverHost004Hooks::trackedDeviceButtonTouchedOrig(void * _this, uint32_t unWhichDevice, vr::EVRButtonId eButtonId, double eventTimeOffset) { 65 | trackedDeviceButtonTouchedHook.origFunc(_this, unWhichDevice, eButtonId, eventTimeOffset); 66 | } 67 | 68 | void IVRServerDriverHost004Hooks::trackedDeviceButtonUntouchedOrig(void * _this, uint32_t unWhichDevice, vr::EVRButtonId eButtonId, double eventTimeOffset) { 69 | trackedDeviceButtonUntouchedHook.origFunc(_this, unWhichDevice, eButtonId, eventTimeOffset); 70 | } 71 | 72 | void IVRServerDriverHost004Hooks::trackedDeviceAxisUpdatedOrig(void * _this, uint32_t unWhichDevice, uint32_t unWhichAxis, const vr::VRControllerAxis_t & axisState) { 73 | trackedDeviceAxisUpdatedHook.origFunc(_this, unWhichDevice, unWhichAxis, axisState); 74 | } 75 | 76 | 77 | bool IVRServerDriverHost004Hooks::_trackedDeviceAdded(void* _this, const char *pchDeviceSerialNumber, vr::ETrackedDeviceClass eDeviceClass, void *pDriver) { 78 | LOG(TRACE) << "IVRServerDriverHost004Hooks::_trackedDeviceAdded(" << _this << ", " << pchDeviceSerialNumber << ", " << eDeviceClass << ", " << pDriver << ")"; 79 | serverDriver->hooksTrackedDeviceAdded(_this, 4, pchDeviceSerialNumber, eDeviceClass, pDriver); 80 | auto retval = trackedDeviceAddedHook.origFunc(_this, pchDeviceSerialNumber, eDeviceClass, pDriver); 81 | return retval; 82 | } 83 | 84 | void IVRServerDriverHost004Hooks::_trackedDevicePoseUpdated(void* _this, uint32_t unWhichDevice, const vr::DriverPose_t& newPose, uint32_t unPoseStructSize) { 85 | // Call rates: 86 | // 87 | // Vive HMD: 1120 calls/s 88 | // Vive Controller: 369 calls/s each 89 | // 90 | // Time is key. If we assume 1 HMD and 13 controllers, we have a total of ~6000 calls/s. That's about 166 microseconds per call at 100% load. 91 | auto poseCopy = newPose; 92 | if (serverDriver->hooksTrackedDevicePoseUpdated(_this, 4, unWhichDevice, poseCopy, unPoseStructSize)) { 93 | trackedDevicePoseUpdatedHook.origFunc(_this, unWhichDevice, poseCopy, unPoseStructSize); 94 | } 95 | } 96 | 97 | void IVRServerDriverHost004Hooks::_trackedDeviceButtonPressed(void* _this, uint32_t unWhichDevice, vr::EVRButtonId eButtonId, double eventTimeOffset) { 98 | if (serverDriver->hooksTrackedDeviceButtonPressed(_this, 4, unWhichDevice, eButtonId, eventTimeOffset)) { 99 | trackedDeviceButtonPressedHook.origFunc(_this, unWhichDevice, eButtonId, eventTimeOffset); 100 | } 101 | } 102 | 103 | void IVRServerDriverHost004Hooks::_trackedDeviceButtonUnpressed(void* _this, uint32_t unWhichDevice, vr::EVRButtonId eButtonId, double eventTimeOffset) { 104 | if (serverDriver->hooksTrackedDeviceButtonUnpressed(_this, 4, unWhichDevice, eButtonId, eventTimeOffset)) { 105 | trackedDeviceButtonUnpressedHook.origFunc(_this, unWhichDevice, eButtonId, eventTimeOffset); 106 | } 107 | } 108 | 109 | void IVRServerDriverHost004Hooks::_trackedDeviceButtonTouched(void* _this, uint32_t unWhichDevice, vr::EVRButtonId eButtonId, double eventTimeOffset) { 110 | if (serverDriver->hooksTrackedDeviceButtonTouched(_this, 4, unWhichDevice, eButtonId, eventTimeOffset)) { 111 | trackedDeviceButtonTouchedHook.origFunc(_this, unWhichDevice, eButtonId, eventTimeOffset); 112 | } 113 | } 114 | 115 | void IVRServerDriverHost004Hooks::_trackedDeviceButtonUntouched(void* _this, uint32_t unWhichDevice, vr::EVRButtonId eButtonId, double eventTimeOffset) { 116 | if (serverDriver->hooksTrackedDeviceButtonUntouched(_this, 4, unWhichDevice, eButtonId, eventTimeOffset)) { 117 | trackedDeviceButtonUntouchedHook.origFunc(_this, unWhichDevice, eButtonId, eventTimeOffset); 118 | } 119 | } 120 | 121 | void IVRServerDriverHost004Hooks::_trackedDeviceAxisUpdated(void* _this, uint32_t unWhichDevice, uint32_t unWhichAxis, const vr::VRControllerAxis_t & axisState) { 122 | auto stateCopy = axisState; 123 | if (serverDriver->hooksTrackedDeviceAxisUpdated(_this, 4, unWhichDevice, unWhichAxis, stateCopy)) { 124 | trackedDeviceAxisUpdatedHook.origFunc(_this, unWhichDevice, unWhichAxis, stateCopy); 125 | } 126 | } 127 | 128 | 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/hooks/IVRServerDriverHost004Hooks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common.h" 4 | #include 5 | #include 6 | 7 | 8 | namespace vrinputemulator { 9 | namespace driver { 10 | 11 | 12 | class IVRServerDriverHost004Hooks : public InterfaceHooks { 13 | public: 14 | typedef bool(*trackedDeviceAdded_t)(void*, const char*, vr::ETrackedDeviceClass, void*); 15 | typedef void(*trackedDevicePoseUpdated_t)(void*, uint32_t, const vr::DriverPose_t&, uint32_t); 16 | typedef void(*trackedDeviceButtonPressed_t)(void*, uint32_t, vr::EVRButtonId, double); 17 | typedef void(*trackedDeviceButtonUnpressed_t)(void*, uint32_t, vr::EVRButtonId, double); 18 | typedef void(*trackedDeviceButtonTouched_t)(void*, uint32_t, vr::EVRButtonId, double); 19 | typedef void(*trackedDeviceButtonUntouched_t)(void*, uint32_t, vr::EVRButtonId, double); 20 | typedef void(*trackedDeviceAxisUpdated_t)(void*, uint32_t, uint32_t, const vr::VRControllerAxis_t&); 21 | 22 | static std::shared_ptr createHooks(void* iptr); 23 | virtual ~IVRServerDriverHost004Hooks(); 24 | 25 | static void trackedDevicePoseUpdatedOrig(void* _this, uint32_t unWhichDevice, const vr::DriverPose_t& newPose, uint32_t unPoseStructSize); 26 | static void trackedDeviceButtonPressedOrig(void* _this, uint32_t unWhichDevice, vr::EVRButtonId eButtonId, double eventTimeOffset); 27 | static void trackedDeviceButtonUnpressedOrig(void* _this, uint32_t unWhichDevice, vr::EVRButtonId eButtonId, double eventTimeOffset); 28 | static void trackedDeviceButtonTouchedOrig(void* _this, uint32_t unWhichDevice, vr::EVRButtonId eButtonId, double eventTimeOffset); 29 | static void trackedDeviceButtonUntouchedOrig(void* _this, uint32_t unWhichDevice, vr::EVRButtonId eButtonId, double eventTimeOffset); 30 | static void trackedDeviceAxisUpdatedOrig(void* _this, uint32_t unWhichDevice, uint32_t unWhichAxis, const vr::VRControllerAxis_t & axisState); 31 | 32 | private: 33 | bool _isHooked = false; 34 | 35 | IVRServerDriverHost004Hooks(void* iptr); 36 | 37 | static HookData trackedDeviceAddedHook; 38 | static HookData trackedDevicePoseUpdatedHook; 39 | static HookData trackedDeviceButtonPressedHook; 40 | static HookData trackedDeviceButtonUnpressedHook; 41 | static HookData trackedDeviceButtonTouchedHook; 42 | static HookData trackedDeviceButtonUntouchedHook; 43 | static HookData trackedDeviceAxisUpdatedHook; 44 | 45 | static bool _trackedDeviceAdded(void* _this, const char *pchDeviceSerialNumber, vr::ETrackedDeviceClass eDeviceClass, void *pDriver); 46 | static void _trackedDevicePoseUpdated(void* _this, uint32_t unWhichDevice, const vr::DriverPose_t& newPose, uint32_t unPoseStructSize); 47 | static void _trackedDeviceButtonPressed(void* _this, uint32_t unWhichDevice, vr::EVRButtonId eButtonId, double eventTimeOffset); 48 | static void _trackedDeviceButtonUnpressed(void* _this, uint32_t unWhichDevice, vr::EVRButtonId eButtonId, double eventTimeOffset); 49 | static void _trackedDeviceButtonTouched(void* _this, uint32_t unWhichDevice, vr::EVRButtonId eButtonId, double eventTimeOffset); 50 | static void _trackedDeviceButtonUntouched(void* _this, uint32_t unWhichDevice, vr::EVRButtonId eButtonId, double eventTimeOffset); 51 | static void _trackedDeviceAxisUpdated(void* _this, uint32_t unWhichDevice, uint32_t unWhichAxis, const vr::VRControllerAxis_t & axisState); 52 | 53 | }; 54 | 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/hooks/IVRServerDriverHost005Hooks.cpp: -------------------------------------------------------------------------------- 1 | #include "IVRServerDriverHost005Hooks.h" 2 | 3 | #include "../driver/ServerDriver.h" 4 | 5 | 6 | namespace vrinputemulator { 7 | namespace driver { 8 | 9 | 10 | HookData IVRServerDriverHost005Hooks::trackedDeviceAddedHook; 11 | HookData IVRServerDriverHost005Hooks::trackedDevicePoseUpdatedHook; 12 | HookData IVRServerDriverHost005Hooks::pollNextEventHook; 13 | 14 | 15 | IVRServerDriverHost005Hooks::IVRServerDriverHost005Hooks(void* iptr) { 16 | if (!_isHooked) { 17 | CREATE_MH_HOOK(trackedDeviceAddedHook, _trackedDeviceAdded, "IVRServerDriverHost005::TrackedDeviceAdded", iptr, 0); 18 | CREATE_MH_HOOK(trackedDevicePoseUpdatedHook, _trackedDevicePoseUpdated, "IVRServerDriverHost005::TrackedDevicePoseUpdated", iptr, 1); 19 | CREATE_MH_HOOK(pollNextEventHook, _pollNextEvent, "IVRServerDriverHost005::PollNextEvent", iptr, 5); 20 | _isHooked = true; 21 | } 22 | } 23 | 24 | 25 | IVRServerDriverHost005Hooks::~IVRServerDriverHost005Hooks() { 26 | if (_isHooked) { 27 | REMOVE_MH_HOOK(trackedDeviceAddedHook); 28 | REMOVE_MH_HOOK(trackedDevicePoseUpdatedHook); 29 | REMOVE_MH_HOOK(pollNextEventHook); 30 | _isHooked = false; 31 | } 32 | } 33 | 34 | 35 | std::shared_ptr IVRServerDriverHost005Hooks::createHooks(void * iptr) { 36 | std::shared_ptr retval = std::shared_ptr(new IVRServerDriverHost005Hooks(iptr)); 37 | return retval; 38 | } 39 | 40 | void IVRServerDriverHost005Hooks::trackedDevicePoseUpdatedOrig(void * _this, uint32_t unWhichDevice, const vr::DriverPose_t & newPose, uint32_t unPoseStructSize) { 41 | trackedDevicePoseUpdatedHook.origFunc(_this, unWhichDevice, newPose, unPoseStructSize); 42 | } 43 | 44 | 45 | bool IVRServerDriverHost005Hooks::_trackedDeviceAdded(void* _this, const char *pchDeviceSerialNumber, vr::ETrackedDeviceClass eDeviceClass, void *pDriver) { 46 | LOG(TRACE) << "IVRServerDriverHost005Hooks::_trackedDeviceAdded(" << _this << ", " << pchDeviceSerialNumber << ", " << eDeviceClass << ", " << pDriver << ")"; 47 | serverDriver->hooksTrackedDeviceAdded(_this, 5, pchDeviceSerialNumber, eDeviceClass, pDriver); 48 | auto retval = trackedDeviceAddedHook.origFunc(_this, pchDeviceSerialNumber, eDeviceClass, pDriver); 49 | return retval; 50 | } 51 | 52 | void IVRServerDriverHost005Hooks::_trackedDevicePoseUpdated(void* _this, uint32_t unWhichDevice, const vr::DriverPose_t& newPose, uint32_t unPoseStructSize) { 53 | // Call rates: 54 | // 55 | // Vive HMD: 1120 calls/s 56 | // Vive Controller: 369 calls/s each 57 | // 58 | // Time is key. If we assume 1 HMD and 13 controllers, we have a total of ~6000 calls/s. That's about 166 microseconds per call at 100% load. 59 | auto poseCopy = newPose; 60 | if (serverDriver->hooksTrackedDevicePoseUpdated(_this, 5, unWhichDevice, poseCopy, unPoseStructSize)) { 61 | trackedDevicePoseUpdatedHook.origFunc(_this, unWhichDevice, poseCopy, unPoseStructSize); 62 | } 63 | } 64 | 65 | bool IVRServerDriverHost005Hooks::_pollNextEvent(void* _this, void* pEvent, uint32_t uncbVREvent) { 66 | auto injectedEvent = serverDriver->getDriverEventForInjection(_this); 67 | if (injectedEvent.first) { 68 | if (injectedEvent.second == uncbVREvent) { 69 | memcpy(pEvent, injectedEvent.first.get(), uncbVREvent); 70 | auto event = (vr::VREvent_t*)pEvent; 71 | LOG(DEBUG) << "IVRServerDriverHost005Hooks::_pollNextEvent: Injecting event: " << event->eventType << ", " << event->trackedDeviceIndex; 72 | return true; 73 | } else { 74 | auto event = (vr::VREvent_t*)injectedEvent.first.get(); 75 | LOG(ERROR) << "IVRServerDriverHost005Hooks::_pollNextEvent: Could not inject event (" << event->eventType << ", " << event->trackedDeviceIndex 76 | << ") because size does not match, expected " << uncbVREvent << " but got " << injectedEvent.second; 77 | } 78 | } 79 | bool retval, hretval; 80 | do { 81 | retval = pollNextEventHook.origFunc(_this, pEvent, uncbVREvent); 82 | if (retval) { 83 | hretval = serverDriver->hooksPollNextEvent(_this, 5, pEvent, uncbVREvent); 84 | } 85 | } while (retval && !hretval); 86 | return retval; 87 | } 88 | 89 | 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/hooks/IVRServerDriverHost005Hooks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common.h" 4 | #include 5 | #include 6 | 7 | 8 | namespace vrinputemulator { 9 | namespace driver { 10 | 11 | 12 | class IVRServerDriverHost005Hooks : public InterfaceHooks { 13 | public: 14 | typedef bool(*trackedDeviceAdded_t)(void*, const char*, vr::ETrackedDeviceClass, void*); 15 | typedef void(*trackedDevicePoseUpdated_t)(void*, uint32_t, const vr::DriverPose_t&, uint32_t); 16 | typedef bool(*pollNextEvent_t)(void*, void*, uint32_t); 17 | 18 | static std::shared_ptr createHooks(void* iptr); 19 | virtual ~IVRServerDriverHost005Hooks(); 20 | 21 | static void trackedDevicePoseUpdatedOrig(void* _this, uint32_t unWhichDevice, const vr::DriverPose_t& newPose, uint32_t unPoseStructSize); 22 | 23 | private: 24 | bool _isHooked = false; 25 | 26 | IVRServerDriverHost005Hooks(void* iptr); 27 | 28 | static HookData trackedDeviceAddedHook; 29 | static HookData trackedDevicePoseUpdatedHook; 30 | static HookData pollNextEventHook; 31 | 32 | static bool _trackedDeviceAdded(void* _this, const char *pchDeviceSerialNumber, vr::ETrackedDeviceClass eDeviceClass, void *pDriver); 33 | static void _trackedDevicePoseUpdated(void* _this, uint32_t unWhichDevice, const vr::DriverPose_t& newPose, uint32_t unPoseStructSize); 34 | static bool _pollNextEvent(void* _this, void* pEvent, uint32_t uncbVREvent); 35 | 36 | }; 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/hooks/common.cpp: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | #include "../logging.h" 4 | #include "IVRDriverContextHooks.h" 5 | #include "IVRServerDriverHost004Hooks.h" 6 | #include "IVRServerDriverHost005Hooks.h" 7 | #include "ITrackedDeviceServerDriver005Hooks.h" 8 | #include "IVRControllerComponent001Hooks.h" 9 | #include "IVRDriverInput001Hooks.h" 10 | #include "IVRProperties001Hooks.h" 11 | 12 | 13 | namespace vrinputemulator { 14 | namespace driver { 15 | 16 | 17 | ServerDriver* InterfaceHooks::serverDriver = nullptr; 18 | 19 | 20 | std::shared_ptr InterfaceHooks::hookInterface(void* interfaceRef, std::string interfaceVersion) { 21 | std::shared_ptr retval; 22 | if (interfaceVersion.compare("IVRDriverContext") == 0) { 23 | retval = IVRDriverContextHooks::createHooks(interfaceRef); 24 | } else if (interfaceVersion.compare("IVRServerDriverHost_004") == 0) { 25 | retval = IVRServerDriverHost004Hooks::createHooks(interfaceRef); 26 | } else if (interfaceVersion.compare("IVRServerDriverHost_005") == 0) { 27 | retval = IVRServerDriverHost005Hooks::createHooks(interfaceRef); 28 | } else if (interfaceVersion.compare("IVRDriverInput_001") == 0) { 29 | retval = IVRDriverInput001Hooks::createHooks(interfaceRef); 30 | } else if (interfaceVersion.compare("ITrackedDeviceServerDriver_005") == 0) { 31 | retval = ITrackedDeviceServerDriver005Hooks::createHooks(interfaceRef); 32 | } else if (interfaceVersion.compare("IVRControllerComponent_001") == 0) { 33 | retval = IVRControllerComponent001Hooks::createHooks(interfaceRef); 34 | } else if (interfaceVersion.compare("IVRProperties_001") == 0) { 35 | retval = IVRProperties001Hooks::createHooks(interfaceRef); 36 | } 37 | return retval; 38 | } 39 | 40 | 41 | } 42 | } 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/hooks/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "../logging.h" 7 | 8 | 9 | namespace vr { 10 | enum EVRInputError; 11 | enum EVRScalarType; 12 | enum EVRScalarUnits; 13 | typedef uint64_t VRInputComponentHandle_t; 14 | } 15 | 16 | 17 | namespace vrinputemulator { 18 | namespace driver { 19 | 20 | 21 | #define CREATE_MH_HOOK(detourInfo, detourFunc, logName, objPtr, vtableOffset) {\ 22 | detourInfo.targetFunc = (*((void***)objPtr))[vtableOffset]; \ 23 | MH_STATUS mhError = MH_CreateHook(detourInfo.targetFunc, (void*)&detourFunc, reinterpret_cast(&detourInfo.origFunc)); \ 24 | if (mhError == MH_OK) { \ 25 | mhError = MH_EnableHook(detourInfo.targetFunc); \ 26 | if (mhError == MH_OK) { \ 27 | detourInfo.enabled = true; \ 28 | LOG(INFO) << logName << " hook is enabled (Address: " << std::hex << detourInfo.targetFunc << std::dec << ")"; \ 29 | } else { \ 30 | MH_RemoveHook(detourInfo.targetFunc); \ 31 | LOG(ERROR) << "Error while enabling " << logName << " hook: " << MH_StatusToString(mhError); \ 32 | } \ 33 | } else { \ 34 | LOG(ERROR) << "Error while creating " << logName << " hook: " << MH_StatusToString(mhError); \ 35 | }\ 36 | } 37 | 38 | 39 | #define REMOVE_MH_HOOK(detourInfo) {\ 40 | if (detourInfo.enabled) { \ 41 | MH_RemoveHook(detourInfo.targetFunc); \ 42 | detourInfo.enabled = false; \ 43 | }\ 44 | } 45 | 46 | 47 | //forward declarations 48 | class ServerDriver; 49 | class IVRDriverContextHooks; 50 | class IVRServerDriverHost004Hooks; 51 | 52 | template 53 | struct HookData { 54 | bool enabled = false; 55 | void* targetFunc = nullptr; 56 | T origFunc = nullptr; 57 | }; 58 | 59 | 60 | 61 | class InterfaceHooks { 62 | public: 63 | virtual ~InterfaceHooks() {} 64 | 65 | static std::shared_ptr hookInterface(void* interfaceRef, std::string interfaceVersion); 66 | 67 | static void setServerDriver(ServerDriver* driver) { serverDriver = driver; } 68 | 69 | protected: 70 | static ServerDriver* serverDriver; 71 | }; 72 | 73 | 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /driver_vrinputemulator/src/logging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // easylogging includes 4 | #ifdef NDEBUG 5 | #undef NDEBUG 6 | #define ELPP_THREAD_SAFE 7 | #define ELPP_NO_DEFAULT_LOG_FILE 8 | #include 9 | #define NDEBUG 10 | #else 11 | #define ELPP_THREAD_SAFE 12 | #define ELPP_NO_DEFAULT_LOG_FILE 13 | #include 14 | #endif 15 | -------------------------------------------------------------------------------- /installer/installer.nsi: -------------------------------------------------------------------------------- 1 | ;-------------------------------- 2 | ;Include Modern UI 3 | 4 | !include "MUI2.nsh" 5 | 6 | ;-------------------------------- 7 | ;General 8 | 9 | !define OVERLAY_BASEDIR "..\client_overlay\bin\win64" 10 | !define DRIVER_BASEDIR "..\driver_vrinputemulator" 11 | 12 | ;Name and file 13 | Name "OpenVR Input Emulator" 14 | OutFile "OpenVR-InputEmulator.exe" 15 | 16 | ;Default installation folder 17 | InstallDir "$PROGRAMFILES64\OpenVR-InputEmulator" 18 | 19 | ;Get installation folder from registry if available 20 | InstallDirRegKey HKLM "Software\OpenVR-InputEmulator\Overlay" "" 21 | 22 | ;Request application privileges for Windows Vista 23 | RequestExecutionLevel admin 24 | 25 | ;-------------------------------- 26 | ;Variables 27 | 28 | VAR upgradeInstallation 29 | 30 | ;-------------------------------- 31 | ;Interface Settings 32 | 33 | !define MUI_ABORTWARNING 34 | 35 | ;-------------------------------- 36 | ;Pages 37 | 38 | !insertmacro MUI_PAGE_LICENSE "..\LICENSE" 39 | !define MUI_PAGE_CUSTOMFUNCTION_PRE dirPre 40 | !insertmacro MUI_PAGE_DIRECTORY 41 | !insertmacro MUI_PAGE_INSTFILES 42 | 43 | !insertmacro MUI_UNPAGE_CONFIRM 44 | !insertmacro MUI_UNPAGE_INSTFILES 45 | 46 | ;-------------------------------- 47 | ;Languages 48 | 49 | !insertmacro MUI_LANGUAGE "English" 50 | 51 | ;-------------------------------- 52 | ;Macros 53 | 54 | ;-------------------------------- 55 | ;Functions 56 | 57 | Function dirPre 58 | StrCmp $upgradeInstallation "true" 0 +2 59 | Abort 60 | FunctionEnd 61 | 62 | Function .onInit 63 | StrCpy $upgradeInstallation "false" 64 | 65 | ReadRegStr $R0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenVRInputEmulator" "UninstallString" 66 | StrCmp $R0 "" done 67 | 68 | 69 | ; If SteamVR is already running, display a warning message and exit 70 | FindWindow $0 "Qt5QWindowIcon" "SteamVR Status" 71 | StrCmp $0 0 +3 72 | MessageBox MB_OK|MB_ICONEXCLAMATION \ 73 | "SteamVR is still running. Cannot install this software.$\nPlease close SteamVR and try again." 74 | Abort 75 | 76 | 77 | MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \ 78 | "OpenVR Input Emulator is already installed. $\n$\nClick `OK` to upgrade the \ 79 | existing installation or `Cancel` to cancel this upgrade." \ 80 | IDOK upgrade 81 | Abort 82 | 83 | upgrade: 84 | StrCpy $upgradeInstallation "true" 85 | done: 86 | FunctionEnd 87 | 88 | ;-------------------------------- 89 | ;Installer Sections 90 | 91 | Section "Install" SecInstall 92 | 93 | StrCmp $upgradeInstallation "true" 0 noupgrade 94 | DetailPrint "Uninstall previous version..." 95 | ExecWait '"$INSTDIR\Uninstall.exe" /S _?=$INSTDIR' 96 | Delete $INSTDIR\Uninstall.exe 97 | Goto afterupgrade 98 | 99 | noupgrade: 100 | 101 | afterupgrade: 102 | 103 | SetOutPath "$INSTDIR" 104 | 105 | ;ADD YOUR OWN FILES HERE... 106 | File "${OVERLAY_BASEDIR}\LICENSE" 107 | File "${OVERLAY_BASEDIR}\*.exe" 108 | File "${OVERLAY_BASEDIR}\*.dll" 109 | File "${OVERLAY_BASEDIR}\*.bat" 110 | File "${OVERLAY_BASEDIR}\*.vrmanifest" 111 | File "${OVERLAY_BASEDIR}\*.conf" 112 | File /r "${OVERLAY_BASEDIR}\res" 113 | File /r "${OVERLAY_BASEDIR}\qtdata" 114 | 115 | ; Install redistributable 116 | ExecWait '"$INSTDIR\vcredist_x64.exe" /install /quiet' 117 | 118 | Var /GLOBAL vrRuntimePath 119 | nsExec::ExecToStack '"$INSTDIR\OpenVR-InputEmulatorOverlay.exe" -openvrpath' 120 | Pop $0 121 | Pop $vrRuntimePath 122 | DetailPrint "VR runtime path: $vrRuntimePath" 123 | 124 | SetOutPath "$vrRuntimePath\drivers\00vrinputemulator" 125 | File "${DRIVER_BASEDIR}\driver.vrdrivermanifest" 126 | SetOutPath "$vrRuntimePath\drivers\00vrinputemulator\resources" 127 | File "${DRIVER_BASEDIR}\resources\driver.vrresources" 128 | SetOutPath "$vrRuntimePath\drivers\00vrinputemulator\resources\settings" 129 | File "${DRIVER_BASEDIR}\resources\settings\default.vrsettings" 130 | SetOutPath "$vrRuntimePath\drivers\00vrinputemulator\resources\sounds" 131 | File "${DRIVER_BASEDIR}\resources\sounds\audiocue.wav" 132 | File "${DRIVER_BASEDIR}\resources\sounds\License.txt" 133 | SetOutPath "$vrRuntimePath\drivers\00vrinputemulator\bin\win64" 134 | File "${DRIVER_BASEDIR}\bin\x64\driver_00vrinputemulator.dll" 135 | 136 | ; Install the vrmanifest 137 | nsExec::ExecToLog '"$INSTDIR\OpenVR-InputEmulatorOverlay.exe" -installmanifest' 138 | 139 | ; Post-installation step 140 | nsExec::ExecToLog '"$INSTDIR\OpenVR-InputEmulatorOverlay.exe" -postinstallationstep' 141 | 142 | ;Store installation folder 143 | WriteRegStr HKLM "Software\OpenVR-InputEmulator\Overlay" "" $INSTDIR 144 | WriteRegStr HKLM "Software\OpenVR-InputEmulator\Driver" "" $vrRuntimePath 145 | 146 | ;Create uninstaller 147 | WriteUninstaller "$INSTDIR\Uninstall.exe" 148 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenVRInputEmulator" "DisplayName" "OpenVR Input Emulator" 149 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenVRInputEmulator" "UninstallString" "$\"$INSTDIR\Uninstall.exe$\"" 150 | 151 | SectionEnd 152 | 153 | ;-------------------------------- 154 | ;Uninstaller Section 155 | 156 | Section "Uninstall" 157 | ; If SteamVR is already running, display a warning message and exit 158 | FindWindow $0 "Qt5QWindowIcon" "SteamVR Status" 159 | StrCmp $0 0 +3 160 | MessageBox MB_OK|MB_ICONEXCLAMATION \ 161 | "SteamVR is still running. Cannot uninstall this software.$\nPlease close SteamVR and try again." 162 | Abort 163 | 164 | ; Remove the vrmanifest 165 | nsExec::ExecToLog '"$INSTDIR\OpenVR-InputEmulatorOverlay.exe" -removemanifest' 166 | 167 | ; Delete installed files 168 | Var /GLOBAL vrRuntimePath2 169 | ReadRegStr $vrRuntimePath2 HKLM "Software\OpenVR-InputEmulator\Driver" "" 170 | DetailPrint "VR runtime path: $vrRuntimePath2" 171 | Delete "$vrRuntimePath2\drivers\00vrinputemulator\driver.vrdrivermanifest" 172 | Delete "$vrRuntimePath2\drivers\00vrinputemulator\resources\driver.vrresources" 173 | Delete "$vrRuntimePath2\drivers\00vrinputemulator\resources\settings\default.vrsettings" 174 | Delete "$vrRuntimePath2\drivers\00vrinputemulator\resources\sounds\audiocue.wav" 175 | Delete "$vrRuntimePath2\drivers\00vrinputemulator\resources\sounds\License.txt" 176 | Delete "$vrRuntimePath2\drivers\00vrinputemulator\bin\win64\driver_00vrinputemulator.dll" 177 | Delete "$vrRuntimePath2\drivers\00vrinputemulator\bin\win64\driver_vrinputemulator.log" 178 | RMdir "$vrRuntimePath2\drivers\00vrinputemulator\resources\settings" 179 | RMdir "$vrRuntimePath2\drivers\00vrinputemulator\resources\sounds" 180 | RMdir "$vrRuntimePath2\drivers\00vrinputemulator\resources\" 181 | RMdir "$vrRuntimePath2\drivers\00vrinputemulator\bin\win64\" 182 | RMdir "$vrRuntimePath2\drivers\00vrinputemulator\bin\" 183 | RMdir "$vrRuntimePath2\drivers\00vrinputemulator\" 184 | 185 | !include uninstallFiles.list 186 | 187 | DeleteRegKey HKLM "Software\OpenVR-InputEmulator\Overlay" 188 | DeleteRegKey HKLM "Software\OpenVR-InputEmulator\Driver" 189 | DeleteRegKey HKLM "Software\OpenVR-InputEmulator" 190 | DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenVRInputEmulator" 191 | SectionEnd 192 | 193 | -------------------------------------------------------------------------------- /installer/listUninstallFiles.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Execute this script in the root folder of the install dir 4 | # Dont't forget to set OUTPUTFILE to a path that is writeable 5 | 6 | OUTPUTFILE=../../installed_files.txt 7 | INSTALLDIR=. 8 | 9 | # Get command line arguments 10 | if [ $# -eq 1 ]; then 11 | OUTPUTFILE=$1 12 | elif [ $# -gt 1 ]; then 13 | OUTPUTFILE=$1 14 | INSTALLDIR=$2 15 | fi 16 | 17 | # Find all files 18 | find "$INSTALLDIR" -iname '*' -type f -exec echo "Delete \$INSTDIR/{}" \; > $OUTPUTFILE 19 | 20 | # Find all directories and print them out in reverse order 21 | find "$INSTALLDIR" -iname '*' -type d -exec echo "RMdir \$INSTDIR/{}" \; | tac.exe >> $OUTPUTFILE 22 | 23 | # Remove "/./" from the file paths 24 | sed -i 's/\/\.//g' $OUTPUTFILE 25 | 26 | # Replace "/" with "\" 27 | sed -i 's/\//\\/g' $OUTPUTFILE 28 | -------------------------------------------------------------------------------- /lib_vrinputemulator/include/config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define VRINPUTEMULATOR_EASYLOGGING 0 4 | -------------------------------------------------------------------------------- /lib_vrinputemulator/include/openvr_math.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | 6 | inline vr::HmdQuaternion_t operator+(const vr::HmdQuaternion_t& lhs, const vr::HmdQuaternion_t& rhs) { 7 | return { 8 | lhs.w + rhs.w, 9 | lhs.x + rhs.x, 10 | lhs.y + rhs.y, 11 | lhs.z + rhs.z 12 | }; 13 | } 14 | 15 | 16 | inline vr::HmdQuaternion_t operator-(const vr::HmdQuaternion_t& lhs, const vr::HmdQuaternion_t& rhs) { 17 | return{ 18 | lhs.w - rhs.w, 19 | lhs.x - rhs.x, 20 | lhs.y - rhs.y, 21 | lhs.z - rhs.z 22 | }; 23 | } 24 | 25 | 26 | inline vr::HmdQuaternion_t operator*(const vr::HmdQuaternion_t& lhs, const vr::HmdQuaternion_t& rhs) { 27 | return { 28 | (lhs.w * rhs.w) - (lhs.x * rhs.x) - (lhs.y * rhs.y) - (lhs.z * rhs.z), 29 | (lhs.w * rhs.x) + (lhs.x * rhs.w) + (lhs.y * rhs.z) - (lhs.z * rhs.y), 30 | (lhs.w * rhs.y) + (lhs.y * rhs.w) + (lhs.z * rhs.x) - (lhs.x * rhs.z), 31 | (lhs.w * rhs.z) + (lhs.z * rhs.w) + (lhs.x * rhs.y) - (lhs.y * rhs.x) 32 | }; 33 | } 34 | 35 | 36 | inline vr::HmdVector3d_t operator+(const vr::HmdVector3d_t& lhs, const vr::HmdVector3d_t& rhs) { 37 | return { 38 | lhs.v[0] + rhs.v[0], 39 | lhs.v[1] + rhs.v[1], 40 | lhs.v[2] + rhs.v[2] 41 | }; 42 | } 43 | 44 | inline vr::HmdVector3d_t operator+(const vr::HmdVector3d_t& lhs, const double(&rhs)[3]) { 45 | return{ 46 | lhs.v[0] + rhs[0], 47 | lhs.v[1] + rhs[1], 48 | lhs.v[2] + rhs[2] 49 | }; 50 | } 51 | 52 | inline vr::HmdVector3d_t operator-(const vr::HmdVector3d_t& lhs, const vr::HmdVector3d_t& rhs) { 53 | return{ 54 | lhs.v[0] - rhs.v[0], 55 | lhs.v[1] - rhs.v[1], 56 | lhs.v[2] - rhs.v[2] 57 | }; 58 | } 59 | 60 | inline vr::HmdVector3d_t operator-(const vr::HmdVector3d_t& lhs, const double (&rhs)[3]) { 61 | return{ 62 | lhs.v[0] - rhs[0], 63 | lhs.v[1] - rhs[1], 64 | lhs.v[2] - rhs[2] 65 | }; 66 | } 67 | 68 | 69 | inline vr::HmdVector3d_t operator*(const vr::HmdVector3d_t& lhs, const double rhs) { 70 | return{ 71 | lhs.v[0] * rhs, 72 | lhs.v[1] * rhs, 73 | lhs.v[2] * rhs 74 | }; 75 | } 76 | 77 | 78 | inline vr::HmdVector3d_t operator/(const vr::HmdVector3d_t& lhs, const double rhs) { 79 | return{ 80 | lhs.v[0] / rhs, 81 | lhs.v[1] / rhs, 82 | lhs.v[2] / rhs 83 | }; 84 | } 85 | 86 | 87 | namespace vrmath { 88 | 89 | template int signum(T v) { 90 | return (v > (T)0) ? 1 : ((v < (T)0) ? -1 : 0); 91 | } 92 | 93 | inline vr::HmdQuaternion_t quaternionFromRotationAxis(double rot, double ux, double uy, double uz) { 94 | auto ha = rot / 2; 95 | return{ 96 | std::cos(ha), 97 | ux * std::sin(ha), 98 | uy * std::sin(ha), 99 | uz * std::sin(ha) 100 | }; 101 | } 102 | 103 | inline vr::HmdQuaternion_t quaternionFromRotationX(double rot) { 104 | auto ha = rot / 2; 105 | return{ 106 | std::cos(ha), 107 | std::sin(ha), 108 | 0.0f, 109 | 0.0f 110 | }; 111 | } 112 | 113 | inline vr::HmdQuaternion_t quaternionFromRotationY(double rot) { 114 | auto ha = rot / 2; 115 | return{ 116 | std::cos(ha), 117 | 0.0f, 118 | std::sin(ha), 119 | 0.0f 120 | }; 121 | } 122 | 123 | inline vr::HmdQuaternion_t quaternionFromRotationZ(double rot) { 124 | auto ha = rot / 2; 125 | return{ 126 | std::cos(ha), 127 | 0.0f, 128 | 0.0f, 129 | std::sin(ha) 130 | }; 131 | } 132 | 133 | inline vr::HmdQuaternion_t quaternionFromYawPitchRoll(double yaw, double pitch, double roll) { 134 | return quaternionFromRotationY(yaw) * quaternionFromRotationX(pitch) * quaternionFromRotationZ(roll); 135 | } 136 | 137 | inline vr::HmdQuaternion_t quaternionFromRotationMatrix(const vr::HmdMatrix34_t& mat) { 138 | auto a = mat.m; 139 | vr::HmdQuaternion_t q; 140 | double trace = a[0][0] + a[1][1] + a[2][2]; 141 | if (trace > 0) { 142 | double s = 0.5 / sqrt(trace + 1.0); 143 | q.w = 0.25 / s; 144 | q.x = (a[1][2] - a[2][1]) * s; 145 | q.y = (a[2][0] - a[0][2]) * s; 146 | q.z = (a[0][1] - a[1][0]) * s; 147 | } else { 148 | if (a[0][0] > a[1][1] && a[0][0] > a[2][2]) { 149 | double s = 2.0 * sqrt(1.0 + a[0][0] - a[1][1] - a[2][2]); 150 | q.w = (a[1][2] - a[2][1]) / s; 151 | q.x = 0.25 * s; 152 | q.y = (a[1][0] + a[0][1]) / s; 153 | q.z = (a[2][0] + a[0][2]) / s; 154 | } else if (a[1][1] > a[2][2]) { 155 | double s = 2.0 * sqrt(1.0 + a[1][1] - a[0][0] - a[2][2]); 156 | q.w = (a[2][0] - a[0][2]) / s; 157 | q.x = (a[1][0] + a[0][1]) / s; 158 | q.y = 0.25 * s; 159 | q.z = (a[2][1] + a[1][2]) / s; 160 | } else { 161 | double s = 2.0 * sqrt(1.0 + a[2][2] - a[0][0] - a[1][1]); 162 | q.w = (a[0][1] - a[1][0]) / s; 163 | q.x = (a[2][0] + a[0][2]) / s; 164 | q.y = (a[2][1] + a[1][2]) / s; 165 | q.z = 0.25 * s; 166 | } 167 | } 168 | q.x = -q.x; 169 | q.y = -q.y; 170 | q.z = -q.z; 171 | return q; 172 | } 173 | 174 | inline vr::HmdQuaternion_t quaternionConjugate(const vr::HmdQuaternion_t& quat) { 175 | return { 176 | quat.w, 177 | -quat.x, 178 | -quat.y, 179 | -quat.z, 180 | }; 181 | } 182 | 183 | inline vr::HmdVector3d_t quaternionRotateVector(const vr::HmdQuaternion_t& quat, const vr::HmdVector3d_t& vector, bool reverse = false) { 184 | if (reverse) { 185 | vr::HmdQuaternion_t pin = { 0.0, vector.v[0], vector.v[1] , vector.v[2] }; 186 | auto pout = vrmath::quaternionConjugate(quat) * pin * quat; 187 | return {pout.x, pout.y, pout.z}; 188 | } else { 189 | vr::HmdQuaternion_t pin = { 0.0, vector.v[0], vector.v[1] , vector.v[2] }; 190 | auto pout = quat * pin * vrmath::quaternionConjugate(quat); 191 | return { pout.x, pout.y, pout.z }; 192 | } 193 | } 194 | 195 | inline vr::HmdVector3d_t quaternionRotateVector(const vr::HmdQuaternion_t& quat, const vr::HmdQuaternion_t& quatInv, const vr::HmdVector3d_t& vector, bool reverse = false) { 196 | if (reverse) { 197 | vr::HmdQuaternion_t pin = { 0.0, vector.v[0], vector.v[1] , vector.v[2] }; 198 | auto pout = quatInv * pin * quat; 199 | return{ pout.x, pout.y, pout.z }; 200 | } else { 201 | vr::HmdQuaternion_t pin = { 0.0, vector.v[0], vector.v[1] , vector.v[2] }; 202 | auto pout = quat * pin * quatInv; 203 | return{ pout.x, pout.y, pout.z }; 204 | } 205 | } 206 | 207 | inline vr::HmdVector3d_t quaternionRotateVector(const vr::HmdQuaternion_t& quat, const double (&vector)[3], bool reverse = false) { 208 | if (reverse) { 209 | vr::HmdQuaternion_t pin = { 0.0, vector[0], vector[1] , vector[2] }; 210 | auto pout = vrmath::quaternionConjugate(quat) * pin * quat; 211 | return{ pout.x, pout.y, pout.z }; 212 | } else { 213 | vr::HmdQuaternion_t pin = { 0.0, vector[0], vector[1] , vector[2] }; 214 | auto pout = quat * pin * vrmath::quaternionConjugate(quat); 215 | return{ pout.x, pout.y, pout.z }; 216 | } 217 | } 218 | 219 | inline vr::HmdVector3d_t quaternionRotateVector(const vr::HmdQuaternion_t& quat, const vr::HmdQuaternion_t& quatInv, const double(&vector)[3], bool reverse = false) { 220 | if (reverse) { 221 | vr::HmdQuaternion_t pin = { 0.0, vector[0], vector[1] , vector[2] }; 222 | auto pout = quatInv * pin * quat; 223 | return{ pout.x, pout.y, pout.z }; 224 | } else { 225 | vr::HmdQuaternion_t pin = { 0.0, vector[0], vector[1] , vector[2] }; 226 | auto pout = quat * pin * quatInv; 227 | return{ pout.x, pout.y, pout.z }; 228 | } 229 | } 230 | 231 | inline vr::HmdMatrix34_t matMul33(const vr::HmdMatrix34_t& a, const vr::HmdMatrix34_t& b) { 232 | vr::HmdMatrix34_t result; 233 | for (unsigned i = 0; i < 3; i++) { 234 | for (unsigned j = 0; j < 3; j++) { 235 | result.m[i][j] = 0.0f; 236 | for (unsigned k = 0; k < 3; k++) { 237 | result.m[i][j] += a.m[i][k] * b.m[k][j]; 238 | } 239 | } 240 | } 241 | return result; 242 | } 243 | 244 | inline vr::HmdVector3_t matMul33(const vr::HmdMatrix34_t& a, const vr::HmdVector3_t& b) { 245 | vr::HmdVector3_t result; 246 | for (unsigned i = 0; i < 3; i++) { 247 | result.v[i] = 0.0f; 248 | for (unsigned k = 0; k < 3; k++) { 249 | result.v[i] += a.m[i][k] * b.v[k]; 250 | }; 251 | } 252 | return result; 253 | } 254 | 255 | inline vr::HmdVector3d_t matMul33(const vr::HmdMatrix34_t& a, const vr::HmdVector3d_t& b) { 256 | vr::HmdVector3d_t result; 257 | for (unsigned i = 0; i < 3; i++) { 258 | result.v[i] = 0.0f; 259 | for (unsigned k = 0; k < 3; k++) { 260 | result.v[i] += a.m[i][k] * b.v[k]; 261 | }; 262 | } 263 | return result; 264 | } 265 | 266 | inline vr::HmdVector3_t matMul33(const vr::HmdVector3_t& a, const vr::HmdMatrix34_t& b) { 267 | vr::HmdVector3_t result; 268 | for (unsigned i = 0; i < 3; i++) { 269 | result.v[i] = 0.0f; 270 | for (unsigned k = 0; k < 3; k++) { 271 | result.v[i] += a.v[k] * b.m[k][i]; 272 | }; 273 | } 274 | return result; 275 | } 276 | 277 | inline vr::HmdVector3d_t matMul33(const vr::HmdVector3d_t& a, const vr::HmdMatrix34_t& b) { 278 | vr::HmdVector3d_t result; 279 | for (unsigned i = 0; i < 3; i++) { 280 | result.v[i] = 0.0f; 281 | for (unsigned k = 0; k < 3; k++) { 282 | result.v[i] += a.v[k] * b.m[k][i]; 283 | }; 284 | } 285 | return result; 286 | } 287 | 288 | inline vr::HmdMatrix34_t transposeMul33(const vr::HmdMatrix34_t& a) { 289 | vr::HmdMatrix34_t result; 290 | for (unsigned i = 0; i < 3; i++) { 291 | for (unsigned k = 0; k < 3; k++) { 292 | result.m[i][k] = a.m[k][i]; 293 | } 294 | } 295 | result.m[0][3] = a.m[0][3]; 296 | result.m[1][3] = a.m[1][3]; 297 | result.m[2][3] = a.m[2][3]; 298 | return result; 299 | } 300 | } 301 | 302 | -------------------------------------------------------------------------------- /lib_vrinputemulator/include/vrinputemulator_types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | 6 | namespace vrinputemulator { 7 | 8 | static const char* const vrsettings_SectionName = "driver_00vrinputemulator"; 9 | static const char* const vrsettings_overrideHmdManufacturer_string = "overrideHmdManufacturer"; 10 | static const char* const vrsettings_overrideHmdModel_string = "overrideHmdModel"; 11 | static const char* const vrsettings_overrideHmdTrackingSystem_string = "overrideHmdTrackingSystem"; 12 | static const char* const vrsettings_genericTrackerFakeController_bool = "genericTrackerFakeController"; 13 | 14 | enum class VirtualDeviceType : uint32_t { 15 | None = 0, 16 | TrackedController = 1 17 | }; 18 | 19 | 20 | enum class ButtonEventType : uint32_t { 21 | None = 0, 22 | ButtonPressed = 1, 23 | ButtonUnpressed = 2, 24 | ButtonTouched = 3, 25 | ButtonUntouched = 4, 26 | }; 27 | 28 | 29 | enum class DevicePropertyValueType : uint32_t { 30 | None = 0, 31 | FLOAT = 1, 32 | INT32 = 2, 33 | UINT64 = 3, 34 | BOOL = 4, 35 | STRING = 5, 36 | MATRIX34 = 20, 37 | MATRIX44 = 21, 38 | VECTOR3 = 22, 39 | VECTOR4 = 23 40 | }; 41 | 42 | 43 | struct DeviceOffsets { 44 | uint32_t deviceId; 45 | bool offsetsEnabled; 46 | vr::HmdQuaternion_t worldFromDriverRotationOffset; 47 | vr::HmdVector3d_t worldFromDriverTranslationOffset; 48 | vr::HmdQuaternion_t driverFromHeadRotationOffset; 49 | vr::HmdVector3d_t driverFromHeadTranslationOffset; 50 | vr::HmdQuaternion_t deviceRotationOffset; 51 | vr::HmdVector3d_t deviceTranslationOffset; 52 | }; 53 | 54 | 55 | struct DeviceInfo { 56 | uint32_t deviceId; 57 | vr::ETrackedDeviceClass deviceClass; 58 | int deviceMode; 59 | uint32_t refDeviceId; 60 | bool offsetsEnabled; 61 | bool redirectSuspended; 62 | }; 63 | 64 | 65 | enum class MotionCompensationVelAccMode : uint32_t { 66 | Disabled = 0, 67 | SetZero = 1, 68 | SubstractMotionRef = 2, 69 | LinearApproximation = 3, 70 | KalmanFilter = 4 71 | }; 72 | 73 | 74 | enum class DigitalBindingType : uint32_t { 75 | NoRemapping = 0, 76 | Disabled = 1, 77 | OpenVR = 2, 78 | Keyboard = 3, 79 | SuspendRedirectMode = 4, 80 | ToggleTouchpadEmulationFix = 5 81 | }; 82 | 83 | 84 | struct DigitalBinding { 85 | DigitalBindingType type = DigitalBindingType::NoRemapping; 86 | 87 | union BindingUnion { 88 | struct { 89 | uint32_t controllerId; 90 | uint32_t buttonId; 91 | } openvr; 92 | 93 | struct { 94 | bool shiftPressed = false; 95 | bool ctrlPressed = false; 96 | bool altPressed = false; 97 | uint32_t keyCode = 0x00; 98 | bool sendScanCode = true; 99 | } keyboard; 100 | 101 | BindingUnion() {} 102 | } data; 103 | 104 | bool toggleEnabled = false; 105 | uint32_t toggleDelay = 0; 106 | 107 | bool autoTriggerEnabled = false; 108 | uint32_t autoTriggerFrequency = 1; 109 | 110 | DigitalBinding() {} 111 | }; 112 | 113 | 114 | struct DigitalInputRemapping { 115 | bool valid; 116 | DigitalBinding binding; 117 | 118 | bool touchAsClick = false; 119 | 120 | bool longPressEnabled = false; 121 | uint32_t longPressThreshold = 1000u; 122 | DigitalBinding longPressBinding; 123 | bool longPressImmediateRelease = false; 124 | 125 | bool doublePressEnabled = false; 126 | uint32_t doublePressThreshold = 300; 127 | DigitalBinding doublePressBinding; 128 | bool doublePressImmediateRelease = false; 129 | 130 | DigitalInputRemapping(bool valid = false) : valid(valid) {} 131 | }; 132 | 133 | 134 | enum class AnalogBindingType : uint32_t { 135 | NoRemapping, 136 | Disabled, 137 | OpenVR 138 | }; 139 | 140 | struct AnalogBinding { 141 | AnalogBindingType type; 142 | union BindingUnion { 143 | struct { 144 | uint32_t controllerId = vr::k_unTrackedDeviceIndexInvalid; 145 | uint32_t axisId = 0; 146 | } openvr; 147 | BindingUnion() {} 148 | } data; 149 | bool invertXAxis = false; 150 | bool invertYAxis = false; 151 | bool swapAxes = false; 152 | float lowerDeadzone = 0.0; 153 | float upperDeadzone = 1.0; 154 | unsigned touchpadEmulationMode = 0; // 0 .. Disabled, 1 .. Position Based, 2 .. Position Based (Deferred Zero Updates) 155 | bool buttonPressDeadzoneFix = false; 156 | 157 | AnalogBinding(AnalogBindingType type = AnalogBindingType::NoRemapping) : type(type) {} 158 | }; 159 | 160 | 161 | struct AnalogInputRemapping { 162 | bool valid; 163 | AnalogBinding binding; 164 | 165 | AnalogInputRemapping(bool valid = false) : valid(valid) {} 166 | }; 167 | 168 | 169 | } // end namespace vrinputemulator 170 | -------------------------------------------------------------------------------- /lib_vrinputemulator/src/logging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // easylogging includes 4 | #ifdef NDEBUG 5 | #undef NDEBUG 6 | #define ELPP_THREAD_SAFE 7 | #define ELPP_NO_DEFAULT_LOG_FILE 8 | #include 9 | #define NDEBUG 10 | #else 11 | #define ELPP_THREAD_SAFE 12 | #define ELPP_NO_DEFAULT_LOG_FILE 13 | #include 14 | #endif 15 | -------------------------------------------------------------------------------- /scripts/create_virtual_controller.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | IF [%1] == [] ( 4 | SET SERIAL=controller01 5 | ) ELSE ( 6 | SET "SERIAL=%~1" 7 | ) 8 | 9 | REM client_commandline.exe returns a virtual device id we need for the calls below 10 | for /f %%i in ('client_commandline.exe addcontroller "%SERIAL%"') do set VirtualDeviceId=%%i 11 | 12 | IF [%VirtualDeviceId%] == [Error] ( 13 | echo "Couldn't create virtual controller" 14 | ) ELSE ( 15 | 16 | REM Set device properties 17 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 1000 string lighthouse 18 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 1001 string "Vive Controller MV" 19 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 1003 string vr_controller_vive_1_5 20 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 1004 bool 0 21 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 1005 string HTC 22 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 1006 string "1465809478 htcvrsoftware@firmware-win32 2016-06-13 FPGA 1.6/0/0 VRC 1465809477 Radio 1466630404" 23 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 1007 string "product 129 rev 1.5.0 lot 2000/0/0 0" 24 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 1010 bool 1 25 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 1017 uint64 2164327680 26 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 1018 uint64 1465809478 27 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 1029 int32 2 28 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 3001 uint64 12884901895 29 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 3002 int32 1 30 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 3003 int32 3 31 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 3004 int32 0 32 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 3005 int32 0 33 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 3006 int32 0 34 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 3007 int32 0 35 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 5000 string icons 36 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 5001 string {htc}controller_status_off.png 37 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 5002 string {htc}controller_status_searching.gif 38 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 5003 string {htc}controller_status_searching_alert.gif 39 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 5004 string {htc}controller_status_ready.png 40 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 5005 string {htc}controller_status_ready_alert.png 41 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 5006 string {htc}controller_status_error.png 42 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 5007 string {htc}controller_status_standby.png 43 | client_commandline.exe setdeviceproperty %VirtualDeviceId% 5008 string {htc}controller_status_ready_low.png 44 | 45 | REM Let OpenVR know that there is a new device 46 | client_commandline.exe publishdevice %VirtualDeviceId% 47 | 48 | REM New devices are initially in disconnected state 49 | client_commandline.exe setdeviceconnection %VirtualDeviceId% 1 50 | 51 | REM set device position 52 | client_commandline.exe setdeviceposition %VirtualDeviceId% 0 0 0 53 | ) 54 | -------------------------------------------------------------------------------- /third-party/MinHook/include/MinHook.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__) 32 | #error MinHook supports only x86 and x64 systems. 33 | #endif 34 | 35 | #include 36 | 37 | // MinHook Error Codes. 38 | typedef enum MH_STATUS 39 | { 40 | // Unknown error. Should not be returned. 41 | MH_UNKNOWN = -1, 42 | 43 | // Successful. 44 | MH_OK = 0, 45 | 46 | // MinHook is already initialized. 47 | MH_ERROR_ALREADY_INITIALIZED, 48 | 49 | // MinHook is not initialized yet, or already uninitialized. 50 | MH_ERROR_NOT_INITIALIZED, 51 | 52 | // The hook for the specified target function is already created. 53 | MH_ERROR_ALREADY_CREATED, 54 | 55 | // The hook for the specified target function is not created yet. 56 | MH_ERROR_NOT_CREATED, 57 | 58 | // The hook for the specified target function is already enabled. 59 | MH_ERROR_ENABLED, 60 | 61 | // The hook for the specified target function is not enabled yet, or already 62 | // disabled. 63 | MH_ERROR_DISABLED, 64 | 65 | // The specified pointer is invalid. It points the address of non-allocated 66 | // and/or non-executable region. 67 | MH_ERROR_NOT_EXECUTABLE, 68 | 69 | // The specified target function cannot be hooked. 70 | MH_ERROR_UNSUPPORTED_FUNCTION, 71 | 72 | // Failed to allocate memory. 73 | MH_ERROR_MEMORY_ALLOC, 74 | 75 | // Failed to change the memory protection. 76 | MH_ERROR_MEMORY_PROTECT, 77 | 78 | // The specified module is not loaded. 79 | MH_ERROR_MODULE_NOT_FOUND, 80 | 81 | // The specified function is not found. 82 | MH_ERROR_FUNCTION_NOT_FOUND 83 | } 84 | MH_STATUS; 85 | 86 | // Can be passed as a parameter to MH_EnableHook, MH_DisableHook, 87 | // MH_QueueEnableHook or MH_QueueDisableHook. 88 | #define MH_ALL_HOOKS NULL 89 | 90 | #ifdef __cplusplus 91 | extern "C" { 92 | #endif 93 | 94 | // Initialize the MinHook library. You must call this function EXACTLY ONCE 95 | // at the beginning of your program. 96 | MH_STATUS WINAPI MH_Initialize(VOID); 97 | 98 | // Uninitialize the MinHook library. You must call this function EXACTLY 99 | // ONCE at the end of your program. 100 | MH_STATUS WINAPI MH_Uninitialize(VOID); 101 | 102 | // Creates a Hook for the specified target function, in disabled state. 103 | // Parameters: 104 | // pTarget [in] A pointer to the target function, which will be 105 | // overridden by the detour function. 106 | // pDetour [in] A pointer to the detour function, which will override 107 | // the target function. 108 | // ppOriginal [out] A pointer to the trampoline function, which will be 109 | // used to call the original target function. 110 | // This parameter can be NULL. 111 | MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal); 112 | 113 | // Creates a Hook for the specified API function, in disabled state. 114 | // Parameters: 115 | // pszModule [in] A pointer to the loaded module name which contains the 116 | // target function. 117 | // pszTarget [in] A pointer to the target function name, which will be 118 | // overridden by the detour function. 119 | // pDetour [in] A pointer to the detour function, which will override 120 | // the target function. 121 | // ppOriginal [out] A pointer to the trampoline function, which will be 122 | // used to call the original target function. 123 | // This parameter can be NULL. 124 | MH_STATUS WINAPI MH_CreateHookApi( 125 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal); 126 | 127 | // Creates a Hook for the specified API function, in disabled state. 128 | // Parameters: 129 | // pszModule [in] A pointer to the loaded module name which contains the 130 | // target function. 131 | // pszTarget [in] A pointer to the target function name, which will be 132 | // overridden by the detour function. 133 | // pDetour [in] A pointer to the detour function, which will override 134 | // the target function. 135 | // ppOriginal [out] A pointer to the trampoline function, which will be 136 | // used to call the original target function. 137 | // This parameter can be NULL. 138 | // ppTarget [out] A pointer to the target function, which will be used 139 | // with other functions. 140 | // This parameter can be NULL. 141 | MH_STATUS WINAPI MH_CreateHookApiEx( 142 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget); 143 | 144 | // Removes an already created hook. 145 | // Parameters: 146 | // pTarget [in] A pointer to the target function. 147 | MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget); 148 | 149 | // Enables an already created hook. 150 | // Parameters: 151 | // pTarget [in] A pointer to the target function. 152 | // If this parameter is MH_ALL_HOOKS, all created hooks are 153 | // enabled in one go. 154 | MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget); 155 | 156 | // Disables an already created hook. 157 | // Parameters: 158 | // pTarget [in] A pointer to the target function. 159 | // If this parameter is MH_ALL_HOOKS, all created hooks are 160 | // disabled in one go. 161 | MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget); 162 | 163 | // Queues to enable an already created hook. 164 | // Parameters: 165 | // pTarget [in] A pointer to the target function. 166 | // If this parameter is MH_ALL_HOOKS, all created hooks are 167 | // queued to be enabled. 168 | MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget); 169 | 170 | // Queues to disable an already created hook. 171 | // Parameters: 172 | // pTarget [in] A pointer to the target function. 173 | // If this parameter is MH_ALL_HOOKS, all created hooks are 174 | // queued to be disabled. 175 | MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget); 176 | 177 | // Applies all queued changes in one go. 178 | MH_STATUS WINAPI MH_ApplyQueued(VOID); 179 | 180 | // Translates the MH_STATUS to its name as a string. 181 | const char * WINAPI MH_StatusToString(MH_STATUS status); 182 | 183 | #ifdef __cplusplus 184 | } 185 | #endif 186 | 187 | -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v100-md.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v100-md.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v100-mdd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v100-mdd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v100-mt.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v100-mt.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v100-mtd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v100-mtd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v110-md.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v110-md.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v110-mdd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v110-mdd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v110-mt.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v110-mt.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v110-mtd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v110-mtd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v120-md.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v120-md.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v120-mdd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v120-mdd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v120-mt.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v120-mt.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v120-mtd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v120-mtd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v140-md.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v140-md.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v140-mdd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v140-mdd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v140-mt.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v140-mt.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v140-mtd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v140-mtd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v141-md.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v141-md.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v141-mdd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v141-mdd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v141-mt.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v141-mt.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v141-mtd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v141-mtd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v90-md.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v90-md.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v90-mdd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v90-mdd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v90-mt.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v90-mt.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x64-v90-mtd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x64-v90-mtd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v100-md.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v100-md.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v100-mdd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v100-mdd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v100-mt.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v100-mt.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v100-mtd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v100-mtd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v110-md.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v110-md.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v110-mdd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v110-mdd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v110-mt.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v110-mt.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v110-mtd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v110-mtd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v120-md.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v120-md.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v120-mdd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v120-mdd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v120-mt.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v120-mt.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v120-mtd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v120-mtd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v140-md.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v140-md.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v140-mdd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v140-mdd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v140-mt.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v140-mt.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v140-mtd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v140-mtd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v141-md.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v141-md.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v141-mdd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v141-mdd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v141-mt.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v141-mt.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v141-mtd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v141-mtd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v90-md.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v90-md.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v90-mdd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v90-mdd.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v90-mt.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v90-mt.lib -------------------------------------------------------------------------------- /third-party/MinHook/lib/libMinHook-x86-v90-mtd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharkyh20/OpenVR-InputEmulator/de7e1ec9ab1f0aa5766d58ac65db061ba6615d2d/third-party/MinHook/lib/libMinHook-x86-v90-mtd.lib -------------------------------------------------------------------------------- /third-party/MinHook/readme.txt: -------------------------------------------------------------------------------- 1 | Each file name has these tags: 2 | 3 | "x86", "x64": 4 | CPU archtecture 5 | 6 | "v90", "v100", "v110", "v120", "v140", "v141": 7 | Platform toolset (compiler version) 8 | Choose "v110" for "v110_xp", "v120" for "v120_xp", "v140" for "v140_xp", "v141" for "v141_xp" 9 | 10 | "md", "mt", "mdd", "mtd": 11 | Runtime Link (Dynamic/Static) and Config (Release/Debug) 12 | Corresponding to "/MD", "/MT", "/MDd" and "/MTd" compiler options respectively. 13 | -------------------------------------------------------------------------------- /third-party/easylogging++/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 muflihun.com 4 | 5 | http://github.com/easylogging/ 6 | http://easylogging.muflihun.com 7 | http://muflihun.com 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy of 10 | this software and associated documentation files (the "Software"), to deal in 11 | the Software without restriction, including without limitation the rights to 12 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 13 | the Software, and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 21 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 22 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 23 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | --------------------------------------------------------------------------------