|
|
1.1 ! root 1: /* ! 2: Copyright (C) 1996-1997 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 <dinput.h> ! 24: #include "quakedef.h" ! 25: #include "winquake.h" ! 26: //#include "dosisms.h" ! 27: ! 28: #define DINPUT_BUFFERSIZE 16 ! 29: #define iDirectInputCreate(a,b,c,d) pDirectInputCreate(a,b,c,d) ! 30: ! 31: HRESULT (WINAPI *pDirectInputCreate)(HINSTANCE hinst, DWORD dwVersion, ! 32: LPDIRECTINPUT * lplpDirectInput, LPUNKNOWN punkOuter); ! 33: ! 34: // mouse variables ! 35: cvar_t m_filter = {"m_filter","0"}; ! 36: ! 37: int mouse_buttons; ! 38: int mouse_oldbuttonstate; ! 39: POINT current_pos; ! 40: int mouse_x, mouse_y, old_mouse_x, old_mouse_y, mx_accum, my_accum; ! 41: ! 42: static qboolean restore_spi; ! 43: static int originalmouseparms[3], newmouseparms[3] = {0, 0, 1}; ! 44: qboolean mouseinitialized; ! 45: static qboolean mouseparmsvalid, mouseactivatetoggle; ! 46: static qboolean mouseshowtoggle = 1; ! 47: static qboolean dinput_acquired; ! 48: static unsigned int mstate_di; ! 49: unsigned int uiWheelMessage; ! 50: ! 51: qboolean mouseactive; ! 52: ! 53: // joystick defines and variables ! 54: // where should defines be moved? ! 55: #define JOY_ABSOLUTE_AXIS 0x00000000 // control like a joystick ! 56: #define JOY_RELATIVE_AXIS 0x00000010 // control like a mouse, spinner, trackball ! 57: #define JOY_MAX_AXES 6 // X, Y, Z, R, U, V ! 58: #define JOY_AXIS_X 0 ! 59: #define JOY_AXIS_Y 1 ! 60: #define JOY_AXIS_Z 2 ! 61: #define JOY_AXIS_R 3 ! 62: #define JOY_AXIS_U 4 ! 63: #define JOY_AXIS_V 5 ! 64: ! 65: enum _ControlList ! 66: { ! 67: AxisNada = 0, AxisForward, AxisLook, AxisSide, AxisTurn ! 68: }; ! 69: ! 70: DWORD dwAxisFlags[JOY_MAX_AXES] = ! 71: { ! 72: JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, JOY_RETURNR, JOY_RETURNU, JOY_RETURNV ! 73: }; ! 74: ! 75: DWORD dwAxisMap[JOY_MAX_AXES]; ! 76: DWORD dwControlMap[JOY_MAX_AXES]; ! 77: PDWORD pdwRawValue[JOY_MAX_AXES]; ! 78: ! 79: // none of these cvars are saved over a session ! 80: // this means that advanced controller configuration needs to be executed ! 81: // each time. this avoids any problems with getting back to a default usage ! 82: // or when changing from one controller to another. this way at least something ! 83: // works. ! 84: cvar_t in_joystick = {"joystick","0", true}; ! 85: cvar_t joy_name = {"joyname", "joystick"}; ! 86: cvar_t joy_advanced = {"joyadvanced", "0"}; ! 87: cvar_t joy_advaxisx = {"joyadvaxisx", "0"}; ! 88: cvar_t joy_advaxisy = {"joyadvaxisy", "0"}; ! 89: cvar_t joy_advaxisz = {"joyadvaxisz", "0"}; ! 90: cvar_t joy_advaxisr = {"joyadvaxisr", "0"}; ! 91: cvar_t joy_advaxisu = {"joyadvaxisu", "0"}; ! 92: cvar_t joy_advaxisv = {"joyadvaxisv", "0"}; ! 93: cvar_t joy_forwardthreshold = {"joyforwardthreshold", "0.15"}; ! 94: cvar_t joy_sidethreshold = {"joysidethreshold", "0.15"}; ! 95: cvar_t joy_pitchthreshold = {"joypitchthreshold", "0.15"}; ! 96: cvar_t joy_yawthreshold = {"joyyawthreshold", "0.15"}; ! 97: cvar_t joy_forwardsensitivity = {"joyforwardsensitivity", "-1.0"}; ! 98: cvar_t joy_sidesensitivity = {"joysidesensitivity", "-1.0"}; ! 99: cvar_t joy_pitchsensitivity = {"joypitchsensitivity", "1.0"}; ! 100: cvar_t joy_yawsensitivity = {"joyyawsensitivity", "-1.0"}; ! 101: cvar_t joy_wwhack1 = {"joywwhack1", "0.0"}; ! 102: cvar_t joy_wwhack2 = {"joywwhack2", "0.0"}; ! 103: ! 104: qboolean joy_avail, joy_advancedinit, joy_haspov; ! 105: DWORD joy_oldbuttonstate, joy_oldpovstate; ! 106: ! 107: int joy_id; ! 108: DWORD joy_flags; ! 109: DWORD joy_numbuttons; ! 110: ! 111: static LPDIRECTINPUT g_pdi; ! 112: static LPDIRECTINPUTDEVICE g_pMouse; ! 113: ! 114: static JOYINFOEX ji; ! 115: ! 116: static HINSTANCE hInstDI; ! 117: ! 118: static qboolean dinput; ! 119: ! 120: typedef struct MYDATA { ! 121: LONG lX; // X axis goes here ! 122: LONG lY; // Y axis goes here ! 123: LONG lZ; // Z axis goes here ! 124: BYTE bButtonA; // One button goes here ! 125: BYTE bButtonB; // Another button goes here ! 126: BYTE bButtonC; // Another button goes here ! 127: BYTE bButtonD; // Another button goes here ! 128: } MYDATA; ! 129: ! 130: static DIOBJECTDATAFORMAT rgodf[] = { ! 131: { &GUID_XAxis, FIELD_OFFSET(MYDATA, lX), DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, ! 132: { &GUID_YAxis, FIELD_OFFSET(MYDATA, lY), DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, ! 133: { &GUID_ZAxis, FIELD_OFFSET(MYDATA, lZ), 0x80000000 | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,}, ! 134: { 0, FIELD_OFFSET(MYDATA, bButtonA), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, ! 135: { 0, FIELD_OFFSET(MYDATA, bButtonB), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, ! 136: { 0, FIELD_OFFSET(MYDATA, bButtonC), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, ! 137: { 0, FIELD_OFFSET(MYDATA, bButtonD), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,}, ! 138: }; ! 139: ! 140: #define NUM_OBJECTS (sizeof(rgodf) / sizeof(rgodf[0])) ! 141: ! 142: static DIDATAFORMAT df = { ! 143: sizeof(DIDATAFORMAT), // this structure ! 144: sizeof(DIOBJECTDATAFORMAT), // size of object data format ! 145: DIDF_RELAXIS, // absolute axis coordinates ! 146: sizeof(MYDATA), // device data size ! 147: NUM_OBJECTS, // number of objects ! 148: rgodf, // and here they are ! 149: }; ! 150: ! 151: // forward-referenced functions ! 152: void IN_StartupJoystick (void); ! 153: void Joy_AdvancedUpdate_f (void); ! 154: void IN_JoyMove (usercmd_t *cmd); ! 155: ! 156: ! 157: /* ! 158: =========== ! 159: Force_CenterView_f ! 160: =========== ! 161: */ ! 162: void Force_CenterView_f (void) ! 163: { ! 164: cl.viewangles[PITCH] = 0; ! 165: } ! 166: ! 167: ! 168: /* ! 169: =========== ! 170: IN_UpdateClipCursor ! 171: =========== ! 172: */ ! 173: void IN_UpdateClipCursor (void) ! 174: { ! 175: ! 176: if (mouseinitialized && mouseactive && !dinput) ! 177: { ! 178: ClipCursor (&window_rect); ! 179: } ! 180: } ! 181: ! 182: ! 183: /* ! 184: =========== ! 185: IN_ShowMouse ! 186: =========== ! 187: */ ! 188: void IN_ShowMouse (void) ! 189: { ! 190: ! 191: if (!mouseshowtoggle) ! 192: { ! 193: ShowCursor (TRUE); ! 194: mouseshowtoggle = 1; ! 195: } ! 196: } ! 197: ! 198: ! 199: /* ! 200: =========== ! 201: IN_HideMouse ! 202: =========== ! 203: */ ! 204: void IN_HideMouse (void) ! 205: { ! 206: ! 207: if (mouseshowtoggle) ! 208: { ! 209: ShowCursor (FALSE); ! 210: mouseshowtoggle = 0; ! 211: } ! 212: } ! 213: ! 214: ! 215: /* ! 216: =========== ! 217: IN_ActivateMouse ! 218: =========== ! 219: */ ! 220: void IN_ActivateMouse (void) ! 221: { ! 222: ! 223: mouseactivatetoggle = true; ! 224: ! 225: if (mouseinitialized) ! 226: { ! 227: if (dinput) ! 228: { ! 229: if (g_pMouse) ! 230: { ! 231: if (!dinput_acquired) ! 232: { ! 233: IDirectInputDevice_Acquire(g_pMouse); ! 234: dinput_acquired = true; ! 235: } ! 236: } ! 237: else ! 238: { ! 239: return; ! 240: } ! 241: } ! 242: else ! 243: { ! 244: if (mouseparmsvalid) ! 245: restore_spi = SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0); ! 246: ! 247: SetCursorPos (window_center_x, window_center_y); ! 248: SetCapture (mainwindow); ! 249: ClipCursor (&window_rect); ! 250: } ! 251: ! 252: mouseactive = true; ! 253: } ! 254: } ! 255: ! 256: ! 257: /* ! 258: =========== ! 259: IN_SetQuakeMouseState ! 260: =========== ! 261: */ ! 262: void IN_SetQuakeMouseState (void) ! 263: { ! 264: if (mouseactivatetoggle) ! 265: IN_ActivateMouse (); ! 266: } ! 267: ! 268: ! 269: /* ! 270: =========== ! 271: IN_DeactivateMouse ! 272: =========== ! 273: */ ! 274: void IN_DeactivateMouse (void) ! 275: { ! 276: ! 277: mouseactivatetoggle = false; ! 278: ! 279: if (mouseinitialized) ! 280: { ! 281: if (dinput) ! 282: { ! 283: if (g_pMouse) ! 284: { ! 285: if (dinput_acquired) ! 286: { ! 287: IDirectInputDevice_Unacquire(g_pMouse); ! 288: dinput_acquired = false; ! 289: } ! 290: } ! 291: } ! 292: else ! 293: { ! 294: if (restore_spi) ! 295: SystemParametersInfo (SPI_SETMOUSE, 0, originalmouseparms, 0); ! 296: ! 297: ClipCursor (NULL); ! 298: ReleaseCapture (); ! 299: } ! 300: ! 301: mouseactive = false; ! 302: } ! 303: } ! 304: ! 305: ! 306: /* ! 307: =========== ! 308: IN_RestoreOriginalMouseState ! 309: =========== ! 310: */ ! 311: void IN_RestoreOriginalMouseState (void) ! 312: { ! 313: if (mouseactivatetoggle) ! 314: { ! 315: IN_DeactivateMouse (); ! 316: mouseactivatetoggle = true; ! 317: } ! 318: ! 319: // try to redraw the cursor so it gets reinitialized, because sometimes it ! 320: // has garbage after the mode switch ! 321: ShowCursor (TRUE); ! 322: ShowCursor (FALSE); ! 323: } ! 324: ! 325: ! 326: /* ! 327: =========== ! 328: IN_InitDInput ! 329: =========== ! 330: */ ! 331: qboolean IN_InitDInput (void) ! 332: { ! 333: HRESULT hr; ! 334: DIPROPDWORD dipdw = { ! 335: { ! 336: sizeof(DIPROPDWORD), // diph.dwSize ! 337: sizeof(DIPROPHEADER), // diph.dwHeaderSize ! 338: 0, // diph.dwObj ! 339: DIPH_DEVICE, // diph.dwHow ! 340: }, ! 341: DINPUT_BUFFERSIZE, // dwData ! 342: }; ! 343: ! 344: if (!hInstDI) ! 345: { ! 346: hInstDI = LoadLibrary("dinput.dll"); ! 347: ! 348: if (hInstDI == NULL) ! 349: { ! 350: Con_SafePrintf ("Couldn't load dinput.dll\n"); ! 351: return false; ! 352: } ! 353: } ! 354: ! 355: if (!pDirectInputCreate) ! 356: { ! 357: pDirectInputCreate = (void *)GetProcAddress(hInstDI,"DirectInputCreateA"); ! 358: ! 359: if (!pDirectInputCreate) ! 360: { ! 361: Con_SafePrintf ("Couldn't get DI proc addr\n"); ! 362: return false; ! 363: } ! 364: } ! 365: ! 366: // register with DirectInput and get an IDirectInput to play with. ! 367: hr = iDirectInputCreate(global_hInstance, DIRECTINPUT_VERSION, &g_pdi, NULL); ! 368: ! 369: if (FAILED(hr)) ! 370: { ! 371: return false; ! 372: } ! 373: ! 374: // obtain an interface to the system mouse device. ! 375: hr = IDirectInput_CreateDevice(g_pdi, &GUID_SysMouse, &g_pMouse, NULL); ! 376: ! 377: if (FAILED(hr)) ! 378: { ! 379: Con_SafePrintf ("Couldn't open DI mouse device\n"); ! 380: return false; ! 381: } ! 382: ! 383: // set the data format to "mouse format". ! 384: hr = IDirectInputDevice_SetDataFormat(g_pMouse, &df); ! 385: ! 386: if (FAILED(hr)) ! 387: { ! 388: Con_SafePrintf ("Couldn't set DI mouse format\n"); ! 389: return false; ! 390: } ! 391: ! 392: // set the cooperativity level. ! 393: hr = IDirectInputDevice_SetCooperativeLevel(g_pMouse, mainwindow, ! 394: DISCL_EXCLUSIVE | DISCL_FOREGROUND); ! 395: ! 396: if (FAILED(hr)) ! 397: { ! 398: Con_SafePrintf ("Couldn't set DI coop level\n"); ! 399: return false; ! 400: } ! 401: ! 402: ! 403: // set the buffer size to DINPUT_BUFFERSIZE elements. ! 404: // the buffer size is a DWORD property associated with the device ! 405: hr = IDirectInputDevice_SetProperty(g_pMouse, DIPROP_BUFFERSIZE, &dipdw.diph); ! 406: ! 407: if (FAILED(hr)) ! 408: { ! 409: Con_SafePrintf ("Couldn't set DI buffersize\n"); ! 410: return false; ! 411: } ! 412: ! 413: return true; ! 414: } ! 415: ! 416: ! 417: /* ! 418: =========== ! 419: IN_StartupMouse ! 420: =========== ! 421: */ ! 422: void IN_StartupMouse (void) ! 423: { ! 424: HDC hdc; ! 425: ! 426: if ( COM_CheckParm ("-nomouse") ) ! 427: return; ! 428: ! 429: mouseinitialized = true; ! 430: ! 431: if (COM_CheckParm ("-dinput")) ! 432: { ! 433: dinput = IN_InitDInput (); ! 434: ! 435: if (dinput) ! 436: { ! 437: Con_SafePrintf ("DirectInput initialized\n"); ! 438: } ! 439: else ! 440: { ! 441: Con_SafePrintf ("DirectInput not initialized\n"); ! 442: } ! 443: } ! 444: ! 445: if (!dinput) ! 446: { ! 447: mouseparmsvalid = SystemParametersInfo (SPI_GETMOUSE, 0, originalmouseparms, 0); ! 448: ! 449: if (mouseparmsvalid) ! 450: { ! 451: if ( COM_CheckParm ("-noforcemspd") ) ! 452: newmouseparms[2] = originalmouseparms[2]; ! 453: ! 454: if ( COM_CheckParm ("-noforcemaccel") ) ! 455: { ! 456: newmouseparms[0] = originalmouseparms[0]; ! 457: newmouseparms[1] = originalmouseparms[1]; ! 458: } ! 459: ! 460: if ( COM_CheckParm ("-noforcemparms") ) ! 461: { ! 462: newmouseparms[0] = originalmouseparms[0]; ! 463: newmouseparms[1] = originalmouseparms[1]; ! 464: newmouseparms[2] = originalmouseparms[2]; ! 465: } ! 466: } ! 467: } ! 468: ! 469: mouse_buttons = 3; ! 470: ! 471: // if a fullscreen video mode was set before the mouse was initialized, ! 472: // set the mouse state appropriately ! 473: if (mouseactivatetoggle) ! 474: IN_ActivateMouse (); ! 475: } ! 476: ! 477: ! 478: /* ! 479: =========== ! 480: IN_Init ! 481: =========== ! 482: */ ! 483: void IN_Init (void) ! 484: { ! 485: // mouse variables ! 486: Cvar_RegisterVariable (&m_filter); ! 487: ! 488: // joystick variables ! 489: Cvar_RegisterVariable (&in_joystick); ! 490: Cvar_RegisterVariable (&joy_name); ! 491: Cvar_RegisterVariable (&joy_advanced); ! 492: Cvar_RegisterVariable (&joy_advaxisx); ! 493: Cvar_RegisterVariable (&joy_advaxisy); ! 494: Cvar_RegisterVariable (&joy_advaxisz); ! 495: Cvar_RegisterVariable (&joy_advaxisr); ! 496: Cvar_RegisterVariable (&joy_advaxisu); ! 497: Cvar_RegisterVariable (&joy_advaxisv); ! 498: Cvar_RegisterVariable (&joy_forwardthreshold); ! 499: Cvar_RegisterVariable (&joy_sidethreshold); ! 500: Cvar_RegisterVariable (&joy_pitchthreshold); ! 501: Cvar_RegisterVariable (&joy_yawthreshold); ! 502: Cvar_RegisterVariable (&joy_forwardsensitivity); ! 503: Cvar_RegisterVariable (&joy_sidesensitivity); ! 504: Cvar_RegisterVariable (&joy_pitchsensitivity); ! 505: Cvar_RegisterVariable (&joy_yawsensitivity); ! 506: Cvar_RegisterVariable (&joy_wwhack1); ! 507: Cvar_RegisterVariable (&joy_wwhack2); ! 508: ! 509: Cmd_AddCommand ("force_centerview", Force_CenterView_f); ! 510: Cmd_AddCommand ("joyadvancedupdate", Joy_AdvancedUpdate_f); ! 511: ! 512: uiWheelMessage = RegisterWindowMessage ( "MSWHEEL_ROLLMSG" ); ! 513: ! 514: IN_StartupMouse (); ! 515: IN_StartupJoystick (); ! 516: } ! 517: ! 518: /* ! 519: =========== ! 520: IN_Shutdown ! 521: =========== ! 522: */ ! 523: void IN_Shutdown (void) ! 524: { ! 525: ! 526: IN_DeactivateMouse (); ! 527: IN_ShowMouse (); ! 528: ! 529: if (g_pMouse) ! 530: { ! 531: IDirectInputDevice_Release(g_pMouse); ! 532: g_pMouse = NULL; ! 533: } ! 534: ! 535: if (g_pdi) ! 536: { ! 537: IDirectInput_Release(g_pdi); ! 538: g_pdi = NULL; ! 539: } ! 540: } ! 541: ! 542: ! 543: /* ! 544: =========== ! 545: IN_MouseEvent ! 546: =========== ! 547: */ ! 548: void IN_MouseEvent (int mstate) ! 549: { ! 550: int i; ! 551: ! 552: if (mouseactive && !dinput) ! 553: { ! 554: // perform button actions ! 555: for (i=0 ; i<mouse_buttons ; i++) ! 556: { ! 557: if ( (mstate & (1<<i)) && ! 558: !(mouse_oldbuttonstate & (1<<i)) ) ! 559: { ! 560: Key_Event (K_MOUSE1 + i, true); ! 561: } ! 562: ! 563: if ( !(mstate & (1<<i)) && ! 564: (mouse_oldbuttonstate & (1<<i)) ) ! 565: { ! 566: Key_Event (K_MOUSE1 + i, false); ! 567: } ! 568: } ! 569: ! 570: mouse_oldbuttonstate = mstate; ! 571: } ! 572: } ! 573: ! 574: ! 575: /* ! 576: =========== ! 577: IN_MouseMove ! 578: =========== ! 579: */ ! 580: void IN_MouseMove (usercmd_t *cmd) ! 581: { ! 582: int mx, my; ! 583: HDC hdc; ! 584: int i; ! 585: DIDEVICEOBJECTDATA od; ! 586: DWORD dwElements; ! 587: HRESULT hr; ! 588: ! 589: if (!mouseactive) ! 590: return; ! 591: ! 592: if (dinput) ! 593: { ! 594: mx = 0; ! 595: my = 0; ! 596: ! 597: for (;;) ! 598: { ! 599: dwElements = 1; ! 600: ! 601: hr = IDirectInputDevice_GetDeviceData(g_pMouse, ! 602: sizeof(DIDEVICEOBJECTDATA), &od, &dwElements, 0); ! 603: ! 604: if ((hr == DIERR_INPUTLOST) || (hr == DIERR_NOTACQUIRED)) ! 605: { ! 606: dinput_acquired = true; ! 607: IDirectInputDevice_Acquire(g_pMouse); ! 608: break; ! 609: } ! 610: ! 611: /* Unable to read data or no data available */ ! 612: if (FAILED(hr) || dwElements == 0) ! 613: { ! 614: break; ! 615: } ! 616: ! 617: /* Look at the element to see what happened */ ! 618: ! 619: switch (od.dwOfs) ! 620: { ! 621: case DIMOFS_X: ! 622: mx += od.dwData; ! 623: break; ! 624: ! 625: case DIMOFS_Y: ! 626: my += od.dwData; ! 627: break; ! 628: ! 629: case DIMOFS_BUTTON0: ! 630: if (od.dwData & 0x80) ! 631: mstate_di |= 1; ! 632: else ! 633: mstate_di &= ~1; ! 634: break; ! 635: ! 636: case DIMOFS_BUTTON1: ! 637: if (od.dwData & 0x80) ! 638: mstate_di |= (1<<1); ! 639: else ! 640: mstate_di &= ~(1<<1); ! 641: break; ! 642: ! 643: case DIMOFS_BUTTON2: ! 644: if (od.dwData & 0x80) ! 645: mstate_di |= (1<<2); ! 646: else ! 647: mstate_di &= ~(1<<2); ! 648: break; ! 649: } ! 650: } ! 651: ! 652: // perform button actions ! 653: for (i=0 ; i<mouse_buttons ; i++) ! 654: { ! 655: if ( (mstate_di & (1<<i)) && ! 656: !(mouse_oldbuttonstate & (1<<i)) ) ! 657: { ! 658: Key_Event (K_MOUSE1 + i, true); ! 659: } ! 660: ! 661: if ( !(mstate_di & (1<<i)) && ! 662: (mouse_oldbuttonstate & (1<<i)) ) ! 663: { ! 664: Key_Event (K_MOUSE1 + i, false); ! 665: } ! 666: } ! 667: ! 668: mouse_oldbuttonstate = mstate_di; ! 669: } ! 670: else ! 671: { ! 672: GetCursorPos (¤t_pos); ! 673: mx = current_pos.x - window_center_x + mx_accum; ! 674: my = current_pos.y - window_center_y + my_accum; ! 675: mx_accum = 0; ! 676: my_accum = 0; ! 677: } ! 678: ! 679: if (m_filter.value) ! 680: { ! 681: mouse_x = (mx + old_mouse_x) * 0.5; ! 682: mouse_y = (my + old_mouse_y) * 0.5; ! 683: } ! 684: else ! 685: { ! 686: mouse_x = mx; ! 687: mouse_y = my; ! 688: } ! 689: ! 690: old_mouse_x = mx; ! 691: old_mouse_y = my; ! 692: ! 693: mouse_x *= sensitivity.value; ! 694: mouse_y *= sensitivity.value; ! 695: ! 696: // add mouse X/Y movement to cmd ! 697: if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) )) ! 698: cmd->sidemove += m_side.value * mouse_x; ! 699: else ! 700: cl.viewangles[YAW] -= m_yaw.value * mouse_x; ! 701: ! 702: if (in_mlook.state & 1) ! 703: V_StopPitchDrift (); ! 704: ! 705: if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) ! 706: { ! 707: cl.viewangles[PITCH] += m_pitch.value * mouse_y; ! 708: if (cl.viewangles[PITCH] > 80) ! 709: cl.viewangles[PITCH] = 80; ! 710: if (cl.viewangles[PITCH] < -70) ! 711: cl.viewangles[PITCH] = -70; ! 712: } ! 713: else ! 714: { ! 715: if ((in_strafe.state & 1) && noclip_anglehack) ! 716: cmd->upmove -= m_forward.value * mouse_y; ! 717: else ! 718: cmd->forwardmove -= m_forward.value * mouse_y; ! 719: } ! 720: ! 721: // if the mouse has moved, force it to the center, so there's room to move ! 722: if (mx || my) ! 723: { ! 724: SetCursorPos (window_center_x, window_center_y); ! 725: } ! 726: } ! 727: ! 728: ! 729: /* ! 730: =========== ! 731: IN_Move ! 732: =========== ! 733: */ ! 734: void IN_Move (usercmd_t *cmd) ! 735: { ! 736: ! 737: if (ActiveApp && !Minimized) ! 738: { ! 739: IN_MouseMove (cmd); ! 740: IN_JoyMove (cmd); ! 741: } ! 742: } ! 743: ! 744: ! 745: /* ! 746: =========== ! 747: IN_Accumulate ! 748: =========== ! 749: */ ! 750: void IN_Accumulate (void) ! 751: { ! 752: int mx, my; ! 753: HDC hdc; ! 754: ! 755: if (mouseactive) ! 756: { ! 757: GetCursorPos (¤t_pos); ! 758: ! 759: mx_accum += current_pos.x - window_center_x; ! 760: my_accum += current_pos.y - window_center_y; ! 761: ! 762: // force the mouse to the center, so there's room to move ! 763: SetCursorPos (window_center_x, window_center_y); ! 764: } ! 765: } ! 766: ! 767: ! 768: /* ! 769: =================== ! 770: IN_ClearStates ! 771: =================== ! 772: */ ! 773: void IN_ClearStates (void) ! 774: { ! 775: ! 776: if (mouseactive) ! 777: { ! 778: mx_accum = 0; ! 779: my_accum = 0; ! 780: mouse_oldbuttonstate = 0; ! 781: } ! 782: } ! 783: ! 784: ! 785: /* ! 786: =============== ! 787: IN_StartupJoystick ! 788: =============== ! 789: */ ! 790: void IN_StartupJoystick (void) ! 791: { ! 792: int i, numdevs; ! 793: JOYCAPS jc; ! 794: MMRESULT mmr; ! 795: ! 796: // assume no joystick ! 797: joy_avail = false; ! 798: ! 799: // abort startup if user requests no joystick ! 800: if ( COM_CheckParm ("-nojoy") ) ! 801: return; ! 802: ! 803: // verify joystick driver is present ! 804: if ((numdevs = joyGetNumDevs ()) == 0) ! 805: { ! 806: Con_Printf ("\njoystick not found -- driver not present\n\n"); ! 807: return; ! 808: } ! 809: ! 810: // cycle through the joystick ids for the first valid one ! 811: for (joy_id=0 ; joy_id<numdevs ; joy_id++) ! 812: { ! 813: memset (&ji, 0, sizeof(ji)); ! 814: ji.dwSize = sizeof(ji); ! 815: ji.dwFlags = JOY_RETURNCENTERED; ! 816: ! 817: if ((mmr = joyGetPosEx (joy_id, &ji)) == JOYERR_NOERROR) ! 818: break; ! 819: } ! 820: ! 821: // abort startup if we didn't find a valid joystick ! 822: if (mmr != JOYERR_NOERROR) ! 823: { ! 824: Con_Printf ("\njoystick not found -- no valid joysticks (%x)\n\n", mmr); ! 825: return; ! 826: } ! 827: ! 828: // get the capabilities of the selected joystick ! 829: // abort startup if command fails ! 830: memset (&jc, 0, sizeof(jc)); ! 831: if ((mmr = joyGetDevCaps (joy_id, &jc, sizeof(jc))) != JOYERR_NOERROR) ! 832: { ! 833: Con_Printf ("\njoystick not found -- invalid joystick capabilities (%x)\n\n", mmr); ! 834: return; ! 835: } ! 836: ! 837: // save the joystick's number of buttons and POV status ! 838: joy_numbuttons = jc.wNumButtons; ! 839: joy_haspov = jc.wCaps & JOYCAPS_HASPOV; ! 840: ! 841: // old button and POV states default to no buttons pressed ! 842: joy_oldbuttonstate = joy_oldpovstate = 0; ! 843: ! 844: // mark the joystick as available and advanced initialization not completed ! 845: // this is needed as cvars are not available during initialization ! 846: ! 847: joy_avail = true; ! 848: joy_advancedinit = false; ! 849: ! 850: Con_Printf ("\njoystick detected\n\n"); ! 851: } ! 852: ! 853: ! 854: /* ! 855: =========== ! 856: RawValuePointer ! 857: =========== ! 858: */ ! 859: PDWORD RawValuePointer (int axis) ! 860: { ! 861: switch (axis) ! 862: { ! 863: case JOY_AXIS_X: ! 864: return &ji.dwXpos; ! 865: case JOY_AXIS_Y: ! 866: return &ji.dwYpos; ! 867: case JOY_AXIS_Z: ! 868: return &ji.dwZpos; ! 869: case JOY_AXIS_R: ! 870: return &ji.dwRpos; ! 871: case JOY_AXIS_U: ! 872: return &ji.dwUpos; ! 873: case JOY_AXIS_V: ! 874: return &ji.dwVpos; ! 875: } ! 876: } ! 877: ! 878: ! 879: /* ! 880: =========== ! 881: Joy_AdvancedUpdate_f ! 882: =========== ! 883: */ ! 884: void Joy_AdvancedUpdate_f (void) ! 885: { ! 886: ! 887: // called once by IN_ReadJoystick and by user whenever an update is needed ! 888: // cvars are now available ! 889: int i; ! 890: DWORD dwTemp; ! 891: ! 892: // initialize all the maps ! 893: for (i = 0; i < JOY_MAX_AXES; i++) ! 894: { ! 895: dwAxisMap[i] = AxisNada; ! 896: dwControlMap[i] = JOY_ABSOLUTE_AXIS; ! 897: pdwRawValue[i] = RawValuePointer(i); ! 898: } ! 899: ! 900: if( joy_advanced.value == 0.0) ! 901: { ! 902: // default joystick initialization ! 903: // 2 axes only with joystick control ! 904: dwAxisMap[JOY_AXIS_X] = AxisTurn; ! 905: // dwControlMap[JOY_AXIS_X] = JOY_ABSOLUTE_AXIS; ! 906: dwAxisMap[JOY_AXIS_Y] = AxisForward; ! 907: // dwControlMap[JOY_AXIS_Y] = JOY_ABSOLUTE_AXIS; ! 908: } ! 909: else ! 910: { ! 911: if (Q_strcmp (joy_name.string, "joystick") != 0) ! 912: { ! 913: // notify user of advanced controller ! 914: Con_Printf ("\n%s configured\n\n", joy_name.string); ! 915: } ! 916: ! 917: // advanced initialization here ! 918: // data supplied by user via joy_axisn cvars ! 919: dwTemp = (DWORD) joy_advaxisx.value; ! 920: dwAxisMap[JOY_AXIS_X] = dwTemp & 0x0000000f; ! 921: dwControlMap[JOY_AXIS_X] = dwTemp & JOY_RELATIVE_AXIS; ! 922: dwTemp = (DWORD) joy_advaxisy.value; ! 923: dwAxisMap[JOY_AXIS_Y] = dwTemp & 0x0000000f; ! 924: dwControlMap[JOY_AXIS_Y] = dwTemp & JOY_RELATIVE_AXIS; ! 925: dwTemp = (DWORD) joy_advaxisz.value; ! 926: dwAxisMap[JOY_AXIS_Z] = dwTemp & 0x0000000f; ! 927: dwControlMap[JOY_AXIS_Z] = dwTemp & JOY_RELATIVE_AXIS; ! 928: dwTemp = (DWORD) joy_advaxisr.value; ! 929: dwAxisMap[JOY_AXIS_R] = dwTemp & 0x0000000f; ! 930: dwControlMap[JOY_AXIS_R] = dwTemp & JOY_RELATIVE_AXIS; ! 931: dwTemp = (DWORD) joy_advaxisu.value; ! 932: dwAxisMap[JOY_AXIS_U] = dwTemp & 0x0000000f; ! 933: dwControlMap[JOY_AXIS_U] = dwTemp & JOY_RELATIVE_AXIS; ! 934: dwTemp = (DWORD) joy_advaxisv.value; ! 935: dwAxisMap[JOY_AXIS_V] = dwTemp & 0x0000000f; ! 936: dwControlMap[JOY_AXIS_V] = dwTemp & JOY_RELATIVE_AXIS; ! 937: } ! 938: ! 939: // compute the axes to collect from DirectInput ! 940: joy_flags = JOY_RETURNCENTERED | JOY_RETURNBUTTONS | JOY_RETURNPOV; ! 941: for (i = 0; i < JOY_MAX_AXES; i++) ! 942: { ! 943: if (dwAxisMap[i] != AxisNada) ! 944: { ! 945: joy_flags |= dwAxisFlags[i]; ! 946: } ! 947: } ! 948: } ! 949: ! 950: ! 951: /* ! 952: =========== ! 953: IN_Commands ! 954: =========== ! 955: */ ! 956: void IN_Commands (void) ! 957: { ! 958: int i, key_index; ! 959: DWORD buttonstate, povstate; ! 960: ! 961: if (!joy_avail) ! 962: { ! 963: return; ! 964: } ! 965: ! 966: ! 967: // loop through the joystick buttons ! 968: // key a joystick event or auxillary event for higher number buttons for each state change ! 969: buttonstate = ji.dwButtons; ! 970: for (i=0 ; i < joy_numbuttons ; i++) ! 971: { ! 972: if ( (buttonstate & (1<<i)) && !(joy_oldbuttonstate & (1<<i)) ) ! 973: { ! 974: key_index = (i < 4) ? K_JOY1 : K_AUX1; ! 975: Key_Event (key_index + i, true); ! 976: } ! 977: ! 978: if ( !(buttonstate & (1<<i)) && (joy_oldbuttonstate & (1<<i)) ) ! 979: { ! 980: key_index = (i < 4) ? K_JOY1 : K_AUX1; ! 981: Key_Event (key_index + i, false); ! 982: } ! 983: } ! 984: joy_oldbuttonstate = buttonstate; ! 985: ! 986: if (joy_haspov) ! 987: { ! 988: // convert POV information into 4 bits of state information ! 989: // this avoids any potential problems related to moving from one ! 990: // direction to another without going through the center position ! 991: povstate = 0; ! 992: if(ji.dwPOV != JOY_POVCENTERED) ! 993: { ! 994: if (ji.dwPOV == JOY_POVFORWARD) ! 995: povstate |= 0x01; ! 996: if (ji.dwPOV == JOY_POVRIGHT) ! 997: povstate |= 0x02; ! 998: if (ji.dwPOV == JOY_POVBACKWARD) ! 999: povstate |= 0x04; ! 1000: if (ji.dwPOV == JOY_POVLEFT) ! 1001: povstate |= 0x08; ! 1002: } ! 1003: // determine which bits have changed and key an auxillary event for each change ! 1004: for (i=0 ; i < 4 ; i++) ! 1005: { ! 1006: if ( (povstate & (1<<i)) && !(joy_oldpovstate & (1<<i)) ) ! 1007: { ! 1008: Key_Event (K_AUX29 + i, true); ! 1009: } ! 1010: ! 1011: if ( !(povstate & (1<<i)) && (joy_oldpovstate & (1<<i)) ) ! 1012: { ! 1013: Key_Event (K_AUX29 + i, false); ! 1014: } ! 1015: } ! 1016: joy_oldpovstate = povstate; ! 1017: } ! 1018: } ! 1019: ! 1020: ! 1021: /* ! 1022: =============== ! 1023: IN_ReadJoystick ! 1024: =============== ! 1025: */ ! 1026: qboolean IN_ReadJoystick (void) ! 1027: { ! 1028: ! 1029: memset (&ji, 0, sizeof(ji)); ! 1030: ji.dwSize = sizeof(ji); ! 1031: ji.dwFlags = joy_flags; ! 1032: ! 1033: if (joyGetPosEx (joy_id, &ji) == JOYERR_NOERROR) ! 1034: { ! 1035: // this is a hack -- there is a bug in the Logitech WingMan Warrior DirectInput Driver ! 1036: // rather than having 32768 be the zero point, they have the zero point at 32668 ! 1037: // go figure -- anyway, now we get the full resolution out of the device ! 1038: if (joy_wwhack1.value != 0.0) ! 1039: { ! 1040: ji.dwUpos += 100; ! 1041: } ! 1042: return true; ! 1043: } ! 1044: else ! 1045: { ! 1046: // read error occurred ! 1047: // turning off the joystick seems too harsh for 1 read error,\ ! 1048: // but what should be done? ! 1049: // Con_Printf ("IN_ReadJoystick: no response\n"); ! 1050: // joy_avail = false; ! 1051: return false; ! 1052: } ! 1053: } ! 1054: ! 1055: ! 1056: /* ! 1057: =========== ! 1058: IN_JoyMove ! 1059: =========== ! 1060: */ ! 1061: void IN_JoyMove (usercmd_t *cmd) ! 1062: { ! 1063: float speed, aspeed; ! 1064: float fAxisValue, fTemp; ! 1065: int i; ! 1066: ! 1067: // complete initialization if first time in ! 1068: // this is needed as cvars are not available at initialization time ! 1069: if( joy_advancedinit != true ) ! 1070: { ! 1071: Joy_AdvancedUpdate_f(); ! 1072: joy_advancedinit = true; ! 1073: } ! 1074: ! 1075: // verify joystick is available and that the user wants to use it ! 1076: if (!joy_avail || !in_joystick.value) ! 1077: { ! 1078: return; ! 1079: } ! 1080: ! 1081: // collect the joystick data, if possible ! 1082: if (IN_ReadJoystick () != true) ! 1083: { ! 1084: return; ! 1085: } ! 1086: ! 1087: if (in_speed.state & 1) ! 1088: speed = cl_movespeedkey.value; ! 1089: else ! 1090: speed = 1; ! 1091: aspeed = speed * host_frametime; ! 1092: ! 1093: // loop through the axes ! 1094: for (i = 0; i < JOY_MAX_AXES; i++) ! 1095: { ! 1096: // get the floating point zero-centered, potentially-inverted data for the current axis ! 1097: fAxisValue = (float) *pdwRawValue[i]; ! 1098: // move centerpoint to zero ! 1099: fAxisValue -= 32768.0; ! 1100: ! 1101: if (joy_wwhack2.value != 0.0) ! 1102: { ! 1103: if (dwAxisMap[i] == AxisTurn) ! 1104: { ! 1105: // this is a special formula for the Logitech WingMan Warrior ! 1106: // y=ax^b; where a = 300 and b = 1.3 ! 1107: // also x values are in increments of 800 (so this is factored out) ! 1108: // then bounds check result to level out excessively high spin rates ! 1109: fTemp = 300.0 * pow(abs(fAxisValue) / 800.0, 1.3); ! 1110: if (fTemp > 14000.0) ! 1111: fTemp = 14000.0; ! 1112: // restore direction information ! 1113: fAxisValue = (fAxisValue > 0.0) ? fTemp : -fTemp; ! 1114: } ! 1115: } ! 1116: ! 1117: // convert range from -32768..32767 to -1..1 ! 1118: fAxisValue /= 32768.0; ! 1119: ! 1120: switch (dwAxisMap[i]) ! 1121: { ! 1122: case AxisForward: ! 1123: if ((joy_advanced.value == 0.0) && (in_mlook.state & 1)) ! 1124: { ! 1125: // user wants forward control to become look control ! 1126: if (fabs(fAxisValue) > joy_pitchthreshold.value) ! 1127: { ! 1128: // if mouse invert is on, invert the joystick pitch value ! 1129: // only absolute control support here (joy_advanced is false) ! 1130: if (m_pitch.value < 0.0) ! 1131: { ! 1132: cl.viewangles[PITCH] -= (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value; ! 1133: } ! 1134: else ! 1135: { ! 1136: cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value; ! 1137: } ! 1138: V_StopPitchDrift(); ! 1139: } ! 1140: else ! 1141: { ! 1142: // no pitch movement ! 1143: // disable pitch return-to-center unless requested by user ! 1144: // *** this code can be removed when the lookspring bug is fixed ! 1145: // *** the bug always has the lookspring feature on ! 1146: if(lookspring.value == 0.0) ! 1147: V_StopPitchDrift(); ! 1148: } ! 1149: } ! 1150: else ! 1151: { ! 1152: // user wants forward control to be forward control ! 1153: if (fabs(fAxisValue) > joy_forwardthreshold.value) ! 1154: { ! 1155: cmd->forwardmove += (fAxisValue * joy_forwardsensitivity.value) * speed * cl_forwardspeed.value; ! 1156: } ! 1157: } ! 1158: break; ! 1159: ! 1160: case AxisSide: ! 1161: if (fabs(fAxisValue) > joy_sidethreshold.value) ! 1162: { ! 1163: cmd->sidemove += (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value; ! 1164: } ! 1165: break; ! 1166: ! 1167: case AxisTurn: ! 1168: if ((in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1))) ! 1169: { ! 1170: // user wants turn control to become side control ! 1171: if (fabs(fAxisValue) > joy_sidethreshold.value) ! 1172: { ! 1173: cmd->sidemove -= (fAxisValue * joy_sidesensitivity.value) * speed * cl_sidespeed.value; ! 1174: } ! 1175: } ! 1176: else ! 1177: { ! 1178: // user wants turn control to be turn control ! 1179: if (fabs(fAxisValue) > joy_yawthreshold.value) ! 1180: { ! 1181: if(dwControlMap[i] == JOY_ABSOLUTE_AXIS) ! 1182: { ! 1183: cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity.value) * aspeed * cl_yawspeed.value; ! 1184: } ! 1185: else ! 1186: { ! 1187: cl.viewangles[YAW] += (fAxisValue * joy_yawsensitivity.value) * speed * 180.0; ! 1188: } ! 1189: ! 1190: } ! 1191: } ! 1192: break; ! 1193: ! 1194: case AxisLook: ! 1195: if (in_mlook.state & 1) ! 1196: { ! 1197: if (fabs(fAxisValue) > joy_pitchthreshold.value) ! 1198: { ! 1199: // pitch movement detected and pitch movement desired by user ! 1200: if(dwControlMap[i] == JOY_ABSOLUTE_AXIS) ! 1201: { ! 1202: cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * aspeed * cl_pitchspeed.value; ! 1203: } ! 1204: else ! 1205: { ! 1206: cl.viewangles[PITCH] += (fAxisValue * joy_pitchsensitivity.value) * speed * 180.0; ! 1207: } ! 1208: V_StopPitchDrift(); ! 1209: } ! 1210: else ! 1211: { ! 1212: // no pitch movement ! 1213: // disable pitch return-to-center unless requested by user ! 1214: // *** this code can be removed when the lookspring bug is fixed ! 1215: // *** the bug always has the lookspring feature on ! 1216: if(lookspring.value == 0.0) ! 1217: V_StopPitchDrift(); ! 1218: } ! 1219: } ! 1220: break; ! 1221: ! 1222: default: ! 1223: break; ! 1224: } ! 1225: } ! 1226: ! 1227: // bounds check pitch ! 1228: if (cl.viewangles[PITCH] > 80.0) ! 1229: cl.viewangles[PITCH] = 80.0; ! 1230: if (cl.viewangles[PITCH] < -70.0) ! 1231: cl.viewangles[PITCH] = -70.0; ! 1232: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.