Spinning Topp Logo BlackTopp Studios
inc
eventmanager.cpp
1 // © Copyright 2010 - 2016 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 Boole 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.
211  void RemovePollingCheck(ManualCheckIterator Reduce, PollingType _PollingCheck)
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  const String EventManager::ImplementationName = "DefaultEventManager";
272  const ManagerBase::ManagerType EventManager::InterfaceType = ManagerBase::MT_EventManager;
273 
274  /// @todo TODO: Make the EventManager completely thread safe. IF this is completely thread safe, we can spawn numerous individual thread each accessing this and
275  /// and the performance gain would almost scale directly with cpu core count increases. Look at boost scoped_lock
277  {
278  UInt32 InitSDLSystems = SDL_WasInit(0);
279  if( (SDL_INIT_JOYSTICK & InitSDLSystems) == 0 )
280  {
281  if( SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) < 0 )
282  { MEZZ_EXCEPTION(ExceptionBase::INTERNAL_EXCEPTION,String("Failed to Initialize SDL for Joystick input, SDL Error: ") + SDL_GetError()); }
283  }
284  if( !(SDL_INIT_GAMECONTROLLER | InitSDLSystems) )
285  {
286  if( SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_NOPARACHUTE) < 0 )
287  { MEZZ_EXCEPTION(ExceptionBase::INTERNAL_EXCEPTION,String("Failed to Initialize SDL for Game Controller input, SDL Error: ") + SDL_GetError()); }
288  }
290  this->_Data->EventPumpWork = new EventPumpWorkUnit(this);
291  }
292 
294  {
295  UInt32 InitSDLSystems = SDL_WasInit(0);
296  if( (SDL_INIT_JOYSTICK & InitSDLSystems) == 0 )
297  {
298  if( SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) < 0 )
299  { MEZZ_EXCEPTION(ExceptionBase::INTERNAL_EXCEPTION,String("Failed to Initialize SDL for Joystick input, SDL Error: ") + SDL_GetError()); }
300  }
301  if( !(SDL_INIT_GAMECONTROLLER | InitSDLSystems) )
302  {
303  if( SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_NOPARACHUTE) < 0 )
304  { MEZZ_EXCEPTION(ExceptionBase::INTERNAL_EXCEPTION,String("Failed to Initialize SDL for Game Controller input, SDL Error: ") + SDL_GetError()); }
305  }
307  this->_Data->EventPumpWork = new EventPumpWorkUnit(this);
308  /// @todo This class currently doesn't initialize anything from XML, if that changes this constructor needs to be expanded.
309  }
310 
312  {
313  this->Deinitialize();
314  //EndRelativeMouseMode();
315 
316  delete _Data->EventPumpWork;
317 
318  for(std::list<EventBase*>::iterator Iter = _Data->EventQ.begin(); Iter!=_Data->EventQ.end(); Iter++)
319  { delete *Iter; }
320  delete _Data;
321 
323  Input::InputManager::GetSingletonPtr()->ReleaseAllControllers();
324 
325  UInt32 InitSDLSystems = SDL_WasInit(0);
326  if( SDL_INIT_JOYSTICK | InitSDLSystems )
327  {
328  SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
329  }
330  if( SDL_INIT_GAMECONTROLLER | InitSDLSystems )
331  {
332  SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
333  }
334  }
335 
337  {
338 // if (NULL == SDL_GetEventFilter()) //Verify the Event filter is installed, if not, then install it.
339  if(SDL_FALSE == SDL_GetEventFilter(0, 0))
340  {
341  SDL_SetEventFilter( Internal::MezzSDLFilter, 0);
342  }else{
343  if(4==Internal::MezzSDLFilter(0,0)) //Pass it a null pointer to get it to "Not Callback Mode"
344  {
345  this->AddEvent(new EventQuit()); //We need to make a quit event
346  }else{
347  //all clear
348  }
349  }
350  }
351 
352  ///////////////////////////////////////////////////////////////////////////////
353  // Management functions - Work with all events
354 
356  { return _Data->EventQ.size(); }
357 
359  {
360  if(_Data->EventQ.empty())
361  { return 0; }
362  EventBase* results = _Data->EventQ.front();
363  return results;
364  }
365 
367  {
368  if(_Data->EventQ.empty())
369  { return 0; }
370  EventBase* results = _Data->EventQ.front();
371  _Data->EventQ.pop_front();
372  return results;
373  }
374 
376  { _Data->EventQ.pop_front(); }
377 
379  { _Data->EventQ.push_back(EventToAdd); }
380 
382  {
383  for( std::list<EventBase*>::iterator EvIt = _Data->EventQ.begin() ; EvIt != _Data->EventQ.end() ; ++EvIt )
384  {
385  if(EventToRemove == (*EvIt))
386  {
387  _Data->EventQ.erase(EvIt);
388  return;
389  }
390  }
391  }
392 
394  {
395  SDL_PumpEvents();
396  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
397 
398  RawEvent FromSDLRaw; //used to hold data as we go through loop
399  EventUserInput* FromSDLEvent = new EventUserInput(); //Used to build up all of our userinput data into one event
400  //Boole ClearKeyPresses=false; //if true All the keypresses will be dropped and all keys will be assumed to be up
401 
402  // Here we iterate through manual check to insert any requested polling checks and perpetuate button and key down events
404  {
405  if(Internal::EventManagerInternalData::Keypress & Iter->second) //if the keypress event is in there, then the key must be down
406  { FromSDLEvent->AddCode(Input::BUTTON_DOWN, Iter->first); }
407  else
408  { FromSDLEvent->AddCode(Input::BUTTON_UP, Iter->first); } //It must be just a polling check
409  }// */
410 
411  /* Here is a list of SDL event which aren't coded yet.
412  //event types
413  Tabbed items are fully working
414  items with one space are partially implemented of known to not work
415  other items are unimplemented
416  SDL_FIRSTEVENT unused (do not remove) Application events
417  SDL_QUIT user-requested quit Window events
418  SDL_WINDOWEVENT window state change
419  SDL_SYSWMEVENT system specific event Keyboard events
420  SDL_KEYDOWN key pressed
421  SDL_KEYUP key released
422  SDL_TEXTEDITING keyboard text editing (composition)
423  SDL_TEXTINPUT keyboard text input Mouse events
424  SDL_MOUSEMOTION mouse moved
425  SDL_MOUSEBUTTONDOWN mouse button pressed
426  SDL_MOUSEBUTTONUP mouse button released
427  SDL_MOUSEWHEEL mouse wheel motion Tablet or multiple mice input device events
428  SDL_INPUTMOTION input moved
429  SDL_INPUTBUTTONDOWN input button pressed
430  SDL_INPUTBUTTONUP input button released
431  SDL_INPUTWHEEL input wheel motion
432  SDL_INPUTPROXIMITYIN input pen entered proximity
433  SDL_INPUTPROXIMITYOUT input pen left proximity Joystick events
434  SDL_JOYAXISMOTION joystick axis motion
435  SDL_JOYBALLMOTION joystick trackball motion
436  SDL_JOYHATMOTION joystick hat position change
437  SDL_JOYBUTTONDOWN joystick button pressed
438  SDL_JOYBUTTONUP joystick button released Touch events
439  SDL_FINGERDOWN
440  SDL_FINGERUP
441  SDL_FINGERMOTION
442  SDL_TOUCHBUTTONDOWN
443  SDL_TOUCHBUTTONUP Gesture events
444  SDL_DOLLARGESTURE
445  SDL_DOLLARRECORD
446  SDL_MULTIGESTURE Clipboard events
447  SDL_CLIPBOARDUPDATE the clipboard changed Obsolete events
448  SDL_EVENT_COMPAT1 SDL 1.2 events for compatibility
449  SDL_EVENT_COMPAT2 SDL 1.2 events for compatibility
450  SDL_EVENT_COMPAT3 SDL 1.2 events for compatibility These are for your use, and should be allocated with
451  SDL_RegisterEvents()
452  SDL_USEREVENT a user-specified event
453  SDL_LASTEVENT only for bounding internal arrays
454  */
455 
456  while(SDL_PollEvent(&FromSDLRaw))
457  {
458  switch(FromSDLRaw.type)
459  {
460  //Events and User input sorted by estimate frequency
461  case SDL_MOUSEBUTTONUP: case SDL_KEYUP: case SDL_JOYBUTTONUP:
462  case SDL_KEYDOWN: case SDL_MOUSEBUTTONDOWN: case SDL_JOYBUTTONDOWN:
463  case SDL_JOYAXISMOTION: case SDL_JOYHATMOTION: case SDL_JOYBALLMOTION:
464  case SDL_MOUSEMOTION: case SDL_TEXTINPUT:
465  FromSDLEvent->AddCodes( Input::MetaCode::CreateMetaCodes(FromSDLRaw) );
466  break;
467 
468  case SDL_WINDOWEVENT: {
469  EventGameWindow* React = new EventGameWindow(FromSDLRaw);
470  /*if(EventGameWindow::GAME_WINDOW_FOCUS_LOST==React->GetEventID()) //we dropp all keypresses when windows are switched
471  { ClearKeyPresses = true; }// */
472  this->AddEvent(React);
473  break; }
474 
475  case SDL_SYSWMEVENT:
476  // call a function with ifdefs here
477  break;
478 
479  // Error conditions
480  case SDL_FIRSTEVENT: // Capture and ignore or throw error
481  { MEZZ_EXCEPTION(ExceptionBase::PARAMETERS_EXCEPTION,"Unexpected 'FIRSTEVENT' event in event manager. User input seems corrupted."); break; }
482 
483  case SDL_QUIT: //when SDL closes, but this really should be handled somewhere else, like the UpdateQuitEvents() function
484  { MEZZ_EXCEPTION(ExceptionBase::PARAMETERS_EXCEPTION,"Unexpected Quit event in event manager."); break; }
485 
486  default: //Never thrown by SDL, but could be added by a user
487  //Entresol::GetSingletonPtr()->LogAndThrow("Unknown SDL Event Inserted.");
488  //Entresol::GetSingletonPtr()->_Log("Unknown SDL Event Inserted. Likely an unhandled SDL 1.3 event");
489  break;
490  }
491  //free(FromSDLRaw); //Does this need to Happen?
492  }
493 
494  /*if(ClearKeyPresses)
495  { this->_Data->DropAllKeyPresses(); }// */
496 
497  #ifdef MEZZDEBUG
498  /*Entresol::GetSingletonPtr()->Log("User Input entered this Frame");
499  for(EventUserInput::iterator LIter=FromSDLEvent->begin(); FromSDLEvent->end()!=LIter; ++LIter)
500  {
501  Entresol::GetSingletonPtr()->Log(*LIter);
502  }
503  Entresol::GetSingletonPtr()->Log("End Of User Input entered this Frame");
504  Entresol::GetSingletonPtr()->DoMainLoopLogging();// */
505  #endif
506 
507  // Check to see if we should add a User input event or not. We wouldn't want to pass an empty event
508  if(FromSDLEvent->GetMetaCodeCount()==0)
509  {
510  delete FromSDLEvent;
511  }else{
512  _Data->EventQ.push_back(FromSDLEvent);
513  }
514  }
515 
516  ///////////////////////////////////////////////////////////////////////////////
517  // Filtered management functions - GameWindow Events
518 
520  { return dynamic_cast<EventGameWindow*> (this->GetNextSpecificEvent(EventBase::GameWindow)); }
521 
523  { return dynamic_cast<EventGameWindow*> (this->PopNextSpecificEvent(EventBase::GameWindow)); }
524 
527 
528  std::list<EventGameWindow*>* EventManager::GetAllGameWindowEvents()
529  { return (std::list<EventGameWindow*>*)this->GetAllSpecificEvents(EventBase::GameWindow); }
530 
531  ///////////////////////////////////////////////////////////////////////////////
532  // Filtered management functions - User Input Events
533 
535  { return dynamic_cast<EventUserInput*> (this->GetNextSpecificEvent(EventBase::UserInput)); }
536 
538  { return dynamic_cast<EventUserInput*> (this->PopNextSpecificEvent(EventBase::UserInput)); }
539 
542 
543  std::list<EventUserInput*>* EventManager::GetAllUserInputEvents()
544  { return (std::list<EventUserInput*>*)this->GetAllSpecificEvents(EventBase::UserInput); }
545 
546  ///////////////////////////////////////////////////////////////////////////////
547  // Filtered management functions - Quit Event
548 
550  { return dynamic_cast<EventQuit*> (this->GetNextSpecificEvent(EventBase::QuitMessage)); }
551 
553  { return dynamic_cast<EventQuit*> (this->PopNextSpecificEvent(EventBase::QuitMessage)); }
554 
557 
558  std::list<EventQuit*>* EventManager::GetAllQuitEvents()
559  { return (std::list<EventQuit*>*)this->GetAllSpecificEvents(EventBase::QuitMessage); }
560 
561  ///////////////////////////////////////////////////////////////////////////////
562  // Filtered management functions - You choose YAYYYY!!!
563  ///////////////////////////////////////
565  {
566  EventBase* results = 0;
567  for(std::list<EventBase*>::iterator Iter = _Data->EventQ.begin(); Iter!=_Data->EventQ.end(); ++Iter)
568  {
569  if((*Iter)->GetType()==SpecificType)
570  {
571  results = (*Iter);
572  return results;
573  }
574  }
575  return results;
576  }
577 
579  {
580  EventBase* results = 0;
581  for(std::list<EventBase*>::iterator Iter = _Data->EventQ.begin(); Iter!=_Data->EventQ.end(); ++Iter)
582  {
583  if((*Iter)->GetType()==SpecificType)
584  {
585  results = (*Iter);
586  _Data->EventQ.erase(Iter);
587  return results;
588  }
589  }
590  return results;
591  }
592 
594  {
595  for(std::list<EventBase*>::iterator Iter = _Data->EventQ.begin(); Iter!=_Data->EventQ.end(); ++Iter)
596  {
597  if((*Iter)->GetType()==SpecificType)
598  {
599  _Data->EventQ.erase(Iter);
600  return;
601  }
602  }
603  }
604 
605  std::list<EventBase*>* EventManager::GetAllSpecificEvents(EventBase::EventType SpecificType)
606  {
607  std::list<EventBase*>* TempList = new std::list<EventBase*>;
608 
609  for(std::list<EventBase*>::iterator Iter = _Data->EventQ.begin(); Iter!=_Data->EventQ.end(); ++Iter)
610  {
611  if((*Iter)->GetType()==SpecificType)
612  {
613  TempList->push_back(*Iter);
614  }
615  }
616  return TempList;
617  }
618 
620  {
621  for( std::list<EventBase*>::iterator Iter = _Data->EventQ.begin() ; Iter!=_Data->EventQ.end() ; )
622  {
623  if((*Iter)->GetType()==SpecificType)
624  {
625  std::list<EventBase*>::iterator prev = Iter++;
626  this->_Data->EventQ.erase(prev);
627  }
628  else ++Iter;
629  }
630  }
631 
632  ///////////////////////////////////////////////////////////////////////////////
633  // Polling Functions
634 
635  void EventManager::AddPollingCheck(const Input::MetaCode& InputToTryPolling)
636  {
637  if(InputToTryPolling.IsPollable())
638  {
639  this->_Data->AddInputCodeToManualCheck(InputToTryPolling.GetCode(), Internal::EventManagerInternalData::Polling);
640  }else{
641  MEZZ_EXCEPTION(ExceptionBase::PARAMETERS_EXCEPTION,"Unsupported Polling Check on this Platform");
642  }
643  }
644 
645  void EventManager::RemovePollingCheck(const Input::MetaCode& InputToStopPolling)
646  {
647  this->_Data->RemoveInputCodeToManualCheck(InputToStopPolling.GetCode(), Internal::EventManagerInternalData::Polling);
648  }
649 
650  ///////////////////////////////////////////////////////////////////////////////
651  // Utility
652 
654  {
655  if( !this->Initialized )
656  {
657  this->TheEntresol->GetScheduler().AddWorkUnitMain( this->_Data->EventPumpWork, "EventPumpWork" );
658  this->Initialized = true;
659  }
660  }
661 
663  {
664  if( this->Initialized )
665  {
667  this->Initialized = false;
668  }
669  }
670 
672  { return this->_Data->EventPumpWork; }
673 
674  ///////////////////////////////////////////////////////////////////////////////
675  // Type Identifier Methods
676 
678  { return EventManager::InterfaceType; }
679 
682 
683  ///////////////////////////////////////////////////////////////////////////////
684  // DefaultEventManagerFactory Methods
685 
687  { }
688 
690  { }
691 
694 
696  { return EventManager::InterfaceType; }
697 
699  {
701  /// @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.
703  }else return new EventManager();
704  }
705 
707  {
709  /// @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.
711  }else return new EventManager(XMLNode);
712  }
713 
715  { delete ToBeDestroyed; }
716 }//Mezzanine
717 
718 
719 ///////////////////////////////////////////////////////////////////////////////
720 // Class External << Operators for streaming or assignment
721 std::ostream& operator << (std::ostream& stream, const Mezzanine::EventManager& Mgr)
722 {
723  stream << "<EventManager Version=\"1\">";
724  for(std::list<Mezzanine::EventBase*>::iterator Iter = Mgr._Data->EventQ.begin(); Iter!=Mgr._Data->EventQ.end(); ++Iter)
725  { stream << **Iter; }
727  { stream << "<ManualCheck Version=\"1\" PollingType=\"" << Iter->second << "\" InputCode=\"" << Iter->first << "\" />"; }
728  stream << "</EventManager>";
729 
730  return stream;
731 }
732 
733 std::istream& MEZZ_LIB operator >> (std::istream& stream, Mezzanine::EventManager& Mgr)
734 {
737 
738  Doc->GetFirstChild() >> Mgr;
739 
740  return stream;
741 }
742 
744 {
745  if(Mezzanine::String(OneNode.Name()) == Mezzanine::String("EventManager"))
746  {
747  if (OneNode.GetAttribute("Version").AsInt() == 1)
748  {
749  Mezzanine::XML::Node Child = OneNode.GetFirstChild();
750  while(Child)
751  {
752  Mezzanine::String TagName(Child.Name());
753  if(TagName.length()>6) // I am pretty sure that the easiest wat to identify an event is by looking at the 6th
754  { // Character and seeing what the actual name of the event is. So that is what this does.
755  switch(TagName[5])
756  {
757  case 'l':{
759  (Child.GetAttribute("InputCode").AsInt()),
760  (Child.GetAttribute("PollingType").AsInt())
761  );}
762  break;
763  case 'G':{
765  Child >> *temp;
766  Mgr.AddEvent(temp); }
767  break;
768  case 'Q':{
770  Child >> *temp;
771  Mgr.AddEvent(temp); }
772  break;
773  case 'U':{
775  Child >> *temp;
776  Mgr.AddEvent(temp); }
777  break;
778  case 'O':{
779  MEZZ_EXCEPTION(Mezzanine::ExceptionBase::PARAMETERS_EXCEPTION,"Attemping to serialize a Mezzanine::Event::Other... not sure what you are trying to serialize."); }
780  break;
781  default:{
782  MEZZ_EXCEPTION(Mezzanine::ExceptionBase::PARAMETERS_EXCEPTION,"Attemping to serialize a Mezzanine::Event... not sure what you are trying to serialize."); }
783  break;
784  }
785  }else{
786  MEZZ_EXCEPTION(Mezzanine::ExceptionBase::PARAMETERS_EXCEPTION,"Invalid event, name is not long enough to identify event.");
787  } // end if name length
788  Child = Child.GetNextSibling();
789  } // end while
790  }else{
791  MEZZ_EXCEPTION(Mezzanine::ExceptionBase::INVALID_VERSION_EXCEPTION,"Incompatible XML Version for EventManager: Not Version 1");
792  } // if version
793  }else{
794  MEZZ_EXCEPTION(Mezzanine::ExceptionBase::PARAMETERS_EXCEPTION,"Attempting to deserialize an EventManager, event mananger not found.");
795  }// if event
796 }
797 
798 
799 
800 #endif
String GetOneTag(std::istream &stream)
Gets the first tag out of the Stream and returns it as a String.
Definition: xmlstring.cpp:72
std::ostream & operator<<(std::ostream &stream, const Mezzanine::LinearInterpolator< T > &Lint)
Used to Serialize an Mezzanine::LinearInterpolator to a human readable stream.
Definition: interpolator.h:433
void AddMetaCodesToManualCheck(std::vector< Input::MetaCode > Transport, PollingType _PollingCheck)
Used to insert Codes into the list of items to be manually checked.
std::list< EventUserInput * > * GetAllUserInputEvents()
This returns a complete list of all the User Input events.
InputCode
The InputCode enum defines all the posible types of inputs.
EventPumpWorkUnit * EventPumpWork
This is the workunit that does the work each frame.
std::list< EventQuit * > * GetAllQuitEvents()
This returns a complete list of all the quit events.
virtual void DoWork(Threading::DefaultThreadSpecificStorage::Type &CurrentThreadStorage)
This does the actual work of the getting the data form the OS.
static EventManager * SingletonPtr
The one and only pointer to the single object.
Definition: singleton.h:72
void UpdateEvents()
Pulls Events from the all the subsystems for use in the EventManager.
void RemoveMetaCodesToManualCheck(const Input::MetaCode &OneCode, PollingType _PollingCheck)
Removes one type of polling check.
std::list< EventGameWindow * > * GetAllGameWindowEvents()
This returns a complete list of all the Render Time events.
Thrown when an unknown internal error occurred.
Definition: exception.h:116
std::stringstream Logger
In case we ever replace the stringstream with another class, this will allow us to swap it out...
Definition: datatypes.h:180
bool Boole
Generally acts a single bit, true or false.
Definition: datatypes.h:173
EventGameWindow * PopNextGameWindowEvent()
Returns a pointer to the Next GameWindow event and removes it from the Que.
EventUserInput * PopNextUserInputEvent()
Returns a pointer to the Next User Input event and removes it from the Que.
virtual void AddWorkUnitMain(iWorkUnit *MoreWork, const String &WorkUnitName)
Add a normal Mezzanine::Threading::iWorkUnit to this For fcheduling.
Used to increase encapsulation, just a bit.
void AddInputCodeToManualCheck(Input::InputCode OneCode, PollingType _PollingCheck)
Adds one type of polling check.
EventPumpWorkUnit & operator=(const EventPumpWorkUnit &Other)
Protected assignment operator. THIS IS NOT ALLOWED.
ManagerType
A listing of Manager Types.
Definition: managerbase.h:65
EventBase * GetNextSpecificEvent(EventBase::EventType SpecificType)
Returns a pointer to the Next kind event of the Specified type.
std::list< EventBase * > EventQ
The Queue that all the events get stored in.
Document * PreParseClassFromSingleTag(const String &NameSpace, const String &ClassName, const String &OneTag)
Perform a basic series of checks for extracting meaning from a single xml tag.
Definition: xmlstring.cpp:116
EventPumpWorkUnit(const EventPumpWorkUnit &Other)
Protected copy constructor. THIS IS NOT ALLOWED.
virtual void RemoveWorkUnitMain(iWorkUnit *LessWork)
Remove a WorkUnit from the main pool of WorkUnits (and not from the groups of Affinity or MonpolyWork...
Node GetFirstChild() const
Get the first child Node of this Node.
#define MEZZ_EXCEPTION(num, desc)
An easy way to throw exceptions with rich information.
Definition: exception.h:3048
DefaultEventManagerFactory()
Class constructor.
A simple reference counting pointer.
Definition: countedptr.h:70
Thrown when a version is accessed/parsed/required and it cannot work correctly or is missing...
Definition: exception.h:112
void RemovePollingCheck(const Input::MetaCode &InputToStopPolling)
Removes Events from the list(s) of what needs to be polled.
This is a container for MetaCodes that is used in the EventManager.
Boole IsPollable() const
Is this metacode a pollable event.
Definition: metacode.cpp:373
virtual void Initialize()
Configures this manager for use prior to entering the main loop.
Threading::FrameScheduler & GetScheduler()
Gets the core structure responsible for scheduling work in the Entresol main loop.
Definition: entresol.cpp:495
EventUserInput * GetNextUserInputEvent()
Returns a pointer to the Next User Input event.
std::map< Input::InputCode, PollingType > ManualCheck
A unified polling and event repeater the Inputcode is the kind of event to check for each frame...
Every frame the OS must be queried for changes to the state, this does that querying on behalf of an ...
Definition: eventmanager.h:108
EventBase * PopNextSpecificEvent(EventBase::EventType SpecificType)
Returns a pointer to the Next kind event of the Specified type, and removes it from the Que...
EventPumpWorkUnit * GetEventPumpWork()
Gets the work unit responsible for pumping events from the OS.
SDL_Event RawEvent
This is an internal datatype use to communicate with the User input Subsystem.
Definition: datatypes.h:219
static const String ImplementationName
A String containing the name of this manager implementation.
Definition: eventmanager.h:164
EventQuit * GetNextQuitEvent()
Returns a pointer to the Next EventQuit.
Internal::EventManagerInternalData * _Data
All the internal data for this EventManager.
Definition: eventmanager.h:170
EventBase * PopNextEvent()
Return a pointer to the Next event, and removes the Event from storage.
Node GetNextSibling() const
Attempt to retrieve the next sibling of this Node.
EventManager()
Default constructor.
void DropAllKeyPresses()
Drops all keypresses from the list of items to be perpetuated each frame.
EventManagerInternalData()
Constructor, it only inits pointers to 0.
A thread specific collection of double-buffered and algorithm specific resources. ...
static const ManagerBase::ManagerType InterfaceType
A ManagerType enum value used to describe the type of interface/functionality this manager provides...
Definition: eventmanager.h:166
static Boole SingletonValid()
Checks to see if the singleton pointer is valid.
Definition: singleton.h:110
void AddInputCodesToManualCheck(int OneCode, int _PollingCheck)
Adds one type of polling check where the data is only available as Ints.
virtual String GetImplementationTypeName() const
This Allows any manager name to be sent to a stream. Primarily used for logging.
EventType
A listing of values that can be used to identify Events.
Definition: eventbase.h:66
static InputManager * GetSingletonPtr()
Fetches a pointer to the singleton.
Definition: singleton.h:97
std::list< EventBase * > * GetAllSpecificEvents(EventBase::EventType SpecificType)
This returns a complete list of all the specified events.
This is the base class for all managers that do no describe properties of a single world...
void RemoveNextUserInputEvent()
Removes the First User Input Event From the que without looking at it.
EventGameWindow * GetNextGameWindowEvent()
Returns a pointer to the Next GameWindow event.
The base class for all events.
Definition: eventbase.h:61
A light-weight handle for manipulating nodes in DOM tree.
Definition: node.h:89
void AddPollingCheck(const Input::MetaCode &InputToTryPolling)
Generates extra events each iteration of the main loop, based on user input polling.
void RemoveNextGameWindowEvent()
Removes the First GameWindow Event From the que without looking at it.
void RemoveMetaCodesToManualCheck(std::vector< Input::MetaCode > Transport, PollingType _PollingCheck)
Remove Items form the internal manual check list.
virtual ~EventPumpWorkUnit()
Virtual Deconstructor.
int AsInt(int def=0) const
Attempts to convert the value of the attribute to an int and returns the results. ...
uint32_t UInt32
An 32-bit unsigned integer.
Definition: datatypes.h:126
void RemoveAllSpecificEvents(EventBase::EventType SpecificType)
This removes all the events of the specified type.
static MetaCodeContainer CreateMetaCodes(const RawEvent &Raw)
Internal creation method.
Definition: metacode.cpp:99
void AddEvent(EventBase *EventToAdd)
Adds an event of any kind to the end of the Event Queue.
void RemoveEvent(EventBase *EventToRemove)
Removes an event of any kind from the Event Queue.
Input::MetaCode AddCode(const Input::MetaCode &Code_)
Adds a MetaCode.
void RemoveNextQuitEvent()
Removes the First EventQuit From the que without looking at it.
Entresol * TheEntresol
The actual pointer to the Entresol core class.
Definition: managerbase.h:108
This is intended to convey the message that quitting needs to happen.
Definition: eventquit.h:63
PollingType
The kinds of data that can be stored in Manual Check.
Logger & GetUsableLogger()
Get the usable logger for this thread specific resource.
size_t GetRemainingEventCount()
Gets a count of events.
String GetManagerImplName() const
Gets the name of the manager that is created by this factory.
std::list< NameValuePair > NameValuePairList
This is a datatype mostly used for describing settings or parameters that can't be declared in advanc...
Definition: datatypes.h:206
Input::InputCode GetCode() const
This Returns the Inputcode.
Definition: metacode.cpp:244
void DestroyManager(EntresolManager *ToBeDestroyed)
Destroys a Manager created by this factory.
virtual ~DefaultEventManagerFactory()
Class destructor.
void RemoveInputCodeToManualCheck(const Input::InputCode &OneCode, PollingType _PollingCheck)
Removes one type of polling check.
Thrown when parameters are checked at runtime and found invalid.
Definition: exception.h:108
This Determines the kind of user input.
Definition: metacode.h:93
size_t GetMetaCodeCount()
Retrieves a count of the stored Metacodes.
virtual ManagerType GetInterfaceType() const
This returns the type of this manager.
void AddCodes(const std::vector< Input::MetaCode > &Codes)
Add Several MetaCodes from a vector.
void RemovePollingCheck(ManualCheckIterator Reduce, PollingType _PollingCheck)
Remove a kind polling check from an item or remove item if that is the last check.
void RemoveNextSpecificEvent(EventBase::EventType SpecificType)
Returns a pointer to the Next kind event of the Specified type, and removes it from the Que...
EventQuit * PopNextQuitEvent()
Returns a pointer to the Next EventQuit and removes it from the Que.
#define MEZZ_LIB
Some platforms require special decorations to denote what is exported/imported in a share library...
void AddMetaCodesToManualCheck(const Input::MetaCode &OneCode, PollingType _PollingCheck)
Adds one type of polling check where the data is only available as Ints.
The bulk of the engine components go in this namspace.
Definition: actor.cpp:56
std::istream & operator>>(std::istream &stream, Mezzanine::LinearInterpolator< T > &Lint)
Used to de-serialize an Mezzanine::LinearInterpolator from a stream.
Definition: interpolator.h:448
Convey the message that Something happened to a game window.
EntresolManager * CreateManager(const NameValuePairList &Params)
Creates a manager of the type represented by this factory.
const Char8 * Name() const
ptrdiff_tGet the name of this Node.
void UpdateQuitEvents()
Checks for quit messages and adds them to the queue.
std::map< Input::InputCode, PollingType >::iterator ManualCheckIterator
an Iterator suitable for use with internal structures that correlate polling type and metacodes ...
ManagerBase::ManagerType GetManagerType() const
Gets the type of manager that is created by this factory.
EventManager * TargetManager
The Manager this does the work for.
Definition: eventmanager.h:113
virtual void Deinitialize()
Removes this manager from any necessary configuration so it can be safely disposed of...
void RemoveNextEvent()
Removes an Event From the que without looking at it.
This is a container for Events and facilitates the transfer of data.
Definition: eventmanager.h:160
std::string String
A datatype used to a series of characters.
Definition: datatypes.h:159
EventBase * GetNextEvent()
Return a pointer to the Next event.
Attribute GetAttribute(const Char8 *Name) const
Attempt to get an Attribute on this Node with a given name.
virtual ~EventManager()
Default Deconstructor.
Boole Initialized
Simple Boole indicating whether or not this manager has been initialized.
Definition: managerbase.h:111