Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 1196 was 1195, checked in by rgrieder, 17 years ago
  • added OIS to the orxonox src directory
  • adapted VS files
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    {
[1195]157      if (inputSystem_->getNumberOfDevices(OIS::OISKeyboard) > 0)
[1193]158      {
159        keyboard_ = (OIS::Keyboard*)inputSystem_->createInputObject(OIS::OISKeyboard, true);
160        // register our listener in OIS.
161        keyboard_->setEventCallback(this);
162        // note: OIS will not detect keys that have already been down when the keyboard was created.
163        CCOUT(ORX_DEBUG) << "Created OIS keyboard" << std::endl;
[918]164      }
[1193]165      else
166        CCOUT(ORX_WARNING) << "Warning: No keyboard found!" << std::endl;
167    }
168    catch (OIS::Exception ex)
169    {
170      CCOUT(ORX_WARNING) << "Warning: Failed to create an OIS keyboard\n"
171          << "OIS error message: \"" << ex.eText << "\"" << std::endl;
172      keyboard_ = 0;
173    }
174  }
175
176  /**
177    @brief Creates a mouse and sets the event handler.
178  */
179  void InputManager::_initialiseMouse()
180  {
181    try
182    {
[1195]183      if (inputSystem_->getNumberOfDevices(OIS::OISMouse) > 0)
[934]184      {
[1193]185        mouse_ = static_cast<OIS::Mouse*>(inputSystem_->createInputObject(OIS::OISMouse, true));
186        // register our listener in OIS.
187        mouse_->setEventCallback(this);
188        CCOUT(ORX_DEBUG) << "Created OIS keyboard" << std::endl;
[934]189      }
[1193]190      else
191        CCOUT(ORX_WARNING) << "Warning: No mouse found!" << std::endl;
[918]192    }
[1193]193    catch (OIS::Exception ex)
194    {
195      CCOUT(ORX_WARNING) << "Warning: Failed to create an OIS mouse\n"
196          << "OIS error message: \"" << ex.eText << "\"" << std::endl;
197      mouse_ = 0;
198    }
199  }
[922]200
[1193]201  /**
202    @brief Creates all joy sticks and sets the event handler.
203  */
204  void InputManager::_initialiseJoySticks()
205  {
206    if (inputSystem_->getNumberOfDevices(OIS::OISJoyStick) > 0)
207    {
208      _setNumberOfJoysticks(inputSystem_->getNumberOfDevices(OIS::OISJoyStick));
209      for (std::vector<OIS::JoyStick*>::iterator it = joySticks_.begin(); it != joySticks_.end(); it++)
210      {
211        try
212        {
213          *it = static_cast<OIS::JoyStick*>(inputSystem_->createInputObject(OIS::OISJoyStick, true));
214          // register our listener in OIS.
215          (*it)->setEventCallback(this);
216          CCOUT(ORX_DEBUG) << "Created OIS joy stick with ID " << (*it)->getID() << std::endl;
217        }
218        catch (OIS::Exception ex)
219        {
220          CCOUT(ORX_WARNING) << "Warning: Failed to create OIS joy stick with ID" << (*it)->getID() << "\n"
221              << "OIS error message: \"" << ex.eText << "\"" << std::endl;
222          (*it) = 0;
223        }
224      }
225    }
226    else
227      CCOUT(ORX_WARNING) << "Warning: Joy stick support requested, but no joy stick was found" << std::endl;
228  }
[1022]229
[1193]230  /**
231    @brief Resizes all lists related to joy sticks and sets joy stick bindings to "".
232    @param size Number of joy sticks available.
233  */
234  void InputManager::_setNumberOfJoysticks(int size)
235  {
236    this->bindingsJoyStickButtonHold_   .resize(size);
237    this->bindingsJoyStickButtonPress_  .resize(size);
238    this->bindingsJoyStickButtonRelease_.resize(size);
239    this->bJoyStickButtonBindingsActive_.resize(size);
240    this->joyStickButtonsDown_          .resize(size);
241    this->joySticks_                    .resize(size);
242    for (int j = 0; j < size; j++)
243    {
244      bindingsJoyStickButtonPress_  [j].resize(numberOfJoyStickButtons_s);
245      bindingsJoyStickButtonRelease_[j].resize(numberOfJoyStickButtons_s);
246      bindingsJoyStickButtonHold_   [j].resize(numberOfJoyStickButtons_s);
247      for (int i = 0; i < numberOfJoyStickButtons_s; i++)
248      {
249        this->bindingsJoyStickButtonPress_  [j][i] = "";
250        this->bindingsJoyStickButtonRelease_[j][i] = "";
251        this->bindingsJoyStickButtonHold_   [j][i] = "";
252      }
253    }
254  }
[922]255
[1193]256  /**
257    @brief Loads the key and button bindings.
258  */
259  bool InputManager::_loadBindings()
260  {
261    CCOUT(ORX_DEBUG) << "Loading key bindings..." << std::endl;
[934]262
[1193]263    // clear all the bindings at first.
264    _clearBindings();
[1182]265
[1193]266    // TODO: Insert the code to load the bindings from file.
267    this->bindingsKeyPress_[OIS::KC_NUMPADENTER] = "activateConsole";
268    this->bindingsKeyPress_[OIS::KC_ESCAPE] = "exit";
269    this->bindingsKeyHold_[OIS::KC_U] = "exec disco.txt";
270
271    CCOUT(ORX_DEBUG) << "Loading key bindings done." << std::endl;
[934]272    return true;
[918]273  }
274
[1193]275  /**
276    @brief Overwrites all bindings with ""
277  */
278  void InputManager::_clearBindings()
[1182]279  {
280    for (int i = 0; i < numberOfKeys_s; i++)
281    {
[1193]282      this->bindingsKeyPress_  [i] = "";
[1182]283      this->bindingsKeyRelease_[i] = "";
[1193]284      this->bindingsKeyHold_   [i] = "";
[1182]285    }
[1193]286    for (int i = 0; i < numberOfMouseButtons_s; i++)
287    {
288      this->bindingsMouseButtonPress_  [i] = "";
289      this->bindingsMouseButtonRelease_[i] = "";
290      this->bindingsMouseButtonHold_   [i] = "";
291    }
292    for (unsigned int j = 0; j < joySticks_.size(); j++)
293    {
294      for (int i = 0; i < numberOfJoyStickButtons_s; i++)
295      {
296        this->bindingsJoyStickButtonPress_  [j][i] = "";
297        this->bindingsJoyStickButtonRelease_[j][i] = "";
298        this->bindingsJoyStickButtonHold_   [j][i] = "";
299      }
300    }
[1182]301  }
302
[919]303  /**
[1193]304    @brief Destroys all the created input devices and sets the InputManager to construction state.
[928]305  */
[1182]306  void InputManager::_destroy()
[928]307  {
[1193]308    CCOUT(ORX_DEBUG) << "Destroying ..." << std::endl;
[928]309
[1193]310    if (state_ != IS_UNINIT)
311    {
312      this->listenersKeyActive_.clear();
313      this->listenersMouseActive_.clear();
314      this->listenersJoySticksActive_.clear();
315      this->listenersKey_.clear();
316      this->listenersMouse_.clear();
317      this->listenersJoySticks_.clear();
[1035]318
[1193]319      this->keysDown_.clear();
320      this->mouseButtonsDown_.clear();
321
322      _clearBindings();
323
324      if (keyboard_)
325        inputSystem_->destroyInputObject(keyboard_);
326      keyboard_ = 0;
327
328      if (mouse_)
329        inputSystem_->destroyInputObject(mouse_);
330      mouse_ = 0;
331
332      if (joySticks_.size() > 0)
333      {
334        for (unsigned int i = 0; i < joySticks_.size(); i++)
335        {
336          if (joySticks_[i] != 0)
337            inputSystem_->destroyInputObject(joySticks_[i]);
338        }
339        _setNumberOfJoysticks(0);
340      }
341
342      if (inputSystem_)
343        OIS::InputManager::destroyInputSystem(inputSystem_);
344      inputSystem_ = 0;
345
346      if (listenersKey_.find("buffer") != listenersKey_.end())
347        delete listenersKey_["buffer"];
348
349      this->state_ = IS_UNINIT;
[1182]350    }
[1193]351    else
352      CCOUT(ORX_WARNING) << "Warning: Cannot be destroyed, since not initialised." << std::endl;
[1035]353
[1193]354    CCOUT(ORX_DEBUG) << "Destroying done." << std::endl;
[928]355  }
356
[1193]357
358  // ###############################
[1195]359  // ###    Interface Methods    ###
[1193]360  // ###############################
361
[928]362  /**
[1195]363    @brief Updates the InputManager. Tick is called by Orxonox.
[919]364    @param dt Delta time
365  */
[973]366  void InputManager::tick(float dt)
[918]367  {
[1182]368    if (state_ == IS_UNINIT)
369      return;
370
[1022]371    // reset the game if it has changed
[1182]372    if (state_ != stateRequest_)
[1022]373    {
[1182]374      switch (stateRequest_)
[1022]375      {
[1182]376      case IS_NORMAL:
[1193]377        this->listenersKeyActive_.clear();
378        this->listenersMouseActive_.clear();
379        this->listenersJoySticksActive_.clear();
380        this->bKeyBindingsActive_            = true;
381        this->bMouseButtonBindingsActive_    = true;
[1195]382        for (unsigned int i = 0; i < joySticks_.size(); i++)
383          this->bJoyStickButtonBindingsActive_[i] = true;
[1022]384        break;
[1193]385
[1182]386      case IS_GUI:
[1193]387        // FIXME: do stuff
[1022]388        break;
[1193]389
[1182]390      case IS_CONSOLE:
[1193]391        this->listenersKeyActive_.clear();
392        this->listenersMouseActive_.clear();
[1195]393        this->listenersJoySticksActive_.clear();
[1193]394        this->bKeyBindingsActive_            = false;
395        this->bMouseButtonBindingsActive_    = true;
[1195]396        for (unsigned int i = 0; i < joySticks_.size(); i++)
397          this->bJoyStickButtonBindingsActive_[i] = true;
[1193]398        if (listenersKey_.find("buffer") != listenersKey_.end())
399          listenersKeyActive_.push_back(listenersKey_["buffer"]);
400        else
401        {
402          // someone fiddled with the InputBuffer
403          CCOUT(2) << "Error: Cannot redirect input to console, InputBuffer instance missing." << std::endl;
404          this->bKeyBindingsActive_ = true;
405        }
[1022]406        break;
[1193]407
408      case IS_NONE:
409        this->listenersKeyActive_.clear();
410        this->listenersMouseActive_.clear();
[1195]411        this->listenersJoySticksActive_.clear();
[1193]412        this->bKeyBindingsActive_            = false;
413        this->bMouseButtonBindingsActive_    = false;
[1195]414        for (unsigned int i = 0; i < joySticks_.size(); i++)
415          this->bJoyStickButtonBindingsActive_[i] = false;
[1193]416        break;
417
[1182]418      case IS_CUSTOM:
419        // don't do anything
[1022]420        break;
[1195]421
422      case IS_UNINIT:
423        // this can't happen
424        break;
[1022]425      }
[1182]426      state_ = stateRequest_;
[1022]427    }
428
[1193]429    // Capture all the input. This calls the event handlers in InputManager.
[918]430    if (mouse_)
431      mouse_->capture();
432    if (keyboard_)
433      keyboard_->capture();
434  }
435
[1193]436  /*void InputManager::_setDefaultState()
[1182]437  {
[1193]438    this->listenersKeyActive_.clear();
439    this->listenersMouseActive_.clear();
440    this->listenersJoyStickActive_.clear();
441    this->bKeyBindingsActive_            = true;
442    this->bMouseButtonBindingsActive_    = true;
443    this->bJoyStickButtonBindingsActive_ = true;
444  }*/
[1182]445
446
[919]447  /**
[1182]448    @brief Event handler for the keyPressed Event.
449    @param e Event information
450  */
451  bool InputManager::keyPressed(const OIS::KeyEvent &e)
452  {
453    this->keysDown_.push_back(e.key);
454
[1193]455    if (this->bKeyBindingsActive_)
[1182]456    {
457      // find the appropriate key binding
458      std::string cmdStr = bindingsKeyPress_[int(e.key)];
459      if (cmdStr != "")
460      {
461        CommandExecutor::execute(cmdStr);
462        COUT(3) << "Executing command: " << cmdStr << std::endl;
463      }
464    }
465    else
466    {
[1193]467      for (std::list<OIS::KeyListener*>::const_iterator it = listenersKeyActive_.begin(); it != listenersKeyActive_.end(); it++)
[1182]468        (*it)->keyPressed(e);
469    }
470    return true;
471  }
472
473  /**
474    @brief Event handler for the keyReleased Event.
475    @param e Event information
476  */
477  bool InputManager::keyReleased(const OIS::KeyEvent &e)
478  {
479    // remove the key from the keysDown_ list
480    for (std::list<OIS::KeyCode>::iterator it = keysDown_.begin(); it != keysDown_.end(); it++)
481    {
482      if (*it == e.key)
483      {
484        keysDown_.erase(it);
485        break;
486      }
487    }
488
[1193]489    if (this->bKeyBindingsActive_)
[1182]490    {
491      // find the appropriate key binding
492      std::string cmdStr = bindingsKeyRelease_[int(e.key)];
493      if (cmdStr != "")
494      {
495        CommandExecutor::execute(cmdStr);
496        COUT(3) << "Executing command: " << cmdStr << std::endl;
497      }
498    }
499    else
500    {
[1193]501      for (std::list<OIS::KeyListener*>::const_iterator it = listenersKeyActive_.begin(); it != listenersKeyActive_.end(); it++)
[1182]502        (*it)->keyReleased(e);
503    }
504    return true;
505  }
506
507  /**
508    @brief Event handler for the mouseMoved Event.
509    @param e Event information
510  */
511  bool InputManager::mouseMoved(const OIS::MouseEvent &e)
512  {
513    return true;
514  }
515
516  /**
517    @brief Event handler for the mousePressed Event.
518    @param e Event information
519    @param id The ID of the mouse button
520  */
521  bool InputManager::mousePressed(const OIS::MouseEvent &e, OIS::MouseButtonID id)
522  {
523    return true;
524  }
525
526  /**
527    @brief Event handler for the mouseReleased Event.
528    @param e Event information
529    @param id The ID of the mouse button
530  */
531  bool InputManager::mouseReleased(const OIS::MouseEvent &e, OIS::MouseButtonID id)
532  {
533    return true;
534  }
535
536  bool InputManager::buttonPressed(const OIS::JoyStickEvent &arg, int button)
537  {
538    return true;
539  }
540
541  bool InputManager::buttonReleased(const OIS::JoyStickEvent &arg, int button)
542  {
543    return true;
544  }
545
546  bool InputManager::axisMoved(const OIS::JoyStickEvent &arg, int axis)
547  {
548    return true;
549  }
550
551  bool InputManager::sliderMoved(const OIS::JoyStickEvent &arg, int id)
552  {
553    return true;
554  }
555
556  bool InputManager::povMoved(const OIS::JoyStickEvent &arg, int id)
557  {
558    return true;
559  }
560
561
[1193]562  // ################################
563  // ### Static Interface Methods ###
564  // ################################
[1182]565
566  /**
[919]567    @brief Adjusts the mouse window metrics.
568    This method has to be called every time the size of the window changes.
569    @param width The new width of the render window
570    @param height the new height of the render window
571  */
[973]572  void InputManager::setWindowExtents(int width, int height)
[918]573  {
[1193]574    if (_getSingleton().mouse_)
575    {
576      // Set mouse region (if window resizes, we should alter this to reflect as well)
577      const OIS::MouseState &mouseState = _getSingleton().mouse_->getMouseState();
578      mouseState.width  = width;
579      mouseState.height = height;
580    }
[918]581  }
582
[919]583  /**
[1022]584    @brief Sets the input mode to either GUI, inGame or Buffer
585    @param mode The new input mode
586    @remark Only has an affect if the mode actually changes
[922]587  */
[1182]588  void InputManager::setInputState(const InputState state)
[922]589  {
[1182]590    _getSingleton().stateRequest_ = state;
[922]591  }
592
593  /**
[1022]594    @brief Returns the current input handling method
595    @return The current input mode.
[919]596  */
[1182]597  InputManager::InputState InputManager::getInputState()
[918]598  {
[1182]599    return _getSingleton().state_;
[918]600  }
601
[1182]602  void InputManager::destroy()
[1066]603  {
[1182]604    _getSingleton()._destroy();
[1066]605  }
606
[1193]607  bool InputManager::initialise(size_t windowHnd, int windowWidth, int windowHeight,
608    bool createKeyboard, bool createMouse, bool createJoySticks)
[1182]609  {
[1193]610    return _getSingleton()._initialise(windowHnd, windowWidth, windowHeight,
611          createKeyboard, createMouse, createJoySticks);
[1182]612  }
[1066]613
[1195]614  /*bool InputManager::initialiseKeyboard()
615  {
616  }
617
618  bool InputManager::initialiseMouse()
619  {
620  }
621
622  bool InputManager::initialiseJoySticks()
623  {
624  }*/
625
[1182]626  bool InputManager::addKeyListener(OIS::KeyListener *listener, const std::string& name)
627  {
[1193]628    if (_getSingleton().listenersKey_.find(name) == _getSingleton().listenersKey_.end())
[1182]629    {
[1193]630      _getSingleton().listenersKey_[name] = listener;
[1182]631      return true;
632    }
633    else
634      return false;
635  }
636
637  bool InputManager::removeKeyListener(const std::string &name)
638  {
[1193]639    std::map<std::string, OIS::KeyListener*>::iterator it = _getSingleton().listenersKey_.find(name);
640    if (it != _getSingleton().listenersKey_.end())
[1182]641    {
[1193]642      _getSingleton().listenersKey_.erase(it);
[1182]643      return true;
644    }
645    else
646      return false;
647  }
648
649  OIS::KeyListener* InputManager::getKeyListener(const std::string& name)
650  {
[1193]651    std::map<std::string, OIS::KeyListener*>::iterator it = _getSingleton().listenersKey_.find(name);
652    if (it != _getSingleton().listenersKey_.end())
[1182]653    {
654      return (*it).second;
655    }
656    else
657      return 0;
658  }
659
[918]660}
Note: See TracBrowser for help on using the repository browser.