Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 1195 was 1195, checked in by rgrieder, 16 years ago
  • added OIS to the orxonox src directory
  • adapted VS files
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 (inputSystem_->getNumberOfDevices(OIS::OISKeyboard) > 0)
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;
164      }
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    {
183      if (inputSystem_->getNumberOfDevices(OIS::OISMouse) > 0)
184      {
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;
189      }
190      else
191        CCOUT(ORX_WARNING) << "Warning: No mouse found!" << std::endl;
192    }
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  }
200
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  }
229
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  }
255
256  /**
257    @brief Loads the key and button bindings.
258  */
259  bool InputManager::_loadBindings()
260  {
261    CCOUT(ORX_DEBUG) << "Loading key bindings..." << std::endl;
262
263    // clear all the bindings at first.
264    _clearBindings();
265
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;
272    return true;
273  }
274
275  /**
276    @brief Overwrites all bindings with ""
277  */
278  void InputManager::_clearBindings()
279  {
280    for (int i = 0; i < numberOfKeys_s; i++)
281    {
282      this->bindingsKeyPress_  [i] = "";
283      this->bindingsKeyRelease_[i] = "";
284      this->bindingsKeyHold_   [i] = "";
285    }
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    }
301  }
302
303  /**
304    @brief Destroys all the created input devices and sets the InputManager to construction state.
305  */
306  void InputManager::_destroy()
307  {
308    CCOUT(ORX_DEBUG) << "Destroying ..." << std::endl;
309
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();
318
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;
350    }
351    else
352      CCOUT(ORX_WARNING) << "Warning: Cannot be destroyed, since not initialised." << std::endl;
353
354    CCOUT(ORX_DEBUG) << "Destroying done." << std::endl;
355  }
356
357
358  // ###############################
359  // ###    Interface Methods    ###
360  // ###############################
361
362  /**
363    @brief Updates the InputManager. Tick is called by Orxonox.
364    @param dt Delta time
365  */
366  void InputManager::tick(float dt)
367  {
368    if (state_ == IS_UNINIT)
369      return;
370
371    // reset the game if it has changed
372    if (state_ != stateRequest_)
373    {
374      switch (stateRequest_)
375      {
376      case IS_NORMAL:
377        this->listenersKeyActive_.clear();
378        this->listenersMouseActive_.clear();
379        this->listenersJoySticksActive_.clear();
380        this->bKeyBindingsActive_            = true;
381        this->bMouseButtonBindingsActive_    = true;
382        for (unsigned int i = 0; i < joySticks_.size(); i++)
383          this->bJoyStickButtonBindingsActive_[i] = true;
384        break;
385
386      case IS_GUI:
387        // FIXME: do stuff
388        break;
389
390      case IS_CONSOLE:
391        this->listenersKeyActive_.clear();
392        this->listenersMouseActive_.clear();
393        this->listenersJoySticksActive_.clear();
394        this->bKeyBindingsActive_            = false;
395        this->bMouseButtonBindingsActive_    = true;
396        for (unsigned int i = 0; i < joySticks_.size(); i++)
397          this->bJoyStickButtonBindingsActive_[i] = true;
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        }
406        break;
407
408      case IS_NONE:
409        this->listenersKeyActive_.clear();
410        this->listenersMouseActive_.clear();
411        this->listenersJoySticksActive_.clear();
412        this->bKeyBindingsActive_            = false;
413        this->bMouseButtonBindingsActive_    = false;
414        for (unsigned int i = 0; i < joySticks_.size(); i++)
415          this->bJoyStickButtonBindingsActive_[i] = false;
416        break;
417
418      case IS_CUSTOM:
419        // don't do anything
420        break;
421
422      case IS_UNINIT:
423        // this can't happen
424        break;
425      }
426      state_ = stateRequest_;
427    }
428
429    // Capture all the input. This calls the event handlers in InputManager.
430    if (mouse_)
431      mouse_->capture();
432    if (keyboard_)
433      keyboard_->capture();
434  }
435
436  /*void InputManager::_setDefaultState()
437  {
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  }*/
445
446
447  /**
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
455    if (this->bKeyBindingsActive_)
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    {
467      for (std::list<OIS::KeyListener*>::const_iterator it = listenersKeyActive_.begin(); it != listenersKeyActive_.end(); it++)
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
489    if (this->bKeyBindingsActive_)
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    {
501      for (std::list<OIS::KeyListener*>::const_iterator it = listenersKeyActive_.begin(); it != listenersKeyActive_.end(); it++)
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
562  // ################################
563  // ### Static Interface Methods ###
564  // ################################
565
566  /**
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  */
572  void InputManager::setWindowExtents(int width, int height)
573  {
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    }
581  }
582
583  /**
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
587  */
588  void InputManager::setInputState(const InputState state)
589  {
590    _getSingleton().stateRequest_ = state;
591  }
592
593  /**
594    @brief Returns the current input handling method
595    @return The current input mode.
596  */
597  InputManager::InputState InputManager::getInputState()
598  {
599    return _getSingleton().state_;
600  }
601
602  void InputManager::destroy()
603  {
604    _getSingleton()._destroy();
605  }
606
607  bool InputManager::initialise(size_t windowHnd, int windowWidth, int windowHeight,
608    bool createKeyboard, bool createMouse, bool createJoySticks)
609  {
610    return _getSingleton()._initialise(windowHnd, windowWidth, windowHeight,
611          createKeyboard, createMouse, createJoySticks);
612  }
613
614  /*bool InputManager::initialiseKeyboard()
615  {
616  }
617
618  bool InputManager::initialiseMouse()
619  {
620  }
621
622  bool InputManager::initialiseJoySticks()
623  {
624  }*/
625
626  bool InputManager::addKeyListener(OIS::KeyListener *listener, const std::string& name)
627  {
628    if (_getSingleton().listenersKey_.find(name) == _getSingleton().listenersKey_.end())
629    {
630      _getSingleton().listenersKey_[name] = listener;
631      return true;
632    }
633    else
634      return false;
635  }
636
637  bool InputManager::removeKeyListener(const std::string &name)
638  {
639    std::map<std::string, OIS::KeyListener*>::iterator it = _getSingleton().listenersKey_.find(name);
640    if (it != _getSingleton().listenersKey_.end())
641    {
642      _getSingleton().listenersKey_.erase(it);
643      return true;
644    }
645    else
646      return false;
647  }
648
649  OIS::KeyListener* InputManager::getKeyListener(const std::string& name)
650  {
651    std::map<std::string, OIS::KeyListener*>::iterator it = _getSingleton().listenersKey_.find(name);
652    if (it != _getSingleton().listenersKey_.end())
653    {
654      return (*it).second;
655    }
656    else
657      return 0;
658  }
659
660}
Note: See TracBrowser for help on using the repository browser.