in_win.c (19786B)
1 /* 2 Copyright (C) 1997-2001 Id Software, Inc. 3 4 This program is free software; you can redistribute it and/or 5 modify it under the terms of the GNU General Public License 6 as published by the Free Software Foundation; either version 2 7 of the License, or (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13 See the GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19 */ 20 // in_win.c -- windows 95 mouse and joystick code 21 // 02/21/97 JCB Added extended DirectInput code to support external controllers. 22 23 #include "../client/client.h" 24 #include "winquake.h" 25 26 extern unsigned sys_msg_time; 27 28 // joystick defines and variables 29 // where should defines be moved? 30 #define JOY_ABSOLUTE_AXIS 0x00000000 // control like a joystick 31 #define JOY_RELATIVE_AXIS 0x00000010 // control like a mouse, spinner, trackball 32 #define JOY_MAX_AXES 6 // X, Y, Z, R, U, V 33 #define JOY_AXIS_X 0 34 #define JOY_AXIS_Y 1 35 #define JOY_AXIS_Z 2 36 #define JOY_AXIS_R 3 37 #define JOY_AXIS_U 4 38 #define JOY_AXIS_V 5 39 40 enum _ControlList 41 { 42 AxisNada = 0, AxisForward, AxisLook, AxisSide, AxisTurn, AxisUp 43 }; 44 45 DWORD dwAxisFlags[JOY_MAX_AXES] = 46 { 47 JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, JOY_RETURNR, JOY_RETURNU, JOY_RETURNV 48 }; 49 50 DWORD dwAxisMap[JOY_MAX_AXES]; 51 DWORD dwControlMap[JOY_MAX_AXES]; 52 PDWORD pdwRawValue[JOY_MAX_AXES]; 53 54 cvar_t *in_mouse; 55 cvar_t *in_joystick; 56 57 58 // none of these cvars are saved over a session 59 // this means that advanced controller configuration needs to be executed 60 // each time. this avoids any problems with getting back to a default usage 61 // or when changing from one controller to another. this way at least something 62 // works. 63 cvar_t *joy_name; 64 cvar_t *joy_advanced; 65 cvar_t *joy_advaxisx; 66 cvar_t *joy_advaxisy; 67 cvar_t *joy_advaxisz; 68 cvar_t *joy_advaxisr; 69 cvar_t *joy_advaxisu; 70 cvar_t *joy_advaxisv; 71 cvar_t *joy_forwardthreshold; 72 cvar_t *joy_sidethreshold; 73 cvar_t *joy_pitchthreshold; 74 cvar_t *joy_yawthreshold; 75 cvar_t *joy_forwardsensitivity; 76 cvar_t *joy_sidesensitivity; 77 cvar_t *joy_pitchsensitivity; 78 cvar_t *joy_yawsensitivity; 79 cvar_t *joy_upthreshold; 80 cvar_t *joy_upsensitivity; 81 82 qboolean joy_avail, joy_advancedinit, joy_haspov; 83 DWORD joy_oldbuttonstate, joy_oldpovstate; 84 85 int joy_id; 86 DWORD joy_flags; 87 DWORD joy_numbuttons; 88 89 static JOYINFOEX ji; 90 91 qboolean in_appactive; 92 93 // forward-referenced functions 94 void IN_StartupJoystick (void); 95 void Joy_AdvancedUpdate_f (void); 96 void IN_JoyMove (usercmd_t *cmd); 97 98 /* 99 ============================================================ 100 101 MOUSE CONTROL 102 103 ============================================================ 104 */ 105 106 // mouse variables 107 cvar_t *m_filter; 108 109 qboolean mlooking; 110 111 void IN_MLookDown (void) { mlooking = true; } 112 void IN_MLookUp (void) { 113 mlooking = false; 114 if (!freelook->value && lookspring->value) 115 IN_CenterView (); 116 } 117 118 int mouse_buttons; 119 int mouse_oldbuttonstate; 120 POINT current_pos; 121 int mouse_x, mouse_y, old_mouse_x, old_mouse_y, mx_accum, my_accum; 122 123 int old_x, old_y; 124 125 qboolean mouseactive; // false when not focus app 126 127 qboolean restore_spi; 128 qboolean mouseinitialized; 129 int originalmouseparms[3], newmouseparms[3] = {0, 0, 1}; 130 qboolean mouseparmsvalid; 131 132 int window_center_x, window_center_y; 133 RECT window_rect; 134 135 136 /* 137 =========== 138 IN_ActivateMouse 139 140 Called when the window gains focus or changes in some way 141 =========== 142 */ 143 void IN_ActivateMouse (void) 144 { 145 int width, height; 146 147 if (!mouseinitialized) 148 return; 149 if (!in_mouse->value) 150 { 151 mouseactive = false; 152 return; 153 } 154 if (mouseactive) 155 return; 156 157 mouseactive = true; 158 159 if (mouseparmsvalid) 160 restore_spi = SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0); 161 162 width = GetSystemMetrics (SM_CXSCREEN); 163 height = GetSystemMetrics (SM_CYSCREEN); 164 165 GetWindowRect ( cl_hwnd, &window_rect); 166 if (window_rect.left < 0) 167 window_rect.left = 0; 168 if (window_rect.top < 0) 169 window_rect.top = 0; 170 if (window_rect.right >= width) 171 window_rect.right = width-1; 172 if (window_rect.bottom >= height-1) 173 window_rect.bottom = height-1; 174 175 window_center_x = (window_rect.right + window_rect.left)/2; 176 window_center_y = (window_rect.top + window_rect.bottom)/2; 177 178 SetCursorPos (window_center_x, window_center_y); 179 180 old_x = window_center_x; 181 old_y = window_center_y; 182 183 SetCapture ( cl_hwnd ); 184 ClipCursor (&window_rect); 185 while (ShowCursor (FALSE) >= 0) 186 ; 187 } 188 189 190 /* 191 =========== 192 IN_DeactivateMouse 193 194 Called when the window loses focus 195 =========== 196 */ 197 void IN_DeactivateMouse (void) 198 { 199 if (!mouseinitialized) 200 return; 201 if (!mouseactive) 202 return; 203 204 if (restore_spi) 205 SystemParametersInfo (SPI_SETMOUSE, 0, originalmouseparms, 0); 206 207 mouseactive = false; 208 209 ClipCursor (NULL); 210 ReleaseCapture (); 211 while (ShowCursor (TRUE) < 0) 212 ; 213 } 214 215 216 217 /* 218 =========== 219 IN_StartupMouse 220 =========== 221 */ 222 void IN_StartupMouse (void) 223 { 224 cvar_t *cv; 225 226 cv = Cvar_Get ("in_initmouse", "1", CVAR_NOSET); 227 if ( !cv->value ) 228 return; 229 230 mouseinitialized = true; 231 mouseparmsvalid = SystemParametersInfo (SPI_GETMOUSE, 0, originalmouseparms, 0); 232 mouse_buttons = 3; 233 } 234 235 /* 236 =========== 237 IN_MouseEvent 238 =========== 239 */ 240 void IN_MouseEvent (int mstate) 241 { 242 int i; 243 244 if (!mouseinitialized) 245 return; 246 247 // perform button actions 248 for (i=0 ; i<mouse_buttons ; i++) 249 { 250 if ( (mstate & (1<<i)) && 251 !(mouse_oldbuttonstate & (1<<i)) ) 252 { 253 Key_Event (K_MOUSE1 + i, true, sys_msg_time); 254 } 255 256 if ( !(mstate & (1<<i)) && 257 (mouse_oldbuttonstate & (1<<i)) ) 258 { 259 Key_Event (K_MOUSE1 + i, false, sys_msg_time); 260 } 261 } 262 263 mouse_oldbuttonstate = mstate; 264 } 265 266 267 /* 268 =========== 269 IN_MouseMove 270 =========== 271 */ 272 void IN_MouseMove (usercmd_t *cmd) 273 { 274 int mx, my; 275 276 if (!mouseactive) 277 return; 278 279 // find mouse movement 280 if (!GetCursorPos (¤t_pos)) 281 return; 282 283 mx = current_pos.x - window_center_x; 284 my = current_pos.y - window_center_y; 285 286 #if 0 287 if (!mx && !my) 288 return; 289 #endif 290 291 if (m_filter->value) 292 { 293 mouse_x = (mx + old_mouse_x) * 0.5; 294 mouse_y = (my + old_mouse_y) * 0.5; 295 } 296 else 297 { 298 mouse_x = mx; 299 mouse_y = my; 300 } 301 302 old_mouse_x = mx; 303 old_mouse_y = my; 304 305 mouse_x *= sensitivity->value; 306 mouse_y *= sensitivity->value; 307 308 // add mouse X/Y movement to cmd 309 if ( (in_strafe.state & 1) || (lookstrafe->value && mlooking )) 310 cmd->sidemove += m_side->value * mouse_x; 311 else 312 cl.viewangles[YAW] -= m_yaw->value * mouse_x; 313 314 if ( (mlooking || freelook->value) && !(in_strafe.state & 1)) 315 { 316 cl.viewangles[PITCH] += m_pitch->value * mouse_y; 317 } 318 else 319 { 320 cmd->forwardmove -= m_forward->value * mouse_y; 321 } 322 323 // force the mouse to the center, so there's room to move 324 if (mx || my) 325 SetCursorPos (window_center_x, window_center_y); 326 } 327 328 329 /* 330 ========================================================================= 331 332 VIEW CENTERING 333 334 ========================================================================= 335 */ 336 337 cvar_t *v_centermove; 338 cvar_t *v_centerspeed; 339 340 341 /* 342 =========== 343 IN_Init 344 =========== 345 */ 346 void IN_Init (void) 347 { 348 // mouse variables 349 m_filter = Cvar_Get ("m_filter", "0", 0); 350 in_mouse = Cvar_Get ("in_mouse", "1", CVAR_ARCHIVE); 351 352 // joystick variables 353 in_joystick = Cvar_Get ("in_joystick", "0", CVAR_ARCHIVE); 354 joy_name = Cvar_Get ("joy_name", "joystick", 0); 355 joy_advanced = Cvar_Get ("joy_advanced", "0", 0); 356 joy_advaxisx = Cvar_Get ("joy_advaxisx", "0", 0); 357 joy_advaxisy = Cvar_Get ("joy_advaxisy", "0", 0); 358 joy_advaxisz = Cvar_Get ("joy_advaxisz", "0", 0); 359 joy_advaxisr = Cvar_Get ("joy_advaxisr", "0", 0); 360 joy_advaxisu = Cvar_Get ("joy_advaxisu", "0", 0); 361 joy_advaxisv = Cvar_Get ("joy_advaxisv", "0", 0); 362 joy_forwardthreshold = Cvar_Get ("joy_forwardthreshold", "0.15", 0); 363 joy_sidethreshold = Cvar_Get ("joy_sidethreshold", "0.15", 0); 364 joy_upthreshold = Cvar_Get ("joy_upthreshold", "0.15", 0); 365 joy_pitchthreshold = Cvar_Get ("joy_pitchthreshold", "0.15", 0); 366 joy_yawthreshold = Cvar_Get ("joy_yawthreshold", "0.15", 0); 367 joy_forwardsensitivity = Cvar_Get ("joy_forwardsensitivity", "-1", 0); 368 joy_sidesensitivity = Cvar_Get ("joy_sidesensitivity", "-1", 0); 369 joy_upsensitivity = Cvar_Get ("joy_upsensitivity", "-1", 0); 370 joy_pitchsensitivity = Cvar_Get ("joy_pitchsensitivity", "1", 0); 371 joy_yawsensitivity = Cvar_Get ("joy_yawsensitivity", "-1", 0); 372 373 // centering 374 v_centermove = Cvar_Get ("v_centermove", "0.15", 0); 375 v_centerspeed = Cvar_Get ("v_centerspeed", "500", 0); 376 377 Cmd_AddCommand ("+mlook", IN_MLookDown); 378 Cmd_AddCommand ("-mlook", IN_MLookUp); 379 380 Cmd_AddCommand ("joy_advancedupdate", Joy_AdvancedUpdate_f); 381 382 IN_StartupMouse (); 383 IN_StartupJoystick (); 384 } 385 386 /* 387 =========== 388 IN_Shutdown 389 =========== 390 */ 391 void IN_Shutdown (void) 392 { 393 IN_DeactivateMouse (); 394 } 395 396 397 /* 398 =========== 399 IN_Activate 400 401 Called when the main window gains or loses focus. 402 The window may have been destroyed and recreated 403 between a deactivate and an activate. 404 =========== 405 */ 406 void IN_Activate (qboolean active) 407 { 408 in_appactive = active; 409 mouseactive = !active; // force a new window check or turn off 410 } 411 412 413 /* 414 ================== 415 IN_Frame 416 417 Called every frame, even if not generating commands 418 ================== 419 */ 420 void IN_Frame (void) 421 { 422 if (!mouseinitialized) 423 return; 424 425 if (!in_mouse || !in_appactive) 426 { 427 IN_DeactivateMouse (); 428 return; 429 } 430 431 if ( !cl.refresh_prepped 432 || cls.key_dest == key_console 433 || cls.key_dest == key_menu) 434 { 435 // temporarily deactivate if in fullscreen 436 if (Cvar_VariableValue ("vid_fullscreen") == 0) 437 { 438 IN_DeactivateMouse (); 439 return; 440 } 441 } 442 443 IN_ActivateMouse (); 444 } 445 446 /* 447 =========== 448 IN_Move 449 =========== 450 */ 451 void IN_Move (usercmd_t *cmd) 452 { 453 IN_MouseMove (cmd); 454 455 if (ActiveApp) 456 IN_JoyMove (cmd); 457 } 458 459 460 /* 461 =================== 462 IN_ClearStates 463 =================== 464 */ 465 void IN_ClearStates (void) 466 { 467 mx_accum = 0; 468 my_accum = 0; 469 mouse_oldbuttonstate = 0; 470 } 471 472 473 /* 474 ========================================================================= 475 476 JOYSTICK 477 478 ========================================================================= 479 */ 480 481 /* 482 =============== 483 IN_StartupJoystick 484 =============== 485 */ 486 void IN_StartupJoystick (void) 487 { 488 int numdevs; 489 JOYCAPS jc; 490 MMRESULT mmr; 491 cvar_t *cv; 492 493 // assume no joystick 494 joy_avail = false; 495 496 // abort startup if user requests no joystick 497 cv = Cvar_Get ("in_initjoy", "1", CVAR_NOSET); 498 if ( !cv->value ) 499 return; 500 501 // verify joystick driver is present 502 if ((numdevs = joyGetNumDevs ()) == 0) 503 { 504 // Com_Printf ("\njoystick not found -- driver not present\n\n"); 505 return; 506 } 507 508 // cycle through the joystick ids for the first valid one 509 for (joy_id=0 ; joy_id<numdevs ; joy_id++) 510 { 511 memset (&ji, 0, sizeof(ji)); 512 ji.dwSize = sizeof(ji); 513 ji.dwFlags = JOY_RETURNCENTERED; 514 515 if ((mmr = joyGetPosEx (joy_id, &ji)) == JOYERR_NOERROR) 516 break; 517 } 518 519 // abort startup if we didn't find a valid joystick 520 if (mmr != JOYERR_NOERROR) 521 { 522 Com_Printf ("\njoystick not found -- no valid joysticks (%x)\n\n", mmr); 523 return; 524 } 525 526 // get the capabilities of the selected joystick 527 // abort startup if command fails 528 memset (&jc, 0, sizeof(jc)); 529 if ((mmr = joyGetDevCaps (joy_id, &jc, sizeof(jc))) != JOYERR_NOERROR) 530 { 531 Com_Printf ("\njoystick not found -- invalid joystick capabilities (%x)\n\n", mmr); 532 return; 533 } 534 535 // save the joystick's number of buttons and POV status 536 joy_numbuttons = jc.wNumButtons; 537 joy_haspov = jc.wCaps & JOYCAPS_HASPOV; 538 539 // old button and POV states default to no buttons pressed 540 joy_oldbuttonstate = joy_oldpovstate = 0; 541 542 // mark the joystick as available and advanced initialization not completed 543 // this is needed as cvars are not available during initialization 544 545 joy_avail = true; 546 joy_advancedinit = false; 547 548 Com_Printf ("\njoystick detected\n\n"); 549 } 550 551 552 /* 553 =========== 554 RawValuePointer 555 =========== 556 */ 557 PDWORD RawValuePointer (int axis) 558 { 559 switch (axis) 560 { 561 case JOY_AXIS_X: 562 return &ji.dwXpos; 563 case JOY_AXIS_Y: 564 return &ji.dwYpos; 565 case JOY_AXIS_Z: 566 return &ji.dwZpos; 567 case JOY_AXIS_R: 568 return &ji.dwRpos; 569 case JOY_AXIS_U: 570 return &ji.dwUpos; 571 case JOY_AXIS_V: 572 return &ji.dwVpos; 573 } 574 } 575 576 577 /* 578 =========== 579 Joy_AdvancedUpdate_f 580 =========== 581 */ 582 void Joy_AdvancedUpdate_f (void) 583 { 584 585 // called once by IN_ReadJoystick and by user whenever an update is needed 586 // cvars are now available 587 int i; 588 DWORD dwTemp; 589 590 // initialize all the maps 591 for (i = 0; i < JOY_MAX_AXES; i++) 592 { 593 dwAxisMap[i] = AxisNada; 594 dwControlMap[i] = JOY_ABSOLUTE_AXIS; 595 pdwRawValue[i] = RawValuePointer(i); 596 } 597 598 if( joy_advanced->value == 0.0) 599 { 600 // default joystick initialization 601 // 2 axes only with joystick control 602 dwAxisMap[JOY_AXIS_X] = AxisTurn; 603 // dwControlMap[JOY_AXIS_X] = JOY_ABSOLUTE_AXIS; 604 dwAxisMap[JOY_AXIS_Y] = AxisForward; 605 // dwControlMap[JOY_AXIS_Y] = JOY_ABSOLUTE_AXIS; 606 } 607 else 608 { 609 if (strcmp (joy_name->string, "joystick") != 0) 610 { 611 // notify user of advanced controller 612 Com_Printf ("\n%s configured\n\n", joy_name->string); 613 } 614 615 // advanced initialization here 616 // data supplied by user via joy_axisn cvars 617 dwTemp = (DWORD) joy_advaxisx->value; 618 dwAxisMap[JOY_AXIS_X] = dwTemp & 0x0000000f; 619 dwControlMap[JOY_AXIS_X] = dwTemp & JOY_RELATIVE_AXIS; 620 dwTemp = (DWORD) joy_advaxisy->value; 621 dwAxisMap[JOY_AXIS_Y] = dwTemp & 0x0000000f; 622 dwControlMap[JOY_AXIS_Y] = dwTemp & JOY_RELATIVE_AXIS; 623 dwTemp = (DWORD) joy_advaxisz->value; 624 dwAxisMap[JOY_AXIS_Z] = dwTemp & 0x0000000f; 625 dwControlMap[JOY_AXIS_Z] = dwTemp & JOY_RELATIVE_AXIS; 626 dwTemp = (DWORD) joy_advaxisr->value; 627 dwAxisMap[JOY_AXIS_R] = dwTemp & 0x0000000f; 628 dwControlMap[JOY_AXIS_R] = dwTemp & JOY_RELATIVE_AXIS; 629 dwTemp = (DWORD) joy_advaxisu->value; 630 dwAxisMap[JOY_AXIS_U] = dwTemp & 0x0000000f; 631 dwControlMap[JOY_AXIS_U] = dwTemp & JOY_RELATIVE_AXIS; 632 dwTemp = (DWORD) joy_advaxisv->value; 633 dwAxisMap[JOY_AXIS_V] = dwTemp & 0x0000000f; 634 dwControlMap[JOY_AXIS_V] = dwTemp & JOY_RELATIVE_AXIS; 635 } 636 637 // compute the axes to collect from DirectInput 638 joy_flags = JOY_RETURNCENTERED | JOY_RETURNBUTTONS | JOY_RETURNPOV; 639 for (i = 0; i < JOY_MAX_AXES; i++) 640 { 641 if (dwAxisMap[i] != AxisNada) 642 { 643 joy_flags |= dwAxisFlags[i]; 644 } 645 } 646 } 647 648 649 /* 650 =========== 651 IN_Commands 652 =========== 653 */ 654 void IN_Commands (void) 655 { 656 int i, key_index; 657 DWORD buttonstate, povstate; 658 659 if (!joy_avail) 660 { 661 return; 662 } 663 664 665 // loop through the joystick buttons 666 // key a joystick event or auxillary event for higher number buttons for each state change 667 buttonstate = ji.dwButtons; 668 for (i=0 ; i < joy_numbuttons ; i++) 669 { 670 if ( (buttonstate & (1<<i)) && !(joy_oldbuttonstate & (1<<i)) ) 671 { 672 key_index = (i < 4) ? K_JOY1 : K_AUX1; 673 Key_Event (key_index + i, true, 0); 674 } 675 676 if ( !(buttonstate & (1<<i)) && (joy_oldbuttonstate & (1<<i)) ) 677 { 678 key_index = (i < 4) ? K_JOY1 : K_AUX1; 679 Key_Event (key_index + i, false, 0); 680 } 681 } 682 joy_oldbuttonstate = buttonstate; 683 684 if (joy_haspov) 685 { 686 // convert POV information into 4 bits of state information 687 // this avoids any potential problems related to moving from one 688 // direction to another without going through the center position 689 povstate = 0; 690 if(ji.dwPOV != JOY_POVCENTERED) 691 { 692 if (ji.dwPOV == JOY_POVFORWARD) 693 povstate |= 0x01; 694 if (ji.dwPOV == JOY_POVRIGHT) 695 povstate |= 0x02; 696 if (ji.dwPOV == JOY_POVBACKWARD) 697 povstate |= 0x04; 698 if (ji.dwPOV == JOY_POVLEFT) 699 povstate |= 0x08; 700 } 701 // determine which bits have changed and key an auxillary event for each change 702 for (i=0 ; i < 4 ; i++) 703 { 704 if ( (povstate & (1<<i)) && !(joy_oldpovstate & (1<<i)) ) 705 { 706 Key_Event (K_AUX29 + i, true, 0); 707 } 708 709 if ( !(povstate & (1<<i)) && (joy_oldpovstate & (1<<i)) ) 710 { 711 Key_Event (K_AUX29 + i, false, 0); 712 } 713 } 714 joy_oldpovstate = povstate; 715 } 716 } 717 718 719 /* 720 =============== 721 IN_ReadJoystick 722 =============== 723 */ 724 qboolean IN_ReadJoystick (void) 725 { 726 727 memset (&ji, 0, sizeof(ji)); 728 ji.dwSize = sizeof(ji); 729 ji.dwFlags = joy_flags; 730 731 if (joyGetPosEx (joy_id, &ji) == JOYERR_NOERROR) 732 { 733 return true; 734 } 735 else 736 { 737 // read error occurred 738 // turning off the joystick seems too harsh for 1 read error,\ 739 // but what should be done? 740 // Com_Printf ("IN_ReadJoystick: no response\n"); 741 // joy_avail = false; 742 return false; 743 } 744 } 745 746 747 /* 748 =========== 749 IN_JoyMove 750 =========== 751 */ 752 void IN_JoyMove (usercmd_t *cmd) 753 { 754 float speed, aspeed; 755 float fAxisValue; 756 int i; 757 758 // complete initialization if first time in 759 // this is needed as cvars are not available at initialization time 760 if( joy_advancedinit != true ) 761 { 762 Joy_AdvancedUpdate_f(); 763 joy_advancedinit = true; 764 } 765 766 // verify joystick is available and that the user wants to use it 767 if (!joy_avail || !in_joystick->value) 768 { 769 return; 770 } 771 772 // collect the joystick data, if possible 773 if (IN_ReadJoystick () != true) 774 { 775 return; 776 } 777 778 if ( (in_speed.state & 1) ^ (int)cl_run->value) 779 speed = 2; 780 else 781 speed = 1; 782 aspeed = speed * cls.frametime; 783 784 // loop through the axes 785 for (i = 0; i < JOY_MAX_AXES; i++) 786 { 787 // get the floating point zero-centered, potentially-inverted data for the current axis 788 fAxisValue = (float) *pdwRawValue[i]; 789 // move centerpoint to zero 790 fAxisValue -= 32768.0; 791 792 // convert range from -32768..32767 to -1..1 793 fAxisValue /= 32768.0; 794 795 switch (dwAxisMap[i]) 796 { 797 case AxisForward: 798 if ((joy_advanced->value == 0.0) && mlooking) 799 { 800 // user wants forward control to become look control 801 if (fabs(fAxisValue) > joy_pitchthreshold->value) 802 { 803 // if mouse invert is on, invert the joystick pitch value 804 // only absolute control support here (joy_advanced is false) 805 if (m_pitch->value < 0.0) 806 { 807 cl.viewangles[PITCH] -= (fAxisValue * joy_pitchsensitivity->value) * aspeed * cl_pitchspeed->value; 808 } 809 else 810 { 811 cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity->value) * aspeed * cl_pitchspeed->value; 812 } 813 } 814 } 815 else 816 { 817 // user wants forward control to be forward control 818 if (fabs(fAxisValue) > joy_forwardthreshold->value) 819 { 820 cmd->forwardmove += (fAxisValue * joy_forwardsensitivity->value) * speed * cl_forwardspeed->value; 821 } 822 } 823 break; 824 825 case AxisSide: 826 if (fabs(fAxisValue) > joy_sidethreshold->value) 827 { 828 cmd->sidemove += (fAxisValue * joy_sidesensitivity->value) * speed * cl_sidespeed->value; 829 } 830 break; 831 832 case AxisUp: 833 if (fabs(fAxisValue) > joy_upthreshold->value) 834 { 835 cmd->upmove += (fAxisValue * joy_upsensitivity->value) * speed * cl_upspeed->value; 836 } 837 break; 838 839 case AxisTurn: 840 if ((in_strafe.state & 1) || (lookstrafe->value && mlooking)) 841 { 842 // user wants turn control to become side control 843 if (fabs(fAxisValue) > joy_sidethreshold->value) 844 { 845 cmd->sidemove -= (fAxisValue * joy_sidesensitivity->value) * speed * cl_sidespeed->value; 846 } 847 } 848 else 849 { 850 // user wants turn control to be turn control 851 if (fabs(fAxisValue) > joy_yawthreshold->value) 852 { 853 if(dwControlMap[i] == JOY_ABSOLUTE_AXIS) 854 { 855 cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity->value) * aspeed * cl_yawspeed->value; 856 } 857 else 858 { 859 cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity->value) * speed * 180.0; 860 } 861 862 } 863 } 864 break; 865 866 case AxisLook: 867 if (mlooking) 868 { 869 if (fabs(fAxisValue) > joy_pitchthreshold->value) 870 { 871 // pitch movement detected and pitch movement desired by user 872 if(dwControlMap[i] == JOY_ABSOLUTE_AXIS) 873 { 874 cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity->value) * aspeed * cl_pitchspeed->value; 875 } 876 else 877 { 878 cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity->value) * speed * 180.0; 879 } 880 } 881 } 882 break; 883 884 default: 885 break; 886 } 887 } 888 } 889