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
RevLine 
[918]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
[1056]3 *                    > www.orxonox.net <
[918]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:
[934]25 *      ...
[918]26 *
27 */
[973]28
[918]29/**
[1193]30  @file
31  @brief Implementation of the InputManager that captures all the input from OIS
32         and redirects it to listeners if necessary.
[918]33 */
34
[1062]35#include "InputManager.h"
36#include "CoreIncludes.h"
37#include "Debug.h"
[1066]38#include "InputBuffer.h"
[1084]39#include "ConsoleCommand.h"
[1182]40#include "util/Convert.h"
[918]41
42namespace orxonox
43{
[1193]44  // ###############################
45  // ###    Internal Methods     ###
46  // ###############################
47
[919]48  /**
[1193]49    @brief Constructor only sets member fields to initial zero values
50           and registers the class in the class hierarchy.
[919]51  */
[973]52  InputManager::InputManager() :
[1034]53      inputSystem_(0), keyboard_(0), mouse_(0),
[1182]54      state_(IS_UNINIT), stateRequest_(IS_UNINIT)
[918]55  {
[1193]56    // overwrite every key binding with ""
57    _clearBindings();
58    _setNumberOfJoysticks(0);
59
[1089]60    RegisterObject(InputManager);
[918]61  }
62
[919]63  /**
[1182]64    @brief The one instance of the InputManager is stored in this function.
65    @return A reference to the only instance of the InputManager
[929]66  */
[1182]67  InputManager& InputManager::_getSingleton()
[929]68  {
[1182]69    static InputManager theOnlyInstance;
70    return theOnlyInstance;
[929]71  }
72
73  /**
[1193]74    @brief Destructor only called at the end of the program, after main.
[919]75  */
[1182]76  InputManager::~InputManager()
[919]77  {
[1182]78    this->_destroy();
[919]79  }
80
81  /**
[1193]82    @brief Creates the OIS::InputMananger, the keyboard, the mouse and
83           the joysticks and assigns the key bindings.
[919]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  */
[1193]88  bool InputManager::_initialise(size_t windowHnd, int windowWidth, int windowHeight,
89        bool createKeyboard, bool createMouse, bool createJoySticks)
[919]90  {
[1193]91    if (state_ == IS_UNINIT)
[918]92    {
[1193]93      CCOUT(ORX_DEBUG) << "Initialising OIS components..." << std::endl;
94
[918]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
[1182]102//#if defined OIS_LINUX_PLATFORM
103//      paramList.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true")));
104//#endif
[928]105
[934]106      try
[918]107      {
[934]108        inputSystem_ = OIS::InputManager::createInputSystem(paramList);
[1193]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      }
[918]118
[1193]119      if (createKeyboard)
120        _initialiseKeyboard();
[918]121
[1193]122      if (createMouse)
123        _initialiseMouse();
[1182]124
[1193]125      if (createJoySticks)
126        _initialiseJoySticks();
[934]127
[1193]128      // Set mouse/joystick region
129      setWindowExtents(windowWidth, windowHeight);
[1182]130
[1193]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;
[918]168      }
[1193]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
[934]192      {
[1193]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;
[934]197      }
[1193]198      else
199        CCOUT(ORX_WARNING) << "Warning: No mouse found!" << std::endl;
[918]200    }
[1193]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  }
[922]208
[1193]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  }
[1022]243
[1193]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  }
[922]269
[1193]270  /**
271    @brief Loads the key and button bindings.
272  */
273  bool InputManager::_loadBindings()
274  {
275    CCOUT(ORX_DEBUG) << "Loading key bindings..." << std::endl;
[934]276
[1193]277    // clear all the bindings at first.
278    _clearBindings();
[1182]279
[1193]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;
[934]286    return true;
[918]287  }
288
[1193]289  /**
290    @brief Overwrites all bindings with ""
291  */
292  void InputManager::_clearBindings()
[1182]293  {
294    for (int i = 0; i < numberOfKeys_s; i++)
295    {
[1193]296      this->bindingsKeyPress_  [i] = "";
[1182]297      this->bindingsKeyRelease_[i] = "";
[1193]298      this->bindingsKeyHold_   [i] = "";
[1182]299    }
[1193]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    }
[1182]315  }
316
[919]317  /**
[1193]318    @brief Destroys all the created input devices and sets the InputManager to construction state.
[928]319  */
[1182]320  void InputManager::_destroy()
[928]321  {
[1193]322    CCOUT(ORX_DEBUG) << "Destroying ..." << std::endl;
[928]323
[1193]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();
[1035]332
[1193]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;
[1182]364    }
[1193]365    else
366      CCOUT(ORX_WARNING) << "Warning: Cannot be destroyed, since not initialised." << std::endl;
[1035]367
[1193]368    CCOUT(ORX_DEBUG) << "Destroying done." << std::endl;
[928]369  }
370
[1193]371
372  // ###############################
373  // ###  Public Member Methods  ###
374  // ###############################
375
[928]376  /**
[973]377    @brief Updates the InputManager
[919]378    @param dt Delta time
379  */
[973]380  void InputManager::tick(float dt)
[918]381  {
[1182]382    if (state_ == IS_UNINIT)
383      return;
384
[1022]385    // reset the game if it has changed
[1182]386    if (state_ != stateRequest_)
[1022]387    {
[1182]388      switch (stateRequest_)
[1022]389      {
[1182]390      case IS_NORMAL:
[1193]391        this->listenersKeyActive_.clear();
392        this->listenersMouseActive_.clear();
393        this->listenersJoySticksActive_.clear();
394        this->bKeyBindingsActive_            = true;
395        this->bMouseButtonBindingsActive_    = true;
396        //this->bJoySticksButtonBindingsActive_ = true;
[1022]397        break;
[1193]398
[1182]399      case IS_GUI:
[1193]400        // FIXME: do stuff
[1022]401        break;
[1193]402
[1182]403      case IS_CONSOLE:
[1193]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        }
[1022]418        break;
[1193]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
[1182]429      case IS_CUSTOM:
430        // don't do anything
[1022]431        break;
432      }
[1182]433      state_ = stateRequest_;
[1022]434    }
435
[1193]436    // Capture all the input. This calls the event handlers in InputManager.
[918]437    if (mouse_)
438      mouse_->capture();
439    if (keyboard_)
440      keyboard_->capture();
441  }
442
[1193]443  /*void InputManager::_setDefaultState()
[1182]444  {
[1193]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  }*/
[1182]452
453
[919]454  /**
[1182]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
[1193]462    if (this->bKeyBindingsActive_)
[1182]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    {
[1193]474      for (std::list<OIS::KeyListener*>::const_iterator it = listenersKeyActive_.begin(); it != listenersKeyActive_.end(); it++)
[1182]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
[1193]496    if (this->bKeyBindingsActive_)
[1182]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    {
[1193]508      for (std::list<OIS::KeyListener*>::const_iterator it = listenersKeyActive_.begin(); it != listenersKeyActive_.end(); it++)
[1182]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
[1193]569  // ################################
570  // ### Static Interface Methods ###
571  // ################################
[1182]572
573  /**
[919]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  */
[973]579  void InputManager::setWindowExtents(int width, int height)
[918]580  {
[1193]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    }
[918]588  }
589
[919]590  /**
[1022]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
[922]594  */
[1182]595  void InputManager::setInputState(const InputState state)
[922]596  {
[1182]597    _getSingleton().stateRequest_ = state;
[922]598  }
599
600  /**
[1022]601    @brief Returns the current input handling method
602    @return The current input mode.
[919]603  */
[1182]604  InputManager::InputState InputManager::getInputState()
[918]605  {
[1182]606    return _getSingleton().state_;
[918]607  }
608
[1182]609  void InputManager::destroy()
[1066]610  {
[1182]611    _getSingleton()._destroy();
[1066]612  }
613
[1193]614  bool InputManager::initialise(size_t windowHnd, int windowWidth, int windowHeight,
615    bool createKeyboard, bool createMouse, bool createJoySticks)
[1182]616  {
[1193]617    return _getSingleton()._initialise(windowHnd, windowWidth, windowHeight,
618          createKeyboard, createMouse, createJoySticks);
[1182]619  }
[1066]620
[1182]621  bool InputManager::addKeyListener(OIS::KeyListener *listener, const std::string& name)
622  {
[1193]623    if (_getSingleton().listenersKey_.find(name) == _getSingleton().listenersKey_.end())
[1182]624    {
[1193]625      _getSingleton().listenersKey_[name] = listener;
[1182]626      return true;
627    }
628    else
629      return false;
630  }
631
632  bool InputManager::removeKeyListener(const std::string &name)
633  {
[1193]634    std::map<std::string, OIS::KeyListener*>::iterator it = _getSingleton().listenersKey_.find(name);
635    if (it != _getSingleton().listenersKey_.end())
[1182]636    {
[1193]637      _getSingleton().listenersKey_.erase(it);
[1182]638      return true;
639    }
640    else
641      return false;
642  }
643
644  OIS::KeyListener* InputManager::getKeyListener(const std::string& name)
645  {
[1193]646    std::map<std::string, OIS::KeyListener*>::iterator it = _getSingleton().listenersKey_.find(name);
647    if (it != _getSingleton().listenersKey_.end())
[1182]648    {
649      return (*it).second;
650    }
651    else
652      return 0;
653  }
654
[918]655}
Note: See TracBrowser for help on using the repository browser.