Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/input/src/core/InputManager.cc @ 1193

Last change on this file since 1193 was 1193, checked in by rgrieder, 16 years ago
  • OIS initialise should be complete, but need to use cmake to determine version number..
  • merged trunk back
File size: 18.6 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Reto Grieder
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30  @file
31  @brief Implementation of the InputManager that captures all the input from OIS
32         and redirects it to listeners if necessary.
33 */
34
35#include "InputManager.h"
36#include "CoreIncludes.h"
37#include "Debug.h"
38#include "InputBuffer.h"
39#include "ConsoleCommand.h"
40#include "util/Convert.h"
41
42namespace orxonox
43{
44  // ###############################
45  // ###    Internal Methods     ###
46  // ###############################
47
48  /**
49    @brief Constructor only sets member fields to initial zero values
50           and registers the class in the class hierarchy.
51  */
52  InputManager::InputManager() :
53      inputSystem_(0), keyboard_(0), mouse_(0),
54      state_(IS_UNINIT), stateRequest_(IS_UNINIT)
55  {
56    // overwrite every key binding with ""
57    _clearBindings();
58    _setNumberOfJoysticks(0);
59
60    RegisterObject(InputManager);
61  }
62
63  /**
64    @brief The one instance of the InputManager is stored in this function.
65    @return A reference to the only instance of the InputManager
66  */
67  InputManager& InputManager::_getSingleton()
68  {
69    static InputManager theOnlyInstance;
70    return theOnlyInstance;
71  }
72
73  /**
74    @brief Destructor only called at the end of the program, after main.
75  */
76  InputManager::~InputManager()
77  {
78    this->_destroy();
79  }
80
81  /**
82    @brief Creates the OIS::InputMananger, the keyboard, the mouse and
83           the joysticks and assigns the key bindings.
84    @param windowHnd The window handle of the render window
85    @param windowWidth The width of the render window
86    @param windowHeight The height of the render window
87  */
88  bool InputManager::_initialise(size_t windowHnd, int windowWidth, int windowHeight,
89        bool createKeyboard, bool createMouse, bool createJoySticks)
90  {
91    if (state_ == IS_UNINIT)
92    {
93      CCOUT(ORX_DEBUG) << "Initialising OIS components..." << std::endl;
94
95      OIS::ParamList paramList;
96      std::ostringstream windowHndStr;
97
98      // Fill parameter list
99      windowHndStr << (unsigned int)windowHnd;
100      paramList.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
101
102//#if defined OIS_LINUX_PLATFORM
103//      paramList.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true")));
104//#endif
105
106      try
107      {
108        inputSystem_ = OIS::InputManager::createInputSystem(paramList);
109        CCOUT(ORX_DEBUG) << "Created OIS input system" << std::endl;
110      }
111      catch (OIS::Exception ex)
112      {
113        CCOUT(ORX_ERROR) << "Error: Failed creating an OIS input system."
114            << "OIS message: \"" << ex.eText << "\"" << std::endl;
115        inputSystem_ = 0;
116        return false;
117      }
118
119      if (createKeyboard)
120        _initialiseKeyboard();
121
122      if (createMouse)
123        _initialiseMouse();
124
125      if (createJoySticks)
126        _initialiseJoySticks();
127
128      // Set mouse/joystick region
129      setWindowExtents(windowWidth, windowHeight);
130
131      this->state_ = IS_NONE;
132      CCOUT(ORX_DEBUG) << "Initialising OIS components done." << std::endl;
133    }
134    else
135    {
136      CCOUT(ORX_WARNING) << "Warning: OIS compoments already initialised, skipping" << std::endl;
137    }
138
139    // InputManager holds the input buffer --> create one and add it.
140    addKeyListener(new InputBuffer(), "buffer");
141
142    // Read all the key bindings and assign them
143    if (!_loadBindings())
144      return false;
145
146    CCOUT(ORX_DEBUG) << "Initialising complete." << std::endl;
147    return true;
148  }
149
150  /**
151    @brief Creates a keyboard and sets the event handler.
152  */
153  void InputManager::_initialiseKeyboard()
154  {
155    try
156    {
157#if (OIS_VERSION >> 8) == 0x0100
158    if (inputSystem_->numKeyboards() > 0)
159#elif (OIS_VERSION >> 8) == 0x0102
160    if (inputSystem_->getNumberOfDevices(OIS::OISKeyboard) > 0)
161#endif
162      {
163        keyboard_ = (OIS::Keyboard*)inputSystem_->createInputObject(OIS::OISKeyboard, true);
164        // register our listener in OIS.
165        keyboard_->setEventCallback(this);
166        // note: OIS will not detect keys that have already been down when the keyboard was created.
167        CCOUT(ORX_DEBUG) << "Created OIS keyboard" << std::endl;
168      }
169      else
170        CCOUT(ORX_WARNING) << "Warning: No keyboard found!" << std::endl;
171    }
172    catch (OIS::Exception ex)
173    {
174      CCOUT(ORX_WARNING) << "Warning: Failed to create an OIS keyboard\n"
175          << "OIS error message: \"" << ex.eText << "\"" << std::endl;
176      keyboard_ = 0;
177    }
178  }
179
180  /**
181    @brief Creates a mouse and sets the event handler.
182  */
183  void InputManager::_initialiseMouse()
184  {
185    try
186    {
187#if (OIS_VERSION >> 8) == 0x0100
188    if (inputSystem_->numMice() > 0)
189#elif (OIS_VERSION >> 8) == 0x0102
190    if (inputSystem_->getNumberOfDevices(OIS::OISMouse) > 0)
191#endif
192      {
193        mouse_ = static_cast<OIS::Mouse*>(inputSystem_->createInputObject(OIS::OISMouse, true));
194        // register our listener in OIS.
195        mouse_->setEventCallback(this);
196        CCOUT(ORX_DEBUG) << "Created OIS keyboard" << std::endl;
197      }
198      else
199        CCOUT(ORX_WARNING) << "Warning: No mouse found!" << std::endl;
200    }
201    catch (OIS::Exception ex)
202    {
203      CCOUT(ORX_WARNING) << "Warning: Failed to create an OIS mouse\n"
204          << "OIS error message: \"" << ex.eText << "\"" << std::endl;
205      mouse_ = 0;
206    }
207  }
208
209  /**
210    @brief Creates all joy sticks and sets the event handler.
211  */
212  void InputManager::_initialiseJoySticks()
213  {
214#if (OIS_VERSION >> 8) == 0x0100
215    if (inputSystem_->numJoySticks() > 0)
216    {
217      _setNumberOfJoysticks(inputSystem_->numJoySticks());
218#elif (OIS_VERSION >> 8) == 0x0102
219    if (inputSystem_->getNumberOfDevices(OIS::OISJoyStick) > 0)
220    {
221      _setNumberOfJoysticks(inputSystem_->getNumberOfDevices(OIS::OISJoyStick));
222#endif
223      for (std::vector<OIS::JoyStick*>::iterator it = joySticks_.begin(); it != joySticks_.end(); it++)
224      {
225        try
226        {
227          *it = static_cast<OIS::JoyStick*>(inputSystem_->createInputObject(OIS::OISJoyStick, true));
228          // register our listener in OIS.
229          (*it)->setEventCallback(this);
230          CCOUT(ORX_DEBUG) << "Created OIS joy stick with ID " << (*it)->getID() << std::endl;
231        }
232        catch (OIS::Exception ex)
233        {
234          CCOUT(ORX_WARNING) << "Warning: Failed to create OIS joy stick with ID" << (*it)->getID() << "\n"
235              << "OIS error message: \"" << ex.eText << "\"" << std::endl;
236          (*it) = 0;
237        }
238      }
239    }
240    else
241      CCOUT(ORX_WARNING) << "Warning: Joy stick support requested, but no joy stick was found" << std::endl;
242  }
243
244  /**
245    @brief Resizes all lists related to joy sticks and sets joy stick bindings to "".
246    @param size Number of joy sticks available.
247  */
248  void InputManager::_setNumberOfJoysticks(int size)
249  {
250    this->bindingsJoyStickButtonHold_   .resize(size);
251    this->bindingsJoyStickButtonPress_  .resize(size);
252    this->bindingsJoyStickButtonRelease_.resize(size);
253    this->bJoyStickButtonBindingsActive_.resize(size);
254    this->joyStickButtonsDown_          .resize(size);
255    this->joySticks_                    .resize(size);
256    for (int j = 0; j < size; j++)
257    {
258      bindingsJoyStickButtonPress_  [j].resize(numberOfJoyStickButtons_s);
259      bindingsJoyStickButtonRelease_[j].resize(numberOfJoyStickButtons_s);
260      bindingsJoyStickButtonHold_   [j].resize(numberOfJoyStickButtons_s);
261      for (int i = 0; i < numberOfJoyStickButtons_s; i++)
262      {
263        this->bindingsJoyStickButtonPress_  [j][i] = "";
264        this->bindingsJoyStickButtonRelease_[j][i] = "";
265        this->bindingsJoyStickButtonHold_   [j][i] = "";
266      }
267    }
268  }
269
270  /**
271    @brief Loads the key and button bindings.
272  */
273  bool InputManager::_loadBindings()
274  {
275    CCOUT(ORX_DEBUG) << "Loading key bindings..." << std::endl;
276
277    // clear all the bindings at first.
278    _clearBindings();
279
280    // TODO: Insert the code to load the bindings from file.
281    this->bindingsKeyPress_[OIS::KC_NUMPADENTER] = "activateConsole";
282    this->bindingsKeyPress_[OIS::KC_ESCAPE] = "exit";
283    this->bindingsKeyHold_[OIS::KC_U] = "exec disco.txt";
284
285    CCOUT(ORX_DEBUG) << "Loading key bindings done." << std::endl;
286    return true;
287  }
288
289  /**
290    @brief Overwrites all bindings with ""
291  */
292  void InputManager::_clearBindings()
293  {
294    for (int i = 0; i < numberOfKeys_s; i++)
295    {
296      this->bindingsKeyPress_  [i] = "";
297      this->bindingsKeyRelease_[i] = "";
298      this->bindingsKeyHold_   [i] = "";
299    }
300    for (int i = 0; i < numberOfMouseButtons_s; i++)
301    {
302      this->bindingsMouseButtonPress_  [i] = "";
303      this->bindingsMouseButtonRelease_[i] = "";
304      this->bindingsMouseButtonHold_   [i] = "";
305    }
306    for (unsigned int j = 0; j < joySticks_.size(); j++)
307    {
308      for (int i = 0; i < numberOfJoyStickButtons_s; i++)
309      {
310        this->bindingsJoyStickButtonPress_  [j][i] = "";
311        this->bindingsJoyStickButtonRelease_[j][i] = "";
312        this->bindingsJoyStickButtonHold_   [j][i] = "";
313      }
314    }
315  }
316
317  /**
318    @brief Destroys all the created input devices and sets the InputManager to construction state.
319  */
320  void InputManager::_destroy()
321  {
322    CCOUT(ORX_DEBUG) << "Destroying ..." << std::endl;
323
324    if (state_ != IS_UNINIT)
325    {
326      this->listenersKeyActive_.clear();
327      this->listenersMouseActive_.clear();
328      this->listenersJoySticksActive_.clear();
329      this->listenersKey_.clear();
330      this->listenersMouse_.clear();
331      this->listenersJoySticks_.clear();
332
333      this->keysDown_.clear();
334      this->mouseButtonsDown_.clear();
335
336      _clearBindings();
337
338      if (keyboard_)
339        inputSystem_->destroyInputObject(keyboard_);
340      keyboard_ = 0;
341
342      if (mouse_)
343        inputSystem_->destroyInputObject(mouse_);
344      mouse_ = 0;
345
346      if (joySticks_.size() > 0)
347      {
348        for (unsigned int i = 0; i < joySticks_.size(); i++)
349        {
350          if (joySticks_[i] != 0)
351            inputSystem_->destroyInputObject(joySticks_[i]);
352        }
353        _setNumberOfJoysticks(0);
354      }
355
356      if (inputSystem_)
357        OIS::InputManager::destroyInputSystem(inputSystem_);
358      inputSystem_ = 0;
359
360      if (listenersKey_.find("buffer") != listenersKey_.end())
361        delete listenersKey_["buffer"];
362
363      this->state_ = IS_UNINIT;
364    }
365    else
366      CCOUT(ORX_WARNING) << "Warning: Cannot be destroyed, since not initialised." << std::endl;
367
368    CCOUT(ORX_DEBUG) << "Destroying done." << std::endl;
369  }
370
371
372  // ###############################
373  // ###  Public Member Methods  ###
374  // ###############################
375
376  /**
377    @brief Updates the InputManager
378    @param dt Delta time
379  */
380  void InputManager::tick(float dt)
381  {
382    if (state_ == IS_UNINIT)
383      return;
384
385    // reset the game if it has changed
386    if (state_ != stateRequest_)
387    {
388      switch (stateRequest_)
389      {
390      case IS_NORMAL:
391        this->listenersKeyActive_.clear();
392        this->listenersMouseActive_.clear();
393        this->listenersJoySticksActive_.clear();
394        this->bKeyBindingsActive_            = true;
395        this->bMouseButtonBindingsActive_    = true;
396        //this->bJoySticksButtonBindingsActive_ = true;
397        break;
398
399      case IS_GUI:
400        // FIXME: do stuff
401        break;
402
403      case IS_CONSOLE:
404        this->listenersKeyActive_.clear();
405        this->listenersMouseActive_.clear();
406        //this->listenersJoyStickActive_.clear();
407        this->bKeyBindingsActive_            = false;
408        this->bMouseButtonBindingsActive_    = true;
409        //this->bJoyStickButtonBindingsActive_ = true;
410        if (listenersKey_.find("buffer") != listenersKey_.end())
411          listenersKeyActive_.push_back(listenersKey_["buffer"]);
412        else
413        {
414          // someone fiddled with the InputBuffer
415          CCOUT(2) << "Error: Cannot redirect input to console, InputBuffer instance missing." << std::endl;
416          this->bKeyBindingsActive_ = true;
417        }
418        break;
419
420      case IS_NONE:
421        this->listenersKeyActive_.clear();
422        this->listenersMouseActive_.clear();
423        //this->listenersJoyStickActive_.clear();
424        this->bKeyBindingsActive_            = false;
425        this->bMouseButtonBindingsActive_    = false;
426        //this->bJoyStickButtonBindingsActive_ = false;
427        break;
428
429      case IS_CUSTOM:
430        // don't do anything
431        break;
432      }
433      state_ = stateRequest_;
434    }
435
436    // Capture all the input. This calls the event handlers in InputManager.
437    if (mouse_)
438      mouse_->capture();
439    if (keyboard_)
440      keyboard_->capture();
441  }
442
443  /*void InputManager::_setDefaultState()
444  {
445    this->listenersKeyActive_.clear();
446    this->listenersMouseActive_.clear();
447    this->listenersJoyStickActive_.clear();
448    this->bKeyBindingsActive_            = true;
449    this->bMouseButtonBindingsActive_    = true;
450    this->bJoyStickButtonBindingsActive_ = true;
451  }*/
452
453
454  /**
455    @brief Event handler for the keyPressed Event.
456    @param e Event information
457  */
458  bool InputManager::keyPressed(const OIS::KeyEvent &e)
459  {
460    this->keysDown_.push_back(e.key);
461
462    if (this->bKeyBindingsActive_)
463    {
464      // find the appropriate key binding
465      std::string cmdStr = bindingsKeyPress_[int(e.key)];
466      if (cmdStr != "")
467      {
468        CommandExecutor::execute(cmdStr);
469        COUT(3) << "Executing command: " << cmdStr << std::endl;
470      }
471    }
472    else
473    {
474      for (std::list<OIS::KeyListener*>::const_iterator it = listenersKeyActive_.begin(); it != listenersKeyActive_.end(); it++)
475        (*it)->keyPressed(e);
476    }
477    return true;
478  }
479
480  /**
481    @brief Event handler for the keyReleased Event.
482    @param e Event information
483  */
484  bool InputManager::keyReleased(const OIS::KeyEvent &e)
485  {
486    // remove the key from the keysDown_ list
487    for (std::list<OIS::KeyCode>::iterator it = keysDown_.begin(); it != keysDown_.end(); it++)
488    {
489      if (*it == e.key)
490      {
491        keysDown_.erase(it);
492        break;
493      }
494    }
495
496    if (this->bKeyBindingsActive_)
497    {
498      // find the appropriate key binding
499      std::string cmdStr = bindingsKeyRelease_[int(e.key)];
500      if (cmdStr != "")
501      {
502        CommandExecutor::execute(cmdStr);
503        COUT(3) << "Executing command: " << cmdStr << std::endl;
504      }
505    }
506    else
507    {
508      for (std::list<OIS::KeyListener*>::const_iterator it = listenersKeyActive_.begin(); it != listenersKeyActive_.end(); it++)
509        (*it)->keyReleased(e);
510    }
511    return true;
512  }
513
514  /**
515    @brief Event handler for the mouseMoved Event.
516    @param e Event information
517  */
518  bool InputManager::mouseMoved(const OIS::MouseEvent &e)
519  {
520    return true;
521  }
522
523  /**
524    @brief Event handler for the mousePressed Event.
525    @param e Event information
526    @param id The ID of the mouse button
527  */
528  bool InputManager::mousePressed(const OIS::MouseEvent &e, OIS::MouseButtonID id)
529  {
530    return true;
531  }
532
533  /**
534    @brief Event handler for the mouseReleased Event.
535    @param e Event information
536    @param id The ID of the mouse button
537  */
538  bool InputManager::mouseReleased(const OIS::MouseEvent &e, OIS::MouseButtonID id)
539  {
540    return true;
541  }
542
543  bool InputManager::buttonPressed(const OIS::JoyStickEvent &arg, int button)
544  {
545    return true;
546  }
547
548  bool InputManager::buttonReleased(const OIS::JoyStickEvent &arg, int button)
549  {
550    return true;
551  }
552
553  bool InputManager::axisMoved(const OIS::JoyStickEvent &arg, int axis)
554  {
555    return true;
556  }
557
558  bool InputManager::sliderMoved(const OIS::JoyStickEvent &arg, int id)
559  {
560    return true;
561  }
562
563  bool InputManager::povMoved(const OIS::JoyStickEvent &arg, int id)
564  {
565    return true;
566  }
567
568
569  // ################################
570  // ### Static Interface Methods ###
571  // ################################
572
573  /**
574    @brief Adjusts the mouse window metrics.
575    This method has to be called every time the size of the window changes.
576    @param width The new width of the render window
577    @param height the new height of the render window
578  */
579  void InputManager::setWindowExtents(int width, int height)
580  {
581    if (_getSingleton().mouse_)
582    {
583      // Set mouse region (if window resizes, we should alter this to reflect as well)
584      const OIS::MouseState &mouseState = _getSingleton().mouse_->getMouseState();
585      mouseState.width  = width;
586      mouseState.height = height;
587    }
588  }
589
590  /**
591    @brief Sets the input mode to either GUI, inGame or Buffer
592    @param mode The new input mode
593    @remark Only has an affect if the mode actually changes
594  */
595  void InputManager::setInputState(const InputState state)
596  {
597    _getSingleton().stateRequest_ = state;
598  }
599
600  /**
601    @brief Returns the current input handling method
602    @return The current input mode.
603  */
604  InputManager::InputState InputManager::getInputState()
605  {
606    return _getSingleton().state_;
607  }
608
609  void InputManager::destroy()
610  {
611    _getSingleton()._destroy();
612  }
613
614  bool InputManager::initialise(size_t windowHnd, int windowWidth, int windowHeight,
615    bool createKeyboard, bool createMouse, bool createJoySticks)
616  {
617    return _getSingleton()._initialise(windowHnd, windowWidth, windowHeight,
618          createKeyboard, createMouse, createJoySticks);
619  }
620
621  bool InputManager::addKeyListener(OIS::KeyListener *listener, const std::string& name)
622  {
623    if (_getSingleton().listenersKey_.find(name) == _getSingleton().listenersKey_.end())
624    {
625      _getSingleton().listenersKey_[name] = listener;
626      return true;
627    }
628    else
629      return false;
630  }
631
632  bool InputManager::removeKeyListener(const std::string &name)
633  {
634    std::map<std::string, OIS::KeyListener*>::iterator it = _getSingleton().listenersKey_.find(name);
635    if (it != _getSingleton().listenersKey_.end())
636    {
637      _getSingleton().listenersKey_.erase(it);
638      return true;
639    }
640    else
641      return false;
642  }
643
644  OIS::KeyListener* InputManager::getKeyListener(const std::string& name)
645  {
646    std::map<std::string, OIS::KeyListener*>::iterator it = _getSingleton().listenersKey_.find(name);
647    if (it != _getSingleton().listenersKey_.end())
648    {
649      return (*it).second;
650    }
651    else
652      return 0;
653  }
654
655}
Note: See TracBrowser for help on using the repository browser.