ndof device detection on Windows, safer button handling
This commit is contained in:
@@ -134,7 +134,9 @@ static const NDOF_ButtonT SpacePilotPro_HID_map[] =
|
||||
|
||||
GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys)
|
||||
: m_system(sys)
|
||||
, m_deviceType(NDOF_UnknownDevice) // each platform needs its own device detection code
|
||||
, m_deviceType(NDOF_UnknownDevice) // each platform has its own device detection code
|
||||
, m_buttonCount(0)
|
||||
, m_buttonMask(0)
|
||||
, m_buttons(0)
|
||||
, m_motionTime(1000) // one full second (operators should filter out such large time deltas)
|
||||
, m_prevMotionTime(0)
|
||||
@@ -154,10 +156,26 @@ void GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ
|
||||
switch (product_id)
|
||||
{
|
||||
// -- current devices --
|
||||
case 0xC626: m_deviceType = NDOF_SpaceNavigator; break;
|
||||
case 0xC628: m_deviceType = NDOF_SpaceNavigator; /* for Notebooks */ break;
|
||||
case 0xC627: m_deviceType = NDOF_SpaceExplorer; break;
|
||||
case 0xC629: m_deviceType = NDOF_SpacePilotPro; break;
|
||||
case 0xC626:
|
||||
m_deviceType = NDOF_SpaceNavigator;
|
||||
m_buttonCount = 2;
|
||||
// m_buttonMask = 0x3; // 2 buttons
|
||||
break;
|
||||
case 0xC628:
|
||||
m_deviceType = NDOF_SpaceNavigator; // for Notebooks
|
||||
m_buttonCount = 2;
|
||||
// m_buttonMask = 0x3; // 2 buttons
|
||||
break;
|
||||
case 0xC627:
|
||||
m_deviceType = NDOF_SpaceExplorer;
|
||||
m_buttonCount = 15;
|
||||
// m_buttonMask = 0x7FFF; // 15 buttons
|
||||
break;
|
||||
case 0xC629:
|
||||
m_deviceType = NDOF_SpacePilotPro;
|
||||
m_buttonCount = 29;
|
||||
// m_buttonMask = 0x1FFFFFFF; // 29 buttons
|
||||
break;
|
||||
|
||||
// -- older devices --
|
||||
case 0xC623: puts("ndof: SpaceTraveler not supported, please file a bug report"); break;
|
||||
@@ -169,6 +187,9 @@ void GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ
|
||||
default:
|
||||
printf("ndof: unknown vendor %04hx\n", vendor_id);
|
||||
}
|
||||
|
||||
m_buttonMask = ~(-1 << m_buttonCount);
|
||||
printf("ndof: %d buttons -> %X\n", m_buttonCount, m_buttonMask);
|
||||
}
|
||||
|
||||
void GHOST_NDOFManager::updateTranslation(short t[3], GHOST_TUns64 time)
|
||||
@@ -217,7 +238,8 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64
|
||||
GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow();
|
||||
|
||||
#ifdef DEBUG_NDOF_BUTTONS
|
||||
printf("ndof: button %d -> ", button_number);
|
||||
if (m_deviceType != NDOF_UnknownDevice)
|
||||
printf("ndof: button %d -> ", button_number);
|
||||
#endif
|
||||
|
||||
switch (m_deviceType)
|
||||
@@ -258,6 +280,8 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64
|
||||
|
||||
void GHOST_NDOFManager::updateButtons(int button_bits, GHOST_TUns64 time)
|
||||
{
|
||||
button_bits &= m_buttonMask; // discard any "garbage" bits
|
||||
|
||||
int diff = m_buttons ^ button_bits;
|
||||
|
||||
for (int button_number = 0; button_number <= 31; ++button_number)
|
||||
|
||||
@@ -115,6 +115,8 @@ private:
|
||||
|
||||
|
||||
NDOF_DeviceT m_deviceType;
|
||||
int m_buttonCount;
|
||||
int m_buttonMask;
|
||||
|
||||
short m_translation[3];
|
||||
short m_rotation[3];
|
||||
|
||||
@@ -818,9 +818,28 @@ void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax)
|
||||
minmax->ptMinTrackSize.y=240;
|
||||
}
|
||||
|
||||
bool GHOST_SystemWin32::processNDOF(/*GHOST_WindowWin32* window,*/ RAWINPUT const& raw)
|
||||
bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw)
|
||||
{
|
||||
bool eventSent = false;
|
||||
GHOST_TUns64 now = getMilliSeconds();
|
||||
|
||||
static bool firstEvent = true;
|
||||
if (firstEvent)
|
||||
{ // determine exactly which device is plugged in
|
||||
RID_DEVICE_INFO info;
|
||||
unsigned infoSize = sizeof(RID_DEVICE_INFO);
|
||||
info.cbSize = infoSize;
|
||||
|
||||
GetRawInputDeviceInfo(raw.header.hDevice, RIDI_DEVICEINFO, &info, &infoSize);
|
||||
if (info.dwType == RIM_TYPEHID)
|
||||
{
|
||||
printf("hardware ID = %08X:%08X\n", info.hid.dwVendorId, info.hid.dwProductId);
|
||||
m_ndofManager->setDevice(info.hid.dwVendorId, info.hid.dwProductId);
|
||||
}
|
||||
else puts("<!> not a HID device... mouse/kb perhaps?");
|
||||
|
||||
firstEvent = false;
|
||||
}
|
||||
|
||||
// The NDOF manager sends button changes immediately, and *pretends* to
|
||||
// send motion. Mark as 'sent' so motion will always get dispatched.
|
||||
@@ -839,26 +858,39 @@ bool GHOST_SystemWin32::processNDOF(/*GHOST_WindowWin32* window,*/ RAWINPUT cons
|
||||
{
|
||||
case 1: // translation
|
||||
{
|
||||
short t[3];
|
||||
memcpy(t, data + 1, sizeof(t));
|
||||
m_ndofManager->updateTranslation(t, getMilliSeconds());
|
||||
short axis_data[3];
|
||||
memcpy(axis_data, data + 1, sizeof(axis_data));
|
||||
m_ndofManager->updateTranslation(axis_data, now);
|
||||
// wariness of alignment issues prevents me from saying it this way:
|
||||
// m_ndofManager->updateTranslation((short*)(data + 1), getMilliSeconds());
|
||||
// though it probably (94.7%) would work fine
|
||||
|
||||
if (raw.data.hid.dwSizeHid == 13)
|
||||
{ // this report also includes rotation
|
||||
puts("ndof: combined T + R");
|
||||
memcpy(axis_data, data + 7, sizeof(axis_data));
|
||||
m_ndofManager->updateRotation(axis_data, now);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: // rotation
|
||||
{
|
||||
short r[3];
|
||||
memcpy(r, data + 1, sizeof(r));
|
||||
m_ndofManager->updateRotation(r, getMilliSeconds());
|
||||
short axis_data[3];
|
||||
memcpy(axis_data, data + 1, sizeof(axis_data));
|
||||
m_ndofManager->updateRotation(axis_data, now);
|
||||
break;
|
||||
}
|
||||
case 3: // buttons
|
||||
{
|
||||
// I'm getting garbage bits -- examine whole report:
|
||||
printf("ndof: HID report for buttons [");
|
||||
for (int i = 0; i < raw.data.hid.dwSizeHid; ++i)
|
||||
printf(" %02X", data[i]);
|
||||
printf(" ]\n");
|
||||
|
||||
int button_bits;
|
||||
memcpy(&button_bits, data + 1, sizeof(button_bits));
|
||||
m_ndofManager->updateButtons(button_bits, getMilliSeconds());
|
||||
m_ndofManager->updateButtons(button_bits, now);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -910,7 +942,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
}
|
||||
break;
|
||||
case RIM_TYPEHID:
|
||||
if (system->processNDOF(/*window,*/ raw))
|
||||
if (system->processNDOF(raw))
|
||||
eventHandled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -397,11 +397,10 @@ protected:
|
||||
* Handles Motion and Button events from a SpaceNavigator or related device.
|
||||
* Instead of returning an event object, this function communicates directly
|
||||
* with the GHOST_NDOFManager.
|
||||
* @param window The window receiving the event (the active window).
|
||||
* @param raw RawInput structure with detailed info about the NDOF event
|
||||
* @return Whether an event was generated and sent.
|
||||
*/
|
||||
bool processNDOF(/*GHOST_IWindow *window,*/ RAWINPUT const& raw);
|
||||
bool processNDOF(RAWINPUT const& raw);
|
||||
|
||||
/**
|
||||
* Returns the local state of the modifier keys (from the message queue).
|
||||
|
||||
Reference in New Issue
Block a user