Spinning Topp Logo BlackTopp Studios
inc
inputmanager.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 _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  const String InputManager::ImplementationName = "DefaultInputManager";
163  const ManagerBase::ManagerType InputManager::InterfaceType = ManagerBase::MT_InputManager;
164 
166  IMID(NULL),
167  SystemMouse(NULL),
168  SystemKeyboard(NULL),
169 
170  DeviceUpdateWork(NULL),
171  ThreadResources(NULL)
172  {
173  UInt32 InitSDLSystems = SDL_WasInit(0);
174  if( (SDL_INIT_JOYSTICK & InitSDLSystems) == 0 )
175  {
176  if( SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) < 0 )
177  { MEZZ_EXCEPTION(ExceptionBase::INTERNAL_EXCEPTION,String("Failed to Initialize SDL for Joystick input, SDL Error: ") + SDL_GetError()); }
178  }
179  if( !(SDL_INIT_GAMECONTROLLER | InitSDLSystems) )
180  {
181  if( SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_NOPARACHUTE) < 0 )
182  { MEZZ_EXCEPTION(ExceptionBase::INTERNAL_EXCEPTION,String("Failed to Initialize SDL for Game Controller input, SDL Error: ") + SDL_GetError()); }
183  }
184 
185  this->IMID = new InputManagerInternalData();
186  this->SystemMouse = new Mouse();
187  this->SystemKeyboard = new Keyboard();
188  this->DetectControllers();
189 
190  this->DeviceUpdateWork = new DeviceUpdateWorkUnit(this);
191  }
192 
194  IMID(NULL),
195  SystemMouse(NULL),
196  SystemKeyboard(NULL),
197 
198  DeviceUpdateWork(NULL),
199  ThreadResources(NULL)
200  {
201  UInt32 InitSDLSystems = SDL_WasInit(0);
202  if( (SDL_INIT_JOYSTICK & InitSDLSystems) == 0 )
203  {
204  if( SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) < 0 )
205  { MEZZ_EXCEPTION(ExceptionBase::INTERNAL_EXCEPTION,String("Failed to Initialize SDL for Joystick input, SDL Error: ") + SDL_GetError()); }
206  }
207  if( !(SDL_INIT_GAMECONTROLLER | InitSDLSystems) )
208  {
209  if( SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_NOPARACHUTE) < 0 )
210  { MEZZ_EXCEPTION(ExceptionBase::INTERNAL_EXCEPTION,String("Failed to Initialize SDL for Game Controller input, SDL Error: ") + SDL_GetError()); }
211  }
212 
213  this->IMID = new InputManagerInternalData();
214  this->SystemMouse = new Mouse();
215  this->SystemKeyboard = new Keyboard();
216  this->DetectControllers();
217 
218  this->DeviceUpdateWork = new DeviceUpdateWorkUnit(this);
219  }
220 
222  {
223  this->Deinitialize();
224 
225  delete DeviceUpdateWork;
226 
227  delete SystemMouse;
228  delete SystemKeyboard;
229  this->ReleaseAllControllers();
230  }
231 
232  ///////////////////////////////////////////////////////////////////////////////
233  // InputDevice Management
234 
236  {
237  return this->SystemMouse;
238  }
239 
241  {
242  return this->SystemKeyboard;
243  }
244 
246  {
247  return this->IMID->Controllers.at(Index).first;
248  }
249 
251  {
252  return this->IMID->Controllers.size();
253  }
254 
255  ///////////////////////////////////////////////////////////////////////////////
256  // InputDevice Detection
257 
259  {
260  UInt16 Count;
261  for( Count = 0 ; Count < SDL_NumJoysticks() ; ++Count )
262  {
263  SDL_Joystick* InternalControl = SDL_JoystickOpen(Count);
264  Input::Controller* NewController = new Input::Controller( InternalControl, Count );
265  this->IMID->Controllers.push_back( InternalControlPair(NewController,InternalControl) );
266  }
267  return Count;
268  }
269 
271  {
272  if( this->IMID->Controllers.empty() )
273  return;
274 
275  for( InternalControlIterator ContIt = this->IMID->Controllers.begin() ; ContIt != this->IMID->Controllers.end() ; ++ContIt )
276  {
277  delete (*ContIt).first;
278  SDL_JoystickClose( (SDL_Joystick*)(*ContIt).second );
279  }
280  this->IMID->Controllers.clear();
281  }
282 
283  ///////////////////////////////////////////////////////////////////////////////
284  // Sequenced Input Management
285 
286  void InputManager::AddInputSequence(const MetaCodeContainer& Codes, const Int32& SequenceID)
287  { this->Sequences.AddInputSequence(Codes,SequenceID); }
288 
290  { return this->Sequences.InputSequenceExists(Codes); }
291 
293  { return this->Sequences.GetIDofInputSequence(Codes); }
294 
296  { this->Sequences.RemoveInputSequence(Codes); }
297 
300 
301  ///////////////////////////////////////////////////////////////////////////////
302  // Utility
303 
305  {
306  return InputDeltas;
307  }
308 
310  {
311  if( !this->Initialized )
312  {
313  this->TheEntresol->GetScheduler().AddWorkUnitMain( this->DeviceUpdateWork, "DeviceUpdateWork" );
315  if( EventMan )
316  this->DeviceUpdateWork->AddDependency( EventMan->GetEventPumpWork() );
317 
318  this->Initialized = true;
319  }
320  }
321 
323  {
324  if( this->Initialized )
325  {
328 
329  this->Initialized = false;
330  }
331  }
332 
334  {
335  return this->DeviceUpdateWork;
336  }
337 
338  ///////////////////////////////////////////////////////////////////////////////
339  // Type Identifier Methods
340 
342  { return InputManager::InterfaceType; }
343 
346 
347  ///////////////////////////////////////////////////////////////////////////////
348  // DefaultInputManagerFactory Methods
349 
351  { }
352 
354  { }
355 
358 
360  { return InputManager::InterfaceType; }
361 
363  {
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  /// @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.
375  }else return new InputManager(XMLNode);
376  }
377 
379  { delete ToBeDestroyed; }
380  }//Input
381 }//Mezzanine
382 
383 #endif
int32_t Int32
An 32-bit integer.
Definition: datatypes.h:124
virtual void AddDependency(iWorkUnit *NewDependency)
Force this WorkUnit to Start after another has completed.
Definition: workunit.cpp:99
std::list< EventUserInput * > * GetAllUserInputEvents()
This returns a complete list of all the User Input events.
void DestroyManager(EntresolManager *ToBeDestroyed)
Destroys a Manager created by this factory.
This class represents a controller input device, such as a gamepad or joystick.
Definition: controller.h:54
virtual ~DeviceUpdateWorkUnit()
Class destructor.
Thrown when an unknown internal error occurred.
Definition: exception.h:116
virtual ManagerType GetInterfaceType() const
This returns the type of this manager.
This class represents the mouse input device.
Definition: mouse.h:60
bool Boole
Generally acts a single bit, true or false.
Definition: datatypes.h:173
The First JoyStick event, all Controller Event values will be more than this.
virtual void AddWorkUnitMain(iWorkUnit *MoreWork, const String &WorkUnitName)
Add a normal Mezzanine::Threading::iWorkUnit to this For fcheduling.
static const ManagerBase::ManagerType InterfaceType
A ManagerType enum value used to describe the type of interface/functionality this manager provides...
Definition: inputmanager.h:141
ManagerType
A listing of Manager Types.
Definition: managerbase.h:65
This class represents the keyboard input device. ////////////////////////////////////.
Definition: keyboard.h:55
InputManager * TargetManager
A pointer to the manager this work unit is processing.
Definition: inputmanager.h:70
virtual ~DefaultInputManagerFactory()
Class destructor.
Controller * GetController(const UInt16 Index) const
Gets a controller by index.
The last MouseEvent Code, all Mouse events will be less than this.
Keyboard * SystemKeyboard
The pointer to the object representing the system keyboard.
Definition: inputmanager.h:160
Int32 GetDeviceIndex() const
Gets the currently set device index.
Definition: metacode.cpp:256
virtual void RemoveWorkUnitMain(iWorkUnit *LessWork)
Remove a WorkUnit from the main pool of WorkUnits (and not from the groups of Affinity or MonpolyWork...
#define MEZZ_EXCEPTION(num, desc)
An easy way to throw exceptions with rich information.
Definition: exception.h:3048
InputManager()
Class constructor.
This is a container for MetaCodes that is used in the EventManager.
Threading::FrameScheduler & GetScheduler()
Gets the core structure responsible for scheduling work in the Entresol main loop.
Definition: entresol.cpp:495
void AddInputSequence(const MetaCodeContainer &Codes, const Int32 &SequenceID)
Adds a custom sequence of inputs that this system will look for and generate MetaCode's for when they...
String GetManagerImplName() const
Gets the name of the manager that is created by this factory.
EventPumpWorkUnit * GetEventPumpWork()
Gets the work unit responsible for pumping events from the OS.
InputManagerInternalData * IMID
The pointer to the internal data handled by this manager.
Definition: inputmanager.h:154
virtual void Initialize()
Configures this manager for use prior to entering the main loop.
This is the manager responsible for the handling of input devices and events.
Definition: inputmanager.h:128
UInt16 GetNumControllers() const
Gets the number of controllers detected.
Mouse * SystemMouse
The pointer to the object representing the system mouse.
Definition: inputmanager.h:157
virtual ~InputManager()
Class destructor.
void RemoveInputSequence(const MetaCodeContainer &Codes)
Removes the specified custom sequence of MetaCode's. the vector of MetaCode's doesn't end with a null...
A thread specific collection of double-buffered and algorithm specific resources. ...
static Boole SingletonValid()
Checks to see if the singleton pointer is valid.
Definition: singleton.h:110
uint16_t UInt16
An 16-bit unsigned integer.
Definition: datatypes.h:122
void _Update(const MetaCodeContainer &DeltaCodes, MetaCodeContainer &GeneratedCodes)
Updates this device with the newest data.
This is a Mezzanine::Threading::iWorkUnit for the updating of the physics debug drawer.
Definition: inputmanager.h:65
void AddInputSequence(const MetaCodeContainer &Codes, const Int32 &SequenceID)
Adds a custom sequence of inputs that this system will look for and generate MetaCode's for when they...
Keyboard * GetSystemKeyboard() const
Gets the system keyboard.
static EventManager * GetSingletonPtr()
Fetches a pointer to the singleton.
Definition: singleton.h:97
This is the base class for all managers that do no describe properties of a single world...
A light-weight handle for manipulating nodes in DOM tree.
Definition: node.h:89
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.
void RemoveAllInputSequences()
Removes all stored input sequences.
static const String ImplementationName
A String containing the name of this manager implementation.
Definition: inputmanager.h:139
Boole InputSequenceExists(const MetaCodeContainer &Codes)
Checks to see if the provided sequence of MetaCode's is already being checked for. the vector of MetaCode's doesn't end with a null MetaCode, an exception will be thrown.
This is an class for the handling of internal input data.
ManagerBase::ManagerType GetManagerType() const
Gets the type of manager that is created by this factory.
DeviceUpdateWorkUnit & operator=(const DeviceUpdateWorkUnit &Other)
Protected assignment operator. THIS IS NOT ALLOWED.
Entresol * TheEntresol
The actual pointer to the Entresol core class.
Definition: managerbase.h:108
The last Keyboard InputCode, all Keys values will be less than this, and all Events will be larger th...
DeviceUpdateWorkUnit * DeviceUpdateWork
The work unit that updates the input devices with the newest data.
Definition: inputmanager.h:164
Mouse * GetSystemMouse() const
Gets the system mouse.
SequenceContainer Sequences
Container storing all the cross-device sequences this manager is to check for.
Definition: inputmanager.h:147
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
virtual void ClearDependencies()
Drop any information about what work units this one depends on.
Definition: workunit.cpp:110
virtual void DoWork(Threading::DefaultThreadSpecificStorage::Type &CurrentThreadStorage)
This does any required update of the input devices detected on this system.
DeviceUpdateWorkUnit * GetDeviceUpdateWork()
Gets the work unit responsible for updating the input device classes.
virtual void Deinitialize()
Removes this manager from any necessary configuration so it can be safely disposed of...
DeviceUpdateWorkUnit(const DeviceUpdateWorkUnit &Other)
Protected copy constructor. THIS IS NOT ALLOWED.
void ReleaseAllControllers()
Releases all controller devices from this manager.
Boole InputSequenceExists(const MetaCodeContainer &Codes)
Checks to see if the provided sequence of MetaCode's is already being checked for. the vector of MetaCode's doesn't end with a null MetaCode, an exception will be thrown.
This Determines the kind of user input.
Definition: metacode.h:93
Input::MetaCode::MetaCodeContainer MetaCodeContainer
Convenience datatype for storage of MetaCodes.
Definition: metacode.h:351
MetaCodeContainer InputDeltas
Container storing all the MetaCodes generated for the current frame.
Definition: inputmanager.h:150
Int32 GetIDofInputSequence(const MetaCodeContainer &Codes)
Gets the ID of the provided sequence of MetaCode's. the vector of MetaCode's doesn't end with a null ...
The last Controller Input Code, all Controller events will be less than this.
The bulk of the engine components go in this namspace.
Definition: actor.cpp:56
unsigned long Whole
Whole is an unsigned integer, it will be at least 32bits in size.
Definition: datatypes.h:151
The First Mouse event, all Mouse Event values will be more than this.
void Update(const MetaCodeContainer &NormalCodes, MetaCodeContainer &SequenceCodes)
Adds provided codes to the cache if necessary and checks for sequences that have been met...
EntresolManager * CreateManager(const NameValuePairList &Params)
Creates a manager of the type represented by this factory.
virtual String GetImplementationTypeName() const
This Allows any manager name to be sent to a stream. Primarily used for logging.
const MetaCodeContainer & GetInputDeltas() const
Gets all the input codes that were generated this frame.
Int32 GetIDofInputSequence(const MetaCodeContainer &Codes)
Gets the ID of the provided sequence of MetaCode's. the vector of MetaCode's doesn't end with a null ...
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
void RemoveAllInputSequences()
Removes all stored input sequences.
void RemoveInputSequence(const MetaCodeContainer &Codes)
Removes the specified custom sequence of MetaCode's. the vector of MetaCode's doesn't end with a null...
UInt16 DetectControllers()
Gathers all of the controllers that are connected to the system and creates corresponding devices for...
Boole Initialized
Simple Boole indicating whether or not this manager has been initialized.
Definition: managerbase.h:111