1 /* 2 * InputDevice.h 3 * 4 * Copyright (C) 2001 J. "MUFTI" Scheurich 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program (see the file "COPYING" for details); if 18 * not, write to the Free Software Foundation, Inc., 675 Mass Ave, 19 * Cambridge, MA 02139, USA. 20 */ 21 22 #pragma once 23 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include "stdafx.h" 27 #include "MyString.h" 28 #include "StringArray.h" 29 #include "swt.h" 30 #include "TransformMode.h" 31 #include "EulerAngles.h" 32 #include "Quaternion.h" 33 #include "Map.h" 34 35 class InputDeviceApp; 36 37 // class to access several joystick like devices via a unified interface 38 39 // Example for such devices are spaceballs, magellan-devices, 40 // thumbsticks of gamepads and of course joysticks 8-) 41 42 // This can also be used for Xinput devices, that not deliver zero, 43 // if you take your hand away from the device like dialbox, mouse or 44 // graphics tablett. 45 46 class InputDevice 47 { 48 public: 49 // true if there is a new event from the joystick 50 virtual bool readInputDevice(void) = 0; 51 isValid(void)52 virtual bool isValid(void) { return valid; } 53 54 Quaternion& get_quaternion(TransformMode* tm, bool local, bool check_only); 55 56 virtual Quaternion& get_quaternion(TransformMode* tm=NULL, 57 bool check_only=false); 58 virtual Quaternion& get_localQuaternion(TransformMode* tm=NULL, 59 bool check_only=false); 60 EulerAngles& get_eulerAngles(TransformMode* tm,bool check_only,bool current); 61 62 Vec3f& get_vector(TransformMode* tm); 63 get_number_axes(void)64 int get_number_axes(void) { return number_max_axis - number_ignored_axes; } get_number_max_axis(void)65 int get_number_max_axis(void) { return number_max_axis; } 66 get_number_buttons(void)67 int get_number_buttons(void) { return number_buttons; } 68 69 virtual const char *getDeviceOption(void) const = 0; getDeviceName(void)70 const char *getDeviceName(void) { return device_name; } 71 isWand(void)72 bool isWand(void) { return wandflag; } isHead(void)73 bool isHead(void) { return headflag; } sendalways(void)74 virtual bool sendalways(void) { return alwaysflag; } 75 76 virtual bool allzero(void); 77 isTracker(void)78 virtual bool isTracker(void) { return false; } 79 hasReadDelay(void)80 virtual bool hasReadDelay(void) { return false; } 81 prepareRead(void)82 virtual void prepareRead(void) { return; } 83 84 virtual float maxvalue(int) const=0; 85 useCurrent(void)86 virtual bool useCurrent(void) { return false; } 87 setHeadNavigation(void)88 virtual void setHeadNavigation(void) { } getHeadNavigation(void)89 virtual bool getHeadNavigation(void) { return true; } 90 getxyzfactor(void)91 float getxyzfactor(void) { return xyzfactor; } getrotfactor(void)92 float getrotfactor(void) { return rotfactor; } 93 setxyzfactor(float f)94 void setxyzfactor(float f) { xyzfactor = f; } setrotfactor(float f)95 void setrotfactor(float f) { rotfactor = f; } 96 97 void set_firstflag(void); 98 99 virtual void guessInputDeviceNames(StringArray *names) const = 0; 100 101 static InputDevice *createInputDevice(const char* device_option, 102 const char* device_name); 103 InputDevice(const char * device)104 InputDevice(const char *device) 105 { 106 initialize(); 107 valid=true; 108 if (device==NULL) 109 device_name=NULL; 110 else 111 device_name=strdup(device); 112 } 113 initialize(void)114 void initialize(void) 115 { 116 valid=false; 117 // initialise joystick class default data 118 button_pressed=-1; 119 button_released=-1; 120 number_buttons=0; 121 number_max_axis=0; 122 number_max_axes=7; 123 number_ignored_axes=0; 124 for (int i=0;i<number_max_axes;i++) 125 value[i]=0; 126 headflag=false; 127 wandflag=false; 128 alwaysflag=false; 129 zero_on_release=NULL; 130 sign_swap=NULL; 131 factor=NULL; 132 acceleration=NULL; 133 zero_size_fraction=NULL; 134 num_axis_x=0; 135 num_axis_y=1; 136 num_axis_z=2; 137 num_axis_xrot=3; 138 num_axis_yrot=4; 139 num_axis_zrot=5; 140 num_axis_angle=6; 141 static const char* axesinfodata[6]= { 142 "xrot", 143 "yrot", 144 "zrot", 145 "x", 146 "y", 147 "z" 148 }; 149 for (int i=0;i<6;i++) 150 axesinfo[i]=(char *)axesinfodata[i]; 151 for (int i=0;i<7;i++) 152 firstflag[i]=true; 153 for (int i=0;i<7;i++) 154 oldvalue[i]=0; 155 for (int i=0;i<7;i++) 156 ignore[i]=false; 157 zero_on_release=new bool[number_max_axes]; 158 for (int i=0;i<number_max_axes;i++) 159 zero_on_release[i]=true; 160 alwaysflag=false; 161 xyzfactor=1; 162 rotfactor=1; 163 device_name=NULL; 164 error_message=""; 165 } ~InputDevice()166 virtual ~InputDevice() 167 { 168 if (zero_on_release!=NULL) 169 delete zero_on_release; 170 if (acceleration!=NULL) 171 delete acceleration; 172 } 173 void setAxisInformation(const char* info_string); 174 void setNumberAxes(const char* number); setSendAlways(bool flag)175 void setSendAlways(bool flag) {alwaysflag=flag;} 176 get_ignore(int axis)177 bool get_ignore(int axis) { return ignore[axis]; } 178 int get_sign(int axis_number); 179 int getAxisFromInformation(const char* axesinfo); 180 float get_factor(int axis_number); 181 float get_acceleration(int axis_number); 182 bool get_zero_on_release(int axis_number); 183 float get_zero_size_fraction(int axis_number); 184 getAxesInfo(int i)185 char *getAxesInfo(int i) { return axesinfo[i >= 3 ? i - 3 : i + 3]; } 186 getErrorMessage(void)187 const char *getErrorMessage(void) { return error_message; } 188 getNumAxis(int i)189 int getNumAxis(int i) { 190 switch(i) { 191 case 0: 192 return num_axis_x; 193 case 1: 194 return num_axis_y; 195 case 2: 196 return num_axis_z; 197 case 3: 198 return num_axis_xrot; 199 case 4: 200 return num_axis_yrot; 201 case 5: 202 return num_axis_zrot; 203 } 204 return -1; 205 } 206 207 protected: 208 bool valid; 209 210 float get_x(TransformMode* tm=NULL,bool check_only=false,bool curr=false); 211 float get_y(TransformMode* tm=NULL,bool check_only=false,bool curr=false); 212 float get_z(TransformMode* tm=NULL,bool check_only=false,bool curr=false); 213 float get_xrot(TransformMode* tm=NULL,bool check_only=false,bool curr=false); 214 float get_yrot(TransformMode* tm=NULL,bool check_only=false,bool curr=false); 215 float get_zrot(TransformMode* tm=NULL,bool check_only=false,bool curr=false); 216 float get_angle(TransformMode* tm=NULL,bool check_only=false,bool curr=false); 217 218 // is device a headtracker ? 219 bool headflag; 220 // is device a wand ? 221 bool wandflag; 222 // do device send (amost) always values ? 223 bool alwaysflag; 224 225 // axes of device 226 int number_max_axis; 227 // number of axes used in account (7 (including angle axis)) 228 int number_max_axes; 229 // number of ignored axes of device 230 int number_ignored_axes; 231 232 // 0-2 offset and 3-7 rotation values from joystick (if available) 233 float value[7]; 234 235 // buttons of joystick 236 int number_buttons; 237 bool *button; 238 // last pressed/released button 239 int button_pressed; 240 int button_released; 241 242 // number of axis for values 243 int num_axis_x; 244 int num_axis_y; 245 int num_axis_z; 246 int num_axis_xrot; 247 int num_axis_yrot; 248 int num_axis_zrot; 249 int num_axis_angle; 250 251 // true if axis number deliver zero when device released 252 void set_zero_on_release(int axis_number,bool value); 253 void set_zero_on_release(const char* axis_string,bool value); 254 255 // formula to accelerate values from axis 256 float accelerate(float value,int num_axis); 257 258 // signswap of value from axis 259 void set_sign_swap(int axis_number,bool value); 260 261 // factor: multiplcated to value from axis 262 void set_factor(int axis_number,float value); 263 void set_factor(const char* axis_string,float value); 264 265 // acceleration: additional acceleration parameter 266 void set_acceleration(int axis_number,float value); 267 void set_acceleration(const char* axis_string,float value); 268 269 // percent (relative to max) of value which will be ignored 270 // "insensitivity of device" 271 void set_zero_size_fraction(int axis_number,float value); 272 void set_zero_size_fraction(const char* string,float value); 273 274 MyString error_message; 275 276 protected: 277 278 // function to read/set configuration data like 279 // axisnumbers, zero_on_release, acceleration 280 void setAxisOfInformation(const char* axesinfo,int axis_number); 281 282 bool max_value(int index,TransformMode* tm); 283 float get_value(int index,bool check_only,int num_axis); 284 float get_value(TransformMode* tm, 285 int index, bool check_only, int num_axis, bool current); 286 287 float get_current_value(int index,int num_axis); 288 289 // array of flags for first get from device 290 bool firstflag[7]; 291 292 // flags if the value of a axis should be ignored 293 bool ignore[7]; 294 295 // array of old values from device 296 float oldvalue[7]; 297 298 // array of flags if axis number arrayindex deliver zero when device is 299 // released 300 bool* zero_on_release; 301 302 // array of nullsize in percent 303 float* zero_size_fraction; 304 305 // array of flags, if sign of result is swapped 306 bool* sign_swap; 307 308 // array of factor to multiply with value of axis 309 float* factor; 310 311 // array of acceleration per axis 312 float* acceleration; 313 314 // helper functions for setAxisInformation 315 bool scan_argument(char *string,const char* argument); 316 bool argument_is_axis(const char* string); 317 char* axesinfo[6]; 318 319 float xyzfactor; 320 float rotfactor; 321 322 Quaternion old_quat; 323 Quaternion old_local_quat; 324 325 const char *device_name; 326 }; 327 328 # ifdef LINUX_JOYSTICK 329 330 // using Linux Joystick interface 331 332 # define NAME_LENGTH 128 333 # include <linux/joystick.h> 334 335 class linux_joystick : public InputDevice 336 { 337 public: 338 linux_joystick(const char* device); 339 ~linux_joystick(); 340 bool readInputDevice(void); getDeviceOption(void)341 const char *getDeviceOption(void) const { return "-joystick"; } 342 void guessInputDeviceNames(StringArray *names) const; 343 private: 344 int fd; 345 int version; 346 char name[NAME_LENGTH]; 347 struct js_event js; maxvalue(int i)348 float maxvalue(int i) const {return(32767.0);} 349 float linux_js_factor; 350 }; 351 352 # endif 353 354 # ifdef DIRECTX_JOYSTICK 355 356 // using M$Windows Joystick interface from DirectInput API 357 358 # include <Windows.h> 359 #include <commctrl.h> 360 #include <basetsd.h> 361 #include <dinput.h> 362 363 class windows_joystick : public InputDevice 364 { 365 public: 366 windows_joystick(const char* device); windows_joystick()367 windows_joystick() : InputDevice() {} 368 ~windows_joystick(); 369 bool readInputDevice(void); getDeviceOption(void)370 const char *getDeviceOption(void) const { return "-joystick"; } 371 void guessInputDeviceNames(StringArray *names) const; 372 private: 373 int number_of_joystick; 374 int version; 375 char name[MAXPNAMELEN]; 376 DIJOYSTATE2 js; 377 DIPROPRANGE diprg; 378 int *max_value; 379 int *null_value; maxvalue(int i)380 float maxvalue(int i) const {return max_value[i];} 381 float factor; 382 383 HRESULT InitDirectInput(); 384 LPDIRECTINPUT8 g_pDI; 385 LPDIRECTINPUTDEVICE8 g_pJoystick; 386 }; 387 388 # endif 389 390 # ifdef WINDOWS_JOYSTICK 391 392 // using older M$Windows Joystick API interface ("JOYCAPS" etc.) 393 394 # include <Windows.h> 395 396 class windows_joystick : public InputDevice 397 { 398 public: 399 windows_joystick(const char* device); 400 ~windows_joystick(); 401 bool readInputDevice(void); getDeviceOption(void)402 const char *getDeviceOption(void) const { return "-joystick"; } 403 void guessInputDeviceNames(StringArray *names) const; 404 private: 405 int number_of_joystick; 406 int version; 407 char name[MAXPNAMELEN]; 408 JOYCAPS joycapabilities; 409 JOYINFOEX joyinfo_ex; 410 int *maximum; 411 int *null_value; maxvalue(int i)412 float maxvalue(int i) const {return maximum[i];} 413 float windows_js_factor; 414 }; 415 416 # endif 417 418 # ifdef HAVE_SDL_JOYSTICK 419 420 // using modified Simple DirectMedia Layer joystick interface 421 # include "SDLjoystick/SDL_joystick.h" 422 423 class SDL_joystick : public InputDevice 424 { 425 public: 426 SDL_joystick(const char* device); 427 ~SDL_joystick(); 428 bool readInputDevice(void); getDeviceOption(void)429 const char *getDeviceOption(void) const { return "-SDLjoystick"; } 430 void guessInputDeviceNames(StringArray *names) const; 431 private: 432 SDL_Joystick* js; 433 int number_of_joystick; 434 int *maximum; 435 int *null_value; maxvalue(int i)436 float maxvalue(int i) const {return maximum[i];} 437 float sdl_factor; 438 }; 439 440 # endif 441 442 # ifdef HAVE_XINPUT 443 444 // Xi X11 XInput devices (e.g. spaceball, magellan) 445 446 # include <X11/extensions/XInput.h> 447 extern "C" 448 { 449 # include "swtxinput.h" 450 } 451 452 extern Display* swGetDisplay(void); 453 extern Window* swGetWindow(void); 454 455 class xinput : public InputDevice 456 { 457 public: 458 xinput(const char* device); 459 ~xinput(); 460 bool readInputDevice(void); getDeviceOption(void)461 const char *getDeviceOption(void) const { return "-xinput"; } 462 void guessInputDeviceNames(StringArray *names) const; 463 private: 464 char* name; 465 swXinput* swxinput; 466 float xinput_factor; 467 float *maximum; maxvalue(int i)468 float maxvalue(int i) const {return maximum[i];} 469 int nullsize; 470 }; 471 472 # endif 473 474 # ifdef HAVE_LIBSBALL 475 476 // using libsball library for SpaceTec/LabTec Spaceball devices 477 478 # include <sball.h> 479 480 class spaceball : public InputDevice 481 { 482 public: 483 spaceball(const char* device); 484 ~spaceball(); 485 bool readInputDevice(void); getDeviceOption(void)486 const char *getDeviceOption(void) const { return "-spaceball"; } isValid(void)487 virtual bool isValid(void) { return valid && (sball != NULL); } 488 void guessInputDeviceNames(StringArray *names) const; 489 private: 490 const char* name; 491 SBallHandle sball; maxvalue(int i)492 float maxvalue(int i) const {return maximum;} 493 float maximum; 494 float sball_factor; 495 int nullsize; 496 }; 497 498 # endif 499 500 #ifdef HAVE_NXT_DIALS 501 502 #define USB_ID_VENDOR_LEGO 0x0694 503 #define USB_ID_PRODUCT_NXT 0x0002 504 #define USB_OUT_ENDPOINT 0x01 505 #define USB_IN_ENDPOINT 0x82 506 #define USB_TIMEOUT 1000 507 #define USB_INTERFACE 0 508 #define USB_NXT_CONFIG 1 509 510 class nxtDials : public InputDevice 511 { 512 public: 513 nxtDials(const char* device); 514 virtual ~nxtDials(); 515 bool readInputDevice(void); getDeviceOption(void)516 const char *getDeviceOption(void) const { return "-nxtdials"; } 517 void guessInputDeviceNames(StringArray *names) const; 518 private: 519 const char* name; maxvalue(int i)520 float maxvalue(int i) const {return maximum;} 521 float maximum; 522 float factor; 523 const char* errorString; 524 int getRotationCount(int motorport); 525 526 // USB functions in this class from on libnxtusb.cpp of 527 // http://jgraef.bplaced.de/libnxtusb-0.1b.zip 528 /**************************************************************************** 529 * LibNXTUSB * 530 **************************************************************************** 531 * * 532 * Name: LibNXTUSB 0.1 * 533 * Auhor: Janosch Gräf <jgraef@users.sf.ne t> * 534 * License: GNU/GPL * 535 * * 536 ******************************************************************************** 537 * * 538 * LibNXTUSB - Use your NXT with USB under Linux * 539 * Copyright (C) 2007 Janosch Gräf * 540 * * 541 * This program is free software: you can redistribute it and/or modify * 542 * it under the terms of the GNU General Public License as published by * 543 * the Free Software Foundation, either version 3 of the License, or * 544 * (at your option) any later version. * 545 * * 546 * This program is distributed in the hope that it will be useful, * 547 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 548 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 549 * GNU General Public License for more details. * 550 * * 551 * You should have received a copy of the GNU General Public License * 552 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 553 * * 554 ********************************************************************************/ 555 556 struct usb_dev_handle *nxt_handle; 557 558 void shutdown(); 559 usb_dev_handle *locate_nxt(int index); 560 int usb_sendpacket(char *buffer,int size); 561 int usb_recvpacket(char *buffer,int size); 562 void abortprog(); 563 }; 564 565 #endif 566 567 # ifdef HAVE_WINDOWS_P5 568 569 // using P5 library for P5 devices on M$Windows 570 571 #include "p5dll.h" 572 #include "p5bend.h" 573 #include "P5Motion.h" 574 575 class windowsp5 : public InputDevice 576 { 577 public: 578 windowsp5(const char* device); 579 ~windowsp5(); sendalways(void)580 bool sendalways(void) { return true; } 581 bool readInputDevice(void); getDeviceOption(void)582 const char *getDeviceOption(void) const { return "-p5"; } 583 void guessInputDeviceNames(StringArray *names) const; 584 private: 585 CP5DLL P5; 586 bool bP5Present; 587 char* name; 588 int number_p5; maxvalue(int i)589 float maxvalue(int i) const {return maximum;} 590 float maximum; 591 float p5_factor; 592 int nullsize; 593 }; 594 595 # endif 596 597 # ifdef HAVE_WINDOWS_SPACEBALL 598 599 // using modern driver for SpaceNavigator devices on M$Windows 600 601 class windowsspaceball : public InputDevice 602 { 603 public: 604 windowsspaceball(const char* device); 605 ~windowsspaceball(); getDeviceOption(void)606 const char *getDeviceOption(void) const { return "-spaceball"; } 607 bool readInputDevice(void); 608 void guessInputDeviceNames(StringArray *names) const; 609 private: 610 bool initialized; 611 char* name; maxvalue(int i)612 float maxvalue(int i) const {return maximum;} 613 float maximum; 614 float windows_sball_factor; 615 int nullsize; 616 }; 617 618 # endif 619 620 # ifdef HAVE_AFLOCK 621 622 // using aFlock program from VR Juggler library for 623 // Ascention Flock of birds devices 624 625 # include "Aflock.h" 626 627 class AflockDevice 628 { 629 public: 630 AflockDevice(const char* device); 631 ~AflockDevice(); isValid()632 bool isValid() { return opened; } 633 Aflock* getAflock(void); getDeviceName(void)634 const char *getDeviceName(void) { return name; } 635 void close(); getErrorMessage(void)636 const char *getErrorMessage(void) { return errorMessage; } 637 // parameters 638 void setBaud(char* baudrate_string); 639 void setSync(char* sync_string); 640 void setBlock(char* block_string); 641 void setNumBrds(char* numBrds_string); 642 void setTransmit(char* transmit_string); 643 void setHemi(char* hemi_string); 644 void setFilt(char* filt_string); 645 void setSuddenChangeLock(char* sudden_string); 646 void setReport(char* report_string); 647 void setCalfile(char* calfile_string); 648 void setIgnoreSize(const char* ignoresize_string); 649 start(void)650 void start(void) { if (flock) flock->start(); } stop(void)651 void stop(void) { if (flock) flock->stop(); } 652 getBaudrate(void)653 int getBaudrate(void) { return baudrate; } getNumBrds(void)654 int getNumBrds(void) { return numBrds; } getBlock(void)655 int getBlock(void) { return block; } getTransmit(void)656 int getTransmit(void) { return transmit; } 657 const char* getHemi(void); 658 const char* getFilt(void); getCalfile(void)659 const char* getCalfile(void) { return calfile; } getSudden_change_lock(void)660 bool getSudden_change_lock(void) { return sudden_change_lock; } getReport(void)661 char getReport(void) { return report; } getSync(void)662 int getSync(void) { return sync; } getIgnoreSize()663 float getIgnoreSize() { return ignoreSize; } 664 665 private: 666 char* name; 667 Aflock* flock; 668 bool opened; 669 MyString errorMessage; 670 671 const char* device; 672 int baudrate; 673 int sync; 674 int block; 675 int numBrds; 676 int transmit; 677 BIRD_HEMI hemi; 678 BIRD_FILT filt; 679 bool sudden_change_lock; 680 char report; 681 char* calfile; 682 float ignoreSize; 683 }; 684 685 class aflock : public InputDevice 686 { 687 public: 688 aflock(AflockDevice* device,char* receiver_string,bool headflag); aflock(const char * checkDev)689 aflock(const char *checkDev) : InputDevice("") 690 { 691 aflockDevice = NULL; 692 checkDevice = checkDev; 693 } 694 ~aflock(); 695 bool readInputDevice(void); 696 bool isValid(); sendalways(void)697 bool sendalways(void) { return true; } hasReadDelay(void)698 bool hasReadDelay(void) { return true; } 699 void prepareRead(void); setHeadNavigation(void)700 void setHeadNavigation(void) { headNavigation=true; } getHeadNavigation(void)701 bool getHeadNavigation(void) { return isTracker() && headNavigation; } useCurrent(void)702 bool useCurrent(void) { return true; } getDeviceOption(void)703 const char *getDeviceOption(void) const 704 { 705 if (head) 706 return "-tracker"; 707 else 708 return "-wand"; 709 } 710 void guessInputDeviceNames(StringArray *names) const; 711 private: 712 int receiver; 713 char* name; 714 bool head; 715 bool wand; 716 bool headNavigation; isTracker(void)717 bool isTracker(void) { return head; } isWand(void)718 bool isWand(void) { return wand; } 719 Aflock* flock; 720 AflockDevice* aflockDevice; 721 const char *checkDevice; maxvalue(int i)722 float maxvalue(int i) const {return maximum;} 723 float maximum; 724 float aflock_factor; 725 float degreefactor; 726 bool aflockFirstFlag; 727 float old_value[3]; 728 }; 729 # endif 730 731 class dummyInputDevice : public InputDevice 732 { 733 public: dummyInputDevice(const char * device)734 dummyInputDevice(const char* device) : InputDevice(device) {}; ~dummyInputDevice()735 ~dummyInputDevice() {}; readInputDevice(void)736 bool readInputDevice(void) { return false; } getDeviceOption(void)737 const char *getDeviceOption(void) const { return "-dummy"; } 738 void guessInputDeviceNames(StringArray *names) const; 739 private: maxvalue(int axis)740 float maxvalue(int axis) const { return 0.0; } 741 }; 742 743