0029564: STEP Import and Export failure
[occt.git] / src / WNT / WNT_HIDSpaceMouse.cxx
1 // Copyright (c) 2019-2020 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <WNT_HIDSpaceMouse.hxx>
15
16 namespace
17 {
18   //! Enumeration of known Space Mouse models.
19   enum SpacePid
20   {
21     // VENDOR_ID_LOGITECH
22     SpacePid_SpaceMouse             = 0xC603,
23     SpacePid_CADMan                 = 0xC605,
24     SpacePid_SpaceMouseClassic      = 0xC606,
25     SpacePid_SpaceBall5000          = 0xC621,
26     SpacePid_SpaceTraveler          = 0xC623,
27     SpacePid_SpacePilot             = 0xC625,
28     SpacePid_SpaceNavigator         = 0xC626, //!< has only 2 "menu" buttons (second one is treated as SpaceVKey_Fit)
29     SpacePid_SpaceExplorer          = 0xC627, //!< 15 buttons
30     SpacePid_NavigatorForNotebooks  = 0xC628, //!< has only 2 "menu" buttons (second one is treated as SpaceVKey_Fit)
31     SpacePid_SpacePilotPro          = 0xC629, //!< 31 buttons
32     SpacePid_SpaceMousePro          = 0xC62B, //!< has only 15 buttons, but codes range from 0 to 26
33     // VENDOR_ID_3DCONNEXION
34     SpacePid_SpaceMouseWireless1    = 0xC62E, //!< [plugged in] has only  2 buttons
35     SpacePid_SpaceMouseWireless2    = 0xC62F, //!< [wireless]   has only  2 buttons
36     SpacePid_SpaceMouseProWireless1 = 0xC631, //!< [plugged in] has only 15 buttons
37     SpacePid_SpaceMouseProWireless2 = 0xC632, //!< [wireless]   has only 15 buttons
38     SpacePid_SpaceMouseEnterprise   = 0xC633, //!< 31 buttons
39     SpacePid_SpaceMouseCompact      = 0xC635
40   };
41
42   //! Enumeration of known keys available on various Space Mouse models.
43   enum SpaceVKey
44   {
45     SpaceVKey_INVALID = 0,
46     SpaceVKey_Menu = 1, SpaceVKey_Fit,
47     SpaceVKey_Top, SpaceVKey_Left, SpaceVKey_Right, SpaceVKey_Front, SpaceVKey_Bottom, SpaceVKey_Back,
48     SpaceVKey_RollCW, SpaceVKey_RollCCW,
49     SpaceVKey_ISO1, SpaceVKey_ISO2,
50     SpaceVKey_1, SpaceVKey_2, SpaceVKey_3, SpaceVKey_4, SpaceVKey_5, SpaceVKey_6, SpaceVKey_7, SpaceVKey_8, SpaceVKey_9, SpaceVKey_10,
51     SpaceVKey_Esc, SpaceVKey_Alt, SpaceVKey_Shift, SpaceVKey_Ctrl,
52     SpaceVKey_Rotate, SpaceVKey_PanZoom, SpaceVKey_Dominant,
53     SpaceVKey_Plus, SpaceVKey_Minus,
54   };
55
56   //! The raw value range on tested device is [-350; 350].
57   enum { THE_RAW_RANGE_350 = 350 };
58
59   //! Convert key state bit into virtual key.
60   static SpaceVKey hidToSpaceKey (unsigned long theProductId,
61                                   unsigned short theKeyBit)
62   {
63     static const SpaceVKey THE_PILOT_KEYS[] =
64     {
65       SpaceVKey_1, SpaceVKey_2, SpaceVKey_3, SpaceVKey_4, SpaceVKey_5, SpaceVKey_6,
66       SpaceVKey_Top, SpaceVKey_Left, SpaceVKey_Right, SpaceVKey_Front,
67       SpaceVKey_Esc, SpaceVKey_Alt, SpaceVKey_Shift, SpaceVKey_Ctrl,
68       SpaceVKey_Fit, SpaceVKey_Menu,
69       SpaceVKey_Plus, SpaceVKey_Minus,
70       SpaceVKey_Dominant, SpaceVKey_Rotate
71     };
72     const int THE_NB_PILOT_KEYS = sizeof(THE_PILOT_KEYS) / sizeof(SpaceVKey);
73
74     static const SpaceVKey THE_EXPLORER_KEYS[] =
75     {
76       SpaceVKey_1, SpaceVKey_2,
77       SpaceVKey_Top, SpaceVKey_Left, SpaceVKey_Right, SpaceVKey_Front,
78       SpaceVKey_Esc, SpaceVKey_Alt,  SpaceVKey_Shift, SpaceVKey_Ctrl,
79       SpaceVKey_Fit, SpaceVKey_Menu,
80       SpaceVKey_Plus, SpaceVKey_Minus,
81       SpaceVKey_Rotate
82     };
83     const int THE_NB_EXPLORER_KEYS = sizeof(THE_EXPLORER_KEYS) / sizeof(SpaceVKey);
84
85     // shared by latest 3Dconnexion hardware
86     static const SpaceVKey THE_SPACEMOUSEPRO_KEYS[] =
87     {
88       SpaceVKey_Menu, SpaceVKey_Fit,
89       SpaceVKey_Top, SpaceVKey_Left, SpaceVKey_Right, SpaceVKey_Front, SpaceVKey_Bottom, SpaceVKey_Back,
90       SpaceVKey_RollCW, SpaceVKey_RollCCW, SpaceVKey_ISO1, SpaceVKey_ISO2,
91       SpaceVKey_1, SpaceVKey_2, SpaceVKey_3, SpaceVKey_4,
92       SpaceVKey_5, SpaceVKey_6, SpaceVKey_7, SpaceVKey_8, SpaceVKey_9, SpaceVKey_10,
93       SpaceVKey_Esc, SpaceVKey_Alt, SpaceVKey_Shift, SpaceVKey_Ctrl,
94       SpaceVKey_Rotate,
95       SpaceVKey_PanZoom, SpaceVKey_Dominant, SpaceVKey_Plus, SpaceVKey_Minus
96     };
97     const int THE_NB_SPACEMOUSEPRO_KEYS = sizeof(THE_SPACEMOUSEPRO_KEYS) / sizeof(SpaceVKey);
98
99     switch (theProductId)
100     {
101       case SpacePid_SpacePilot:
102         return theKeyBit < THE_NB_PILOT_KEYS ? THE_PILOT_KEYS[theKeyBit] : SpaceVKey_INVALID;
103       case SpacePid_SpaceExplorer:
104         return theKeyBit < THE_NB_EXPLORER_KEYS ? THE_EXPLORER_KEYS[theKeyBit] : SpaceVKey_INVALID;
105       case SpacePid_SpaceNavigator:
106       case SpacePid_NavigatorForNotebooks:
107       case SpacePid_SpacePilotPro:
108       case SpacePid_SpaceMousePro:
109       case SpacePid_SpaceMouseWireless1:
110       case SpacePid_SpaceMouseWireless2:
111       case SpacePid_SpaceMouseProWireless1:
112       case SpacePid_SpaceMouseProWireless2:
113       case SpacePid_SpaceMouseEnterprise:
114       case SpacePid_SpaceMouseCompact:
115         return theKeyBit < THE_NB_SPACEMOUSEPRO_KEYS ? THE_SPACEMOUSEPRO_KEYS[theKeyBit] : SpaceVKey_INVALID;
116     }
117     return SpaceVKey_INVALID;
118   }
119
120 }
121
122 // =======================================================================
123 // function : WNT_HIDSpaceMouse
124 // purpose  :
125 // =======================================================================
126 WNT_HIDSpaceMouse::WNT_HIDSpaceMouse (unsigned long theProductId,
127                                       const Standard_Byte* theData,
128                                       Standard_Size theSize)
129 : myData (theData),
130   mySize (theSize),
131   myProductId (theProductId),
132   myValueRange (THE_RAW_RANGE_350)
133 {
134   //
135 }
136
137 // =======================================================================
138 // function : IsKnownProduct
139 // purpose  :
140 // =======================================================================
141 bool WNT_HIDSpaceMouse::IsKnownProduct (unsigned long theProductId)
142 {
143   switch (theProductId)
144   {
145     case SpacePid_SpacePilot:
146     case SpacePid_SpaceExplorer:
147     case SpacePid_SpaceNavigator:
148     case SpacePid_NavigatorForNotebooks:
149     case SpacePid_SpacePilotPro:
150     case SpacePid_SpaceMousePro:
151     case SpacePid_SpaceMouseWireless1:
152     case SpacePid_SpaceMouseWireless2:
153     case SpacePid_SpaceMouseProWireless1:
154     case SpacePid_SpaceMouseProWireless2:
155     case SpacePid_SpaceMouseEnterprise:
156     case SpacePid_SpaceMouseCompact:
157       return true;
158   }
159   return false;
160 }
161
162 // =======================================================================
163 // function : Translation
164 // purpose  :
165 // =======================================================================
166 Graphic3d_Vec3d WNT_HIDSpaceMouse::Translation (bool& theIsIdle,
167                                                 bool theIsQuadric) const
168 {
169   theIsIdle = true;
170   return myData[0] == SpaceRawInput_Translation
171       && (mySize == 7 || mySize == 13)
172        ? fromRawVec3 (theIsIdle, myData + 1, true, theIsQuadric)
173        : Graphic3d_Vec3d();
174 }
175
176 // =======================================================================
177 // function : Rotation
178 // purpose  :
179 // =======================================================================
180 Graphic3d_Vec3d WNT_HIDSpaceMouse::Rotation (bool& theIsIdle,
181                                              bool theIsQuadric) const
182 {
183   theIsIdle = true;
184   if (myData[0] == SpaceRawInput_Rotation && mySize == 7)
185   {
186     return fromRawVec3 (theIsIdle, myData + 1, false, theIsQuadric);
187   }
188   else if (myData[0] == SpaceRawInput_Translation && mySize == 13)
189   {
190     return fromRawVec3 (theIsIdle, myData + 7, false, theIsQuadric);
191   }
192   return Graphic3d_Vec3d();
193 }
194
195 // =======================================================================
196 // function : fromRawVec3
197 // purpose  :
198 // =======================================================================
199 Graphic3d_Vec3d WNT_HIDSpaceMouse::fromRawVec3 (bool& theIsIdle,
200                                                 const Standard_Byte* theData,
201                                                 bool theIsTrans,
202                                                 bool theIsQuadric) const
203 {
204   theIsIdle = true;
205   const NCollection_Vec3<int16_t>& aRaw16 = *reinterpret_cast<const NCollection_Vec3<int16_t>*>(theData);
206   Graphic3d_Vec3d aVec (aRaw16.x(), aRaw16.y(), aRaw16.z());
207   if (theIsTrans)
208   {
209     static const int16_t THE_MIN_RAW_TRANS   = 4;
210     static const int16_t THE_MIN_RAW_TRANS_Z = 8;
211     for (int aCompIter = 0; aCompIter < 3; ++aCompIter)
212     {
213       if (aRaw16[aCompIter] > -THE_MIN_RAW_TRANS && aRaw16[aCompIter] < THE_MIN_RAW_TRANS)
214       {
215         aVec[aCompIter] = 0.0;
216       }
217       else
218       {
219         theIsIdle = false;
220       }
221     }
222     if (aRaw16.z() > -THE_MIN_RAW_TRANS_Z && aRaw16.z() < THE_MIN_RAW_TRANS_Z)
223     {
224       aVec.z() = 0.0;
225     }
226   }
227   else
228   {
229     for (int aCompIter = 0; aCompIter < 3; ++aCompIter)
230     {
231       if (aRaw16[aCompIter] != 0)
232       {
233         theIsIdle = false;
234         break;
235       }
236     }
237   }
238
239   // determine raw value range
240   for (int aCompIter = 0; aCompIter < 3; ++aCompIter)
241   {
242     if (aRaw16[aCompIter] > myValueRange
243     || -aRaw16[aCompIter] > myValueRange)
244     {
245       myValueRange = 32767; // SHRT_MAX
246       break;
247     }
248   }
249
250   if (!theIsQuadric)
251   {
252     return aVec / double(myValueRange);
253   }
254
255   for (int aCompIter = 0; aCompIter < 3; ++aCompIter)
256   {
257     aVec[aCompIter] =  aRaw16[aCompIter] > 0
258                     ?  aVec[aCompIter] * aVec[aCompIter]
259                     : -aVec[aCompIter] * aVec[aCompIter];
260   }
261   return aVec / (double(myValueRange) * double(myValueRange));
262 }
263
264 // =======================================================================
265 // function : HidToSpaceKey
266 // purpose  :
267 // =======================================================================
268 Aspect_VKey WNT_HIDSpaceMouse::HidToSpaceKey (unsigned short theKeyBit) const
269 {
270   const SpaceVKey aKey = hidToSpaceKey (myProductId, theKeyBit);
271   switch (aKey)
272   {
273     case SpaceVKey_1:
274     case SpaceVKey_2:
275     case SpaceVKey_3:
276     case SpaceVKey_4:
277     case SpaceVKey_5:
278     case SpaceVKey_6:
279     case SpaceVKey_7:
280     case SpaceVKey_8:
281     case SpaceVKey_9:
282     case SpaceVKey_10:
283       return (int(aKey) - int(SpaceVKey_1)) + Aspect_VKey_1;
284     case SpaceVKey_Esc:
285       return Aspect_VKey_Escape;
286     case SpaceVKey_Shift:
287       return Aspect_VKey_Shift;
288     case SpaceVKey_Alt:
289       return Aspect_VKey_Alt;
290     case SpaceVKey_Ctrl:
291       return Aspect_VKey_Control;
292     case SpaceVKey_Top:
293       return Aspect_VKey_ViewTop;
294     case SpaceVKey_Bottom:
295       return Aspect_VKey_ViewBottom;
296     case SpaceVKey_Left:
297       return Aspect_VKey_ViewLeft;
298     case SpaceVKey_Right:
299       return Aspect_VKey_ViewRight;
300     case SpaceVKey_Front:
301       return Aspect_VKey_ViewFront;
302     case SpaceVKey_Back:
303       return Aspect_VKey_ViewBack;
304     case SpaceVKey_ISO1:
305       return Aspect_VKey_ViewAxoLeftProj;
306     case SpaceVKey_ISO2:
307       return Aspect_VKey_ViewAxoRightProj;
308     case SpaceVKey_Fit:
309       return Aspect_VKey_ViewFitAll;
310     case SpaceVKey_RollCW:
311       return Aspect_VKey_ViewRoll90CW;
312     case SpaceVKey_RollCCW:
313       return Aspect_VKey_ViewRoll90CCW;
314     case SpaceVKey_Rotate:
315       return Aspect_VKey_ViewSwitchRotate;
316     default:
317       break;
318   }
319   return Aspect_VKey_UNKNOWN;
320 }