Game Accessibility Library logo SourceForge.net Logo
Game Accessibility Suite: GASPilot/GASProtoMapper.cpp Source File

GASProtoMapper.cpp

Go to the documentation of this file.
00001 /// \file    GASProtoMapper.cpp
00002 /// \brief   Maps inputs from a controller to various outputs
00003 /// \ingroup CAT
00004 ///
00005 /// Copyright (c) 2008 by Michael Ellison.
00006 /// See COPYING.txt for the \ref gaslicense License (MIT License).
00007 ///
00008 // $Author: mikeellison $
00009 // $Date: 2008-02-01 03:19:21 -0600 (Fri, 01 Feb 2008) $
00010 // $Revision:   $
00011 // $NoKeywords: $
00012 
00013 #include "GASProtoMapper.h"
00014 #include "CATDirectInput.h"
00015 #include "CATDIJoystick.h"
00016 
00017 GASProtoMapper::GASProtoMapper()
00018 {
00019     fDirectInput = 0;
00020     fController  = 0;
00021     fMap         = 0;
00022     fPollFreq    = 50;
00023     fValidAxis   = 0;
00024     fFilterXLow  = 0;
00025     fFilterXHigh = 0;
00026     fFilterZLow  = 0;
00027     fFilterZHigh = 0;
00028     fFilterXRotLow = 0;
00029     fFilterXRotHigh = 0;
00030     fFilterYRotLow = 0;
00031     fFilterYRotHigh = 0;
00032     fCToggle = false;
00033     fLSToggle = false;
00034     fLCToggle = false;
00035     fWPovKeyDown = false;
00036     fSPovKeyDown = false;
00037     fWKeyDown = false;
00038     fSKeyDown = false;
00039     fAKeyDown = false;
00040     fDKeyDown = false;
00041     fSpeedToggle = false;
00042     fInitialized = false;
00043 }
00044 
00045 GASProtoMapper::~GASProtoMapper()
00046 {
00047     if (fInitialized)
00048         (void)Uninitialize();
00049 }
00050 
00051 CATResult GASProtoMapper::Initialize()
00052 {
00053     if (fInitialized)
00054         return CAT_SUCCESS;
00055     
00056     CATResult result;
00057 
00058     fDirectInput = new CATDirectInput();
00059     result = fDirectInput->Init();
00060     if (CATFAILED(result))
00061         Uninitialize();
00062     else
00063         fInitialized = true;
00064 
00065     return result;
00066 }
00067 
00068 CATResult GASProtoMapper::Uninitialize()
00069 {
00070     StopMapping();
00071 
00072     if (fDirectInput)
00073     {
00074         delete fDirectInput;
00075         fDirectInput = 0;
00076     }
00077     if (fFilterXLow)
00078     {
00079         delete fFilterXLow;
00080         fFilterXLow = 0;
00081     }
00082     if (fFilterXHigh)
00083     {
00084         delete fFilterXHigh;
00085         fFilterXHigh = 0;
00086     }
00087     if (fFilterZLow)
00088     {
00089         delete fFilterZLow;
00090         fFilterZLow = 0;
00091     }
00092     if (fFilterZHigh)
00093     {
00094         delete fFilterZHigh;
00095         fFilterZHigh = 0;
00096     }
00097     if (fFilterXRotLow)
00098     {
00099         delete fFilterXRotLow;
00100         fFilterXRotLow = 0;
00101     }
00102     if (fFilterXRotHigh)
00103     {
00104         delete fFilterXRotHigh;
00105         fFilterXRotHigh = 0;
00106     }
00107     if (fFilterYRotLow)
00108     {
00109         delete fFilterYRotLow;
00110         fFilterYRotLow = 0;
00111     }
00112     if (fFilterYRotHigh)
00113     {
00114         delete fFilterYRotHigh;
00115         fFilterYRotHigh = 0;
00116     }
00117 
00118     fInitialized = false;
00119     return CAT_SUCCESS;
00120 }
00121 
00122 
00123 void JoystickListCB(const CATWChar* name, void* userParam)
00124 {
00125     std::vector<CATString>* joystickList = (std::vector<CATString>*)userParam;
00126     joystickList->push_back(name);
00127 }
00128 
00129 
00130 CATResult GASProtoMapper::GetControllerList( std::vector<CATString>& controllerList )
00131 {
00132     if (!fInitialized)
00133         return CATRESULT(CAT_ERR_NOT_INITIALIZED);
00134 
00135     fDirectInput->EnumJoysticks(JoystickListCB,&controllerList);    
00136     
00137     return CAT_SUCCESS;
00138 }
00139 
00140 CATResult GASProtoMapper::GetMappingList(    const CATString&        controllerName,
00141                                              std::vector<CATString>& mappingList)
00142 {
00143     return CAT_SUCCESS;
00144 }
00145 
00146 CATResult GASProtoMapper::StartMapping(      const CATString&        controllerName,
00147                                              const CATString&        mappingName)
00148 {
00149     fController = fDirectInput->CreateJoystick(controllerName);    
00150     
00151     if (!fController)
00152         return CAT_ERROR;
00153 
00154     fValidAxis = fController->GetValidAxis();
00155 
00156     fController->GetStatus(fLastStatus);
00157     fMap = new CATControlMap();
00158 
00159     if (fFilterXLow)
00160         fFilterXLow->Reset();
00161     else
00162         fFilterXLow = new CATFilterAttackDecay(0.99f,0.1f);
00163 
00164     if (fFilterXHigh)
00165         fFilterXHigh->Reset();
00166     else
00167         fFilterXHigh = new CATFilterAttackDecay(0.99f,0.1f);
00168 
00169     if (fFilterZLow)
00170         fFilterZLow->Reset();
00171     else
00172         fFilterZLow = new CATFilterAttackDecay(0.99f,0.01f);
00173 
00174     if (fFilterZHigh)
00175         fFilterZHigh->Reset();
00176     else
00177         fFilterZHigh = new CATFilterAttackDecay(0.99f,0.01f);
00178 
00179     if (fFilterXRotLow)
00180         fFilterXRotLow->Reset();
00181     else
00182         fFilterXRotLow = new CATFilterAttackDecay(0.99f,0.01f);
00183 
00184     if (fFilterXRotHigh)
00185         fFilterXRotHigh->Reset();
00186     else
00187         fFilterXRotHigh = new CATFilterAttackDecay(0.99f,0.01f);
00188 
00189     if (fFilterYRotLow)
00190         fFilterYRotLow->Reset();
00191     else
00192         fFilterYRotLow = new CATFilterAttackDecay(0.99f,0.01f);
00193 
00194     if (fFilterYRotHigh)
00195         fFilterYRotHigh->Reset();
00196     else
00197         fFilterYRotHigh = new CATFilterAttackDecay(0.99f,0.01f);
00198 
00199     this->Start(fPollFreq);
00200 
00201     return CAT_SUCCESS;
00202 }
00203 
00204 CATResult GASProtoMapper::StopMapping()
00205 {
00206     this->Stop();
00207 
00208     if (fController)
00209     {
00210         delete fController;
00211         fController = 0;
00212     }
00213 
00214     if (fMap)
00215     {
00216         delete fMap;
00217         fMap = 0;
00218     }
00219     return CAT_SUCCESS;
00220 }
00221 
00222 
00223 void GASProtoMapper::OnThreadIdle()
00224 {
00225     if (fController)
00226     {
00227         CATJOYSTICKSTRUCT status;
00228 
00229         if (fController->GetStatus(status))
00230         {
00231             for (CATUInt32 i = 0; i < kCATJOYSTICKBTNMAX; i++)
00232             {
00233                 if ((status.buttonMap & (1 << i)) != (fLastStatus.buttonMap & (1 << i)))    
00234                 {
00235                     OnButtonChange( 0 != (status.buttonMap & (1 << i)), i);
00236                 }
00237             }
00238 
00239             // Oh yeah... for mice, axis doesn't need to change for us
00240             // to update position. doh. Just call direct.
00241             OnAxis(status.xHigh,    CATJoystick::X_AXIS_HIGH);
00242             OnAxis(status.xLow,     CATJoystick::X_AXIS_LOW);
00243             OnAxis(status.xRot,     CATJoystick::X_ROT);
00244             OnAxis(status.xRotLow,  CATJoystick::X_ROT_LOW);
00245             OnAxis(status.xRotHigh, CATJoystick::X_ROT_HIGH);
00246             OnAxis(status.yAxis,    CATJoystick::Y_AXIS);
00247             OnAxis(status.yRot,     CATJoystick::Y_ROT);
00248             OnAxis(status.yRotLow,  CATJoystick::Y_ROT_LOW);
00249             OnAxis(status.yRotHigh, CATJoystick::Y_ROT_HIGH);
00250             OnAxis(status.zAxis,    CATJoystick::Z_AXIS);
00251             OnAxis(status.zHigh,    CATJoystick::Z_AXIS_HIGH);
00252             OnAxis(status.zLow,     CATJoystick::Z_AXIS_LOW);
00253             OnAxis(status.zRot,     CATJoystick::Z_ROT);
00254             OnAxis(status.zRotLow,  CATJoystick::Z_ROT_LOW);
00255             OnAxis(status.zRotHigh, CATJoystick::Z_ROT_HIGH);
00256             OnAxis(status.xPov,     CATJoystick::X_POV);
00257             OnAxis(status.yPov,     CATJoystick::Y_POV);
00258 
00259             fLastStatus = status;           
00260 /*
00261             CATString dbg;
00262             dbg.Format(L"x:%03d y:%03d z:%03d rx:%03d ry:%03d rz:%03d\n",
00263                 status.xAxis, status.yAxis, status.zAxis, 
00264                 status.xRot,  status.yRot,  status.zRot);
00265             ::OutputDebugString(dbg);
00266 */
00267         
00268         }
00269 
00270     }
00271 }
00272 
00273 CATUInt32 GASProtoMapper::OnThreadMessage(CATUInt32 msg, CATUInt32 wParam, CATUInt32 lParam)
00274 {
00275     return 0;
00276 }
00277 
00278 void GASProtoMapper::OnAxis(CATInt32 val, CATJoystick::AXIS_TYPE axisType)
00279 {
00280     // Abstracting this the second I get a controller fully mapped out. seriously.
00281     CATInt32 xChange, yChange, wChange;
00282     xChange = yChange = wChange = 0;
00283 
00284     CATFloat32 sensitivity = 1.0f;
00285     CATInt32   xThresh     = 14;
00286     CATInt32   yThresh     = 14;
00287 
00288     switch (axisType)
00289     {
00290         case CATJoystick::X_AXIS_LOW:
00291             {
00292                 if (abs(val) < xThresh)
00293                     val = 0;
00294 
00295                 xChange = -fFilterXLow->Filter(val)* sensitivity;
00296                 mouse_event(MOUSEEVENTF_MOVE, xChange, 0, 0, 0);                
00297             }
00298             break;
00299         case CATJoystick::X_AXIS_HIGH:                
00300             {
00301                 if (abs(val) < xThresh)
00302                     val = 0;
00303 
00304                 xChange = fFilterXHigh->Filter(val)* sensitivity;
00305                 mouse_event(MOUSEEVENTF_MOVE, xChange, 0, 0, 0);                
00306             }
00307             break;
00308 
00309         case CATJoystick::Y_POV:
00310             {
00311                 if (val > 50+yThresh)
00312                 {
00313                     if (!fSPovKeyDown)
00314                     {
00315                         fSPovKeyDown = true;
00316                         PushChar(DIKEYBOARD_S,true);
00317                     }
00318                     
00319                     if (fWPovKeyDown)
00320                     {
00321                         fWPovKeyDown = false;
00322                         PushChar(DIKEYBOARD_W,false);
00323                         // send W up
00324                     }
00325                 }
00326                 else if (val < 50-yThresh)
00327                 {
00328                     if (!fWPovKeyDown)
00329                     {
00330                         fWPovKeyDown = true;                        
00331                         PushChar(DIKEYBOARD_W,true);
00332                     }
00333                     
00334                     if (fSPovKeyDown)
00335                     {
00336                         fSPovKeyDown = false;
00337                         PushChar(DIKEYBOARD_S,false);
00338                         // send S up
00339                     }
00340                 }
00341                 else
00342                 {
00343                     if (fSPovKeyDown)
00344                     {
00345                         fSPovKeyDown = false;
00346                         PushChar(DIKEYBOARD_S,false);
00347                         // S up
00348                     }
00349                     if (fWPovKeyDown)
00350                     {
00351                         fWPovKeyDown = false;
00352                         PushChar(DIKEYBOARD_W,false);
00353                         // W up
00354                     }
00355                 }
00356             }
00357             break;
00358 
00359         case CATJoystick::Y_AXIS:
00360             {
00361                 if (val > 50+yThresh)
00362                 {
00363                     if (!fSKeyDown)
00364                     {
00365                         fSKeyDown = true;
00366                         PushChar(DIKEYBOARD_S,true);
00367                     }
00368                     
00369                     if (fWKeyDown)
00370                     {
00371                         fWKeyDown = false;
00372                         PushChar(DIKEYBOARD_W,false);
00373                         // send W up
00374                     }
00375                 }
00376                 else if (val < 50-yThresh)
00377                 {
00378                     if (!fWKeyDown)
00379                     {
00380                         fWKeyDown = true;                        
00381                         PushChar(DIKEYBOARD_W,true);
00382                     }
00383                     
00384                     if (fSKeyDown)
00385                     {
00386                         fSKeyDown = false;
00387                         PushChar(DIKEYBOARD_S,false);
00388                         // send S up
00389                     }
00390                 }
00391                 else
00392                 {
00393                     if (fSKeyDown)
00394                     {
00395                         fSKeyDown = false;
00396                         PushChar(DIKEYBOARD_S,false);
00397                         // S up
00398                     }
00399                     if (fWKeyDown)
00400                     {
00401                         fWKeyDown = false;
00402                         PushChar(DIKEYBOARD_W,false);
00403                         // W up
00404                     }
00405                 }
00406             }
00407             break;
00408         case CATJoystick::X_POV:
00409             {
00410                 if (val > 50+xThresh)
00411                 {
00412                     if (!fAKeyDown)
00413                     {
00414                         fAKeyDown = true;
00415                         PushChar(DIKEYBOARD_A,true);
00416                     }
00417                     
00418                     if (fDKeyDown)
00419                     {
00420                         fDKeyDown = false;
00421                         PushChar(DIKEYBOARD_D,false);                                                
00422                     }
00423                 }
00424                 else if (val < 50-xThresh)
00425                 {
00426                     if (!fDKeyDown)
00427                     {
00428                         fDKeyDown = true;                        
00429                         PushChar(DIKEYBOARD_D,true);
00430                     }
00431                     
00432                     if (fAKeyDown)
00433                     {
00434                         fAKeyDown = false;
00435                         PushChar(DIKEYBOARD_A,false);                        
00436                     }
00437                 }
00438                 else
00439                 {
00440                     if (fAKeyDown)
00441                     {
00442                         fAKeyDown = false;
00443                         PushChar(DIKEYBOARD_A,false);
00444                     }
00445                     if (fDKeyDown)
00446                     {
00447                         fDKeyDown = false;
00448                         PushChar(DIKEYBOARD_D,false);                        
00449                     }
00450                 }
00451             }
00452             break;
00453 
00454 
00455         case CATJoystick::Z_AXIS_LOW:
00456             {
00457                 if (abs(val) < yThresh)
00458                     val = 0;
00459 
00460                 yChange = -fFilterZLow->Filter(val)* sensitivity;
00461                 mouse_event(MOUSEEVENTF_MOVE, 0, yChange, 0, 0);
00462             }
00463             break;
00464         case CATJoystick::Z_AXIS_HIGH:
00465             {
00466                 if (abs(val) < yThresh)
00467                     val = 0;
00468                 yChange = fFilterZHigh->Filter(val)* sensitivity;
00469                 mouse_event(MOUSEEVENTF_MOVE, 0, yChange, 0, 0);
00470             }
00471             break;
00472 
00473 
00474         case CATJoystick::X_ROT_LOW:
00475             {
00476                 if (abs(val) < xThresh)
00477                     val = 0;
00478 
00479                 xChange = -fFilterXRotLow->Filter(val)* sensitivity;
00480                 mouse_event(MOUSEEVENTF_MOVE, xChange, 0, 0, 0);                
00481             }
00482             break;
00483         case CATJoystick::X_ROT_HIGH:                
00484             {
00485                 if (abs(val) < xThresh)
00486                     val = 0;
00487 
00488                 xChange = fFilterXRotHigh->Filter(val)* sensitivity;
00489                 mouse_event(MOUSEEVENTF_MOVE, xChange, 0, 0, 0);                
00490             }
00491             break;
00492         case CATJoystick::Y_ROT_LOW:
00493             {
00494                 if (abs(val) < yThresh)
00495                     val = 0;
00496 
00497                 yChange = -fFilterYRotLow->Filter(val)* sensitivity;
00498                 mouse_event(MOUSEEVENTF_MOVE, 0, yChange, 0, 0);
00499             }
00500             break;
00501         case CATJoystick::Y_ROT_HIGH:
00502             {
00503                 if (abs(val) < yThresh)
00504                     val = 0;
00505                 yChange = fFilterYRotHigh->Filter(val)* sensitivity;
00506                 mouse_event(MOUSEEVENTF_MOVE, 0, yChange, 0, 0);
00507             }
00508             break;
00509     }
00510 
00511 }
00512 
00513 
00514 void GASProtoMapper::OnButtonChange(bool state, CATUInt32 button)
00515 {       
00516     enum QUADCONTROL_BUTTONS
00517     {
00518         QC_LOWERLEFT  = 0,
00519         QC_CENTERSIP  = 1,
00520         QC_CENTERPUFF = 2,
00521         QC_UPPERLEFT  = 3,
00522         QC_LEFTPUFF   = 4,
00523         QC_RIGHTPUFF  = 5,
00524         QC_STARTSIP   = 6,
00525         QC_STARTPUFF  = 7,
00526         QC_LEFTSIP    = 8,
00527         QC_RIGHTSIP   = 9,
00528         QC_UPPERRIGHT = 10, // ? unused ?
00529         
00530         //
00531         QC_X = 0x7fffffff
00532     };
00533 
00534     CATString dbg;
00535     dbg.Format(L"Button: %d state: %d\n",button,state?1:0);
00536     ::OutputDebugString(dbg);
00537     switch (button)
00538     {
00539         case QC_LOWERLEFT:
00540             if (state)
00541             {
00542                 if (fSpeedToggle)
00543                     PushChar(DIKEYBOARD_F13,true);
00544                 else
00545                     PushChar(DIKEYBOARD_F14,true);
00546             }
00547             else
00548             {
00549                 if (fSpeedToggle)
00550                     PushChar(DIKEYBOARD_F13,false);
00551                 else
00552                     PushChar(DIKEYBOARD_F14,false);
00553 
00554                 fSpeedToggle ^= 1;
00555             }
00556             break;
00557         case QC_CENTERSIP:
00558             if (state)
00559             {
00560                 mouse_event( MOUSEEVENTF_RIGHTDOWN,0,0,0,0);
00561             }
00562             else
00563             {
00564                 mouse_event( MOUSEEVENTF_RIGHTUP,0,0,0,0);
00565             }
00566             break;
00567         case QC_CENTERPUFF:
00568             if (state)
00569             {
00570                 mouse_event( MOUSEEVENTF_LEFTDOWN,0,0,0,0);
00571             }
00572             else
00573             {
00574                 mouse_event( MOUSEEVENTF_LEFTUP,0,0,0,0);
00575             }
00576 
00577             break;
00578         case QC_UPPERLEFT:
00579             PushChar(DIKEYBOARD_F,state);
00580             break;
00581         case QC_LEFTPUFF:
00582             if (state)
00583             {
00584                 if (fCToggle)
00585                 {
00586                     PushChar(DIKEYBOARD_C,true);
00587                 }
00588                 else
00589                 {
00590                     PushChar(DIKEYBOARD_C,false);
00591                 }
00592                 fCToggle ^= 1;
00593             }
00594             PushChar(DIKEYBOARD_R,state);
00595             break;
00596         case QC_RIGHTPUFF:
00597             if (state)
00598             {
00599                 if (fLSToggle)
00600                 {
00601                     PushChar(DIKEYBOARD_LSHIFT,true);
00602                 }
00603                 else
00604                 {
00605                     PushChar(DIKEYBOARD_LSHIFT,false);                    
00606                 }
00607                 fLSToggle ^= 1;
00608             }
00609             break;
00610         case QC_STARTSIP:
00611             // Reset all currently down keys on escape...
00612             PushChar(DIKEYBOARD_ESCAPE,state);
00613             {
00614                 if (fWKeyDown || fWPovKeyDown)
00615                 {
00616                     PushChar(DIKEYBOARD_W,false);
00617                     fWKeyDown = false;
00618                     fWPovKeyDown = false;
00619                 }
00620                 if (fSKeyDown || fSKeyDown)
00621                 {
00622                     PushChar(DIKEYBOARD_S,false);
00623                     fSKeyDown = false;
00624                     fSPovKeyDown = false;
00625                 }
00626                 if (fAKeyDown)
00627                 {
00628                     PushChar(DIKEYBOARD_A,false);
00629                     fAKeyDown = false;
00630                 }
00631                 if (fDKeyDown)
00632                 {
00633                     PushChar(DIKEYBOARD_D,false);
00634                     fDKeyDown = false;
00635                 }
00636                 if (fSpeedToggle)
00637                 {
00638                     PushChar(DIKEYBOARD_F14,true);
00639                     PushChar(DIKEYBOARD_F14,false);
00640                     fSpeedToggle = false;
00641                 }
00642                 if (fCToggle)
00643                 {
00644                     PushChar(DIKEYBOARD_C,false);
00645                     fCToggle = false;
00646                 }
00647                 if (fLSToggle)
00648                 {
00649                     PushChar(DIKEYBOARD_LSHIFT,false);
00650                     fLSToggle = false;
00651                 }
00652                 if (fLCToggle)
00653                 {
00654                     PushChar(DIKEYBOARD_LCONTROL,false);
00655                     fLCToggle = false;
00656                 }
00657             }
00658             
00659             break;
00660         case QC_STARTPUFF:
00661             PushChar(DIKEYBOARD_TAB,state);
00662             Sleep(100);
00663             PushChar(DIKEYBOARD_E,state);
00664             break;
00665         case QC_LEFTSIP:            
00666             if (state)
00667             {
00668                 mouse_event(MOUSEEVENTF_WHEEL | MOUSEEVENTF_ABSOLUTE, 0,0, WHEEL_DELTA, 0);
00669             }            
00670             break;
00671         case QC_RIGHTSIP:
00672             if (state)
00673             {
00674                 if (fLCToggle)
00675                 {
00676                     PushChar(DIKEYBOARD_LCONTROL,true);
00677                 }
00678                 else
00679                 {
00680                     PushChar(DIKEYBOARD_LCONTROL,false);                    
00681                 }
00682                 fLCToggle ^= 1;
00683             }            
00684             break;
00685     }       
00686 }
00687 
00688 void GASProtoMapper::PushChar(CATUInt32 scanCode, bool keydown)
00689 {
00690     INPUT input;
00691     input.type = INPUT_KEYBOARD;
00692     input.ki.dwExtraInfo = 0;
00693     input.ki.dwFlags = KEYEVENTF_SCANCODE | (keydown ? 0 : KEYEVENTF_KEYUP);
00694     input.ki.wScan = scanCode;
00695     input.ki.wVk = 0;
00696     input.ki.time = 0;
00697     SendInput(1,&input,sizeof(INPUT));
00698 }

Generated on Mon Feb 11 04:09:59 2008 for Game Accessibility Suite by doxygen 1.5.4