Annotation of quakeworld/client/in_win.c, revision 1.1

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 (&current_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 (&current_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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.