GHOST/NDOF: Extend NDOF devices support on Windows

Commit adds support for new format of RawInput packets used by
3Dconnexion devices: SpaceMouse Enterprise, Keyboard Pro and Numpad Pro
specifically. This required distinguishing processing button data
delivered as a bitmask and as a numbers array.

Basically it allows for using said devices buttons in Blender including
using these buttons in shortcuts.

Changes work only for Windows. MacOS will allow only for older format
that is bitmask.

Details:

- NDOF button event values have been moved into the public GHOST_Types.h
  header and are no longer aligned to the WM event values.
  This was done so the values could be changed to match hardware/drivers
  without breaking key-maps stored in user preferences.
- Keyboard Pro and Numpad Pro buttons are not currently used because
  they don't map to any standard keyboard events.
  These could be supported, see the PR for details.

Ref: !124155
This commit is contained in:
Kamil Galik
2024-06-24 14:55:35 +02:00
committed by Campbell Barton
parent 6b559c0225
commit 3da3f678eb
11 changed files with 624 additions and 298 deletions
+111
View File
@@ -935,3 +935,114 @@ typedef struct GHOST_XrControllerModelData {
#endif /* WITH_XR_OPENXR */
// NOLINTEND: modernize-use-using
/**
* NDOF device button event types.
*
* SpaceMouse devices ship with an internal identifier number for each button.
* Deprecated versions of the 3DxWare SDK have a `virtualkeys.h` header file
* where some of these numbers are found but it is basically an arbitrary assignment
* made by the vendor (3Dconnexion) since the application has the freedom to override as necessary.
*/
typedef enum {
GHOST_NDOF_BUTTON_NONE = -1,
/* Used internally, never sent or used as an index. */
GHOST_NDOF_BUTTON_INVALID = 0,
/* These two are available from any 3Dconnexion device. */
GHOST_NDOF_BUTTON_MENU = 1,
GHOST_NDOF_BUTTON_FIT = 2,
/* Standard views. */
GHOST_NDOF_BUTTON_TOP = 3,
GHOST_NDOF_BUTTON_LEFT = 4,
GHOST_NDOF_BUTTON_RIGHT = 5,
GHOST_NDOF_BUTTON_FRONT = 6,
GHOST_NDOF_BUTTON_BOTTOM = 7,
GHOST_NDOF_BUTTON_BACK = 8,
/* 90 degrees rotations. */
GHOST_NDOF_BUTTON_ROLL_CW = 9,
GHOST_NDOF_BUTTON_ROLL_CCW = 10,
/* More views. */
GHOST_NDOF_BUTTON_ISO1 = 11,
GHOST_NDOF_BUTTON_ISO2 = 12,
/* General-purpose buttons.
* Users can assign functions via keymap editor. */
GHOST_NDOF_BUTTON_1 = 13,
GHOST_NDOF_BUTTON_2 = 14,
GHOST_NDOF_BUTTON_3 = 15,
GHOST_NDOF_BUTTON_4 = 16,
GHOST_NDOF_BUTTON_5 = 17,
GHOST_NDOF_BUTTON_6 = 18,
GHOST_NDOF_BUTTON_7 = 19,
GHOST_NDOF_BUTTON_8 = 20,
GHOST_NDOF_BUTTON_9 = 21,
GHOST_NDOF_BUTTON_10 = 22,
/* Keyboard keys. */
GHOST_NDOF_BUTTON_ESC = 23,
GHOST_NDOF_BUTTON_ALT = 24,
GHOST_NDOF_BUTTON_SHIFT = 25,
GHOST_NDOF_BUTTON_CTRL = 26,
/* Device control. */
GHOST_NDOF_BUTTON_ROTATE = 27,
GHOST_NDOF_BUTTON_PANZOOM = 28,
GHOST_NDOF_BUTTON_DOMINANT = 29,
GHOST_NDOF_BUTTON_PLUS = 30,
GHOST_NDOF_BUTTON_MINUS = 31,
/* New spin buttons. */
GHOST_NDOF_BUTTON_SPIN_CW = 32,
GHOST_NDOF_BUTTON_SPIN_CCW = 33,
GHOST_NDOF_BUTTON_TILT_CW = 34,
GHOST_NDOF_BUTTON_TILT_CCW = 35,
/* Keyboard keys. */
GHOST_NDOF_BUTTON_ENTER = 36,
GHOST_NDOF_BUTTON_DELETE = 37,
/* Keyboard Pro special buttons. */
GHOST_NDOF_BUTTON_KBP_F1 = 41,
GHOST_NDOF_BUTTON_KBP_F2 = 42,
GHOST_NDOF_BUTTON_KBP_F3 = 43,
GHOST_NDOF_BUTTON_KBP_F4 = 44,
GHOST_NDOF_BUTTON_KBP_F5 = 45,
GHOST_NDOF_BUTTON_KBP_F6 = 46,
GHOST_NDOF_BUTTON_KBP_F7 = 47,
GHOST_NDOF_BUTTON_KBP_F8 = 48,
GHOST_NDOF_BUTTON_KBP_F9 = 49,
GHOST_NDOF_BUTTON_KBP_F10 = 50,
GHOST_NDOF_BUTTON_KBP_F11 = 51,
GHOST_NDOF_BUTTON_KBP_F12 = 52,
/* General-purpose buttons.
* Users can assign functions via keymap editor. */
GHOST_NDOF_BUTTON_11 = 77,
GHOST_NDOF_BUTTON_12 = 78,
/* Store views. */
GHOST_NDOF_BUTTON_V1 = 103,
GHOST_NDOF_BUTTON_V2 = 104,
GHOST_NDOF_BUTTON_V3 = 105,
GHOST_NDOF_BUTTON_SAVE_V1 = 139,
GHOST_NDOF_BUTTON_SAVE_V2 = 140,
GHOST_NDOF_BUTTON_SAVE_V3 = 141,
/* Keyboard keys. */
GHOST_NDOF_BUTTON_TAB = 175,
GHOST_NDOF_BUTTON_SPACE = 176,
/* Numpad Pro special buttons. */
GHOST_NDOF_BUTTON_NP_F1 = 229,
GHOST_NDOF_BUTTON_NP_F2 = 230,
GHOST_NDOF_BUTTON_NP_F3 = 231,
GHOST_NDOF_BUTTON_NP_F4 = 232,
GHOST_NDOF_BUTTON_USER = 0x10000
} GHOST_NDOF_ButtonT;
+285 -173
View File
@@ -6,15 +6,25 @@
#include "GHOST_Debug.hh"
#include "GHOST_EventKey.hh"
#include "GHOST_EventNDOF.hh"
#include "GHOST_Types.h"
#include "GHOST_WindowManager.hh"
#include "GHOST_utildefines.hh"
/* Logging, use `ghost.ndof.*` prefix. */
#include "CLG_log.h"
#include <algorithm>
#include <array>
#include <climits>
#include <cmath>
#include <cstring> /* For memory functions. */
#include <map>
/**
* 3Dconnexion keyboards and keypads use specific keys that have no standard equivalent.
* These could be supported as generic "custom" keys, see !124155 review for details.
*/
// #define USE_3DCONNEXION_NONSTANDARD_KEYS
/* -------------------------------------------------------------------- */
/** \name NDOF Enum Strings
@@ -30,55 +40,80 @@ static const char *ndof_progress_string[] = {
};
/* Printable values for #NDOF_ButtonT enum (keep aligned) */
static const char *ndof_button_names[] = {
/* Exclude `NDOF_BUTTON_NONE` (-1). */
"NDOF_BUTTON_MENU",
"NDOF_BUTTON_FIT",
"NDOF_BUTTON_TOP",
"NDOF_BUTTON_BOTTOM",
"NDOF_BUTTON_LEFT",
"NDOF_BUTTON_RIGHT",
"NDOF_BUTTON_FRONT",
"NDOF_BUTTON_BACK",
"NDOF_BUTTON_ISO1",
"NDOF_BUTTON_ISO2",
"NDOF_BUTTON_ROLL_CW",
"NDOF_BUTTON_ROLL_CCW",
"NDOF_BUTTON_SPIN_CW",
"NDOF_BUTTON_SPIN_CCW",
"NDOF_BUTTON_TILT_CW",
"NDOF_BUTTON_TILT_CCW",
"NDOF_BUTTON_ROTATE",
"NDOF_BUTTON_PANZOOM",
"NDOF_BUTTON_DOMINANT",
"NDOF_BUTTON_PLUS",
"NDOF_BUTTON_MINUS",
"NDOF_BUTTON_1",
"NDOF_BUTTON_2",
"NDOF_BUTTON_3",
"NDOF_BUTTON_4",
"NDOF_BUTTON_5",
"NDOF_BUTTON_6",
"NDOF_BUTTON_7",
"NDOF_BUTTON_8",
"NDOF_BUTTON_9",
"NDOF_BUTTON_10",
"NDOF_BUTTON_A",
"NDOF_BUTTON_B",
"NDOF_BUTTON_C",
"NDOF_BUTTON_V1",
"NDOF_BUTTON_V2",
"NDOF_BUTTON_V3",
/* Keyboard emulation. */
"NDOF_BUTTON_ESC",
"NDOF_BUTTON_ENTER",
"NDOF_BUTTON_DELETE",
"NDOF_BUTTON_TAB",
"NDOF_BUTTON_SPACE",
"NDOF_BUTTON_ALT",
"NDOF_BUTTON_SHIFT",
"NDOF_BUTTON_CTRL",
#define MAP_ENTRY(button) \
{ \
GHOST_##button, #button \
}
static const std::map<GHOST_NDOF_ButtonT, const char *> ndof_button_names = {
/* Disable wrapping, it makes it difficult to read. */
/* clang-format off */
MAP_ENTRY(NDOF_BUTTON_INVALID),
MAP_ENTRY(NDOF_BUTTON_MENU),
MAP_ENTRY(NDOF_BUTTON_FIT),
MAP_ENTRY(NDOF_BUTTON_TOP),
MAP_ENTRY(NDOF_BUTTON_LEFT),
MAP_ENTRY(NDOF_BUTTON_RIGHT),
MAP_ENTRY(NDOF_BUTTON_FRONT),
MAP_ENTRY(NDOF_BUTTON_BOTTOM),
MAP_ENTRY(NDOF_BUTTON_BACK),
MAP_ENTRY(NDOF_BUTTON_ROLL_CW),
MAP_ENTRY(NDOF_BUTTON_ROLL_CCW),
MAP_ENTRY(NDOF_BUTTON_SPIN_CW),
MAP_ENTRY(NDOF_BUTTON_SPIN_CCW),
MAP_ENTRY(NDOF_BUTTON_TILT_CW),
MAP_ENTRY(NDOF_BUTTON_TILT_CCW),
MAP_ENTRY(NDOF_BUTTON_ISO1),
MAP_ENTRY(NDOF_BUTTON_ISO2),
MAP_ENTRY(NDOF_BUTTON_1),
MAP_ENTRY(NDOF_BUTTON_2),
MAP_ENTRY(NDOF_BUTTON_3),
MAP_ENTRY(NDOF_BUTTON_4),
MAP_ENTRY(NDOF_BUTTON_5),
MAP_ENTRY(NDOF_BUTTON_6),
MAP_ENTRY(NDOF_BUTTON_7),
MAP_ENTRY(NDOF_BUTTON_8),
MAP_ENTRY(NDOF_BUTTON_9),
MAP_ENTRY(NDOF_BUTTON_10),
MAP_ENTRY(NDOF_BUTTON_11),
MAP_ENTRY(NDOF_BUTTON_12),
MAP_ENTRY(NDOF_BUTTON_ESC),
MAP_ENTRY(NDOF_BUTTON_ALT),
MAP_ENTRY(NDOF_BUTTON_SHIFT),
MAP_ENTRY(NDOF_BUTTON_CTRL),
MAP_ENTRY(NDOF_BUTTON_ENTER),
MAP_ENTRY(NDOF_BUTTON_DELETE),
MAP_ENTRY(NDOF_BUTTON_TAB),
MAP_ENTRY(NDOF_BUTTON_SPACE),
MAP_ENTRY(NDOF_BUTTON_ROTATE),
MAP_ENTRY(NDOF_BUTTON_PANZOOM),
MAP_ENTRY(NDOF_BUTTON_DOMINANT),
MAP_ENTRY(NDOF_BUTTON_PLUS),
MAP_ENTRY(NDOF_BUTTON_MINUS),
MAP_ENTRY(NDOF_BUTTON_V1),
MAP_ENTRY(NDOF_BUTTON_V2),
MAP_ENTRY(NDOF_BUTTON_V3),
MAP_ENTRY(NDOF_BUTTON_SAVE_V1),
MAP_ENTRY(NDOF_BUTTON_SAVE_V2),
MAP_ENTRY(NDOF_BUTTON_SAVE_V3),
MAP_ENTRY(NDOF_BUTTON_KBP_F1),
MAP_ENTRY(NDOF_BUTTON_KBP_F2),
MAP_ENTRY(NDOF_BUTTON_KBP_F3),
MAP_ENTRY(NDOF_BUTTON_KBP_F4),
MAP_ENTRY(NDOF_BUTTON_KBP_F5),
MAP_ENTRY(NDOF_BUTTON_KBP_F6),
MAP_ENTRY(NDOF_BUTTON_KBP_F7),
MAP_ENTRY(NDOF_BUTTON_KBP_F8),
MAP_ENTRY(NDOF_BUTTON_KBP_F9),
MAP_ENTRY(NDOF_BUTTON_KBP_F10),
MAP_ENTRY(NDOF_BUTTON_KBP_F11),
MAP_ENTRY(NDOF_BUTTON_KBP_F12),
MAP_ENTRY(NDOF_BUTTON_NP_F1),
MAP_ENTRY(NDOF_BUTTON_NP_F2),
MAP_ENTRY(NDOF_BUTTON_NP_F3),
MAP_ENTRY(NDOF_BUTTON_NP_F4),
/* clang-format on */
};
#undef MAP_ENTRY
static const char *ndof_device_names[] = {
"UnknownDevice",
@@ -92,6 +127,8 @@ static const char *ndof_device_names[] = {
"SpacePilot",
"Spaceball5000",
"SpaceTraveler",
"Keyboard Pro",
"Numpad Pro",
};
/** \} */
@@ -100,97 +137,69 @@ static const char *ndof_device_names[] = {
/** \name NDOF Button Maps
* \{ */
/* Shared by the latest 3Dconnexion hardware
/**
* Shared by the some 3Dconnexion hardware
* SpacePilotPro uses all of these
* smaller devices use only some, based on button mask. */
static const NDOF_ButtonT ndof_HID_map_Modern3Dx[] = {
NDOF_BUTTON_MENU, NDOF_BUTTON_FIT, NDOF_BUTTON_TOP, NDOF_BUTTON_LEFT,
NDOF_BUTTON_RIGHT, NDOF_BUTTON_FRONT, NDOF_BUTTON_BOTTOM, NDOF_BUTTON_BACK,
NDOF_BUTTON_ROLL_CW, NDOF_BUTTON_ROLL_CCW, NDOF_BUTTON_ISO1, NDOF_BUTTON_ISO2,
NDOF_BUTTON_1, NDOF_BUTTON_2, NDOF_BUTTON_3, NDOF_BUTTON_4,
NDOF_BUTTON_5, NDOF_BUTTON_6, NDOF_BUTTON_7, NDOF_BUTTON_8,
NDOF_BUTTON_9, NDOF_BUTTON_10, NDOF_BUTTON_ESC, NDOF_BUTTON_ALT,
NDOF_BUTTON_SHIFT, NDOF_BUTTON_CTRL, NDOF_BUTTON_ROTATE, NDOF_BUTTON_PANZOOM,
NDOF_BUTTON_DOMINANT, NDOF_BUTTON_PLUS, NDOF_BUTTON_MINUS};
* SpaceMouse Pro and SpaceNavigator use only some, based on button mask.
*/
static const GHOST_NDOF_ButtonT ndof_HID_map_Shared3Dx[] = {
GHOST_NDOF_BUTTON_MENU, GHOST_NDOF_BUTTON_FIT, GHOST_NDOF_BUTTON_TOP,
GHOST_NDOF_BUTTON_LEFT, GHOST_NDOF_BUTTON_RIGHT, GHOST_NDOF_BUTTON_FRONT,
GHOST_NDOF_BUTTON_BOTTOM, GHOST_NDOF_BUTTON_BACK, GHOST_NDOF_BUTTON_ROLL_CW,
GHOST_NDOF_BUTTON_ROLL_CCW, GHOST_NDOF_BUTTON_ISO1, GHOST_NDOF_BUTTON_ISO2,
GHOST_NDOF_BUTTON_1, GHOST_NDOF_BUTTON_2, GHOST_NDOF_BUTTON_3,
GHOST_NDOF_BUTTON_4, GHOST_NDOF_BUTTON_5, GHOST_NDOF_BUTTON_6,
GHOST_NDOF_BUTTON_7, GHOST_NDOF_BUTTON_8, GHOST_NDOF_BUTTON_9,
GHOST_NDOF_BUTTON_10, GHOST_NDOF_BUTTON_ESC, GHOST_NDOF_BUTTON_ALT,
GHOST_NDOF_BUTTON_SHIFT, GHOST_NDOF_BUTTON_CTRL, GHOST_NDOF_BUTTON_ROTATE,
GHOST_NDOF_BUTTON_PANZOOM, GHOST_NDOF_BUTTON_DOMINANT, GHOST_NDOF_BUTTON_PLUS,
GHOST_NDOF_BUTTON_MINUS,
};
static const NDOF_ButtonT ndof_HID_map_SpaceExplorer[] = {
NDOF_BUTTON_1,
NDOF_BUTTON_2,
NDOF_BUTTON_TOP,
NDOF_BUTTON_LEFT,
NDOF_BUTTON_RIGHT,
NDOF_BUTTON_FRONT,
NDOF_BUTTON_ESC,
NDOF_BUTTON_ALT,
NDOF_BUTTON_SHIFT,
NDOF_BUTTON_CTRL,
NDOF_BUTTON_FIT,
NDOF_BUTTON_MENU,
NDOF_BUTTON_PLUS,
NDOF_BUTTON_MINUS,
NDOF_BUTTON_ROTATE,
static const GHOST_NDOF_ButtonT ndof_HID_map_SpaceExplorer[] = {
GHOST_NDOF_BUTTON_1,
GHOST_NDOF_BUTTON_2,
GHOST_NDOF_BUTTON_TOP,
GHOST_NDOF_BUTTON_LEFT,
GHOST_NDOF_BUTTON_RIGHT,
GHOST_NDOF_BUTTON_FRONT,
GHOST_NDOF_BUTTON_ESC,
GHOST_NDOF_BUTTON_ALT,
GHOST_NDOF_BUTTON_SHIFT,
GHOST_NDOF_BUTTON_CTRL,
GHOST_NDOF_BUTTON_FIT,
GHOST_NDOF_BUTTON_MENU,
GHOST_NDOF_BUTTON_PLUS,
GHOST_NDOF_BUTTON_MINUS,
GHOST_NDOF_BUTTON_ROTATE,
};
/* This is the older SpacePilot (sans Pro). */
static const NDOF_ButtonT ndof_HID_map_SpacePilot[] = {
NDOF_BUTTON_1, NDOF_BUTTON_2, NDOF_BUTTON_3, NDOF_BUTTON_4,
NDOF_BUTTON_5, NDOF_BUTTON_6, NDOF_BUTTON_TOP, NDOF_BUTTON_LEFT,
NDOF_BUTTON_RIGHT, NDOF_BUTTON_FRONT, NDOF_BUTTON_ESC, NDOF_BUTTON_ALT,
NDOF_BUTTON_SHIFT, NDOF_BUTTON_CTRL, NDOF_BUTTON_FIT, NDOF_BUTTON_MENU,
NDOF_BUTTON_PLUS, NDOF_BUTTON_MINUS, NDOF_BUTTON_DOMINANT, NDOF_BUTTON_ROTATE,
NDOF_BUTTON_NONE /* the CONFIG button -- what does it do? */
static const GHOST_NDOF_ButtonT ndof_HID_map_SpacePilot[] = {
GHOST_NDOF_BUTTON_1, GHOST_NDOF_BUTTON_2,
GHOST_NDOF_BUTTON_3, GHOST_NDOF_BUTTON_4,
GHOST_NDOF_BUTTON_5, GHOST_NDOF_BUTTON_6,
GHOST_NDOF_BUTTON_TOP, GHOST_NDOF_BUTTON_LEFT,
GHOST_NDOF_BUTTON_RIGHT, GHOST_NDOF_BUTTON_FRONT,
GHOST_NDOF_BUTTON_ESC, GHOST_NDOF_BUTTON_ALT,
GHOST_NDOF_BUTTON_SHIFT, GHOST_NDOF_BUTTON_CTRL,
GHOST_NDOF_BUTTON_FIT, GHOST_NDOF_BUTTON_MENU,
GHOST_NDOF_BUTTON_PLUS, GHOST_NDOF_BUTTON_MINUS,
GHOST_NDOF_BUTTON_DOMINANT, GHOST_NDOF_BUTTON_ROTATE,
GHOST_NDOF_BUTTON_INVALID /* the CONFIG button -- what does it do? */
};
static const NDOF_ButtonT ndof_HID_map_Generic[] = {
NDOF_BUTTON_1,
NDOF_BUTTON_2,
NDOF_BUTTON_3,
NDOF_BUTTON_4,
NDOF_BUTTON_5,
NDOF_BUTTON_6,
NDOF_BUTTON_7,
NDOF_BUTTON_8,
NDOF_BUTTON_9,
NDOF_BUTTON_A,
NDOF_BUTTON_B,
NDOF_BUTTON_C,
static const GHOST_NDOF_ButtonT ndof_HID_map_Generic[] = {
GHOST_NDOF_BUTTON_1,
GHOST_NDOF_BUTTON_2,
GHOST_NDOF_BUTTON_3,
GHOST_NDOF_BUTTON_4,
GHOST_NDOF_BUTTON_5,
GHOST_NDOF_BUTTON_6,
GHOST_NDOF_BUTTON_7,
GHOST_NDOF_BUTTON_8,
GHOST_NDOF_BUTTON_9,
};
/* Values taken from: https://github.com/FreeSpacenav/spacenavd/wiki/Device-button-names */
static const NDOF_ButtonT ndof_HID_map_SpaceMouseEnterprise[] = {
NDOF_BUTTON_1, /* (0) */
NDOF_BUTTON_2, /* (1) */
NDOF_BUTTON_3, /* (2) */
NDOF_BUTTON_4, /* (3) */
NDOF_BUTTON_5, /* (4) */
NDOF_BUTTON_6, /* (5) */
NDOF_BUTTON_7, /* (6) */
NDOF_BUTTON_8, /* (7) */
NDOF_BUTTON_9, /* (8) */
NDOF_BUTTON_A, /* Labeled "10" (9). */
NDOF_BUTTON_B, /* Labeled "11" (10). */
NDOF_BUTTON_C, /* Labeled "12" (11). */
NDOF_BUTTON_MENU, /* (12). */
NDOF_BUTTON_FIT, /* (13). */
NDOF_BUTTON_TOP, /* (14). */
NDOF_BUTTON_RIGHT, /* (15). */
NDOF_BUTTON_FRONT, /* (16). */
NDOF_BUTTON_ROLL_CW, /* (17). */
NDOF_BUTTON_ESC, /* (18). */
NDOF_BUTTON_ALT, /* (19). */
NDOF_BUTTON_SHIFT, /* (20). */
NDOF_BUTTON_CTRL, /* (21). */
NDOF_BUTTON_ROTATE, /* Labeled "Lock Rotate" (22). */
NDOF_BUTTON_ENTER, /* Labeled "Enter" (23). */
NDOF_BUTTON_DELETE, /* (24). */
NDOF_BUTTON_TAB, /* (25). */
NDOF_BUTTON_SPACE, /* (26). */
NDOF_BUTTON_V1, /* Labeled "V1" (27). */
NDOF_BUTTON_V2, /* Labeled "V2" (28). */
NDOF_BUTTON_V3, /* Labeled "V3" (29). */
NDOF_BUTTON_ISO1, /* Labeled "ISO1" (30). */
};
/** \} */
/* -------------------------------------------------------------------- */
@@ -206,6 +215,8 @@ GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System &sys)
hid_map_button_mask_(0),
hid_map_(ndof_HID_map_Generic),
button_depressed_(0),
pressed_buttons_cache_(),
pressed_long_buttons_cache_(),
motion_time_(0),
motion_time_prev_(0),
motion_state_(GHOST_kNotStarted),
@@ -255,7 +266,7 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id)
{
device_type_ = NDOF_SpaceNavigator;
hid_map_button_num_ = 2;
hid_map_ = ndof_HID_map_Modern3Dx;
hid_map_ = ndof_HID_map_Shared3Dx;
break;
}
case 0xC627: {
@@ -267,14 +278,14 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id)
case 0xC629: {
device_type_ = NDOF_SpacePilotPro;
hid_map_button_num_ = 31;
hid_map_ = ndof_HID_map_Modern3Dx;
hid_map_ = ndof_HID_map_Shared3Dx;
break;
}
case 0xC62B: {
device_type_ = NDOF_SpaceMousePro;
hid_map_button_num_ = 27; /* 15 physical buttons, but HID codes range from 0 to 26. */
hid_map_button_mask_ = 0x07C0F137;
hid_map_ = ndof_HID_map_Modern3Dx;
hid_map_ = ndof_HID_map_Shared3Dx;
break;
}
@@ -308,7 +319,7 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id)
{
device_type_ = NDOF_SpaceMouseWireless;
hid_map_button_num_ = 2;
hid_map_ = ndof_HID_map_Modern3Dx;
hid_map_ = ndof_HID_map_Shared3Dx;
break;
}
case 0xC631: /* SpaceMouse Pro Wireless (cabled). */
@@ -320,13 +331,21 @@ bool GHOST_NDOFManager::setDevice(ushort vendor_id, ushort product_id)
device_type_ = NDOF_SpaceMouseProWireless;
hid_map_button_num_ = 27; /* 15 physical buttons, but HID codes range from 0 to 26. */
hid_map_button_mask_ = 0x07C0F137;
hid_map_ = ndof_HID_map_Modern3Dx;
hid_map_ = ndof_HID_map_Shared3Dx;
break;
}
case 0xC633: {
case 0xC633: /* Newer devices don't need to use button mappings. */
{
device_type_ = NDOF_SpaceMouseEnterprise;
hid_map_button_num_ = 31;
hid_map_ = ndof_HID_map_SpaceMouseEnterprise;
break;
}
case 0xC664:
case 0xC668: {
device_type_ = NDOF_KeyboardPro;
break;
}
case 0xC665: {
device_type_ = NDOF_NumpadPro;
break;
}
default: {
@@ -382,46 +401,90 @@ void GHOST_NDOFManager::updateRotation(const int r[3], uint64_t time)
static CLG_LogRef LOG_NDOF_BUTTONS = {"ghost.ndof.buttons"};
#define LOG (&LOG_NDOF_BUTTONS)
static GHOST_TKey ghost_map_keyboard_from_ndof_buttom(const NDOF_ButtonT button)
static GHOST_TKey ghost_map_keyboard_from_ndof_buttom(const GHOST_NDOF_ButtonT button)
{
switch (button) {
case NDOF_BUTTON_ESC: {
case GHOST_NDOF_BUTTON_ESC: {
return GHOST_kKeyEsc;
}
case NDOF_BUTTON_ENTER: {
case GHOST_NDOF_BUTTON_ENTER: {
return GHOST_kKeyEnter;
}
case NDOF_BUTTON_DELETE: {
case GHOST_NDOF_BUTTON_DELETE: {
return GHOST_kKeyDelete;
}
case NDOF_BUTTON_TAB: {
case GHOST_NDOF_BUTTON_TAB: {
return GHOST_kKeyTab;
}
case NDOF_BUTTON_SPACE: {
case GHOST_NDOF_BUTTON_SPACE: {
return GHOST_kKeySpace;
}
case NDOF_BUTTON_ALT: {
case GHOST_NDOF_BUTTON_ALT: {
return GHOST_kKeyLeftAlt;
}
case NDOF_BUTTON_SHIFT: {
case GHOST_NDOF_BUTTON_SHIFT: {
return GHOST_kKeyLeftShift;
}
case NDOF_BUTTON_CTRL: {
case GHOST_NDOF_BUTTON_CTRL: {
return GHOST_kKeyLeftControl;
}
#ifdef USE_3DCONNEXION_NONSTANDARD_KEYS
case GHOST_NDOF_BUTTON_NP_F1:
case GHOST_NDOF_BUTTON_KBP_F1: {
return GHOST_kKeyF1;
}
case GHOST_NDOF_BUTTON_NP_F2:
case GHOST_NDOF_BUTTON_KBP_F2: {
return GHOST_kKeyF2;
}
case GHOST_NDOF_BUTTON_NP_F3:
case GHOST_NDOF_BUTTON_KBP_F3: {
return GHOST_kKeyF3;
}
case GHOST_NDOF_BUTTON_NP_F4:
case GHOST_NDOF_BUTTON_KBP_F4: {
return GHOST_kKeyF4;
}
case GHOST_NDOF_BUTTON_KBP_F5: {
return GHOST_kKeyF5;
}
case GHOST_NDOF_BUTTON_KBP_F6: {
return GHOST_kKeyF6;
}
case GHOST_NDOF_BUTTON_KBP_F7: {
return GHOST_kKeyF7;
}
case GHOST_NDOF_BUTTON_KBP_F8: {
return GHOST_kKeyF8;
}
case GHOST_NDOF_BUTTON_KBP_F9: {
return GHOST_kKeyF9;
}
case GHOST_NDOF_BUTTON_KBP_F10: {
return GHOST_kKeyF10;
}
case GHOST_NDOF_BUTTON_KBP_F11: {
return GHOST_kKeyF11;
}
case GHOST_NDOF_BUTTON_KBP_F12: {
return GHOST_kKeyF12;
}
#endif /* !USE_3DCONNEXION_NONSTANDARD_KEYS */
default: {
return GHOST_kKeyUnknown;
}
}
}
void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button,
void GHOST_NDOFManager::sendButtonEvent(GHOST_NDOF_ButtonT button,
bool press,
uint64_t time,
GHOST_IWindow *window)
{
GHOST_ASSERT(button > NDOF_BUTTON_NONE && button < NDOF_BUTTON_NUM,
"rogue button trying to escape NDOF manager");
GHOST_ASSERT(button > GHOST_NDOF_BUTTON_NONE && button < GHOST_NDOF_BUTTON_USER,
"rogue button trying to escape GHOST_NDOF manager");
const GHOST_EventNDOFButton *event = new GHOST_EventNDOFButton(time, window);
GHOST_TEventNDOFButtonData *data = (GHOST_TEventNDOFButtonData *)event->getData();
@@ -445,17 +508,16 @@ void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key,
void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t time)
{
if (button_number >= hid_map_button_num_) {
CLOG_INFO(LOG,
2,
"button=%d, press=%d (out of range %d, ignoring!)",
button_number,
int(press),
hid_map_button_num_);
return;
GHOST_NDOF_ButtonT button = static_cast<GHOST_NDOF_ButtonT>(button_number);
/* For bistmask devices button maping isn't unified, therefore check the button map. */
if (std::find(bitmask_devices_.begin(), bitmask_devices_.end(), device_type_) !=
bitmask_devices_.end())
{
button = hid_map_[button_number];
}
const NDOF_ButtonT button = hid_map_[button_number];
if (button == NDOF_BUTTON_NONE) {
if (button == GHOST_NDOF_BUTTON_INVALID) {
CLOG_INFO(
LOG, 2, "button=%d, press=%d (mapped to none, ignoring!)", button_number, int(press));
return;
@@ -466,12 +528,19 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t tim
"button=%d, press=%d, name=%s",
button_number,
int(press),
ndof_button_names[button]);
ndof_button_names.at(button));
#ifndef USE_3DCONNEXION_NONSTANDARD_KEYS
if (((button >= GHOST_NDOF_BUTTON_KBP_F1) && (button <= GHOST_NDOF_BUTTON_KBP_F12)) &&
((button >= GHOST_NDOF_BUTTON_NP_F1) && (button <= GHOST_NDOF_BUTTON_NP_F4)))
{
return;
}
#endif /* !USE_3DCONNEXION_NONSTANDARD_KEYS */
GHOST_IWindow *window = system_.getWindowManager()->getActiveWindow();
/* Delivery will fail, so don't bother sending.
* Do, however update the buttons internal depressed state. */
/* Delivery will fail, so don't bother sending. */
if (window != nullptr) {
const GHOST_TKey key = ghost_map_keyboard_from_ndof_buttom(button);
if (key != GHOST_kKeyUnknown) {
@@ -481,18 +550,18 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, uint64_t tim
sendButtonEvent(button, press, time, window);
}
}
int mask = 1 << button_number;
if (press) {
button_depressed_ |= mask; /* Set this button's bit. */
}
else {
button_depressed_ &= ~mask; /* Clear this button's bit. */
}
}
void GHOST_NDOFManager::updateButtons(int button_bits, uint64_t time)
void GHOST_NDOFManager::updateButtonsBitmask(int button_bits, uint64_t time)
{
/* Some devices send two data packets: bitmask and number array.
* In this case, packet has to be ignored if it came from such a device. */
if (std::find(bitmask_devices_.begin(), bitmask_devices_.end(), device_type_) ==
bitmask_devices_.end())
{
return;
}
button_bits &= hid_map_button_mask_; /* Discard any "garbage" bits. */
int diff = button_depressed_ ^ button_bits;
@@ -502,11 +571,54 @@ void GHOST_NDOFManager::updateButtons(int button_bits, uint64_t time)
if (diff & mask) {
bool press = button_bits & mask;
if (press) {
button_depressed_ |= mask; /* Set this button's bit. */
}
else {
button_depressed_ &= ~mask; /* Clear this button's bit. */
}
updateButton(button_number, press, time);
}
}
}
void GHOST_NDOFManager::updateButtonsArray(NDOF_Button_Array buttons,
uint64_t time,
NDOF_Button_Type type)
{
NDOF_Button_Array &cache = (type == NDOF_Button_Type::LongButton) ? pressed_long_buttons_cache_ :
pressed_buttons_cache_;
/* Find released buttons */
for (const auto &cached_button : cache) {
bool found = false;
for (const auto &button : buttons) {
if (button == cached_button) {
found = true;
break;
}
}
if (!found)
updateButton(cached_button, false, time);
}
/* Find pressed buttons */
for (const auto &button : buttons) {
bool found = false;
for (const auto &cached_button : cache) {
if (button == cached_button) {
found = true;
break;
}
}
if (!found)
updateButton(button, true, time);
}
cache = buttons;
}
#undef LOG
/** \} */
+25 -72
View File
@@ -10,6 +10,8 @@
#include "GHOST_System.hh"
#include <array>
typedef enum {
NDOF_UnknownDevice = 0,
@@ -21,6 +23,8 @@ typedef enum {
NDOF_SpaceMouseWireless,
NDOF_SpaceMouseProWireless,
NDOF_SpaceMouseEnterprise,
NDOF_KeyboardPro,
NDOF_NumpadPro,
/* Older devices. */
NDOF_SpacePilot,
@@ -29,76 +33,9 @@ typedef enum {
} NDOF_DeviceT;
/**
* NDOF device button event types.
*
* \note Button values are stored in DNA as part of key-map items.
* Existing values should not be changed. Otherwise, a mapping must be used,
* see #NDOF_BUTTON_INDEX_AS_EVENT.
*/
typedef enum {
/* Used internally, never sent or used as an index. */
NDOF_BUTTON_NONE = -1,
/* These two are available from any 3Dconnexion device. */
NDOF_BUTTON_MENU,
NDOF_BUTTON_FIT,
/* Standard views. */
NDOF_BUTTON_TOP,
NDOF_BUTTON_BOTTOM,
NDOF_BUTTON_LEFT,
NDOF_BUTTON_RIGHT,
NDOF_BUTTON_FRONT,
NDOF_BUTTON_BACK,
/* More views. */
NDOF_BUTTON_ISO1,
NDOF_BUTTON_ISO2,
/* 90 degree rotations.
* These don't all correspond to physical buttons. */
NDOF_BUTTON_ROLL_CW,
NDOF_BUTTON_ROLL_CCW,
NDOF_BUTTON_SPIN_CW,
NDOF_BUTTON_SPIN_CCW,
NDOF_BUTTON_TILT_CW,
NDOF_BUTTON_TILT_CCW,
/* Device control. */
NDOF_BUTTON_ROTATE,
NDOF_BUTTON_PANZOOM,
NDOF_BUTTON_DOMINANT,
NDOF_BUTTON_PLUS,
NDOF_BUTTON_MINUS,
/* Store Views. */
NDOF_BUTTON_V1,
NDOF_BUTTON_V2,
NDOF_BUTTON_V3,
_NDOF_UNUSED_0,
/* General-purpose buttons.
* Users can assign functions via keymap editor. */
NDOF_BUTTON_1,
NDOF_BUTTON_2,
NDOF_BUTTON_3,
NDOF_BUTTON_4,
NDOF_BUTTON_5,
NDOF_BUTTON_6,
NDOF_BUTTON_7,
NDOF_BUTTON_8,
NDOF_BUTTON_9,
NDOF_BUTTON_10,
/* More general-purpose buttons. */
NDOF_BUTTON_A,
NDOF_BUTTON_B,
NDOF_BUTTON_C,
typedef std::array<GHOST_NDOF_ButtonT, 6> NDOF_Button_Array;
/* Keyboard emulation (keep last as they are mapped to regular keyboard events). */
NDOF_BUTTON_ESC,
NDOF_BUTTON_ENTER,
NDOF_BUTTON_DELETE,
NDOF_BUTTON_TAB,
NDOF_BUTTON_SPACE,
NDOF_BUTTON_ALT,
NDOF_BUTTON_SHIFT,
NDOF_BUTTON_CTRL,
#define NDOF_BUTTON_NUM (NDOF_BUTTON_CTRL + 1)
} NDOF_ButtonT;
typedef enum { ShortButton, LongButton } NDOF_Button_Type;
class GHOST_NDOFManager {
public:
@@ -145,7 +82,8 @@ class GHOST_NDOFManager {
* use HID button encoding (not #NDOF_ButtonT).
*/
void updateButton(int button_number, bool press, uint64_t time);
void updateButtons(int button_bits, uint64_t time);
void updateButtonsBitmask(int button_bits, uint64_t time);
void updateButtonsArray(NDOF_Button_Array buttons, uint64_t time, NDOF_Button_Type type);
/* #NDOFButton events are sent immediately */
/**
@@ -158,17 +96,20 @@ class GHOST_NDOFManager {
GHOST_System &system_;
private:
void sendButtonEvent(NDOF_ButtonT, bool press, uint64_t time, GHOST_IWindow *);
void sendButtonEvent(GHOST_NDOF_ButtonT, bool press, uint64_t time, GHOST_IWindow *);
void sendKeyEvent(GHOST_TKey, bool press, uint64_t time, GHOST_IWindow *);
NDOF_DeviceT device_type_;
int hid_map_button_num_;
int hid_map_button_mask_;
const NDOF_ButtonT *hid_map_;
const GHOST_NDOF_ButtonT *hid_map_;
int translation_[3];
int rotation_[3];
int button_depressed_; /* Bit field. */
NDOF_Button_Array pressed_buttons_cache_;
NDOF_Button_Array pressed_long_buttons_cache_;
uint64_t motion_time_; /* In milliseconds. */
uint64_t motion_time_prev_; /* Time of most recent motion event sent. */
@@ -176,4 +117,16 @@ class GHOST_NDOFManager {
GHOST_TProgress motion_state_;
bool motion_event_pending_;
float motion_dead_zone_; /* Discard motion with each component < this. */
inline static std::array<NDOF_DeviceT, 9> bitmask_devices_ = {
NDOF_SpaceNavigator,
NDOF_SpaceExplorer,
NDOF_SpacePilotPro,
NDOF_SpaceMousePro,
NDOF_SpaceMouseWireless,
NDOF_SpaceMouseProWireless,
NDOF_SpacePilot,
NDOF_Spaceball5000,
NDOF_SpaceTraveler,
};
};
@@ -202,7 +202,7 @@ static void DeviceEvent(uint32_t /*unused*/, uint32_t msg_type, void *msg_arg)
#ifdef DEBUG_NDOF_BUTTONS
printf("button bits: 0x%08x\n", button_bits);
#endif
ndof_manager->updateButtons(button_bits, now);
ndof_manager->updateButtonsBitmask(button_bits, now);
ghost_system->notifyExternalEventProcessed();
break;
}
+60 -17
View File
@@ -7,6 +7,7 @@
*/
#include <limits>
#include <map>
#include "GHOST_EventDragnDrop.hh"
#include "GHOST_EventTrackpad.hh"
@@ -102,6 +103,33 @@
static bool isStartedFromCommandPrompt();
/**
* SpaceMouse devices ship with an internal identifier number for each long press event.
* These values can be found in `<3DxWare installation path>/3DxWinCore/Cfg/Base.xml`.
* For input processing purposes these identifiers have to be mapped to particular button events.
*/
static const std::map<uint16_t, GHOST_NDOF_ButtonT> longButtonHIDsToGHOST_NDOFButtons = {
{3, GHOST_NDOF_BUTTON_BOTTOM},
{5, GHOST_NDOF_BUTTON_LEFT},
{6, GHOST_NDOF_BUTTON_BACK},
{9, GHOST_NDOF_BUTTON_ROLL_CCW},
{11, GHOST_NDOF_BUTTON_ISO2},
{32, GHOST_NDOF_BUTTON_SPIN_CCW},
{34, GHOST_NDOF_BUTTON_TILT_CCW},
{103, GHOST_NDOF_BUTTON_SAVE_V1},
{104, GHOST_NDOF_BUTTON_SAVE_V2},
{105, GHOST_NDOF_BUTTON_SAVE_V3},
};
static GHOST_NDOF_ButtonT translateLongButtonToNDOFButton(uint16_t longKey)
{
const auto iter = longButtonHIDsToGHOST_NDOFButtons.find(longKey);
if (iter == longButtonHIDsToGHOST_NDOFButtons.end()) {
return static_cast<GHOST_NDOF_ButtonT>(longKey);
}
return iter->second;
}
static void initRawInput()
{
#ifdef WITH_INPUT_NDOF
@@ -1403,20 +1431,17 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const &raw)
bool eventSent = false;
uint64_t 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;
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) {
m_ndofManager->setDevice(info.hid.dwVendorId, info.hid.dwProductId);
}
else {
GHOST_PRINT("<!> not a HID device... mouse/kb perhaps?\n");
}
firstEvent = false;
GetRawInputDeviceInfo(raw.header.hDevice, RIDI_DEVICEINFO, &info, &infoSize);
/* Since there can be multiple NDOF devices connected, always set the current device. */
if (info.dwType == RIM_TYPEHID) {
m_ndofManager->setDevice(info.hid.dwVendorId, info.hid.dwProductId);
}
else {
GHOST_PRINT("<!> not a HID device... mouse/kb perhaps?\n");
}
/* The NDOF manager sends button changes immediately, and *pretends* to
@@ -1427,7 +1452,7 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const &raw)
BYTE packetType = data[0];
switch (packetType) {
case 1: { /* Translation. */
case 0x1: { /* Translation. */
const short *axis = (short *)(data + 1);
/* Massage into blender view coords (same goes for rotation). */
const int t[3] = {axis[0], -axis[2], axis[1]};
@@ -1443,17 +1468,35 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const &raw)
}
break;
}
case 2: { /* Rotation. */
case 0x2: { /* Rotation. */
const short *axis = (short *)(data + 1);
const int r[3] = {-axis[0], axis[2], -axis[1]};
m_ndofManager->updateRotation(r, now);
break;
}
case 3: { /* Buttons. */
case 0x3: { /* Buttons bitmask (older devices). */
int button_bits;
memcpy(&button_bits, data + 1, sizeof(button_bits));
m_ndofManager->updateButtons(button_bits, now);
m_ndofManager->updateButtonsBitmask(button_bits, now);
break;
}
case 0x1c: { /* Buttons numbers (newer devices). */
NDOF_Button_Array buttons;
const uint16_t *payload = reinterpret_cast<const uint16_t *>(data + 1);
for (int i = 0; i < buttons.size(); i++) {
buttons[i] = static_cast<GHOST_NDOF_ButtonT>(*(payload + i));
}
m_ndofManager->updateButtonsArray(buttons, now, NDOF_Button_Type::ShortButton);
break;
}
case 0x1d: { /* Buttons (long press, newer devices). */
NDOF_Button_Array buttons;
const uint16_t *payload = reinterpret_cast<const uint16_t *>(data + 1);
for (int i = 0; i < buttons.size(); i++) {
buttons[i] = translateLongButtonToNDOFButton(*(payload + i));
}
m_ndofManager->updateButtonsArray(buttons, now, NDOF_Button_Type::LongButton);
break;
}
}
+5 -3
View File
@@ -1007,6 +1007,9 @@ DEF_ICON_COLOR(EVENT_F24)
DEF_ICON_COLOR(EVENT_NDOF_BUTTON_V1)
DEF_ICON_COLOR(EVENT_NDOF_BUTTON_V2)
DEF_ICON_COLOR(EVENT_NDOF_BUTTON_V3)
DEF_ICON_COLOR(EVENT_NDOF_BUTTON_SAVE_V1)
DEF_ICON_COLOR(EVENT_NDOF_BUTTON_SAVE_V2)
DEF_ICON_COLOR(EVENT_NDOF_BUTTON_SAVE_V3)
DEF_ICON_COLOR(EVENT_NDOF_BUTTON_1)
DEF_ICON_COLOR(EVENT_NDOF_BUTTON_2)
DEF_ICON_COLOR(EVENT_NDOF_BUTTON_3)
@@ -1017,9 +1020,8 @@ DEF_ICON_COLOR(EVENT_NDOF_BUTTON_7)
DEF_ICON_COLOR(EVENT_NDOF_BUTTON_8)
DEF_ICON_COLOR(EVENT_NDOF_BUTTON_9)
DEF_ICON_COLOR(EVENT_NDOF_BUTTON_10)
DEF_ICON_COLOR(EVENT_NDOF_BUTTON_A)
DEF_ICON_COLOR(EVENT_NDOF_BUTTON_B)
DEF_ICON_COLOR(EVENT_NDOF_BUTTON_C)
DEF_ICON_COLOR(EVENT_NDOF_BUTTON_11)
DEF_ICON_COLOR(EVENT_NDOF_BUTTON_12)
DEF_ICON_COLOR(EVENT_NDOF_BUTTON_MENU)
DEF_ICON_COLOR(EVENT_NDOF_BUTTON_FIT)
DEF_ICON_COLOR(EVENT_NDOF_BUTTON_TOP)
@@ -740,6 +740,9 @@ static void init_event_icons()
INIT_EVENT_ICON(ICON_EVENT_NDOF_BUTTON_V1, NDOF_BUTTON_V1, KM_ANY);
INIT_EVENT_ICON(ICON_EVENT_NDOF_BUTTON_V2, NDOF_BUTTON_V2, KM_ANY);
INIT_EVENT_ICON(ICON_EVENT_NDOF_BUTTON_V3, NDOF_BUTTON_V3, KM_ANY);
INIT_EVENT_ICON(ICON_EVENT_NDOF_BUTTON_SAVE_V1, NDOF_BUTTON_SAVE_V1, KM_ANY);
INIT_EVENT_ICON(ICON_EVENT_NDOF_BUTTON_SAVE_V2, NDOF_BUTTON_SAVE_V2, KM_ANY);
INIT_EVENT_ICON(ICON_EVENT_NDOF_BUTTON_SAVE_V3, NDOF_BUTTON_SAVE_V3, KM_ANY);
INIT_EVENT_ICON(ICON_EVENT_NDOF_BUTTON_1, NDOF_BUTTON_1, KM_ANY);
INIT_EVENT_ICON(ICON_EVENT_NDOF_BUTTON_2, NDOF_BUTTON_2, KM_ANY);
INIT_EVENT_ICON(ICON_EVENT_NDOF_BUTTON_3, NDOF_BUTTON_3, KM_ANY);
@@ -750,9 +753,8 @@ static void init_event_icons()
INIT_EVENT_ICON(ICON_EVENT_NDOF_BUTTON_8, NDOF_BUTTON_8, KM_ANY);
INIT_EVENT_ICON(ICON_EVENT_NDOF_BUTTON_9, NDOF_BUTTON_9, KM_ANY);
INIT_EVENT_ICON(ICON_EVENT_NDOF_BUTTON_10, NDOF_BUTTON_10, KM_ANY);
INIT_EVENT_ICON(ICON_EVENT_NDOF_BUTTON_A, NDOF_BUTTON_A, KM_ANY);
INIT_EVENT_ICON(ICON_EVENT_NDOF_BUTTON_B, NDOF_BUTTON_B, KM_ANY);
INIT_EVENT_ICON(ICON_EVENT_NDOF_BUTTON_C, NDOF_BUTTON_C, KM_ANY);
INIT_EVENT_ICON(ICON_EVENT_NDOF_BUTTON_11, NDOF_BUTTON_11, KM_ANY);
INIT_EVENT_ICON(ICON_EVENT_NDOF_BUTTON_12, NDOF_BUTTON_12, KM_ANY);
INIT_EVENT_ICON(ICON_EVENT_NDOF_BUTTON_MENU, NDOF_BUTTON_MENU, KM_ANY);
INIT_EVENT_ICON(ICON_EVENT_NDOF_BUTTON_FIT, NDOF_BUTTON_FIT, KM_ANY);
INIT_EVENT_ICON(ICON_EVENT_NDOF_BUTTON_TOP, NDOF_BUTTON_TOP, KM_ANY);
@@ -320,24 +320,27 @@ void icon_draw_rect_input(float x,
else if (event_type == EVT_RIGHTBRACKETKEY) {
icon_draw_rect_input_text(&rect, color, "]", 12.0f, 1.5f);
}
else if ((event_type >= NDOF_BUTTON_MENU) && (event_type <= NDOF_BUTTON_C)) {
else if (ISNDOF_BUTTON(event_type)) {
if ((event_type >= NDOF_BUTTON_V1) && (event_type <= NDOF_BUTTON_V3)) {
char str[7];
SNPRINTF(str, "%sv%i", BLI_STR_UTF8_CIRCLED_WHITE_BULLET, 1 + event_type - NDOF_BUTTON_V1);
SNPRINTF(str, "%sv%i", BLI_STR_UTF8_CIRCLED_WHITE_BULLET, (event_type + 1) - NDOF_BUTTON_V1);
icon_draw_rect_input_text(&rect, color, str, 7.5f, 0.0f);
}
if ((event_type >= NDOF_BUTTON_SAVE_V1) && (event_type <= NDOF_BUTTON_SAVE_V3)) {
char str[7];
SNPRINTF(
str, "%ss%i", BLI_STR_UTF8_CIRCLED_WHITE_BULLET, (event_type + 1) - NDOF_BUTTON_SAVE_V1);
icon_draw_rect_input_text(&rect, color, str, 7.5f, 0.0f);
}
else if ((event_type >= NDOF_BUTTON_1) && (event_type <= NDOF_BUTTON_9)) {
char str[6];
SNPRINTF(str, "%s%i", BLI_STR_UTF8_CIRCLED_WHITE_BULLET, 1 + event_type - NDOF_BUTTON_1);
SNPRINTF(str, "%s%i", BLI_STR_UTF8_CIRCLED_WHITE_BULLET, (1 + event_type) - NDOF_BUTTON_1);
icon_draw_rect_input_text(&rect, color, str, 9.0f, 0.0f);
}
else if (event_type == NDOF_BUTTON_10) {
icon_draw_rect_input_text(&rect, color, BLI_STR_UTF8_CIRCLED_WHITE_BULLET "10", 7.5f, 0.0f);
}
else if ((event_type >= NDOF_BUTTON_A) && (event_type <= NDOF_BUTTON_C)) {
char str[6];
SNPRINTF(str, "%s%c", BLI_STR_UTF8_CIRCLED_WHITE_BULLET, 'A' + event_type - NDOF_BUTTON_A);
icon_draw_rect_input_text(&rect, color, str, 9.0f, 0.0f);
else if (event_type >= NDOF_BUTTON_10 && event_type <= NDOF_BUTTON_12) {
char str[7];
SNPRINTF(str, "%s1%i", BLI_STR_UTF8_CIRCLED_WHITE_BULLET, event_type - NDOF_BUTTON_10);
icon_draw_rect_input_text(&rect, color, str, 7.5f, 0.0f);
}
else if (event_type == NDOF_BUTTON_MENU) {
icon_draw_rect_input_text(&rect, color, BLI_STR_UTF8_CIRCLED_WHITE_BULLET "Me", 6.5f, 0.0f);
+11 -9
View File
@@ -168,9 +168,8 @@ static const EnumPropertyItem event_ndof_type_items[] = {
{NDOF_BUTTON_8, "NDOF_BUTTON_8", 0, CTX_N_(BLT_I18NCONTEXT_UI_EVENTS, "Button 8"), ""},
{NDOF_BUTTON_9, "NDOF_BUTTON_9", 0, CTX_N_(BLT_I18NCONTEXT_UI_EVENTS, "Button 9"), ""},
{NDOF_BUTTON_10, "NDOF_BUTTON_10", 0, CTX_N_(BLT_I18NCONTEXT_UI_EVENTS, "Button 10"), ""},
{NDOF_BUTTON_A, "NDOF_BUTTON_A", 0, CTX_N_(BLT_I18NCONTEXT_UI_EVENTS, "Button A"), ""},
{NDOF_BUTTON_B, "NDOF_BUTTON_B", 0, CTX_N_(BLT_I18NCONTEXT_UI_EVENTS, "Button B"), ""},
{NDOF_BUTTON_C, "NDOF_BUTTON_C", 0, CTX_N_(BLT_I18NCONTEXT_UI_EVENTS, "Button C"), ""},
{NDOF_BUTTON_11, "NDOF_BUTTON_11", 0, CTX_N_(BLT_I18NCONTEXT_UI_EVENTS, "Button 11"), ""},
{NDOF_BUTTON_12, "NDOF_BUTTON_12", 0, CTX_N_(BLT_I18NCONTEXT_UI_EVENTS, "Button 12"), ""},
# if 0 /* Never used (converted to keyboard events by GHOST). */
/* keyboard emulation */
{NDOF_BUTTON_ESC, "NDOF_BUTTON_ESC", 0, CTX_N_(BLT_I18NCONTEXT_UI_EVENTS, "Esc")},
@@ -422,9 +421,12 @@ const EnumPropertyItem rna_enum_event_type_items[] = {
{NDOF_BUTTON_CTRL, "NDOF_BUTTON_CTRL", 0, "NDOF Ctrl", "NdofCtrl"},
#endif
/* View buttons. */
{NDOF_BUTTON_V1, "NDOF_BUTTON_V1", 0, "NDOF View 1", ""},
{NDOF_BUTTON_V2, "NDOF_BUTTON_V2", 0, "NDOF View 2", ""},
{NDOF_BUTTON_V3, "NDOF_BUTTON_V3", 0, "NDOF View 3", ""},
{NDOF_BUTTON_V1, "NDOF_BUTTON_V1", 0, "NDOF View 1", "NdofView1"},
{NDOF_BUTTON_V2, "NDOF_BUTTON_V2", 0, "NDOF View 2", "NdofView2"},
{NDOF_BUTTON_V3, "NDOF_BUTTON_V3", 0, "NDOF View 3", "NdofView3"},
{NDOF_BUTTON_SAVE_V1, "NDOF_BUTTON_SAVE_V1", 0, "NDOF Save View 1", "NdofSaveView1"},
{NDOF_BUTTON_SAVE_V2, "NDOF_BUTTON_SAVE_V2", 0, "NDOF Save View 2", "NdofSaveView2"},
{NDOF_BUTTON_SAVE_V3, "NDOF_BUTTON_SAVE_V3", 0, "NDOF Save View 3", "NdofSaveView3"},
/* general-purpose buttons */
{NDOF_BUTTON_1, "NDOF_BUTTON_1", 0, "NDOF Button 1", "NdofB1"},
{NDOF_BUTTON_2, "NDOF_BUTTON_2", 0, "NDOF Button 2", "NdofB2"},
@@ -436,9 +438,9 @@ const EnumPropertyItem rna_enum_event_type_items[] = {
{NDOF_BUTTON_8, "NDOF_BUTTON_8", 0, "NDOF Button 8", "NdofB8"},
{NDOF_BUTTON_9, "NDOF_BUTTON_9", 0, "NDOF Button 9", "NdofB9"},
{NDOF_BUTTON_10, "NDOF_BUTTON_10", 0, "NDOF Button 10", "NdofB10"},
{NDOF_BUTTON_A, "NDOF_BUTTON_A", 0, "NDOF Button A", "NdofBA"},
{NDOF_BUTTON_B, "NDOF_BUTTON_B", 0, "NDOF Button B", "NdofBB"},
{NDOF_BUTTON_C, "NDOF_BUTTON_C", 0, "NDOF Button C", "NdofBC"},
{NDOF_BUTTON_11, "NDOF_BUTTON_11", 0, "NDOF Button 11", "NdofB11"},
{NDOF_BUTTON_12, "NDOF_BUTTON_12", 0, "NDOF Button 12", "NdofB12"},
/* Action Zones. */
{EVT_ACTIONZONE_AREA, "ACTIONZONE_AREA", 0, "ActionZone Area", "AZone Area"},
{EVT_ACTIONZONE_REGION, "ACTIONZONE_REGION", 0, "ActionZone Region", "AZone Region"},
@@ -4987,6 +4987,103 @@ void WM_event_add_mousemove(wmWindow *win)
/** \name Ghost Event Conversion
* \{ */
/**
* \return The WM enum for NDOF button or #EVENT_NONE (which should be ignored)
*/
static int wm_event_type_from_ndof_button(GHOST_NDOF_ButtonT button)
{
#define CASE_NDOF_BUTTON(button) \
case GHOST_NDOF_BUTTON_##button: \
return NDOF_BUTTON_##button
#define CASE_NDOF_BUTTON_IGNORE(button) \
case GHOST_NDOF_BUTTON_##button: \
break;
switch (button) {
CASE_NDOF_BUTTON(MENU);
CASE_NDOF_BUTTON(FIT);
CASE_NDOF_BUTTON(TOP);
CASE_NDOF_BUTTON(LEFT);
CASE_NDOF_BUTTON(RIGHT);
CASE_NDOF_BUTTON(FRONT);
CASE_NDOF_BUTTON(BOTTOM);
CASE_NDOF_BUTTON(BACK);
CASE_NDOF_BUTTON(ROLL_CW);
CASE_NDOF_BUTTON(ROLL_CCW);
CASE_NDOF_BUTTON(ISO1);
CASE_NDOF_BUTTON(ISO2);
CASE_NDOF_BUTTON(1);
CASE_NDOF_BUTTON(2);
CASE_NDOF_BUTTON(3);
CASE_NDOF_BUTTON(4);
CASE_NDOF_BUTTON(5);
CASE_NDOF_BUTTON(6);
CASE_NDOF_BUTTON(7);
CASE_NDOF_BUTTON(8);
CASE_NDOF_BUTTON(9);
CASE_NDOF_BUTTON(10);
CASE_NDOF_BUTTON(11);
CASE_NDOF_BUTTON(12);
CASE_NDOF_BUTTON(ROTATE);
CASE_NDOF_BUTTON(PANZOOM);
CASE_NDOF_BUTTON(DOMINANT);
CASE_NDOF_BUTTON(PLUS);
CASE_NDOF_BUTTON(MINUS);
CASE_NDOF_BUTTON(SPIN_CW);
CASE_NDOF_BUTTON(SPIN_CCW);
CASE_NDOF_BUTTON(TILT_CW);
CASE_NDOF_BUTTON(TILT_CCW);
CASE_NDOF_BUTTON(V1);
CASE_NDOF_BUTTON(V2);
CASE_NDOF_BUTTON(V3);
CASE_NDOF_BUTTON(SAVE_V1);
CASE_NDOF_BUTTON(SAVE_V2);
CASE_NDOF_BUTTON(SAVE_V3);
/* Disabled as GHOST converts these to keyboard events
* which use regular keyboard event handling logic. */
/* Keyboard emulation. */
CASE_NDOF_BUTTON_IGNORE(ESC);
CASE_NDOF_BUTTON_IGNORE(ENTER);
CASE_NDOF_BUTTON_IGNORE(DELETE);
CASE_NDOF_BUTTON_IGNORE(TAB);
CASE_NDOF_BUTTON_IGNORE(SPACE);
CASE_NDOF_BUTTON_IGNORE(ALT);
CASE_NDOF_BUTTON_IGNORE(SHIFT);
CASE_NDOF_BUTTON_IGNORE(CTRL);
CASE_NDOF_BUTTON_IGNORE(KBP_F1);
CASE_NDOF_BUTTON_IGNORE(KBP_F2);
CASE_NDOF_BUTTON_IGNORE(KBP_F3);
CASE_NDOF_BUTTON_IGNORE(KBP_F4);
CASE_NDOF_BUTTON_IGNORE(KBP_F5);
CASE_NDOF_BUTTON_IGNORE(KBP_F6);
CASE_NDOF_BUTTON_IGNORE(KBP_F7);
CASE_NDOF_BUTTON_IGNORE(KBP_F8);
CASE_NDOF_BUTTON_IGNORE(KBP_F9);
CASE_NDOF_BUTTON_IGNORE(KBP_F10);
CASE_NDOF_BUTTON_IGNORE(KBP_F11);
CASE_NDOF_BUTTON_IGNORE(KBP_F12);
CASE_NDOF_BUTTON_IGNORE(NP_F1);
CASE_NDOF_BUTTON_IGNORE(NP_F2);
CASE_NDOF_BUTTON_IGNORE(NP_F3);
CASE_NDOF_BUTTON_IGNORE(NP_F4);
/* Quiet switch warnings. */
CASE_NDOF_BUTTON_IGNORE(NONE);
CASE_NDOF_BUTTON_IGNORE(INVALID);
CASE_NDOF_BUTTON_IGNORE(USER);
}
#undef CASE_NDOF_BUTTON
#undef CASE_NDOF_BUTTON_IGNORE
CLOG_WARN(WM_LOG_EVENTS, "unknown event type %d from ndof button", int(button));
return EVENT_NONE;
}
/**
* \return The WM enum for key or #EVENT_NONE (which should be ignored).
*/
@@ -6008,8 +6105,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm,
case GHOST_kEventNDOFButton: {
const GHOST_TEventNDOFButtonData *e = static_cast<const GHOST_TEventNDOFButtonData *>(
customdata);
event.type = NDOF_BUTTON_INDEX_AS_EVENT(e->button);
event.type = wm_event_type_from_ndof_button(static_cast<GHOST_NDOF_ButtonT>(e->button));
switch (e->action) {
case GHOST_kPress:
+10 -8
View File
@@ -281,7 +281,7 @@ enum {
NDOF_BUTTON_DOMINANT = 0x01a3, /* 419 */
NDOF_BUTTON_PLUS = 0x01a4, /* 420 */
NDOF_BUTTON_MINUS = 0x01a5, /* 421 */
/* Store/restore views. */
/* Restore views. */
NDOF_BUTTON_V1 = 0x01a6, /* 422 */
NDOF_BUTTON_V2 = 0x01a7, /* 423 */
NDOF_BUTTON_V3 = 0x01a8, /* 424 */
@@ -297,9 +297,8 @@ enum {
NDOF_BUTTON_9 = 0x01b2, /* 434 */
NDOF_BUTTON_10 = 0x01b3, /* 435 */
/* More general-purpose buttons. */
NDOF_BUTTON_A = 0x01b4, /* 436 */
NDOF_BUTTON_B = 0x01b5, /* 437 */
NDOF_BUTTON_C = 0x01b6, /* 438 */
NDOF_BUTTON_11 = 0x01b4, /* 436 */
NDOF_BUTTON_12 = 0x01b5, /* 437 */
/* Disabled as GHOST converts these to keyboard events
* which use regular keyboard event handling logic. */
@@ -315,8 +314,13 @@ enum {
NDOF_BUTTON_CTRL = 0x01bd, /* 445 */
#endif
#define _NDOF_MAX NDOF_BUTTON_C
#define _NDOF_BUTTON_MAX NDOF_BUTTON_C
/* Store views. */
NDOF_BUTTON_SAVE_V1 = 0x01be, /* 446 */
NDOF_BUTTON_SAVE_V2 = 0x01bf, /* 447 */
NDOF_BUTTON_SAVE_V3 = 0x01c0, /* 448 */
#define _NDOF_MAX NDOF_BUTTON_SAVE_V3
#define _NDOF_BUTTON_MAX NDOF_BUTTON_SAVE_V3
/* ********** End of Input devices. ********** */
@@ -457,8 +461,6 @@ enum eEventType_Mask {
(EVT_TYPE_MASK_KEYBOARD | EVT_TYPE_MASK_MOUSE | EVT_TYPE_MASK_NDOF)
#define EVT_TYPE_MASK_HOTKEY_EXCLUDE EVT_TYPE_MASK_KEYBOARD_MODIFIER
#define NDOF_BUTTON_INDEX_AS_EVENT(i) (_NDOF_BUTTON_MIN + (i))
bool WM_event_type_mask_test(int event_type, enum eEventType_Mask mask);
/** \} */