From 5df6869b379401874fb2cae0c1e33a58aaab8786 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sun, 26 Feb 2012 22:18:16 +0000 Subject: ndof: unified button handling for modern 3Dx devices, also first steps toward keymappable modifiers (shift,ctrl,etc.) --- intern/ghost/intern/GHOST_NDOFManager.cpp | 207 +++++++++++------------------- intern/ghost/intern/GHOST_NDOFManager.h | 11 +- 2 files changed, 82 insertions(+), 136 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 0f5149de037..b16fa8fb90a 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -66,6 +66,11 @@ static const char* ndof_button_names[] = { "NDOF_BUTTON_DOMINANT", "NDOF_BUTTON_PLUS", "NDOF_BUTTON_MINUS", + // keyboard emulation + "NDOF_BUTTON_ESC", + "NDOF_BUTTON_ALT", + "NDOF_BUTTON_SHIFT", + "NDOF_BUTTON_CTRL", // general-purpose buttons "NDOF_BUTTON_1", "NDOF_BUTTON_2", @@ -86,30 +91,10 @@ static const char* ndof_button_names[] = { }; #endif -static const NDOF_ButtonT SpaceNavigator_HID_map[] = { - NDOF_BUTTON_MENU, - NDOF_BUTTON_FIT -}; - -static const NDOF_ButtonT SpaceExplorer_HID_map[] = { - NDOF_BUTTON_1, - NDOF_BUTTON_2, - NDOF_BUTTON_TOP, - NDOF_BUTTON_LEFT, - NDOF_BUTTON_RIGHT, - NDOF_BUTTON_FRONT, - NDOF_BUTTON_NONE, // esc key - NDOF_BUTTON_NONE, // alt key - NDOF_BUTTON_NONE, // shift key - NDOF_BUTTON_NONE, // ctrl key - NDOF_BUTTON_FIT, - NDOF_BUTTON_MENU, - NDOF_BUTTON_PLUS, - NDOF_BUTTON_MINUS, - NDOF_BUTTON_ROTATE -}; - -static const NDOF_ButtonT SpacePilotPro_HID_map[] = { +// shared by the latest 3Dconnexion hardware +// SpacePilotPro uses all of these +// smaller devices use only some, based on button mask +static const NDOF_ButtonT Modern3Dx_HID_map[] = { NDOF_BUTTON_MENU, NDOF_BUTTON_FIT, NDOF_BUTTON_TOP, @@ -132,10 +117,10 @@ static const NDOF_ButtonT SpacePilotPro_HID_map[] = { NDOF_BUTTON_8, NDOF_BUTTON_9, NDOF_BUTTON_10, - NDOF_BUTTON_NONE, // esc key - NDOF_BUTTON_NONE, // alt key - NDOF_BUTTON_NONE, // shift key - NDOF_BUTTON_NONE, // ctrl key + NDOF_BUTTON_ESC, + NDOF_BUTTON_ALT, + NDOF_BUTTON_SHIFT, + NDOF_BUTTON_CTRL, NDOF_BUTTON_ROTATE, NDOF_BUTTON_PANZOOM, NDOF_BUTTON_DOMINANT, @@ -143,35 +128,22 @@ static const NDOF_ButtonT SpacePilotPro_HID_map[] = { NDOF_BUTTON_MINUS }; -// latest HW: button-compatible with SpacePilotPro, just fewer of them -static const NDOF_ButtonT SpaceMousePro_HID_map[] = { - NDOF_BUTTON_MENU, - NDOF_BUTTON_FIT, +static const NDOF_ButtonT SpaceExplorer_HID_map[] = { + NDOF_BUTTON_1, + NDOF_BUTTON_2, NDOF_BUTTON_TOP, - NDOF_BUTTON_NONE, // left + NDOF_BUTTON_LEFT, NDOF_BUTTON_RIGHT, NDOF_BUTTON_FRONT, - NDOF_BUTTON_NONE, // bottom - NDOF_BUTTON_NONE, // back - NDOF_BUTTON_ROLL_CW, - NDOF_BUTTON_NONE, // roll ccw - NDOF_BUTTON_NONE, // iso 1 - NDOF_BUTTON_NONE, // iso 2 - NDOF_BUTTON_1, - NDOF_BUTTON_2, - NDOF_BUTTON_3, - NDOF_BUTTON_4, - NDOF_BUTTON_NONE, // 5 - NDOF_BUTTON_NONE, // 6 - NDOF_BUTTON_NONE, // 7 - NDOF_BUTTON_NONE, // 8 - NDOF_BUTTON_NONE, // 9 - NDOF_BUTTON_NONE, // 10 - NDOF_BUTTON_NONE, // esc key - NDOF_BUTTON_NONE, // alt key - NDOF_BUTTON_NONE, // shift key - NDOF_BUTTON_NONE, // ctrl key - NDOF_BUTTON_ROTATE, + NDOF_BUTTON_ESC, // esc key + NDOF_BUTTON_ALT, // alt key + NDOF_BUTTON_SHIFT, // shift key + NDOF_BUTTON_CTRL, // ctrl key + NDOF_BUTTON_FIT, + NDOF_BUTTON_MENU, + NDOF_BUTTON_PLUS, + NDOF_BUTTON_MINUS, + NDOF_BUTTON_ROTATE }; /* this is the older SpacePilot (sans Pro) @@ -187,10 +159,10 @@ static const NDOF_ButtonT SpacePilot_HID_map[] = { NDOF_BUTTON_LEFT, NDOF_BUTTON_RIGHT, NDOF_BUTTON_FRONT, - NDOF_BUTTON_NONE, // esc key - NDOF_BUTTON_NONE, // alt key - NDOF_BUTTON_NONE, // shift key - NDOF_BUTTON_NONE, // ctrl key + NDOF_BUTTON_ESC, // esc key + NDOF_BUTTON_ALT, // alt key + NDOF_BUTTON_SHIFT, // shift key + NDOF_BUTTON_CTRL, // ctrl key NDOF_BUTTON_FIT, NDOF_BUTTON_MENU, NDOF_BUTTON_PLUS, @@ -200,9 +172,7 @@ static const NDOF_ButtonT SpacePilot_HID_map[] = { NDOF_BUTTON_NONE // the CONFIG button -- what does it do? }; -/* this is the older Spaceball 5000 USB - * thanks to Tehrasha Darkon for info about this device */ -static const NDOF_ButtonT Spaceball5000_HID_map[] = { +static const NDOF_ButtonT Generic_HID_map[] = { NDOF_BUTTON_1, NDOF_BUTTON_2, NDOF_BUTTON_3, @@ -222,6 +192,7 @@ GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) , m_deviceType(NDOF_UnknownDevice) // each platform has its own device detection code , m_buttonCount(0) , m_buttonMask(0) + , m_hidMap(Generic_HID_map) , m_buttons(0) , m_motionTime(0) , m_prevMotionTime(0) @@ -237,38 +208,53 @@ GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short product_id) { - // default to NDOF_UnknownDevice so rogue button events will get discarded + // call this function until it returns true + // it's a good idea to stop calling it after that, as it will "forget" + // whichever device it already found + + // default to safe generic behavior for "unknown" devices + // unidentified devices will emit motion events like normal + // rogue buttons do nothing by default, but can be customized by the user + + m_deviceType = NDOF_UnknownDevice; + m_hidMap = Generic_HID_map; + m_buttonCount = sizeof(Generic_HID_map) / sizeof(NDOF_ButtonT); + m_buttonMask = 0; + // "mystery device" owners can help build a HID_map for their hardware + // A few users have already contributed information about several older devices + // that I don't have access to. Thanks! switch (vendor_id) { case 0x046D: // Logitech (3Dconnexion) switch (product_id) { // -- current devices -- - case 0xC626: + case 0xC626: // full-size SpaceNavigator + case 0xC628: // the "for Notebooks" one puts("ndof: using SpaceNavigator"); m_deviceType = NDOF_SpaceNavigator; m_buttonCount = 2; - break; - case 0xC628: - puts("ndof: using SpaceNavigator for Notebooks"); - m_deviceType = NDOF_SpaceNavigator; // for Notebooks - m_buttonCount = 2; + m_hidMap = Modern3Dx_HID_map; break; case 0xC627: puts("ndof: using SpaceExplorer"); m_deviceType = NDOF_SpaceExplorer; m_buttonCount = 15; + m_hidMap = SpaceExplorer_HID_map; break; case 0xC629: puts("ndof: using SpacePilot Pro"); m_deviceType = NDOF_SpacePilotPro; m_buttonCount = 31; + m_hidMap = Modern3Dx_HID_map; break; case 0xC62B: puts("ndof: using SpaceMouse Pro"); m_deviceType = NDOF_SpaceMousePro; m_buttonCount = 27; // ^^ actually has 15 buttons, but their HID codes range from 0 to 26 + m_buttonMask = 0x07C0F137; + m_hidMap = Modern3Dx_HID_map; break; // -- older devices -- @@ -276,6 +262,7 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ puts("ndof: using SpacePilot"); m_deviceType = NDOF_SpacePilot; m_buttonCount = 21; + m_hidMap = SpacePilot_HID_map; break; case 0xC621: @@ -285,7 +272,8 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ break; case 0xC623: - puts("ndof: SpaceTraveler not supported, please file a bug report"); + puts("ndof: using SpaceTraveler"); + m_deviceType = NDOF_SpaceTraveler; m_buttonCount = 8; break; @@ -297,20 +285,14 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ printf("ndof: unknown device %04hx:%04hx\n", vendor_id, product_id); } - if (m_deviceType == NDOF_UnknownDevice) { - return false; - } - else { + if (m_buttonMask == 0) m_buttonMask = ~(-1 << m_buttonCount); - // special case for SpaceMousePro? maybe... - #ifdef DEBUG_NDOF_BUTTONS - printf("ndof: %d buttons -> hex:%X\n", m_buttonCount, m_buttonMask); + printf("ndof: %d buttons -> hex:%X\n", m_buttonCount, m_buttonMask); #endif - return true; - } + return m_deviceType != NDOF_UnknownDevice; } void GHOST_NDOFManager::updateTranslation(short t[3], GHOST_TUns64 time) @@ -373,62 +355,16 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 printf("ndof: button %d -> ", button_number); #endif - switch (m_deviceType) { - case NDOF_SpaceNavigator: - sendButtonEvent(SpaceNavigator_HID_map[button_number], press, time, window); - break; - case NDOF_SpaceExplorer: - switch (button_number) { - case 6: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break; - case 7: sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); break; - case 8: sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); break; - case 9: sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); break; - default: sendButtonEvent(SpaceExplorer_HID_map[button_number], press, time, window); - } - break; - case NDOF_SpacePilotPro: - switch (button_number) { - case 22: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break; - case 23: sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); break; - case 24: sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); break; - case 25: sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); break; - default: sendButtonEvent(SpacePilotPro_HID_map[button_number], press, time, window); - } - break; - case NDOF_SpaceMousePro: - switch (button_number) { - case 22: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break; - case 23: sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); break; - case 24: sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); break; - case 25: sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); break; - default: sendButtonEvent(SpaceMousePro_HID_map[button_number], press, time, window); - } - break; - case NDOF_SpacePilot: - switch (button_number) { - case 10: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break; - case 11: sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); break; - case 12: sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); break; - case 13: sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); break; - case 20: puts("ndof: ignoring CONFIG button"); break; - default: sendButtonEvent(SpacePilot_HID_map[button_number], press, time, window); - } - break; - case NDOF_Spaceball5000: - // has no special 'keyboard' buttons - sendButtonEvent(Spaceball5000_HID_map[button_number], press, time, window); - break; - case NDOF_UnknownDevice: - printf("ndof: button %d on unknown device (", button_number); - // map to the 'general purpose' buttons - // this is mainly for old serial devices - if (button_number < NDOF_BUTTON_LAST - NDOF_BUTTON_1) { - printf("sending)\n"); - sendButtonEvent((NDOF_ButtonT)(NDOF_BUTTON_1 + button_number), press, time, window); - } - else { - printf("discarding)\n"); - } + NDOF_ButtonT button = m_hidMap[button_number]; + + switch (button) + { + case NDOF_BUTTON_NONE: break; + case NDOF_BUTTON_ESC: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break; + case NDOF_BUTTON_ALT: sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); break; + case NDOF_BUTTON_SHIFT: sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); break; + case NDOF_BUTTON_CTRL: sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); break; + default: sendButtonEvent(button, press, time, window); } int mask = 1 << button_number; @@ -558,6 +494,9 @@ bool GHOST_NDOFManager::sendMotionEvent() printf("ndof motion sent -- %s\n", progress_string[data->progress]); // show details about this motion event + printf(" T=(%d,%d,%d) R=(%d,%d,%d) raw\n", + m_translation[0], m_translation[1], m_translation[2], + m_rotation[0], m_rotation[1], m_rotation[2]); printf(" T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n", data->tx, data->ty, data->tz, data->rx, data->ry, data->rz, diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 9d72691b746..5e16c3fc54c 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -31,7 +31,7 @@ // #define DEBUG_NDOF_BUTTONS typedef enum { - NDOF_UnknownDevice, // <-- motion will work fine, buttons are ignored + NDOF_UnknownDevice, // current devices NDOF_SpaceNavigator, @@ -41,7 +41,8 @@ typedef enum { // older devices NDOF_SpacePilot, - NDOF_Spaceball5000 + NDOF_Spaceball5000, + NDOF_SpaceTraveler } NDOF_DeviceT; @@ -76,6 +77,11 @@ typedef enum { NDOF_BUTTON_DOMINANT, NDOF_BUTTON_PLUS, NDOF_BUTTON_MINUS, + // keyboard emulation + NDOF_BUTTON_ESC, + NDOF_BUTTON_ALT, + NDOF_BUTTON_SHIFT, + NDOF_BUTTON_CTRL, // general-purpose buttons // users can assign functions via keymap editor NDOF_BUTTON_1, @@ -149,6 +155,7 @@ private: NDOF_DeviceT m_deviceType; int m_buttonCount; int m_buttonMask; + const NDOF_ButtonT* m_hidMap; short m_translation[3]; short m_rotation[3]; -- cgit v1.2.3