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
00012 bool NullResponce = AutoInputDeviceTracker.AddDevice( "Null", new DeviceNull );
00013
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
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
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
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
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352