MezzanineEngine 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
eventmanager.cpp
1 // © Copyright 2010 - 2014 BlackTopp Studios Inc.
2 /* This file is part of The Mezzanine Engine.
3 
4  The Mezzanine Engine is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  The Mezzanine Engine 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. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with The Mezzanine Engine. If not, see <http://www.gnu.org/licenses/>.
16 */
17 /* The original authors have included a copy of the license specified above in the
18  'Docs' folder. See 'gpl.txt'
19 */
20 /* We welcome the use of the Mezzanine engine to anyone, including companies who wish to
21  Build professional software and charge for their product.
22 
23  However there are some practical restrictions, so if your project involves
24  any of the following you should contact us and we will try to work something
25  out:
26  - DRM or Copy Protection of any kind(except Copyrights)
27  - Software Patents You Do Not Wish to Freely License
28  - Any Kind of Linking to Non-GPL licensed Works
29  - Are Currently In Violation of Another Copyright Holder's GPL License
30  - If You want to change our code and not add a few hundred MB of stuff to
31  your distribution
32 
33  These and other limitations could cause serious legal problems if you ignore
34  them, so it is best to simply contact us or the Free Software Foundation, if
35  you have any questions.
36 
37  Joseph Toppi - toppij@gmail.com
38  John Blackwood - makoenergy02@gmail.com
39 */
40 #ifndef _eventmanager_cpp
41 #define _eventmanager_cpp
42 ///////////////////////////////////////////////////////////////////////////////
43 //This will capture all event and store them for easy dispatching.
44 //
45 //There will be an instance of this class in the world.
46 ///////////////////////////////////////
47 
48 #include "entresol.h"
49 #include "eventmanager.h"
50 #include "eventbase.h"
51 #include "eventgamewindow.h"
52 #include "eventquit.h"
53 #include "eventuserinput.h"
54 #include "Input/metacode.h"
55 #include "Input/inputmanager.h"
56 
57 #include <map>
58 #include <memory>
59 #include <cassert>
60 
61 #include "SDL.h"
62 
63 namespace Mezzanine
64 {
65  ///////////////////////////////////////////////////////////////////////////////
66  // EventPumpWorkUnit Methods
67 
69  { }
70 
72  { return *this; }
73 
75  TargetManager(Target) { }
76 
78  { }
79 
80  ///////////////////////////////////////////////////////////////////////////////
81  // Utility
82 
84  {
85  Logger& Log = CurrentThreadStorage.GetUsableLogger();
86  Log << "Getting Events from OS." << std::endl;
87  this->TargetManager->UpdateEvents();
88  }
89 
90  /// @internal
91  /// @namespace Mezzanine::internal
92  /// @brief This namespace is used for internal helper classes, and in general it should be ignored by game developers
93  /// @details This whole internal namespace is a home for dirty hacks and internal dependant code. This is where code goes that must implement classes or functions for the various subsytems the Mezzanine engine draws on.
94  namespace Internal
95  {
96  /// @internal
97  /// @brief SDL uses this to filter events it presents to applications
98  /// @details This is used used to filter out SQL_quit messages, and generate appropriate messages for the game developer to use.
99  /// This will always drop quit events, and store that information for later use.
100  /// \n
101  /// If this is passed an event that points to 0 it will function as a method to tell us if an SDL_QUIT message has been thrown
102  /// this will return 2 if it has not seen an SDL_quit, and a 4 if it has
103  /// @param event This is the event SDL expects use to filters, To get real data from this we setup it up so that if the event is a null pointer the function will return data about quit messages
104  /// @param userdata Nothing, a dummy argument that could be used by SDL
105  /// @warning Do not use this. It can only cause problems. This is for SDL, the user input subsystem, to filter certain events.
106  /// @return This will always return either 0 or 1 to SDL. 0 if it should drop the event, which it does to all SDL_quit events, 1 if the event should be allowed, which it does to all events which are not SDL_quit events. If a null pointer was passed, then this will return 4 if it dropped an SDL_Quit, and 2 if it has not droppped an SDL_quit.
107  int MezzSDLFilter(void *userdata, SDL_Event *event )
108  {
109  //We need to protect this thing with a Mutex, SDL 1.3 says this filter could run in different thread.
110  static bool DroppedQuit=false;
111 
112  if(event!=0) //if this is a real event
113  {
114  if ( event->type == SDL_QUIT )
115  {
116  DroppedQuit=true; //Drop all quit events, and track that we dropped them
117  return 0;
118  }
119  return 1;
120  }else{
121  if(DroppedQuit) //4 if we need to make a quit event
122  {
123  DroppedQuit=false; //Reset this so we don't add more in the future by accident
124  return 4;
125  }
126  return 2;
127  }
128  }
129 
130  /// @internal
131  /// @brief Used to increase encapsulation, just a bit.
133  {
134  /// @internal
135  /// @brief The Queue that all the events get stored in
136  std::list<EventBase*> EventQ;
137 
138  /// @internal
139  /// @brief The kinds of data that can be stored in Manual Check
141  Polling =1,
142  Keypress =2,
143 
144  PollingKeyPress = Polling|Keypress
145  };
146 
147  /// @internal
148  /// @brief A unified polling and event repeater
149  /// the Inputcode is the kind of event to check for each frame. The PollingType is used to control what can turn on and off the pollingcheck check.
150  std::map<Input::InputCode, PollingType> ManualCheck;
151 
152  /// @internal
153  /// @brief an Iterator suitable for use with internal structures that correlate polling type and metacodes
154  typedef std::map<Input::InputCode, PollingType>::iterator ManualCheckIterator;
155 
156  /// @internal
157  /// @brief This is the workunit that does the work each frame.
159 
160  /// @internal
161  /// @brief Adds one type of polling check
162  /// @param OneCode The code that will be check for each frame, under the new condition
163  /// @param _PollingCheck This is inserted into a new polling check or it is bitwise or'ed into an existing one, and this will trigger other parts of the code to insert event later on
165  {
166  ManualCheckIterator Which = ManualCheck.find(OneCode);
167  if(ManualCheck.end() == Which )
168  {
169  ManualCheck[OneCode] = _PollingCheck;
170  }else{
171  Which->second = (PollingType)(Which->second | _PollingCheck); //An Item can be multiple kinds of polling checks
172  }
173  }
174 
175  /// @internal
176  /// @brief Adds one type of polling check where the data is only available as Ints
177  /// @param OneCode The code that will be check for each frame, under the new condition
178  /// @param _PollingCheck This is inserted into a new polling check or it is bitwise or'ed into an existing one, and this will trigger other parts of the code to insert event later on
179  void AddInputCodesToManualCheck(int OneCode, int _PollingCheck)
180  {
182  static_cast<Mezzanine::Input::InputCode>(OneCode),
183  static_cast<Mezzanine::Internal::EventManagerInternalData::PollingType>(_PollingCheck)
184  );
185  }
186 
187  /// @internal
188  /// @brief Adds one type of polling check where the data is only available as Ints
189  /// @param OneCode The metacode that contains the input that will be checked for each frame
190  /// @param _PollingCheck This is inserted into a new polling check or it is bitwise or'ed into an existing one, and this will trigger other parts of the code to insert event later on
191  void AddMetaCodesToManualCheck(const Input::MetaCode& OneCode, PollingType _PollingCheck)
192  { AddInputCodesToManualCheck(OneCode.GetCode(),_PollingCheck); }
193 
194  /// @internal
195  /// @brief Used to insert Codes into the list of items to be manually checked
196  /// @param Transport A vector of every Meta that may need to be added to the list
197  /// @param _PollingCheck This is inserted into a new polling check or it is bitwise or'ed into an existing one, and this will trigger other parts of the code to insert event later on
198  void AddMetaCodesToManualCheck(std::vector<Input::MetaCode> Transport, PollingType _PollingCheck)
199  {
200  for ( std::vector<Input::MetaCode>::const_iterator Iter=Transport.begin(); Iter!=Transport.end(); ++Iter)
201  {
202  //Input::InputCode temp = Iter->GetCode();
203  AddInputCodeToManualCheck(Iter->GetCode(), _PollingCheck);
204  }
205  }
206 
207  /// @internal
208  /// @brief Remove a kind polling check from an item or remove item if that is the last check
209  /// @param Reduce An Iterator Referencing an item in manual check
210  /// @param _PollingCheck What kind of Polling Type to Remove.
212  {
213  if( ManualCheck.end() != Reduce )
214  {
215  if(Reduce->second == _PollingCheck)
216  { ManualCheck.erase(Reduce); }
217  else
218  { Reduce->second = (PollingType)(Reduce->second & (~_PollingCheck)); }
219  }
220  }
221 
222  /// @internal
223  /// @brief Removes one type of polling check
224  /// @param OneCode The code that will no longer be checked each frame, under the given condition
225  /// @param _PollingCheck If this matches via bitwise or with the kind of polling check check stored for the existing InputCode then the it will be removed.
226  void RemoveInputCodeToManualCheck(const Input::InputCode& OneCode, PollingType _PollingCheck)
227  {
228  ManualCheckIterator Which = ManualCheck.find(OneCode);
229  RemovePollingCheck( Which, _PollingCheck );
230  }
231 
232  /// @internal
233  /// @brief Removes one type of polling check
234  /// @param OneCode A metacode that contains the the inputcode to remove
235  /// @param _PollingCheck If this matches via bitwise or with the kind of polling check check stored for the existing InputCode then the it will be removed.
236  void RemoveMetaCodesToManualCheck(const Input::MetaCode& OneCode, PollingType _PollingCheck)
237  { RemoveInputCodeToManualCheck(OneCode.GetCode(),_PollingCheck); }
238 
239  /// @internal
240  /// @brief Remove Items form the internal manual check list
241  /// @param Transport A vector of every MetaCode that may need to be removed to the list
242  /// @param _PollingCheck If this matches via bitwise or with the kind of polling check check stored for the existing InputCode then the it will be removed.
243  void RemoveMetaCodesToManualCheck(std::vector<Input::MetaCode> Transport, PollingType _PollingCheck)
244  {
245  for ( std::vector<Input::MetaCode>::iterator Iter=Transport.begin(); Iter!=Transport.end(); ++Iter)
246  { RemoveInputCodeToManualCheck(Iter->GetCode(), _PollingCheck); }
247  }
248 
249  /// @internal
250  /// @brief Drops all keypresses from the list of items to be perpetuated each frame.
252  {
253  for (ManualCheckIterator Which = ManualCheck.begin(); Which!=ManualCheck.end(); ++Which)
254  { RemovePollingCheck(Which, Keypress); }
255  }
256 
257  /// @internal
258  /// @brief Constructor, it only inits pointers to 0
260  : EventPumpWork(NULL)
261  {
262 
263  }
264  };
265  } // /internal
266 
267  ///////////////////////////////////////////////////////////////////////////////
268  // EventManager Methods
269 
270  template<> EventManager* Singleton<EventManager>::SingletonPtr = NULL;
271 
272  /// @todo TODO: Make the EventManager completely thread safe. IF this is completely thread safe, we can spawn numerous individual thread each accessing this and
273  /// and the performance gain would almost scale directly with cpu core count increases. Look at boost scoped_lock
275  {
276  UInt32 InitSDLSystems = SDL_WasInit(0);
277  if( (SDL_INIT_JOYSTICK & InitSDLSystems) == 0 )
278  {
279  if( SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) < 0 )
280  { MEZZ_EXCEPTION(Exception::INTERNAL_EXCEPTION,String("Failed to Initialize SDL for Joystick input, SDL Error: ") + SDL_GetError()); }
281  }
282  if( !(SDL_INIT_GAMECONTROLLER | InitSDLSystems) )
283  {
284  if( SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_NOPARACHUTE) < 0 )
285  { MEZZ_EXCEPTION(Exception::INTERNAL_EXCEPTION,String("Failed to Initialize SDL for Game Controller input, SDL Error: ") + SDL_GetError()); }
286  }
287  this->_Data = new Internal::EventManagerInternalData();
288  this->_Data->EventPumpWork = new EventPumpWorkUnit(this);
289  }
290 
292  {
293  UInt32 InitSDLSystems = SDL_WasInit(0);
294  if( (SDL_INIT_JOYSTICK & InitSDLSystems) == 0 )
295  {
296  if( SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) < 0 )
297  { MEZZ_EXCEPTION(Exception::INTERNAL_EXCEPTION,String("Failed to Initialize SDL for Joystick input, SDL Error: ") + SDL_GetError()); }
298  }
299  if( !(SDL_INIT_GAMECONTROLLER | InitSDLSystems) )
300  {
301  if( SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_NOPARACHUTE) < 0 )
302  { MEZZ_EXCEPTION(Exception::INTERNAL_EXCEPTION,String("Failed to Initialize SDL for Game Controller input, SDL Error: ") + SDL_GetError()); }
303  }
304  this->_Data = new Internal::EventManagerInternalData();
305  this->_Data->EventPumpWork = new EventPumpWorkUnit(this);
306  /// @todo This class currently doesn't initialize anything from XML, if that changes this constructor needs to be expanded.
307  }
308 
310  {
311  this->Deinitialize();
312  //EndRelativeMouseMode();
313 
314  delete _Data->EventPumpWork;
315 
316  for(std::list<EventBase*>::iterator Iter = _Data->EventQ.begin(); Iter!=_Data->EventQ.end(); Iter++)
317  { delete *Iter; }
318  delete _Data;
319 
321  Input::InputManager::GetSingletonPtr()->ReleaseAllControllers();
322 
323  UInt32 InitSDLSystems = SDL_WasInit(0);
324  if( SDL_INIT_JOYSTICK | InitSDLSystems )
325  {
326  SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
327  }
328  if( SDL_INIT_GAMECONTROLLER | InitSDLSystems )
329  {
330  SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
331  }
332  }
333 
334  void EventManager::UpdateQuitEvents()
335  {
336 // if (NULL == SDL_GetEventFilter()) //Verify the Event filter is installed, if not, then install it.
337  if(SDL_FALSE == SDL_GetEventFilter(0, 0))
338  {
339  SDL_SetEventFilter( Internal::MezzSDLFilter, 0);
340  }else{
341  if(4==Internal::MezzSDLFilter(0,0)) //Pass it a null pointer to get it to "Not Callback Mode"
342  {
343  this->AddEvent(new EventQuit()); //We need to make a quit event
344  }else{
345  //all clear
346  }
347  }
348  }
349 
350  ///////////////////////////////////////////////////////////////////////////////
351  // Management functions - Work with all events
352 
354  { return _Data->EventQ.size(); }
355 
357  {
358  if(_Data->EventQ.empty())
359  { return 0; }
360  EventBase* results = _Data->EventQ.front();
361  return results;
362  }
363 
365  {
366  if(_Data->EventQ.empty())
367  { return 0; }
368  EventBase* results = _Data->EventQ.front();
369  _Data->EventQ.pop_front();
370  return results;
371  }
372 
374  { _Data->EventQ.pop_front(); }
375 
377  { _Data->EventQ.push_back(EventToAdd); }
378 
380  {
381  for( std::list<EventBase*>::iterator EvIt = _Data->EventQ.begin() ; EvIt != _Data->EventQ.end() ; ++EvIt )
382  {
383  if(EventToRemove == (*EvIt))
384  {
385  _Data->EventQ.erase(EvIt);
386  return;
387  }
388  }
389  }
390 
392  {
393  SDL_PumpEvents();
394  UpdateQuitEvents(); //quit events skips the preprocessing step and goes straight into the the main Queue, becuase of how we need to get them from sdl
395 
396  RawEvent FromSDLRaw; //used to hold data as we go through loop
397  EventUserInput* FromSDLEvent = new EventUserInput(); //Used to build up all of our userinput data into one event
398  //bool ClearKeyPresses=false; //if true All the keypresses will be dropped and all keys will be assumed to be up
399 
400  // Here we iterate through manual check to insert any requested polling checks and perpetuate button and key down events
401  for(Internal::EventManagerInternalData::ManualCheckIterator Iter=_Data->ManualCheck.begin(); _Data->ManualCheck.end()!=Iter; ++Iter)
402  {
403  if(Internal::EventManagerInternalData::Keypress & Iter->second) //if the keypress event is in there, then the key must be down
404  { FromSDLEvent->AddCode(Input::BUTTON_DOWN, Iter->first); }
405  else
406  { FromSDLEvent->AddCode(Input::BUTTON_UP, Iter->first); } //It must be just a polling check
407  }//*/
408 
409  /* Here is a list of SDL event which aren't coded yet.
410  //event types
411  Tabbed items are fully working
412  items with one space are partially implemented of known to not work
413  other items are unimplemented
414  SDL_FIRSTEVENT unused (do not remove) Application events
415  SDL_QUIT user-requested quit Window events
416  SDL_WINDOWEVENT window state change
417  SDL_SYSWMEVENT system specific event Keyboard events
418  SDL_KEYDOWN key pressed
419  SDL_KEYUP key released
420  SDL_TEXTEDITING keyboard text editing (composition)
421  SDL_TEXTINPUT keyboard text input Mouse events
422  SDL_MOUSEMOTION mouse moved
423  SDL_MOUSEBUTTONDOWN mouse button pressed
424  SDL_MOUSEBUTTONUP mouse button released
425  SDL_MOUSEWHEEL mouse wheel motion Tablet or multiple mice input device events
426  SDL_INPUTMOTION input moved
427  SDL_INPUTBUTTONDOWN input button pressed
428  SDL_INPUTBUTTONUP input button released
429  SDL_INPUTWHEEL input wheel motion
430  SDL_INPUTPROXIMITYIN input pen entered proximity
431  SDL_INPUTPROXIMITYOUT input pen left proximity Joystick events
432  SDL_JOYAXISMOTION joystick axis motion
433  SDL_JOYBALLMOTION joystick trackball motion
434  SDL_JOYHATMOTION joystick hat position change
435  SDL_JOYBUTTONDOWN joystick button pressed
436  SDL_JOYBUTTONUP joystick button released Touch events
437  SDL_FINGERDOWN
438  SDL_FINGERUP
439  SDL_FINGERMOTION
440  SDL_TOUCHBUTTONDOWN
441  SDL_TOUCHBUTTONUP Gesture events
442  SDL_DOLLARGESTURE
443  SDL_DOLLARRECORD
444  SDL_MULTIGESTURE Clipboard events
445  SDL_CLIPBOARDUPDATE the clipboard changed Obsolete events
446  SDL_EVENT_COMPAT1 SDL 1.2 events for compatibility
447  SDL_EVENT_COMPAT2 SDL 1.2 events for compatibility
448  SDL_EVENT_COMPAT3 SDL 1.2 events for compatibility These are for your use, and should be allocated with
449  SDL_RegisterEvents()
450  SDL_USEREVENT a user-specified event
451  SDL_LASTEVENT only for bounding internal arrays
452  */
453 
454  while(SDL_PollEvent(&FromSDLRaw))
455  {
456  switch(FromSDLRaw.type)
457  {
458  //Events and User input sorted by estimate frequency
459  case SDL_MOUSEBUTTONUP: case SDL_KEYUP: case SDL_JOYBUTTONUP:/*{
460  Input::MetaCode ResultCode(FromSDLRaw);
461  _Data->RemoveMetaCodesToManualCheck( FromSDLEvent->AddCode(ResultCode), Internal::EventManagerInternalData::Keypress);
462  break;}//*/
463 
464  case SDL_KEYDOWN: /*{
465  Input::MetaCode ResultCode(FromSDLRaw);
466  if ( !(_Data->ManualCheck[ResultCode.GetCode()]) ) //This checks for operating system level key repititions and skips adding them
467  { _Data->AddMetaCodesToManualCheck( FromSDLEvent->AddCode(ResultCode), Internal::EventManagerInternalData::Keypress); }
468  break; }//*/
469 
470  case SDL_MOUSEBUTTONDOWN: case SDL_JOYBUTTONDOWN:
471  /*_Data->AddMetaCodesToManualCheck( FromSDLEvent->AddCode(FromSDLRaw), Internal::EventManagerInternalData::Keypress);
472  break;//*/
473 
474  case SDL_MOUSEMOTION: case SDL_JOYAXISMOTION: case SDL_JOYHATMOTION: case SDL_JOYBALLMOTION:
475  FromSDLEvent->AddCodesFromRawEvent(FromSDLRaw);
476  break;
477 
478  case SDL_WINDOWEVENT: {
479  EventGameWindow* React = new EventGameWindow(FromSDLRaw);
480  /*if(EventGameWindow::GAME_WINDOW_FOCUS_LOST==React->GetEventID()) //we dropp all keypresses when windows are switched
481  { ClearKeyPresses = true; }//*/
482  this->AddEvent(React);
483  break; }
484 
485  case SDL_SYSWMEVENT:
486  // call a function with ifdefs here
487  break;
488 
489  // Error conditions
490  case SDL_FIRSTEVENT: // ©apture and ignore or throw error
491  { MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Unexpected 'FIRSTEVENT' event in event manager. User input seems corrupted."); break; }
492 
493  case SDL_QUIT: //when SDL closes, but this really should be handled somewhere else, like the UpdateQuitEvents() function
494  { MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Unexpected Quit event in event manager."); break; }
495 
496  default: //Never thrown by SDL, but could be added by a user
497  //Entresol::GetSingletonPtr()->LogAndThrow("Unknown SDL Event Inserted.");
498  Entresol::GetSingletonPtr()->Log("Unknown SDL Event Inserted. Likely an unhandled SDL 1.3 event");
499  break;
500  }
501  //free(FromSDLRaw); //Does this need to Happen?
502  }
503 
504  /*if(ClearKeyPresses)
505  { this->_Data->DropAllKeyPresses(); }//*/
506 
507  #ifdef MEZZDEBUG
508  /*Entresol::GetSingletonPtr()->Log("User Input entered this Frame");
509  for(EventUserInput::iterator LIter=FromSDLEvent->begin(); FromSDLEvent->end()!=LIter; ++LIter)
510  {
511  Entresol::GetSingletonPtr()->Log(*LIter);
512  }
513  Entresol::GetSingletonPtr()->Log("End Of User Input entered this Frame");
514  Entresol::GetSingletonPtr()->DoMainLoopLogging();//*/
515  #endif
516 
517  // ©heck to see if we should add a User input event or not. We wouldn't want to pass an empty event
518  if(FromSDLEvent->GetMetaCodeCount()==0)
519  {
520  delete FromSDLEvent;
521  }else{
522  _Data->EventQ.push_back(FromSDLEvent);
523  }
524  }
525 
526  ///////////////////////////////////////////////////////////////////////////////
527  // Filtered management functions - GameWindow Events
528 
530  { return dynamic_cast<EventGameWindow*> (this->GetNextSpecificEvent(EventBase::GameWindow)); }
531 
533  { return dynamic_cast<EventGameWindow*> (this->PopNextSpecificEvent(EventBase::GameWindow)); }
534 
537 
538  std::list<EventGameWindow*>* EventManager::GetAllGameWindowEvents()
539  { return (std::list<EventGameWindow*>*)this->GetAllSpecificEvents(EventBase::GameWindow); }
540 
541  ///////////////////////////////////////////////////////////////////////////////
542  // Filtered management functions - User Input Events
543 
545  { return dynamic_cast<EventUserInput*> (this->GetNextSpecificEvent(EventBase::UserInput)); }
546 
548  { return dynamic_cast<EventUserInput*> (this->PopNextSpecificEvent(EventBase::UserInput)); }
549 
552 
553  std::list<EventUserInput*>* EventManager::GetAllUserInputEvents()
554  { return (std::list<EventUserInput*>*)this->GetAllSpecificEvents(EventBase::UserInput); }
555 
556  ///////////////////////////////////////////////////////////////////////////////
557  // Filtered management functions - Quit Event
558 
560  { return dynamic_cast<EventQuit*> (this->GetNextSpecificEvent(EventBase::QuitMessage)); }
561 
563  { return dynamic_cast<EventQuit*> (this->PopNextSpecificEvent(EventBase::QuitMessage)); }
564 
567 
568  std::list<EventQuit*>* EventManager::GetAllQuitEvents()
569  { return (std::list<EventQuit*>*)this->GetAllSpecificEvents(EventBase::QuitMessage); }
570 
571  ///////////////////////////////////////////////////////////////////////////////
572  // Filtered management functions - You choose YAYYYY!!!
573  ///////////////////////////////////////
575  {
576  EventBase* results = 0;
577  for(std::list<EventBase*>::iterator Iter = _Data->EventQ.begin(); Iter!=_Data->EventQ.end(); ++Iter)
578  {
579  if((*Iter)->GetType()==SpecificType)
580  {
581  results = (*Iter);
582  return results;
583  }
584  }
585  return results;
586  }
587 
589  {
590  EventBase* results = 0;
591  for(std::list<EventBase*>::iterator Iter = _Data->EventQ.begin(); Iter!=_Data->EventQ.end(); ++Iter)
592  {
593  if((*Iter)->GetType()==SpecificType)
594  {
595  results = (*Iter);
596  _Data->EventQ.erase(Iter);
597  return results;
598  }
599  }
600  return results;
601  }
602 
604  {
605  for(std::list<EventBase*>::iterator Iter = _Data->EventQ.begin(); Iter!=_Data->EventQ.end(); ++Iter)
606  {
607  if((*Iter)->GetType()==SpecificType)
608  {
609  _Data->EventQ.erase(Iter);
610  return;
611  }
612  }
613  }
614 
615  std::list<EventBase*>* EventManager::GetAllSpecificEvents(EventBase::EventType SpecificType)
616  {
617  std::list<EventBase*>* TempList = new std::list<EventBase*>;
618 
619  for(std::list<EventBase*>::iterator Iter = _Data->EventQ.begin(); Iter!=_Data->EventQ.end(); ++Iter)
620  {
621  if((*Iter)->GetType()==SpecificType)
622  {
623  TempList->push_back(*Iter);
624  }
625  }
626  return TempList;
627  }
628 
630  {
631  for( std::list<EventBase*>::iterator Iter = _Data->EventQ.begin() ; Iter!=_Data->EventQ.end() ; )
632  {
633  if((*Iter)->GetType()==SpecificType)
634  {
635  std::list<EventBase*>::iterator prev = Iter++;
636  this->_Data->EventQ.erase(prev);
637  }
638  else ++Iter;
639  }
640  }
641 
642  ///////////////////////////////////////////////////////////////////////////////
643  // Polling Functions
644 
645  void EventManager::AddPollingCheck(const Input::MetaCode& InputToTryPolling)
646  {
647  if(InputToTryPolling.IsPollable())
648  {
649  this->_Data->AddInputCodeToManualCheck(InputToTryPolling.GetCode(), Internal::EventManagerInternalData::Polling);
650  }else{
651  MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Unsupported Polling Check on this Platform");
652  }
653  }
654 
655  void EventManager::RemovePollingCheck(const Input::MetaCode& InputToStopPolling)
656  {
657  this->_Data->RemoveInputCodeToManualCheck(InputToStopPolling.GetCode(), Internal::EventManagerInternalData::Polling);
658  }
659 
660  ///////////////////////////////////////////////////////////////////////////////
661  // Utility
662 
664  {
665  if( !this->Initialized )
666  {
667  this->TheEntresol->GetScheduler().AddWorkUnitMain( this->_Data->EventPumpWork, "EventPumpWork" );
668  this->Initialized = true;
669  }
670  }
671 
673  {
674  if( this->Initialized )
675  {
676  this->TheEntresol->GetScheduler().RemoveWorkUnitMain( this->_Data->EventPumpWork );
677  this->Initialized = false;
678  }
679  }
680 
682  { return this->_Data->EventPumpWork; }
683 
684  ///////////////////////////////////////////////////////////////////////////////
685  // Type Identifier Methods
686 
688  { return ManagerBase::MT_EventManager; }
689 
691  { return "DefaultEventManager"; }
692 
693  ///////////////////////////////////////////////////////////////////////////////
694  // DefaultEventManagerFactory Methods
695 
697  {
698  }
699 
701  {
702  }
703 
705  {
706  return "DefaultEventManager";
707  }
708 
710  {
712  {
713  /// @todo Add something to log a warning that the manager exists and was requested to be constructed when we have a logging manager set up.
715  }else return new EventManager();
716  }
717 
719  {
721  {
722  /// @todo Add something to log a warning that the manager exists and was requested to be constructed when we have a logging manager set up.
724  }else return new EventManager(XMLNode);
725  }
726 
728  {
729  delete ToBeDestroyed;
730  }
731 
732 }//Mezzanine
733 
734 
735 ///////////////////////////////////////////////////////////////////////////////
736 // Class External << Operators for streaming or assignment
737 std::ostream& operator << (std::ostream& stream, const Mezzanine::EventManager& Mgr)
738 {
739  stream << "<EventManager Version=\"1\">";
740  for(std::list<Mezzanine::EventBase*>::iterator Iter = Mgr._Data->EventQ.begin(); Iter!=Mgr._Data->EventQ.end(); ++Iter)
741  { stream << **Iter; }
742  for(Mezzanine::Internal::EventManagerInternalData::ManualCheckIterator Iter=Mgr._Data->ManualCheck.begin(); Iter!=Mgr._Data->ManualCheck.end(); ++Iter)
743  { stream << "<ManualCheck Version=\"1\" PollingType=\"" << Iter->second << "\" InputCode=\"" << Iter->first << "\" />"; }
744  stream << "</EventManager>";
745 
746  return stream;
747 }
748 
749 std::istream& MEZZ_LIB operator >> (std::istream& stream, Mezzanine::EventManager& Mgr)
750 {
753 
754  Doc->GetFirstChild() >> Mgr;
755 
756  return stream;
757 }
758 
759 void operator >> (const Mezzanine::XML::Node& OneNode, Mezzanine::EventManager& Mgr)
760 {
761  if(Mezzanine::String(OneNode.Name()) == Mezzanine::String("EventManager"))
762  {
763  if (OneNode.GetAttribute("Version").AsInt() == 1)
764  {
765  Mezzanine::XML::Node Child = OneNode.GetFirstChild();
766  while(Child)
767  {
768  Mezzanine::String TagName(Child.Name());
769  if(TagName.length()>6) // I am pretty sure that the easiest wat to identify an event is by looking at the 6th
770  { // Character and seeing what the actual name of the event is. So that is what this does.
771  switch(TagName[5])
772  {
773  case 'l':{
774  Mgr._Data->AddInputCodesToManualCheck(
775  (Child.GetAttribute("InputCode").AsInt()),
776  (Child.GetAttribute("PollingType").AsInt())
777  );}
778  break;
779  case 'G':{
781  Child >> *temp;
782  Mgr.AddEvent(temp); }
783  break;
784  case 'Q':{
786  Child >> *temp;
787  Mgr.AddEvent(temp); }
788  break;
789  case 'U':{
791  Child >> *temp;
792  Mgr.AddEvent(temp); }
793  break;
794  case 'O':{
795  MEZZ_EXCEPTION(Mezzanine::Exception::PARAMETERS_EXCEPTION,"Attemping to serialize a Mezzanine::Event::Other... not sure what you are trying to serialize."); }
796  break;
797  default:{
798  MEZZ_EXCEPTION(Mezzanine::Exception::PARAMETERS_EXCEPTION,"Attemping to serialize a Mezzanine::Event... not sure what you are trying to serialize."); }
799  break;
800  }
801  }else{
802  MEZZ_EXCEPTION(Mezzanine::Exception::PARAMETERS_EXCEPTION,"Invalid event, name is not long enough to identify event.");
803  } // end if name length
804  Child = Child.GetNextSibling();
805  } // end while
806  }else{
807  MEZZ_EXCEPTION(Mezzanine::Exception::INVALID_VERSION_EXCEPTION,"Incompatible XML Version for EventManager: Not Version 1");
808  } // if version
809  }else{
810  MEZZ_EXCEPTION(Mezzanine::Exception::PARAMETERS_EXCEPTION,"Attempting to deserialize an EventManager, event mananger not found.");
811  }// if event
812 }
813 
814 
815 
816 #endif