Annotation of quakeworld/client/in_win.c, revision 1.1.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.