3DConnexionDriver.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "EditorDefs.h"
  9. #include "3DConnexionDriver.h"
  10. #if defined(AZ_PLATFORM_WINDOWS)
  11. //////////////////////////////////////////////////////////////////////////
  12. C3DConnexionDriver::C3DConnexionDriver()
  13. {
  14. m_pRawInputDeviceList = 0;
  15. m_pRawInputDevices = 0;
  16. m_nUsagePage1Usage8Devices = 0;
  17. m_fMultiplier = 1.0f;
  18. InitDevice();
  19. }
  20. //////////////////////////////////////////////////////////////////////////
  21. C3DConnexionDriver::~C3DConnexionDriver()
  22. {
  23. }
  24. bool C3DConnexionDriver::InitDevice()
  25. {
  26. // Find the Raw Devices
  27. UINT nDevices;
  28. // Get Number of devices attached
  29. if (GetRawInputDeviceList(nullptr, &nDevices, sizeof(RAWINPUTDEVICELIST)) != 0)
  30. {
  31. return false;
  32. }
  33. // Create list large enough to hold all RAWINPUTDEVICE structs
  34. if ((m_pRawInputDeviceList = (PRAWINPUTDEVICELIST)malloc(sizeof(RAWINPUTDEVICELIST) * nDevices)) == nullptr)
  35. {
  36. return false;
  37. }
  38. // Now get the data on the attached devices
  39. if (GetRawInputDeviceList(m_pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST)) == -1)
  40. {
  41. return false;
  42. }
  43. m_pRawInputDevices = (PRAWINPUTDEVICE)malloc(nDevices * sizeof(RAWINPUTDEVICE));
  44. m_nUsagePage1Usage8Devices = 0;
  45. // Look through device list for RIM_TYPEHID devices with UsagePage == 1, Usage == 8
  46. for (UINT i = 0; i < nDevices; i++)
  47. {
  48. //Doc says RIM_TYPEHID: Data comes from an HID that is not a keyboard or a mouse.
  49. if (m_pRawInputDeviceList[i].dwType == RIM_TYPEHID)
  50. {
  51. RID_DEVICE_INFO dinfo;
  52. UINT sizeofdinfo = sizeof(dinfo);
  53. dinfo.cbSize = sizeofdinfo;
  54. GetRawInputDeviceInfo(m_pRawInputDeviceList[i].hDevice,
  55. RIDI_DEVICEINFO, &dinfo, &sizeofdinfo);
  56. if (dinfo.dwType == RIM_TYPEHID)
  57. {
  58. RID_DEVICE_INFO_HID* phidInfo = &dinfo.hid;
  59. // Add this one to the list of interesting devices?
  60. // Actually only have to do this once to get input from all usage 1, usagePage 8 devices
  61. // This just keeps out the other usages.
  62. // You might want to put up a list for users to select amongst the different devices.
  63. // In particular, to assign separate functionality to the different devices.
  64. if (phidInfo->usUsagePage == 1 && phidInfo->usUsage == 8)
  65. {
  66. m_pRawInputDevices[m_nUsagePage1Usage8Devices].usUsagePage = phidInfo->usUsagePage;
  67. m_pRawInputDevices[m_nUsagePage1Usage8Devices].usUsage = phidInfo->usUsage;
  68. m_pRawInputDevices[m_nUsagePage1Usage8Devices].dwFlags = 0;
  69. m_pRawInputDevices[m_nUsagePage1Usage8Devices].hwndTarget = nullptr;
  70. m_nUsagePage1Usage8Devices++;
  71. }
  72. }
  73. }
  74. }
  75. // Register for input from the devices in the list
  76. if (RegisterRawInputDevices(m_pRawInputDevices, m_nUsagePage1Usage8Devices, sizeof(RAWINPUTDEVICE)) == false)
  77. {
  78. return false;
  79. }
  80. return true;
  81. }
  82. //////////////////////////////////////////////////////////////////////////
  83. bool C3DConnexionDriver::GetInputMessageData(LPARAM lParam, S3DConnexionMessage& msg)
  84. {
  85. ZeroStruct(msg);
  86. RAWINPUTHEADER header;
  87. UINT size = sizeof(header);
  88. if (GetRawInputData((HRAWINPUT)lParam, RID_HEADER, &header, &size, sizeof(RAWINPUTHEADER)) == -1)
  89. {
  90. return false;
  91. }
  92. // Set aside enough memory for the full event
  93. char rawbuffer[128];
  94. LPRAWINPUT event = (LPRAWINPUT)rawbuffer;
  95. size = sizeof(rawbuffer);
  96. if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, event, &size, sizeof(RAWINPUTHEADER)) == -1)
  97. {
  98. return false;
  99. }
  100. else
  101. {
  102. if (event->header.dwType == RIM_TYPEHID)
  103. {
  104. LPRAWHID pRawHid = &event->data.hid;
  105. // Translation or Rotation packet? They come in two different packets.
  106. if (pRawHid->bRawData[0] == 1) // Translation vector
  107. {
  108. msg.raw_translation[0] = (pRawHid->bRawData[1] & 0x000000ff) | ((signed short)(pRawHid->bRawData[2] << 8) & 0xffffff00);
  109. msg.raw_translation[1] = (pRawHid->bRawData[3] & 0x000000ff) | ((signed short)(pRawHid->bRawData[4] << 8) & 0xffffff00);
  110. msg.raw_translation[2] = (pRawHid->bRawData[5] & 0x000000ff) | ((signed short)(pRawHid->bRawData[6] << 8) & 0xffffff00);
  111. msg.vTranslate.x = msg.raw_translation[0] / 255.f * m_fMultiplier;
  112. msg.vTranslate.y = msg.raw_translation[1] / 255.f * m_fMultiplier;
  113. msg.vTranslate.z = msg.raw_translation[2] / 255.f * m_fMultiplier;
  114. msg.bGotTranslation = true;
  115. }
  116. else if (pRawHid->bRawData[0] == 2) // Rotation vector
  117. {
  118. msg.raw_rotation[0] = (pRawHid->bRawData[1] & 0x000000ff) | ((signed short)(pRawHid->bRawData[2] << 8) & 0xffffff00);
  119. msg.raw_rotation[1] = (pRawHid->bRawData[3] & 0x000000ff) | ((signed short)(pRawHid->bRawData[4] << 8) & 0xffffff00);
  120. msg.raw_rotation[2] = (pRawHid->bRawData[5] & 0x000000ff) | ((signed short)(pRawHid->bRawData[6] << 8) & 0xffffff00);
  121. msg.vRotate.x = msg.raw_rotation[0] / 255.f * m_fMultiplier;
  122. msg.vRotate.y = msg.raw_rotation[1] / 255.f * m_fMultiplier;
  123. msg.vRotate.z = msg.raw_rotation[2] / 255.f * m_fMultiplier;
  124. msg.bGotRotation = true;
  125. }
  126. else if (pRawHid->bRawData[0] == 3) // Buttons (display most significant byte to least)
  127. {
  128. msg.buttons[0] = (unsigned char)pRawHid->bRawData[1];
  129. msg.buttons[1] = (unsigned char)pRawHid->bRawData[2];
  130. msg.buttons[2] = (unsigned char)pRawHid->bRawData[3];
  131. CryLog("Button mask: %.2x %.2x %.2x\n", (unsigned char)pRawHid->bRawData[3], (unsigned char)pRawHid->bRawData[2], (unsigned char)pRawHid->bRawData[1]);
  132. if (msg.buttons[0] == 1)
  133. {
  134. m_fMultiplier /= 2.0f;
  135. }
  136. else if (msg.buttons[0] == 2)
  137. {
  138. m_fMultiplier *= 2.0f;
  139. }
  140. }
  141. }
  142. }
  143. return true;
  144. }
  145. #endif