MezzanineEngine 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
inputmanager.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 _inputinputmanager_cpp
41 #define _inputinputmanager_cpp
42 
43 #include "inputmanager.h"
44 #include "eventmanager.h"
45 #include "eventuserinput.h"
46 #include "entresol.h"
47 #include "Input/mouse.h"
48 #include "Input/keyboard.h"
49 #include "Input/controller.h"
50 #include "timer.h"
51 
52 #include "SDL.h"
53 
54 namespace Mezzanine
55 {
56  template<> Input::InputManager* Singleton<Input::InputManager>::SingletonPtr = NULL;
57 
58  namespace Input
59  {
60  ///////////////////////////////////////////////////////////////////////////////
61  /// @class InputManagerInternalData
62  /// @brief This is an class for the handling of internal input data.
63  /// @details
64  ///////////////////////////////////////
66  {
67  public:
68  typedef std::pair<Input::Controller*,SDL_Joystick*> ControllerPair;
69  typedef std::vector< ControllerPair > ControllerContainer;
70  typedef ControllerContainer::iterator ControllerIterator;
71  typedef ControllerContainer::const_iterator ConstControllerIterator;
72  protected:
73  public:
74  ControllerContainer Controllers;
75 
76  /// @brief Class constructor.
78  { }
79  /// @brief Class destructor.
81  { this->Controllers.clear(); }
82  };//InputManangerInternalData
83 
84  typedef InputManagerInternalData::ControllerPair InternalControlPair;
85  typedef InputManagerInternalData::ControllerIterator InternalControlIterator;
86 
87  ///////////////////////////////////////////////////////////////////////////////
88  // DeviceUpdateWorkUnit Methods
89 
91  { }
92 
94  { return *this; }
95 
97  TargetManager(Target) { }
98 
100  { }
101 
102  ///////////////////////////////////////////////////////////////////////////////
103  // Utility
104 
106  {
107  // Set up our containers for the update
108  this->TargetManager->InputDeltas.clear();
109  std::vector< Input::MetaCode > MouseCodes;
110  std::vector< Input::MetaCode > KeyboardCodes;
111  std::vector< std::vector< Input::MetaCode > > ControllerCodes;
112  ControllerCodes.resize( this->TargetManager->GetNumControllers() );
113  // And finally our container for our generated codes
114  std::vector< Input::MetaCode > GeneratedCodes;
115 
116  // Get the user input events for processing
117  std::list<EventUserInput*>* UserInput = EventManager::GetSingletonPtr()->GetAllUserInputEvents();
119 
120  // Process the aquired user input events
121  while( !UserInput->empty() )
122  {
123  EventUserInput* CurrEvent = UserInput->front();
124  for( Whole X = 0 ; X < CurrEvent->size() ; ++X )
125  {
126  Input::MetaCode& CurrCode = CurrEvent->at(X);
127  this->TargetManager->InputDeltas.push_back(CurrCode);
128  if( Input::MOUSE_FIRST <= CurrCode.GetCode() && Input::MOUSE_LAST >= CurrCode.GetCode() ){
129  MouseCodes.push_back( CurrCode );
130  }else if( Input::KEY_FIRST <= CurrCode.GetCode() && Input::KEY_LAST >= CurrCode.GetCode() ){
131  KeyboardCodes.push_back( CurrCode );
132  }else if( Input::CONTROLLER_FIRST <= CurrCode.GetCode() && Input::CONTROLLER_LAST >= CurrCode.GetCode() ){
133  ControllerCodes[ CurrCode.GetDeviceIndex() ].push_back( CurrCode );
134  }
135  }
136 
137  delete CurrEvent;
138  UserInput->pop_front();
139  }
140  delete UserInput;
141  UserInput = NULL;
142 
143  // Update all of our devices with the processed/saved data
144  this->TargetManager->SystemMouse->_Update(MouseCodes,GeneratedCodes);
145  this->TargetManager->SystemKeyboard->_Update(KeyboardCodes,GeneratedCodes);
146  for( Whole X = 0 ; X < this->TargetManager->GetNumControllers() ; ++X )
147  {
148  this->TargetManager->IMID->Controllers.at(X).first->_Update( ControllerCodes.at(X) , GeneratedCodes );
149  }
150  // Do sub-system wide sequence checks if we've done anything
151  if( !this->TargetManager->InputDeltas.empty() )
152  this->TargetManager->Sequences.Update(this->TargetManager->InputDeltas,GeneratedCodes);
153  // Update our delta's if there is anything to update
154  if( !GeneratedCodes.empty() )
155  this->TargetManager->InputDeltas.insert(this->TargetManager->InputDeltas.end(),GeneratedCodes.begin(),GeneratedCodes.end());
156  }
157 
158  ///////////////////////////////////////////////////////////////////////////////
159  // InputManager Methods
160 
161  //template<> InputManager* Singleton<InputManager>::SingletonPtr = NULL;
162 
164  IMID(NULL),
165  SystemMouse(NULL),
166  SystemKeyboard(NULL),
167 
168  DeviceUpdateWork(NULL),
169  ThreadResources(NULL)
170  {
171  UInt32 InitSDLSystems = SDL_WasInit(0);
172  if( (SDL_INIT_JOYSTICK & InitSDLSystems) == 0 )
173  {
174  if( SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) < 0 )
175  { MEZZ_EXCEPTION(Exception::INTERNAL_EXCEPTION,String("Failed to Initialize SDL for Joystick input, SDL Error: ") + SDL_GetError()); }
176  }
177  if( !(SDL_INIT_GAMECONTROLLER | InitSDLSystems) )
178  {
179  if( SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_NOPARACHUTE) < 0 )
180  { MEZZ_EXCEPTION(Exception::INTERNAL_EXCEPTION,String("Failed to Initialize SDL for Game Controller input, SDL Error: ") + SDL_GetError()); }
181  }
182 
183  this->IMID = new InputManagerInternalData();
184  this->SystemMouse = new Mouse();
185  this->SystemKeyboard = new Keyboard();
186  this->DetectControllers();
187 
188  this->DeviceUpdateWork = new DeviceUpdateWorkUnit(this);
189  }
190 
192  IMID(NULL),
193  SystemMouse(NULL),
194  SystemKeyboard(NULL),
195 
196  DeviceUpdateWork(NULL),
197  ThreadResources(NULL)
198  {
199  UInt32 InitSDLSystems = SDL_WasInit(0);
200  if( (SDL_INIT_JOYSTICK & InitSDLSystems) == 0 )
201  {
202  if( SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) < 0 )
203  { MEZZ_EXCEPTION(Exception::INTERNAL_EXCEPTION,String("Failed to Initialize SDL for Joystick input, SDL Error: ") + SDL_GetError()); }
204  }
205  if( !(SDL_INIT_GAMECONTROLLER | InitSDLSystems) )
206  {
207  if( SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_NOPARACHUTE) < 0 )
208  { MEZZ_EXCEPTION(Exception::INTERNAL_EXCEPTION,String("Failed to Initialize SDL for Game Controller input, SDL Error: ") + SDL_GetError()); }
209  }
210 
211  this->IMID = new InputManagerInternalData();
212  this->SystemMouse = new Mouse();
213  this->SystemKeyboard = new Keyboard();
214  this->DetectControllers();
215 
216  this->DeviceUpdateWork = new DeviceUpdateWorkUnit(this);
217  }
218 
220  {
221  this->Deinitialize();
222 
223  delete DeviceUpdateWork;
224 
225  delete SystemMouse;
226  delete SystemKeyboard;
227  this->ReleaseAllControllers();
228  }
229 
230  ///////////////////////////////////////////////////////////////////////////////
231  // InputDevice Management
232 
234  {
235  return this->SystemMouse;
236  }
237 
239  {
240  return this->SystemKeyboard;
241  }
242 
244  {
245  return this->IMID->Controllers.at(Index).first;
246  }
247 
249  {
250  return this->IMID->Controllers.size();
251  }
252 
253  ///////////////////////////////////////////////////////////////////////////////
254  // InputDevice Detection
255 
257  {
258  UInt16 Count;
259  for( Count = 0 ; Count < SDL_NumJoysticks() ; ++Count )
260  {
261  SDL_Joystick* InternalControl = SDL_JoystickOpen(Count);
262  Input::Controller* NewController = new Input::Controller( InternalControl, Count );
263  this->IMID->Controllers.push_back( InternalControlPair(NewController,InternalControl) );
264  }
265  return Count;
266  }
267 
269  {
270  if( this->IMID->Controllers.empty() )
271  return;
272 
273  for( InternalControlIterator ContIt = this->IMID->Controllers.begin() ; ContIt != this->IMID->Controllers.end() ; ++ContIt )
274  {
275  delete (*ContIt).first;
276  SDL_JoystickClose( (SDL_Joystick*)(*ContIt).second );
277  }
278  this->IMID->Controllers.clear();
279  }
280 
281  ///////////////////////////////////////////////////////////////////////////////
282  // Sequenced Input Management
283 
284  void InputManager::AddInputSequence(const MetaCodeContainer& Codes, const Int32& SequenceID)
285  { this->Sequences.AddInputSequence(Codes,SequenceID); }
286 
287  bool InputManager::InputSequenceExists(const MetaCodeContainer& Codes)
288  { return this->Sequences.InputSequenceExists(Codes); }
289 
290  Int32 InputManager::GetIDofInputSequence(const MetaCodeContainer& Codes)
291  { return this->Sequences.GetIDofInputSequence(Codes); }
292 
293  void InputManager::RemoveInputSequence(const MetaCodeContainer& Codes)
294  { this->Sequences.RemoveInputSequence(Codes); }
295 
298 
299  ///////////////////////////////////////////////////////////////////////////////
300  // Utility
301 
302  const MetaCodeContainer& InputManager::GetInputDeltas() const
303  {
304  return InputDeltas;
305  }
306 
308  {
309  if( !this->Initialized )
310  {
311  this->TheEntresol->GetScheduler().AddWorkUnitMain( this->DeviceUpdateWork, "DeviceUpdateWork" );
313  if( EventMan )
314  this->DeviceUpdateWork->AddDependency( EventMan->GetEventPumpWork() );
315 
316  this->Initialized = true;
317  }
318  }
319 
321  {
322  if( this->Initialized )
323  {
326 
327  this->Initialized = false;
328  }
329  }
330 
332  {
333  return this->DeviceUpdateWork;
334  }
335 
336  ///////////////////////////////////////////////////////////////////////////////
337  // Type Identifier Methods
338 
340  { return ManagerBase::MT_InputManager; }
341 
343  { return "DefaultInputManager"; }
344 
345  ///////////////////////////////////////////////////////////////////////////////
346  // DefaultInputManagerFactory Methods
347 
349  {
350  }
351 
353  {
354  }
355 
357  {
358  return "DefaultInputManager";
359  }
360 
362  {
364  {
365  /// @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.
367  }else return new InputManager();
368  }
369 
371  {
373  {
374  /// @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.
376  }else return new InputManager(XMLNode);
377  }
378 
380  {
381  delete ToBeDestroyed;
382  }
383  }//Input
384 }//Mezzanine
385 
386 #endif