MercuryInput.cpp

Go to the documentation of this file.
00001 #include "MercuryInput.h"
00002 #include "MercuryINI.h"
00003 #include "MercuryUtil.h"
00004 #include "MercuryMessages.h"
00005 #include "MercuryDisplay.h"
00006 
00007 MercuryInputManager * INPUTMAN = NULL;
00008 InputDeviceTracker AutoInputDeviceTracker;
00009 InputMappingTracker AutoInputMappingTracker;
00010 
00011 //Setup NULL devices incase we don't compile any in.
00012 bool NullResponce = AutoInputDeviceTracker.AddDevice( "Null", new DeviceNull );
00013 //CursorDevice * DefaultCursorDevice = NULL;
00014 
00015 bool CursorDevice::m_bHasFocus;
00016 
00017 
00018 
00019 InputMessageStruct::InputMessageStruct()
00020 {
00021     button = 0;
00022     code = 0;
00023     device = 0;
00024     type = IET_NONE;
00025 }
00026 
00027 InputMessageStruct::InputMessageStruct( PStack & toload )
00028 {
00029     device = toload.PopItem().GetValueI();
00030     button = toload.PopItem().GetValueI();
00031     type = (EventType)toload.PopItem().GetValueI();
00032     code = toload.PopItem().GetValueI();
00033 }
00034 
00035 void InputDevice::Update()
00036 {
00037     //No code
00038 }
00039 
00040 #define RegisterInputDevice( y ) \
00041     bool c = AutoInputDeviceTracker.AddDevice( #y, new y );
00042 
00043 
00044 bool InputDeviceTracker::AddDevice( MString Name, InputDevice *Device)
00045 {
00046     if ( m_pDevices == NULL )
00047         m_pDevices = new std::map < MString, InputDevice * >;
00048 
00049     if ( m_pDevices->find( Name ) != m_pDevices->end() )
00050     {
00051         SAFE_DELETE((*m_pDevices)[Name]);
00052         return true;
00053     }
00054     
00055     (*m_pDevices)[Name] = Device;
00056 
00057     return false;
00058 }
00059 
00060 InputDevice* InputDeviceTracker::ToDevice( MString Name )
00061 {
00062     if ( m_pDevices == NULL )
00063         return NULL;
00064 
00065     if ( m_pDevices->find( Name ) == m_pDevices->end() )
00066         return NULL;
00067     
00068     return (*m_pDevices)[Name];
00069 }
00070 
00071 MString InputDeviceTracker::ListAvailableDevices()
00072 {
00073     MString ret;
00074     std::map < MString, InputDevice * >::iterator cur,end;
00075     end = m_pDevices->end();
00076     for ( cur = m_pDevices->begin(); cur != end; cur++ )
00077     {
00078         if ( cur != m_pDevices->begin() )
00079             ret += ',';
00080         ret += cur->first;
00081     }
00082     return ret;
00083 }
00084 
00085 InputDeviceTracker::~InputDeviceTracker()
00086 {
00087     std::map < MString, InputDevice * >::iterator cur,end;
00088     end = m_pDevices->end();
00089     for ( cur = m_pDevices->begin(); cur != end; cur++ )
00090         SAFE_DELETE( cur->second );
00091 }
00092 
00093 MercuryInputManager::MercuryInputManager()
00094 {
00095     MString defr = AutoInputDeviceTracker.ListAvailableDevices();
00096     MString def = PREFSMAN->GetValueS( "Input", "Devices", defr, true );
00097     if ( def.length() == 0 )
00098         def = defr;
00099 
00100     const char* devs = def.c_str();
00101     int curloc = 0;
00102     while ( (unsigned)curloc < def.length() )
00103     {
00104         int nextloc = BytesUntil( devs, ", ", curloc, def.length(), 2 );
00105         MString DeviceName = def.substr( curloc, nextloc );
00106 
00107         m_vDevices.push_back( AutoInputDeviceTracker.ToDevice( DeviceName ) );
00108         m_vDevices[m_vDevices.size()-1]->Init(DeviceName);
00109 
00110         curloc += nextloc;
00111         nextloc = BytesNUntil( devs, ", ", curloc, def.length(), 2 );
00112         curloc += nextloc;
00113     }
00114 
00115     AutoInputMappingTracker.ReadInMappingsFromINI();
00116 }
00117 
00118 void MercuryInputManager::Update( )
00119 {
00120     for ( int i = 0; (unsigned)i < m_vDevices.size(); i++ )
00121     {
00122         if ( m_vDevices[i] != NULL )
00123         {
00124             m_vDevices[i]->Update();
00125             InputEvent p = m_vDevices[i]->PopLastEvent();
00126             while ( p.Type != IET_NONE )
00127             {
00128                 InputMessageStruct *k = new InputMessageStruct;
00129                 k->code = AutoInputMappingTracker.InputEventToCode( p );
00130                 k->button = p.ButtonNumber;
00131                 k->type = p.Type;
00132                 k->device = i;
00133                 if (DISPLAY->GetWindow()->HasFocus())
00134                     if ( k->code != -1 )
00135                         MESSAGEMAN->BroadcastMessage( "mappedinput", PStack( PSElement( k->device ), PSElement( k->button ), PSElement( k->type ), PSElement( k->code ) ) );
00136                     else
00137                         MESSAGEMAN->BroadcastMessage( "unmappedinput", PStack( PSElement( k->device ), PSElement( k->button ), PSElement( k->type ), PSElement( k->code ) ) );
00138                 SAFE_DELETE( k );
00139                 p = m_vDevices[i]->PopLastEvent();
00140             }
00141         }
00142     }
00143     if ( DefaultCursorDevice != NULL ) 
00144         DefaultCursorDevice->Update();
00145 }
00146 
00147 bool MercuryInputManager::IsButtonDown( int code )
00148 {
00149     MVector<InputEvent> buttons;
00150     AutoInputMappingTracker.CodeToHardware( code, buttons );
00151     for ( unsigned int i=0; i<buttons.size();i++)
00152         if ( IsButtonDown( buttons[i].DeviceNumber, buttons[i].ButtonNumber ) )
00153             return true;
00154     return false;
00155 }
00156 
00157 
00158 InputEvent MercuryInputManager::PopLastEvent()
00159 {
00160     for ( int i = 0; (unsigned)i < m_vDevices.size(); i++ )
00161     {
00162         if ( m_vDevices[i] != NULL )
00163         {
00164             InputEvent k = m_vDevices[i]->PopLastEvent();
00165             if ( k.Type != IET_NONE )
00166             {
00167                 k.DeviceNumber = i;
00168                 return k;
00169             }
00170         }
00171     }
00172     return InputEvent( 0,0,IET_NONE);
00173 }
00174 
00175 int InputMappingTracker::MakeMappingCode( const MString& Name, const MString Default )
00176 {
00177     if ( m_pAutoCodes == NULL )
00178     {
00179         m_pAutoCodes = new map< MString, MString >;
00180     }
00181     
00182     (*m_pAutoCodes)[Name] = Default;
00183 
00184     return MakeMappingCode( Name );
00185 }
00186 
00187 int InputMappingTracker::MakeMappingCode( const MString& Name )
00188 {
00189     if ( m_pMappings == NULL )
00190     {
00191         m_pMappings = new map < MString, int >;
00192         m_iCurMapNumber = 1;
00193     }
00194 
00195     if ( m_pCodes == NULL )
00196     {
00197         m_pCodes = new std::map < MString , int >;
00198     }
00199 
00200     if ( m_pMappings->find( Name ) == m_pMappings->end() )
00201     {
00202         m_iCurMapNumber++;
00203         (*m_pMappings)[Name] = m_iCurMapNumber;
00204     }
00205 
00206     return (*m_pMappings)[Name];
00207 }
00208 
00209 void InputMappingTracker::ReadInMappingsFromINI()
00210 {
00211     int CurMapNumber = 2;
00212     std::map < MString, int >::iterator cur,end;
00213     end = m_pMappings->end();
00214     for ( cur = m_pMappings->begin(); cur != end; cur++ )
00215     {
00216         MString Name = cur->first;
00217         CurMapNumber = cur->second;
00218         MString k = PREFSMAN->GetValueS( "InputMapper", Name, (*m_pAutoCodes)[Name], true );
00219         const char* devs = k.c_str();
00220         int curloc = 0;
00221         while ( (unsigned)curloc < k.length() )
00222         {
00223             int nextloc = BytesUntil( devs, ", ", curloc, k.length(), 2 );
00224             MString MapName = k.substr( curloc, nextloc );
00225             (*m_pCodes)[MapName] = CurMapNumber;
00226             
00227             //Actually decode the code.
00228 
00229             int strt = BytesUntil( MapName.c_str(), "-", 0, MapName.size(), 1 );
00230             InputEvent ie( 
00231                 atoi( MapName.substr(0,strt).c_str() ), 
00232                 atoi( MapName.substr(strt+1,MapName.length()-strt-1).c_str() ),
00233                 IET_NONE );
00234             if ( m_vDemapped.size() < (unsigned)CurMapNumber+1 )
00235                 m_vDemapped.resize( CurMapNumber+1 );
00236             m_vDemapped[CurMapNumber].push_back(ie);
00237             //Continue parse
00238             curloc += nextloc;
00239             nextloc = BytesNUntil( devs, ", ", curloc, k.length(), 2 );
00240             curloc += nextloc;
00241         }
00242         CurMapNumber++;
00243     }
00244 }
00245 
00246 void InputMappingTracker::CodeToHardware( int code, MVector<InputEvent> &out )
00247 {
00248     if ( (unsigned)code < m_vDemapped.size() )
00249         out = m_vDemapped[code];
00250     else
00251         out.clear();
00252 }
00253 
00254 int InputMappingTracker::InputEventNameToCode( const MString & IE )
00255 { 
00256     if ( m_pCodes == NULL )
00257         return -1;
00258     else
00259         if ( m_pCodes->find( IE ) == m_pCodes->end() ) 
00260             return -1;
00261         else
00262             return (*m_pCodes)[IE]; 
00263 }
00264 
00265 int InputMappingTracker::InputEventToCode( const InputEvent & IE )
00266 { 
00267     return InputEventNameToCode( ssprintf( "%d-%d", IE.DeviceNumber, IE.ButtonNumber ));
00268 }
00269 
00270 CursorDevice::CursorDevice()
00271 {
00272     m_x = 0;
00273     m_y = 0;
00274     m_bHasFocus = true;
00275     m_bSubscribed = false;
00276     m_Xoff = m_Yoff = 200;
00277 }
00278 
00279 void CursorDevice::UpdateFocus( const MString &message, void * data, void * info )
00280 {
00281 }
00282 
00283 char KeyToChar( char cHardwareChar, bool bShiftPressed )
00284 {
00285     if ( cHardwareChar == 10 || cHardwareChar == 13 )
00286         return 10;
00287 
00288     if ( cHardwareChar > 126 || cHardwareChar < 30 )
00289         return 0;
00290 
00291     if ( bShiftPressed )
00292     {
00293         switch ( cHardwareChar )
00294         {
00295         case '`': return '~';
00296         case '1': return '!';
00297         case '2': return '@';
00298         case '3': return '#';
00299         case '4': return '$';
00300         case '5': return '%';
00301         case '6': return '^';
00302         case '7': return '&';
00303         case '8': return '*';
00304         case '9': return '(';
00305         case '0': return ')';
00306         case '-': return '_';
00307         case '=': return '+';
00308         case '\\': return '|';
00309         case '[': return '{';
00310         case ']': return '}';
00311         case ';': return ':';
00312         case '\'': return '\"';
00313         case ',': return '<';
00314         case '.': return '>';
00315         case '/': return '?';
00316         case ' ': return ' ';
00317         }
00318         if ( ( cHardwareChar >= 'a' ) && ( cHardwareChar <= 'z' ) ) 
00319             return cHardwareChar - 'a' + 'A';
00320         return 0;
00321     } else 
00322         return cHardwareChar;       
00323 }
00324 
00325 /* 
00326  * Copyright (c) 2005-2006, Charles Lohr
00327  * All rights reserved.
00328  *
00329  * Redistribution and use in source and binary forms, with or
00330  * without modification, are permitted provided that the following
00331  * conditions are met:
00332  *  -   Redistributions of source code must retain the above
00333  *      copyright notice, this list of conditions and the following disclaimer.
00334  *  -   Redistributions in binary form must reproduce the above copyright
00335  *      notice, this list of conditions and the following disclaimer in
00336  *      the documentation and/or other materials provided with the distribution.
00337  *  -   Neither the name of the Mercury Engine nor the names of its
00338  *      contributors may be used to endorse or promote products derived from
00339  *      this software without specific prior written permission.
00340  *
00341  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00342  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00343  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00344  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
00345  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00346  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00347  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00348  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00349  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00350  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00351  */
00352 

Hosted by SourceForge.net Logo