Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 2814 was 2814, checked in by rgrieder, 16 years ago

InputManager upgrade number one: InputState priorities are managed automatically. However you can still use the enum in InputManager.h and get yourself a high priority.
High priorities are only to be used for special cases like calibrator, console or detector.
All other states are simply pushed onto the normal stack.

  • Property svn:eol-style set to native
File size: 52.3 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
32    Implementation of the InputManager that captures all the input from OIS
33    and redirects it to handlers.
34 */
35
36#include "InputManager.h"
37
38#include <climits>
39#include <cassert>
40
41#include "ois/OISException.h"
42#include "ois/OISInputManager.h"
43
44#include "util/Exception.h"
45#include "core/Clock.h"
46#include "core/CoreIncludes.h"
47#include "core/ConfigValueIncludes.h"
48#include "core/CommandExecutor.h"
49#include "core/ConsoleCommand.h"
50#include "core/CommandLine.h"
51#include "util/Debug.h"
52
53#include "InputBuffer.h"
54#include "KeyBinder.h"
55#include "KeyDetector.h"
56#include "CalibratorCallback.h"
57#include "InputState.h"
58#include "SimpleInputState.h"
59#include "ExtendedInputState.h"
60#include "JoyStickDeviceNumberListener.h"
61
62namespace orxonox
63{
64    SetConsoleCommand(InputManager, calibrate, true);
65    SetConsoleCommand(InputManager, reload, false);
66    SetCommandLineSwitch(keyboard_no_grab);
67
68    EmptyHandler InputManager::EMPTY_HANDLER;
69    InputManager* InputManager::singletonRef_s = 0;
70
71    using namespace InputDevice;
72
73    /**
74    @brief
75        Defines the |= operator for easier use.
76    */
77    inline InputManager::InputManagerState operator|=(InputManager::InputManagerState& lval,
78                                                      InputManager::InputManagerState rval)
79    {
80        return (lval = (InputManager::InputManagerState)(lval | rval));
81    }
82
83    /**
84    @brief
85        Defines the &= operator for easier use.
86    */
87    inline InputManager::InputManagerState operator&=(InputManager::InputManagerState& lval, int rval)
88    {
89        return (lval = (InputManager::InputManagerState)(lval & rval));
90    }
91
92    // ############################################################
93    // #####                  Initialisation                  #####
94    // ##########                                        ##########
95    // ############################################################
96
97    /**
98    @brief
99        Constructor only sets member fields to initial zero values
100        and registers the class in the class hierarchy.
101    */
102    InputManager::InputManager()
103        : inputSystem_(0)
104        , keyboard_(0)
105        , mouse_(0)
106        , joySticksSize_(0)
107        , devicesNum_(0)
108        , windowHnd_(0)
109        , internalState_(Uninitialised)
110        , stateEmpty_(0)
111        , stateMaster_(0)
112        , keyDetector_(0)
113        , calibratorCallbackBuffer_(0)
114        , keyboardModifiers_(0)
115    {
116        RegisterRootObject(InputManager);
117
118        assert(singletonRef_s == 0);
119        singletonRef_s = this;
120
121        setConfigValues();
122    }
123
124    /**
125    @brief
126        Sets the configurable values.
127    */
128    void InputManager::setConfigValues()
129    {
130        SetConfigValue(calibrationFilename_, "joystick_calibration.ini")
131            .description("Ini filename for the the joy stick calibration data.")
132            .callback(this, &InputManager::_calibrationFileCallback);
133    }
134
135    /**
136    @brief
137        Callback for the joy stick calibration config file. @see setConfigValues.
138    */
139    void InputManager::_calibrationFileCallback()
140    {
141        ConfigFileManager::getInstance().setFilename(ConfigFileType::JoyStickCalibration, calibrationFilename_);
142    }
143
144    /**
145    @brief
146        Creates the OIS::InputMananger, the keyboard, the mouse and
147        the joysticks and assigns the key bindings.
148    @param windowHnd
149        The window handle of the render window
150    @param windowWidth
151        The width of the render window
152    @param windowHeight
153        The height of the render window
154    @param joyStickSupport
155        Whether or not to load the joy sticks as well
156    */
157    void InputManager::initialise(size_t windowHnd, int windowWidth, int windowHeight, bool joyStickSupport)
158    {
159        CCOUT(3) << "Initialising Input System..." << std::endl;
160
161        if (!(internalState_ & OISReady))
162        {
163            CCOUT(4) << "Initialising OIS components..." << std::endl;
164
165            // store handle internally so we can reload OIS
166            windowHnd_ = windowHnd;
167
168            OIS::ParamList paramList;
169            std::ostringstream windowHndStr;
170
171            // Fill parameter list
172            windowHndStr << (unsigned int)windowHnd_;
173            paramList.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
174            //paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_NONEXCLUSIVE")));
175            //paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_FOREGROUND")));
176#if defined ORXONOX_PLATFORM_LINUX
177            paramList.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true")));
178            paramList.insert(std::make_pair(std::string("x11_mouse_grab"), "true"));
179            paramList.insert(std::make_pair(std::string("x11_mouse_hide"), "true"));
180            bool kbNoGrab;
181            CommandLine::getValue("keyboard_no_grab", &kbNoGrab);
182            if (kbNoGrab)
183                paramList.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("false")));
184            else
185                paramList.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("true")));
186#endif
187
188            inputSystem_ = OIS::InputManager::createInputSystem(paramList);
189            CCOUT(ORX_DEBUG) << "Created OIS input system" << std::endl;
190
191            _initialiseKeyboard();
192
193            _initialiseMouse();
194
195            if (joyStickSupport)
196                _initialiseJoySticks();
197            // Do this anyway to also inform everything when a joystick was detached.
198            _configureJoySticks();
199
200            // Set mouse/joystick region
201            if (mouse_)
202                setWindowExtents(windowWidth, windowHeight);
203
204            // clear all buffers
205            _clearBuffers();
206
207            internalState_ |= OISReady;
208
209            CCOUT(ORX_DEBUG) << "Initialising OIS components done." << std::endl;
210        }
211        else
212        {
213            CCOUT(2) << "Warning: OIS compoments already initialised, skipping" << std::endl;
214        }
215
216        if (!(internalState_ & InternalsReady))
217        {
218            CCOUT(4) << "Initialising InputStates components..." << std::endl;
219
220            // Lowest priority empty InputState
221            stateEmpty_ = createInputState<SimpleInputState>("empty", InputStatePriority::Empty);
222            stateEmpty_->setHandler(&EMPTY_HANDLER);
223            activeStates_[stateEmpty_->getPriority()] = stateEmpty_;
224
225            // Always active master InputState
226            stateMaster_ = new ExtendedInputState();
227            stateMaster_->setName("master");
228            stateMaster_->setNumOfJoySticks(joySticksSize_);
229
230            // KeyDetector to evaluate a pressed key's name
231            SimpleInputState* detector = createInputState<SimpleInputState>("detector", InputStatePriority::Detector);
232            keyDetector_ = new KeyDetector();
233            detector->setHandler(keyDetector_);
234
235            // Joy stick calibration helper callback
236            SimpleInputState* calibrator = createInputState<SimpleInputState>("calibrator", InputStatePriority::Calibrator);
237            calibrator->setHandler(&EMPTY_HANDLER);
238            calibratorCallbackBuffer_ = new InputBuffer();
239            calibratorCallbackBuffer_->registerListener(this, &InputManager::_completeCalibration, '\r', true);
240            calibrator->setKeyHandler(calibratorCallbackBuffer_);
241
242            internalState_ |= InternalsReady;
243
244            CCOUT(4) << "Initialising InputStates complete." << std::endl;
245        }
246
247        _updateActiveStates();
248
249        CCOUT(3) << "Initialising complete." << std::endl;
250    }
251
252    /**
253    @brief
254        Creates a keyboard and sets the event handler.
255    @return
256        False if keyboard stays uninitialised, true otherwise.
257    */
258    void InputManager::_initialiseKeyboard()
259    {
260        if (keyboard_ != 0)
261        {
262            CCOUT(2) << "Warning: Keyboard already initialised, skipping." << std::endl;
263            return;
264        }
265        if (inputSystem_->getNumberOfDevices(OIS::OISKeyboard) > 0)
266        {
267            keyboard_ = (OIS::Keyboard*)inputSystem_->createInputObject(OIS::OISKeyboard, true);
268            // register our listener in OIS.
269            keyboard_->setEventCallback(this);
270            // note: OIS will not detect keys that have already been down when the keyboard was created.
271            CCOUT(ORX_DEBUG) << "Created OIS keyboard" << std::endl;
272        }
273        else
274        {
275            ThrowException(InitialisationFailed, "No keyboard found!");
276        }
277    }
278
279    /**
280    @brief
281        Creates a mouse and sets the event handler.
282    @return
283        False if mouse stays uninitialised, true otherwise.
284    */
285    void InputManager::_initialiseMouse()
286    {
287        if (mouse_ != 0)
288        {
289            CCOUT(2) << "Warning: Mouse already initialised, skipping." << std::endl;
290            return;
291        }
292        try
293        {
294            if (inputSystem_->getNumberOfDevices(OIS::OISMouse) > 0)
295            {
296                mouse_ = static_cast<OIS::Mouse*>(inputSystem_->createInputObject(OIS::OISMouse, true));
297                // register our listener in OIS.
298                mouse_->setEventCallback(this);
299                CCOUT(ORX_DEBUG) << "Created OIS mouse" << std::endl;
300            }
301            else
302            {
303                CCOUT(ORX_WARNING) << "Warning: No mouse found!" << std::endl;
304            }
305        }
306        catch (OIS::Exception ex)
307        {
308            CCOUT(ORX_WARNING) << "Warning: Failed to create an OIS mouse\n"
309                << "OIS error message: \"" << ex.eText << "\"" << std::endl;
310            mouse_ = 0;
311        }
312    }
313
314    /**
315    @brief
316        Creates all joy sticks and sets the event handler.
317    @return
318        False joy stick stay uninitialised, true otherwise.
319    */
320    void InputManager::_initialiseJoySticks()
321    {
322        if (joySticksSize_ > 0)
323        {
324            CCOUT(2) << "Warning: Joy sticks already initialised, skipping." << std::endl;
325            return;
326        }
327        if (inputSystem_->getNumberOfDevices(OIS::OISJoyStick) > 0)
328        {
329            for (int i = 0; i < inputSystem_->getNumberOfDevices(OIS::OISJoyStick); i++)
330            {
331                try
332                {
333                    OIS::JoyStick* stig = static_cast<OIS::JoyStick*>
334                        (inputSystem_->createInputObject(OIS::OISJoyStick, true));
335                    CCOUT(ORX_DEBUG) << "Created OIS joy stick with ID " << stig->getID() << std::endl;
336                    joySticks_.push_back(stig);
337                    // register our listener in OIS.
338                    stig->setEventCallback(this);
339                }
340                catch (OIS::Exception ex)
341                {
342                    CCOUT(ORX_WARNING) << "Warning: Failed to create OIS joy number" << i << "\n"
343                        << "OIS error message: \"" << ex.eText << "\"" << std::endl;
344                }
345            }
346        }
347        else
348        {
349            //CCOUT(ORX_WARNING) << "Warning: Joy stick support requested, but no joy stick was found" << std::endl;
350        }
351    }
352
353    /**
354    @brief
355        Helper function that loads the config value vector of one coefficient
356    */
357    void loadCalibration(std::vector<int>& list, const std::string& sectionName, const std::string& valueName, size_t size, int defaultValue)
358    {
359        list.resize(size);
360        unsigned int configValueVectorSize = ConfigFileManager::getInstance().getVectorSize(ConfigFileType::JoyStickCalibration, sectionName, valueName);
361        if (configValueVectorSize > size)
362            configValueVectorSize = size;
363
364        for (unsigned int i = 0; i < configValueVectorSize; ++i)
365        {
366            list[i] = omni_cast<int>(ConfigFileManager::getInstance().getValue(
367                ConfigFileType::JoyStickCalibration, sectionName, valueName, i, omni_cast<std::string>(defaultValue), false));
368        }
369
370        // fill the rest with default values
371        for (unsigned int i = configValueVectorSize; i < size; ++i)
372        {
373            list[i] = defaultValue;
374        }
375    }
376
377    /**
378    @brief
379        Sets the size of all the different lists that are dependent on the number
380        of joy stick devices created and loads the joy stick calibration.
381    @remarks
382        No matter whether there are a mouse and/or keyboard, they will always
383        occupy 2 places in the device number dependent lists.
384    */
385    void InputManager::_configureJoySticks()
386    {
387        joySticksSize_ = joySticks_.size();
388        devicesNum_    = 2 + joySticksSize_;
389        joyStickIDs_         .resize(joySticksSize_);
390        joyStickButtonsDown_ .resize(joySticksSize_);
391        povStates_           .resize(joySticksSize_);
392        sliderStates_        .resize(joySticksSize_);
393        joyStickMinValues_   .resize(joySticksSize_);
394        joyStickMaxValues_   .resize(joySticksSize_);
395        joyStickMiddleValues_.resize(joySticksSize_);
396        joyStickCalibrations_.resize(joySticksSize_);
397
398        for (unsigned int iJoyStick = 0; iJoyStick < joySticksSize_; iJoyStick++)
399        {
400            // Generate some sort of execution unique id per joy stick
401            std::string id = "JoyStick_";
402            id += omni_cast<std::string>(joySticks_[iJoyStick]->getNumberOfComponents(OIS::OIS_Button))  + "_";
403            id += omni_cast<std::string>(joySticks_[iJoyStick]->getNumberOfComponents(OIS::OIS_Axis))    + "_";
404            id += omni_cast<std::string>(joySticks_[iJoyStick]->getNumberOfComponents(OIS::OIS_Slider))  + "_";
405            id += omni_cast<std::string>(joySticks_[iJoyStick]->getNumberOfComponents(OIS::OIS_POV))     + "_";
406            id += omni_cast<std::string>(joySticks_[iJoyStick]->getNumberOfComponents(OIS::OIS_Vector3)) + "_";
407            id += joySticks_[iJoyStick]->vendor();
408            for (unsigned int i = 0; i < iJoyStick; ++i)
409            {
410                if (id == joyStickIDs_[i])
411                {
412                    // Two joysticks are probably equal --> add the index as well
413                    id += "_" + omni_cast<std::string>(iJoyStick);
414                }
415            }
416            joyStickIDs_[iJoyStick] = id;
417
418            size_t axes = sliderAxes + (size_t)this->joySticks_[iJoyStick]->getNumberOfComponents(OIS::OIS_Axis);
419            loadCalibration(joyStickMinValues_[iJoyStick], id, "MinValue", axes, -32768);
420            loadCalibration(joyStickMaxValues_[iJoyStick], id, "MaxValue", axes,  32768);
421            loadCalibration(joyStickMiddleValues_[iJoyStick], id, "MiddleValue", axes,      0);
422        }
423
424        _evaluateCalibration();
425
426        // state management
427        activeStatesTop_.resize(devicesNum_);
428
429        // inform all states
430        for (std::map<std::string, InputState*>::const_iterator it = inputStatesByName_.begin();
431            it != inputStatesByName_.end(); ++it)
432        {
433            it->second->setNumOfJoySticks(joySticksSize_);
434        }
435        // inform master state
436        if (stateMaster_)
437            this->stateMaster_->setNumOfJoySticks(joySticksSize_);
438
439        // inform all JoyStick Device Number Listeners
440        for (ObjectList<JoyStickDeviceNumberListener>::iterator it = ObjectList<JoyStickDeviceNumberListener>::begin(); it; ++it)
441            it->JoyStickDeviceNumberChanged(joySticksSize_);
442
443    }
444
445    void InputManager::_evaluateCalibration()
446    {
447        for (unsigned int iJoyStick = 0; iJoyStick < this->joySticksSize_; ++iJoyStick)
448        {
449            for (unsigned int i = 0; i < this->joyStickMinValues_[iJoyStick].size(); i++)
450            {
451                this->joyStickCalibrations_[iJoyStick].middleValue[i] = this->joyStickMiddleValues_[iJoyStick][i];
452                this->joyStickCalibrations_[iJoyStick].negativeCoeff[i] = - 1.0f / (this->joyStickMinValues_[iJoyStick][i] - this->joyStickMiddleValues_[iJoyStick][i]);
453                this->joyStickCalibrations_[iJoyStick].positiveCoeff[i] =   1.0f / (this->joyStickMaxValues_[iJoyStick][i] - this->joyStickMiddleValues_[iJoyStick][i]);
454            }
455        }
456    }
457   
458    void InputManager::_startCalibration()
459    {
460        for (unsigned int iJoyStick = 0; iJoyStick < this->joySticksSize_; ++iJoyStick)
461        {
462            // Set initial values
463            for (unsigned int i = 0; i < this->joyStickMinValues_[iJoyStick].size(); ++i)
464                this->joyStickMinValues_[iJoyStick][i] = INT_MAX;
465            for (unsigned int i = 0; i < this->joyStickMaxValues_[iJoyStick].size(); ++i)
466                this->joyStickMaxValues_[iJoyStick][i] = INT_MIN;
467            for (unsigned int i = 0; i < this->joyStickMiddleValues_[iJoyStick].size(); ++i)
468                this->joyStickMiddleValues_[iJoyStick][i] = 0;
469        }
470
471        getInstance().internalState_ |= Calibrating;
472        getInstance().requestEnterState("calibrator");
473    }
474
475    void InputManager::_completeCalibration()
476    {
477        for (unsigned int iJoyStick = 0; iJoyStick < this->joySticksSize_; ++iJoyStick)
478        {
479            // Get the middle positions now
480            unsigned int iAxis = 0;
481            for (unsigned int i = 0; i < sliderAxes/2; ++i)
482            {
483                this->joyStickMiddleValues_[iJoyStick][iAxis++] = this->joySticks_[iJoyStick]->getJoyStickState().mSliders[i].abX;
484                this->joyStickMiddleValues_[iJoyStick][iAxis++] = this->joySticks_[iJoyStick]->getJoyStickState().mSliders[i].abY;
485            }
486            // Note: joyStickMiddleValues_[iJoyStick] was already correctly resized in _configureJoySticks()
487            assert(joySticks_[iJoyStick]->getJoyStickState().mAxes.size() == joyStickMiddleValues_[iJoyStick].size() - sliderAxes);
488            for (unsigned int i = 0; i < joyStickMiddleValues_[iJoyStick].size() - sliderAxes; ++i)
489            {
490                this->joyStickMiddleValues_[iJoyStick][iAxis++] = this->joySticks_[iJoyStick]->getJoyStickState().mAxes[i].abs;
491            }
492
493            for (unsigned int i = 0; i < joyStickMinValues_[iJoyStick].size(); ++i)
494            {
495                // Minimum values
496                if (joyStickMinValues_[iJoyStick][i] == INT_MAX)
497                    joyStickMinValues_[iJoyStick][i] = -32768;
498                ConfigFileManager::getInstance().setValue(ConfigFileType::JoyStickCalibration,
499                    this->joyStickIDs_[iJoyStick], "MinValue", i, omni_cast<std::string>(joyStickMinValues_[iJoyStick][i]), false);
500
501                // Maximum values
502                if (joyStickMaxValues_[iJoyStick][i] == INT_MIN)
503                    joyStickMaxValues_[iJoyStick][i] = 32767;
504                ConfigFileManager::getInstance().setValue(ConfigFileType::JoyStickCalibration,
505                    this->joyStickIDs_[iJoyStick], "MaxValue", i, omni_cast<std::string>(joyStickMaxValues_[iJoyStick][i]), false);
506
507                // Middle values
508                ConfigFileManager::getInstance().setValue(ConfigFileType::JoyStickCalibration,
509                    this->joyStickIDs_[iJoyStick], "MiddleValue", i, omni_cast<std::string>(joyStickMiddleValues_[iJoyStick][i]), false);
510            }
511        }
512
513        _evaluateCalibration();
514
515        // restore old input state
516        requestLeaveState("calibrator");
517        internalState_ &= ~Calibrating;
518    }
519
520    // ############################################################
521    // #####                    Destruction                   #####
522    // ##########                                        ##########
523    // ############################################################
524
525    /**
526    @brief
527        Destroys all the created input devices and states.
528    */
529    InputManager::~InputManager()
530    {
531        if (internalState_ != Uninitialised)
532        {
533            try
534            {
535                CCOUT(3) << "Destroying ..." << std::endl;
536
537                // kick all active states 'nicely'
538                for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin();
539                    rit != activeStates_.rend(); ++rit)
540                {
541                    (*rit).second->onLeave();
542                }
543
544                // Destroy calibrator helper handler and state
545                delete keyDetector_;
546                requestDestroyState("calibrator");
547                // Destroy KeyDetector and state
548                delete calibratorCallbackBuffer_;
549                requestDestroyState("detector");
550                // destroy the empty InputState
551                _destroyState(this->stateEmpty_);
552                // destroy the master input state. This might trigger a memory leak
553                // because the user has forgotten to destroy the KeyBinder or any Handler!
554                delete stateMaster_;
555
556                // destroy all user InputStates
557                while (inputStatesByName_.size() > 0)
558                    _destroyState((*inputStatesByName_.rbegin()).second);
559
560                // destroy the devices
561                _destroyKeyboard();
562                _destroyMouse();
563                _destroyJoySticks();
564
565                OIS::InputManager::destroyInputSystem(inputSystem_);
566
567                CCOUT(3) << "Destroying done." << std::endl;
568            }
569            catch (OIS::Exception& ex)
570            {
571                CCOUT(1) << "An exception has occured while destroying:\n" << ex.what()
572                         << "This could lead to a possible memory/resource leak!" << std::endl;
573            }
574        }
575
576        singletonRef_s = 0;
577    }
578
579    /**
580    @brief
581        Destroys the keyboard and sets it to 0.
582    */
583    void InputManager::_destroyKeyboard()
584    {
585        assert(inputSystem_);
586        if (keyboard_)
587            inputSystem_->destroyInputObject(keyboard_);
588        keyboard_ = 0;
589        CCOUT(4) << "Keyboard destroyed." << std::endl;
590    }
591
592    /**
593    @brief
594        Destroys the mouse and sets it to 0.
595    */
596    void InputManager::_destroyMouse()
597    {
598        assert(inputSystem_);
599        if (mouse_)
600            inputSystem_->destroyInputObject(mouse_);
601        mouse_ = 0;
602        CCOUT(4) << "Mouse destroyed." << std::endl;
603    }
604
605    /**
606    @brief
607        Destroys all the joy sticks and resizes the lists to 0.
608    */
609    void InputManager::_destroyJoySticks()
610    {
611        if (joySticksSize_ > 0)
612        {
613            assert(inputSystem_);
614            for (unsigned int i = 0; i < joySticksSize_; i++)
615                if (joySticks_[i] != 0)
616                    inputSystem_->destroyInputObject(joySticks_[i]);
617
618            joySticks_.clear();
619            // don't use _configureNumberOfJoySticks(), might mess with registered handler if
620            // downgrading from 2 to 1 joystick
621            //_configureNumberOfJoySticks();
622            joySticksSize_ = 0;
623        }
624        CCOUT(4) << "Joy sticks destroyed." << std::endl;
625    }
626
627    /**
628    @brief
629        Removes and destroys an InputState.
630    @return
631        True if state was removed immediately, false if postponed.
632    */
633    void InputManager::_destroyState(InputState* state)
634    {
635        assert(state && !(this->internalState_ & Ticking));
636        std::map<int, InputState*>::iterator it = this->activeStates_.find(state->getPriority());
637        if (it != this->activeStates_.end())
638        {
639            this->activeStates_.erase(it);
640            _updateActiveStates();
641        }
642        inputStatesByName_.erase(state->getName());
643        delete state;
644    }
645
646    void InputManager::_clearBuffers()
647    {
648        keysDown_.clear();
649        keyboardModifiers_ = 0;
650        mouseButtonsDown_.clear();
651        for (unsigned int i = 0; i < joySticksSize_; ++i)
652        {
653            joyStickButtonsDown_[i].clear();
654            for (int j = 0; j < 4; ++j)
655            {
656                sliderStates_[i].sliderStates[j].x = 0;
657                sliderStates_[i].sliderStates[j].y = 0;
658                povStates_[i][j] = 0;
659            }
660        }
661    }
662
663
664    // ############################################################
665    // #####                     Reloading                    #####
666    // ##########                                        ##########
667    // ############################################################
668
669    /**
670    @brief
671        Public interface. Only reloads immediately if the call stack doesn't
672        include the update() method.
673    @param joyStickSupport
674        Whether or not to initialise joy sticks as well.
675    */
676    void InputManager::reloadInputSystem(bool joyStickSupport)
677    {
678        if (internalState_ & Ticking)
679        {
680            // We cannot destroy OIS right now, because reload was probably
681            // caused by a user clicking on a GUI item. The backtrace would then
682            // include an OIS method. So it would be a very bad thing to destroy it..
683            internalState_ |= ReloadRequest;
684            // Misuse of internalState_: We can easily store the joyStickSupport bool.
685            // use Uninitialised as 0 value in order to make use of the overloaded |= operator
686            internalState_ |= joyStickSupport ? JoyStickSupport : Uninitialised;
687        }
688        else if (internalState_ & OISReady)
689        {
690            _reload(joyStickSupport);
691        }
692        else
693        {
694            CCOUT(2) << "Warning: Cannot reload OIS. May not yet be initialised or"
695                     << "joy sticks are currently calibrating." << std::endl;
696        }
697    }
698
699    /**
700    @brief
701        Internal reload method. Destroys the OIS devices and loads them again.
702    */
703    void InputManager::_reload(bool joyStickSupport)
704    {
705        try
706        {
707            CCOUT(3) << "Reloading ..." << std::endl;
708
709            // Save mouse clipping size
710            int mouseWidth  = mouse_->getMouseState().width;
711            int mouseHeight = mouse_->getMouseState().height;
712
713            internalState_ &= ~OISReady;
714
715            // destroy the devices
716            _destroyKeyboard();
717            _destroyMouse();
718            _destroyJoySticks();
719
720            OIS::InputManager::destroyInputSystem(inputSystem_);
721            inputSystem_ = 0;
722
723            // clear all buffers containing input information
724            _clearBuffers();
725
726            initialise(windowHnd_, mouseWidth, mouseHeight, joyStickSupport);
727
728            CCOUT(3) << "Reloading done." << std::endl;
729        }
730        catch (OIS::Exception& ex)
731        {
732            CCOUT(1) << "An exception has occured while reloading:\n" << ex.what() << std::endl;
733        }
734    }
735
736    // ############################################################
737    // #####                  Runtime Methods                 #####
738    // ##########                                        ##########
739    // ############################################################
740
741    /**
742    @brief
743        Updates the states and the InputState situation.
744    @param time
745        Clock holding the current time.
746    */
747    void InputManager::update(const Clock& time)
748    {
749        if (internalState_ == Uninitialised)
750            return;
751        else if (internalState_ & ReloadRequest)
752        {
753            _reload(internalState_ & JoyStickSupport);
754            internalState_ &= ~ReloadRequest;
755            internalState_ &= ~JoyStickSupport;
756        }
757
758        // check for states to leave
759        if (!stateLeaveRequests_.empty())
760        {
761            for (std::set<InputState*>::reverse_iterator rit = stateLeaveRequests_.rbegin();
762                rit != stateLeaveRequests_.rend(); ++rit)
763            {
764                (*rit)->onLeave();
765                // just to be sure that the state actually is registered
766                assert(inputStatesByName_.find((*rit)->getName()) != inputStatesByName_.end());
767
768                activeStates_.erase((*rit)->getPriority());
769                if ((*rit)->getPriority() < InputStatePriority::HighPriority)
770                    (*rit)->setPriority(0);
771                _updateActiveStates();
772            }
773            stateLeaveRequests_.clear();
774        }
775
776        // check for states to enter
777        if (!stateEnterRequests_.empty())
778        {
779            for (std::set<InputState*>::reverse_iterator rit = stateEnterRequests_.rbegin();
780                rit != stateEnterRequests_.rend(); ++rit)
781            {
782                // just to be sure that the state actually is registered
783                assert(inputStatesByName_.find((*rit)->getName()) != inputStatesByName_.end());
784
785                if ((*rit)->getPriority() == 0)
786                {
787                    // Get smallest possible priority between 1 and maxStateStackSize_s
788                    for(std::map<int, InputState*>::const_reverse_iterator rit2 = activeStates_.rbegin();
789                        rit2 != activeStates_.rend(); ++rit2)
790                    {
791                        if (rit2->first < InputStatePriority::HighPriority)
792                        {
793                            (*rit)->setPriority(rit2->first + 1);
794                            break;
795                        }
796                    }
797                    // In case no normal handler was on the stack
798                    if ((*rit)->getPriority() == 0)
799                        (*rit)->setPriority(1);
800                }
801                activeStates_[(*rit)->getPriority()] = (*rit);
802                _updateActiveStates();
803                (*rit)->onEnter();
804            }
805            stateEnterRequests_.clear();
806        }
807
808        // check for states to destroy
809        if (!stateDestroyRequests_.empty())
810        {
811            for (std::set<InputState*>::reverse_iterator rit = stateDestroyRequests_.rbegin();
812                rit != stateDestroyRequests_.rend(); ++rit)
813            {
814                _destroyState((*rit));
815            }
816            stateDestroyRequests_.clear();
817        }
818
819        // check whether a state has changed its EMPTY_HANDLER situation
820        bool bUpdateRequired = false;
821        for (std::map<int, InputState*>::iterator it = activeStates_.begin(); it != activeStates_.end(); ++it)
822        {
823            if (it->second->handlersChanged())
824            {
825                it->second->resetHandlersChanged();
826                bUpdateRequired = true;
827            }
828        }
829        if (bUpdateRequired)
830            _updateActiveStates();
831
832        // mark that we now start capturing and distributing input
833        internalState_ |= Ticking;
834
835        // Capture all the input. This calls the event handlers in InputManager.
836        if (keyboard_)
837            keyboard_->capture();
838        if (mouse_)
839            mouse_->capture();
840        for (unsigned  int i = 0; i < joySticksSize_; i++)
841            joySticks_[i]->capture();
842
843        if (!(internalState_ & Calibrating))
844        {
845            // call all the handlers for the held key events
846            for (unsigned int iKey = 0; iKey < keysDown_.size(); iKey++)
847            {
848                KeyEvent kEvt(keysDown_[iKey], keyboardModifiers_);
849                activeStatesTop_[Keyboard]->keyHeld(kEvt);
850                stateMaster_->keyHeld(kEvt);
851            }
852
853            // call all the handlers for the held mouse button events
854            for (unsigned int iButton = 0; iButton < mouseButtonsDown_.size(); iButton++)
855            {
856                activeStatesTop_[Mouse]->mouseButtonHeld(mouseButtonsDown_[iButton]);
857                stateMaster_->mouseButtonHeld(mouseButtonsDown_[iButton]);
858            }
859
860            // call all the handlers for the held joy stick button events
861            for (unsigned int iJoyStick  = 0; iJoyStick < joySticksSize_; iJoyStick++)
862                for (unsigned int iButton   = 0; iButton   < joyStickButtonsDown_[iJoyStick].size(); iButton++)
863                {
864                    activeStatesTop_[JoyStick0 + iJoyStick]
865                        ->joyStickButtonHeld(iJoyStick, joyStickButtonsDown_[iJoyStick][iButton]);
866                    stateMaster_->joyStickButtonHeld(iJoyStick, joyStickButtonsDown_[iJoyStick][iButton]);
867                }
868
869            // update the handlers for each active handler
870            for (unsigned int i = 0; i < devicesNum_; ++i)
871            {
872                activeStatesTop_[i]->updateInput(time.getDeltaTime(), i);
873                if (stateMaster_->isInputDeviceEnabled(i))
874                    stateMaster_->updateInput(time.getDeltaTime(), i);
875            }
876
877            // update the handler with a general tick afterwards
878            for (unsigned int i = 0; i < activeStatesTicked_.size(); ++i)
879                activeStatesTicked_[i]->updateInput(time.getDeltaTime());
880            stateMaster_->updateInput(time.getDeltaTime());
881        }
882
883        internalState_ &= ~Ticking;
884    }
885
886    /**
887    @brief
888        Updates the currently active states (according to activeStates_) for each device.
889        Also, a list of all active states (no duplicates!) is compiled for the general update().
890    */
891    void InputManager::_updateActiveStates()
892    {
893        for (std::map<int, InputState*>::const_iterator it = activeStates_.begin(); it != activeStates_.end(); ++it)
894            for (unsigned int i = 0; i < devicesNum_; ++i)
895                if (it->second->isInputDeviceEnabled(i))
896                    activeStatesTop_[i] = it->second;
897
898        // update tickables (every state will only appear once)
899        // Using a std::set to avoid duplicates
900        std::set<InputState*> tempSet;
901        for (unsigned int i = 0; i < devicesNum_; ++i)
902            tempSet.insert(activeStatesTop_[i]);
903
904        // copy the content of the set back to the actual vector
905        activeStatesTicked_.clear();
906        for (std::set<InputState*>::const_iterator it = tempSet.begin();it != tempSet.end(); ++it)
907            activeStatesTicked_.push_back(*it);
908
909        this->mouseButtonsDown_.clear();
910    }
911
912    /**
913    @brief
914        Clears all buffers that store what keys/buttons are being pressed at the moment.
915    */
916    void InputManager::clearBuffers()
917    {
918        this->keysDown_.clear();
919        this->mouseButtonsDown_.clear();
920        for (unsigned int i = 0; i < this->joySticksSize_; ++i)
921            this->joyStickButtonsDown_[i].clear();
922    }
923
924
925    // ############################################################
926    // #####                    OIS events                    #####
927    // ##########                                        ##########
928    // ############################################################
929
930    // ###### Key Events ######
931
932    /**
933    @brief
934        Event handler for the keyPressed Event.
935    @param e
936        Event information
937    */
938    bool InputManager::keyPressed(const OIS::KeyEvent &e)
939    {
940        // check whether the key already is in the list (can happen when focus was lost)
941        unsigned int iKey = 0;
942        while (iKey < keysDown_.size() && keysDown_[iKey].key != (KeyCode::ByEnum)e.key)
943            iKey++;
944        if (iKey == keysDown_.size())
945            keysDown_.push_back(Key(e));
946        else
947        {
948            // This happens when XAutoRepeat is set under linux. The KeyPressed event gets then sent
949            // continuously.
950            return true;
951        }
952
953        // update modifiers
954        if(e.key == OIS::KC_RMENU    || e.key == OIS::KC_LMENU)
955            keyboardModifiers_ |= KeyboardModifier::Alt;   // alt key
956        if(e.key == OIS::KC_RCONTROL || e.key == OIS::KC_LCONTROL)
957            keyboardModifiers_ |= KeyboardModifier::Ctrl;  // ctrl key
958        if(e.key == OIS::KC_RSHIFT   || e.key == OIS::KC_LSHIFT)
959            keyboardModifiers_ |= KeyboardModifier::Shift; // shift key
960
961        KeyEvent kEvt(e, keyboardModifiers_);
962        activeStatesTop_[Keyboard]->keyPressed(kEvt);
963        stateMaster_->keyPressed(kEvt);
964
965        return true;
966    }
967
968    /**
969    @brief
970        Event handler for the keyReleased Event.
971    @param e
972        Event information
973    */
974    bool InputManager::keyReleased(const OIS::KeyEvent &e)
975    {
976        // remove the key from the keysDown_ list
977        for (unsigned int iKey = 0; iKey < keysDown_.size(); iKey++)
978        {
979            if (keysDown_[iKey].key == (KeyCode::ByEnum)e.key)
980            {
981                keysDown_.erase(keysDown_.begin() + iKey);
982                break;
983            }
984        }
985
986        // update modifiers
987        if(e.key == OIS::KC_RMENU    || e.key == OIS::KC_LMENU)
988            keyboardModifiers_ &= ~KeyboardModifier::Alt;   // alt key
989        if(e.key == OIS::KC_RCONTROL || e.key == OIS::KC_LCONTROL)
990            keyboardModifiers_ &= ~KeyboardModifier::Ctrl;  // ctrl key
991        if(e.key == OIS::KC_RSHIFT   || e.key == OIS::KC_LSHIFT)
992            keyboardModifiers_ &= ~KeyboardModifier::Shift; // shift key
993
994        KeyEvent kEvt(e, keyboardModifiers_);
995        activeStatesTop_[Keyboard]->keyReleased(kEvt);
996        stateMaster_->keyReleased(kEvt);
997
998        return true;
999    }
1000
1001
1002    // ###### Mouse Events ######
1003
1004    /**
1005    @brief
1006        Event handler for the mouseMoved Event.
1007    @param e
1008        Event information
1009    */
1010    bool InputManager::mouseMoved(const OIS::MouseEvent &e)
1011    {
1012        // check for actual moved event
1013        if (e.state.X.rel != 0 || e.state.Y.rel != 0)
1014        {
1015            IntVector2 abs(e.state.X.abs, e.state.Y.abs);
1016            IntVector2 rel(e.state.X.rel, e.state.Y.rel);
1017            IntVector2 clippingSize(e.state.width, e.state.height);
1018            activeStatesTop_[Mouse]->mouseMoved(abs, rel, clippingSize);
1019            stateMaster_->mouseMoved(abs, rel, clippingSize);
1020        }
1021
1022        // check for mouse scrolled event
1023        if (e.state.Z.rel != 0)
1024        {
1025            activeStatesTop_[Mouse]->mouseScrolled(e.state.Z.abs, e.state.Z.rel);
1026            stateMaster_->mouseScrolled(e.state.Z.abs, e.state.Z.rel);
1027        }
1028
1029        return true;
1030    }
1031
1032    /**
1033    @brief
1034        Event handler for the mousePressed Event.
1035    @param e
1036        Event information
1037    @param id
1038        The ID of the mouse button
1039    */
1040    bool InputManager::mousePressed(const OIS::MouseEvent &e, OIS::MouseButtonID id)
1041    {
1042        // check whether the button already is in the list (can happen when focus was lost)
1043        unsigned int iButton = 0;
1044        while (iButton < mouseButtonsDown_.size() && mouseButtonsDown_[iButton] != (MouseButtonCode::ByEnum)id)
1045            iButton++;
1046        if (iButton == mouseButtonsDown_.size())
1047            mouseButtonsDown_.push_back((MouseButtonCode::ByEnum)id);
1048
1049        activeStatesTop_[Mouse]->mouseButtonPressed((MouseButtonCode::ByEnum)id);
1050        stateMaster_->mouseButtonPressed((MouseButtonCode::ByEnum)id);
1051
1052        return true;
1053    }
1054
1055    /**
1056    @brief
1057        Event handler for the mouseReleased Event.
1058    @param e
1059        Event information
1060    @param id
1061        The ID of the mouse button
1062    */
1063    bool InputManager::mouseReleased(const OIS::MouseEvent &e, OIS::MouseButtonID id)
1064    {
1065        // remove the button from the keysDown_ list
1066        for (unsigned int iButton = 0; iButton < mouseButtonsDown_.size(); iButton++)
1067        {
1068            if (mouseButtonsDown_[iButton] == (MouseButtonCode::ByEnum)id)
1069            {
1070                mouseButtonsDown_.erase(mouseButtonsDown_.begin() + iButton);
1071                break;
1072            }
1073        }
1074
1075        activeStatesTop_[Mouse]->mouseButtonReleased((MouseButtonCode::ByEnum)id);
1076        stateMaster_->mouseButtonReleased((MouseButtonCode::ByEnum)id);
1077
1078        return true;
1079    }
1080
1081
1082    // ###### Joy Stick Events ######
1083
1084    /**
1085    @brief
1086        Returns the joy stick ID (orxonox) according to a OIS::JoyStickEvent
1087    */
1088    inline unsigned int InputManager::_getJoystick(const OIS::JoyStickEvent& arg)
1089    {
1090        // use the device to identify which one called the method
1091        OIS::JoyStick* joyStick = (OIS::JoyStick*)arg.device;
1092        unsigned int iJoyStick = 0;
1093        while (joySticks_[iJoyStick] != joyStick)
1094            iJoyStick++;
1095        // assert: Unknown joystick fired an event.
1096        assert(iJoyStick != joySticksSize_);
1097        return iJoyStick;
1098    }
1099
1100    bool InputManager::buttonPressed(const OIS::JoyStickEvent &arg, int button)
1101    {
1102        unsigned int iJoyStick = _getJoystick(arg);
1103
1104        // check whether the button already is in the list (can happen when focus was lost)
1105        std::vector<JoyStickButtonCode::ByEnum>& buttonsDown = joyStickButtonsDown_[iJoyStick];
1106        unsigned int iButton = 0;
1107        while (iButton < buttonsDown.size() && buttonsDown[iButton] != button)
1108            iButton++;
1109        if (iButton == buttonsDown.size())
1110            buttonsDown.push_back((JoyStickButtonCode::ByEnum)button);
1111
1112        activeStatesTop_[2 + iJoyStick]->joyStickButtonPressed(iJoyStick, (JoyStickButtonCode::ByEnum)button);
1113        stateMaster_->joyStickButtonPressed(iJoyStick, (JoyStickButtonCode::ByEnum)button);
1114
1115        return true;
1116    }
1117
1118    bool InputManager::buttonReleased(const OIS::JoyStickEvent &arg, int button)
1119    {
1120        unsigned int iJoyStick = _getJoystick(arg);
1121
1122        // remove the button from the joyStickButtonsDown_ list
1123        std::vector<JoyStickButtonCode::ByEnum>& buttonsDown = joyStickButtonsDown_[iJoyStick];
1124        for (unsigned int iButton = 0; iButton < buttonsDown.size(); iButton++)
1125        {
1126            if (buttonsDown[iButton] == button)
1127            {
1128                buttonsDown.erase(buttonsDown.begin() + iButton);
1129                break;
1130            }
1131        }
1132
1133        activeStatesTop_[2 + iJoyStick]->joyStickButtonReleased(iJoyStick, (JoyStickButtonCode::ByEnum)button);
1134        stateMaster_->joyStickButtonReleased(iJoyStick, (JoyStickButtonCode::ByEnum)button);
1135
1136        return true;
1137    }
1138
1139    /**
1140    @brief
1141        Calls the states for a particular axis with our enumeration.
1142        Used by OIS sliders and OIS axes.
1143    */
1144    void InputManager::_fireAxis(unsigned int iJoyStick, int axis, int value)
1145    {
1146        if (internalState_ & Calibrating)
1147        {
1148            if (value < joyStickMinValues_[iJoyStick][axis])
1149                joyStickMinValues_[iJoyStick][axis] = value;
1150            if (value > joyStickMaxValues_[iJoyStick][axis])
1151                joyStickMaxValues_[iJoyStick][axis] = value;
1152        }
1153        else
1154        {
1155            float fValue = value - joyStickCalibrations_[iJoyStick].middleValue[axis];
1156            if (fValue > 0.0f)
1157                fValue *= joyStickCalibrations_[iJoyStick].positiveCoeff[axis];
1158            else
1159                fValue *= joyStickCalibrations_[iJoyStick].negativeCoeff[axis];
1160
1161            activeStatesTop_[2 + iJoyStick]->joyStickAxisMoved(iJoyStick, axis, fValue);
1162            stateMaster_->joyStickAxisMoved(iJoyStick, axis, fValue);
1163        }
1164    }
1165
1166    bool InputManager::axisMoved(const OIS::JoyStickEvent &arg, int axis)
1167    {
1168        unsigned int iJoyStick = _getJoystick(arg);
1169
1170        // keep in mind that the first 8 axes are reserved for the sliders
1171        _fireAxis(iJoyStick, axis + sliderAxes, arg.state.mAxes[axis].abs);
1172
1173        return true;
1174    }
1175
1176    bool InputManager::sliderMoved(const OIS::JoyStickEvent &arg, int id)
1177    {
1178        unsigned int iJoyStick = _getJoystick(arg);
1179
1180        if (sliderStates_[iJoyStick].sliderStates[id].x != arg.state.mSliders[id].abX)
1181            _fireAxis(iJoyStick, id * 2, arg.state.mSliders[id].abX);
1182        else if (sliderStates_[iJoyStick].sliderStates[id].y != arg.state.mSliders[id].abY)
1183            _fireAxis(iJoyStick, id * 2 + 1, arg.state.mSliders[id].abY);
1184
1185        return true;
1186    }
1187
1188    bool InputManager::povMoved(const OIS::JoyStickEvent &arg, int id)
1189    {
1190        unsigned int iJoyStick = _getJoystick(arg);
1191
1192        // translate the POV into 8 simple buttons
1193
1194        int lastState = povStates_[iJoyStick][id];
1195        if (lastState & OIS::Pov::North)
1196            buttonReleased(arg, 32 + id * 4 + 0);
1197        if (lastState & OIS::Pov::South)
1198            buttonReleased(arg, 32 + id * 4 + 1);
1199        if (lastState & OIS::Pov::East)
1200            buttonReleased(arg, 32 + id * 4 + 2);
1201        if (lastState & OIS::Pov::West)
1202            buttonReleased(arg, 32 + id * 4 + 3);
1203
1204        povStates_[iJoyStick].povStates[id] = arg.state.mPOV[id].direction;
1205
1206        int currentState = povStates_[iJoyStick][id];
1207        if (currentState & OIS::Pov::North)
1208            buttonPressed(arg, 32 + id * 4 + 0);
1209        if (currentState & OIS::Pov::South)
1210            buttonPressed(arg, 32 + id * 4 + 1);
1211        if (currentState & OIS::Pov::East)
1212            buttonPressed(arg, 32 + id * 4 + 2);
1213        if (currentState & OIS::Pov::West)
1214            buttonPressed(arg, 32 + id * 4 + 3);
1215
1216        return true;
1217    }
1218
1219
1220    // ############################################################
1221    // #####         Other Public Interface Methods           #####
1222    // ##########                                        ##########
1223    // ############################################################
1224
1225    /**
1226    @brief
1227        Adjusts the mouse window metrics.
1228        This method has to be called every time the size of the window changes.
1229    @param width
1230        The new width of the render window
1231    @param^height
1232        The new height of the render window
1233    */
1234    void InputManager::setWindowExtents(const int width, const int height)
1235    {
1236        if (mouse_)
1237        {
1238            // Set mouse region (if window resizes, we should alter this to reflect as well)
1239            mouse_->getMouseState().width  = width;
1240            mouse_->getMouseState().height = height;
1241        }
1242    }
1243
1244    /**
1245    @brief
1246        Sets the the name of the command used by the KeyDetector as callback.
1247    @param command
1248        Command name as string
1249    */
1250    void InputManager::setKeyDetectorCallback(const std::string& command)
1251    {
1252        this->keyDetector_->setCallbackCommand(command);
1253    }
1254
1255    // ###### InputStates ######
1256
1257    /**
1258    @brief
1259        Adds a new key handler.
1260    @param handler
1261        Pointer to the handler object.
1262    @param name
1263        Unique name of the handler.
1264    @param priority
1265        Determines which InputState gets the input. Higher is better.
1266        Use 0 to handle it implicitely by the order of activation.
1267        Otherwise numbers larger than maxStateStackSize_s have to be used!
1268    @return
1269        True if added, false if name or priority already existed.
1270    */
1271    bool InputManager::_configureInputState(InputState* state, const std::string& name, int priority)
1272    {
1273        if (name == "")
1274            return false;
1275        if (!state)
1276            return false;
1277        if (inputStatesByName_.find(name) == inputStatesByName_.end())
1278        {
1279            if (priority >= InputStatePriority::HighPriority || priority == InputStatePriority::Empty)
1280            {
1281                // Make sure we don't add two high priority states with the same priority
1282                for (std::map<std::string, InputState*>::const_iterator it = this->inputStatesByName_.begin();
1283                    it != this->inputStatesByName_.end(); ++it)
1284                {
1285                    if (it->second->getPriority() == priority)
1286                    {
1287                        COUT(2) << "Warning: Could not add an InputState with the same priority '"
1288                            << priority << "' != 0." << std::endl;
1289                        return false;
1290                    }
1291                }
1292            }
1293            inputStatesByName_[name] = state;
1294            state->setNumOfJoySticks(numberOfJoySticks());
1295            state->setName(name);
1296            if (priority >= InputStatePriority::HighPriority || priority == InputStatePriority::Empty)
1297                state->setPriority(priority);
1298            return true;
1299        }
1300        else
1301        {
1302            COUT(2) << "Warning: Could not add an InputState with the same name '" << name << "'." << std::endl;
1303            return false;
1304        }
1305    }
1306
1307    /**
1308    @brief
1309        Removes and destroys an input state internally.
1310    @param name
1311        Name of the handler.
1312    @return
1313        True if removal was successful, false if name was not found.
1314    @remarks
1315        You can't remove the internal states "empty", "calibrator" and "detector".
1316        The removal process is being postponed if InputManager::update() is currently running.
1317    */
1318    bool InputManager::requestDestroyState(const std::string& name)
1319    {
1320        if (name == "empty")
1321        {
1322            COUT(2) << "InputManager: Removing the empty state is not allowed!" << std::endl;
1323            return false;
1324        }
1325        std::map<std::string, InputState*>::iterator it = inputStatesByName_.find(name);
1326        if (it != inputStatesByName_.end())
1327        {
1328            if (activeStates_.find(it->second->getPriority()) != activeStates_.end())
1329            {
1330                // The state is still active. We have to postpone
1331                stateLeaveRequests_.insert(it->second);
1332                stateDestroyRequests_.insert(it->second);
1333            }
1334            else if (this->internalState_ & Ticking)
1335            {
1336                // cannot remove state while ticking
1337                stateDestroyRequests_.insert(it->second);
1338            }
1339            else
1340                _destroyState(it->second);
1341
1342            return true;
1343        }
1344        return false;
1345    }
1346
1347    /**
1348    @brief
1349        Returns the pointer to the requested InputState.
1350    @param name
1351        Unique name of the state.
1352    @return
1353        Pointer to the instance, 0 if name was not found.
1354    */
1355    InputState* InputManager::getState(const std::string& name)
1356    {
1357        std::map<std::string, InputState*>::iterator it = inputStatesByName_.find(name);
1358        if (it != inputStatesByName_.end())
1359            return it->second;
1360        else
1361            return 0;
1362    }
1363
1364    /**
1365    @brief
1366        Returns the current input state (there might be others active too!)
1367    @return
1368        The current highest prioritised active input state.
1369    */
1370    InputState* InputManager::getCurrentState()
1371    {
1372        return (*activeStates_.rbegin()).second;
1373    }
1374
1375    /**
1376    @brief
1377        Activates a specific input state.
1378        It might not be really activated if the priority is too low!
1379    @param name
1380        Unique name of the state.
1381    @return
1382        False if name was not found, true otherwise.
1383    */
1384    bool InputManager::requestEnterState(const std::string& name)
1385    {
1386        // get pointer from the map with all stored handlers
1387        std::map<std::string, InputState*>::const_iterator it = inputStatesByName_.find(name);
1388        if (it != inputStatesByName_.end())
1389        {
1390            // exists
1391            if (activeStates_.find(it->second->getPriority()) == activeStates_.end())
1392            {
1393                // not active
1394                if (stateDestroyRequests_.find(it->second) == stateDestroyRequests_.end())
1395                {
1396                    // not scheduled for destruction
1397                    // prevents a state being added multiple times
1398                    stateEnterRequests_.insert(it->second);
1399                    return true;
1400                }
1401            }
1402        }
1403        return false;
1404    }
1405
1406    /**
1407    @brief
1408        Deactivates a specific input state.
1409    @param name
1410        Unique name of the state.
1411    @return
1412        False if name was not found, true otherwise.
1413    */
1414    bool InputManager::requestLeaveState(const std::string& name)
1415    {
1416        if (name == "empty")
1417        {
1418            COUT(2) << "InputManager: Leaving the empty state is not allowed!" << std::endl;
1419            return false;
1420        }
1421        // get pointer from the map with all stored handlers
1422        std::map<std::string, InputState*>::const_iterator it = inputStatesByName_.find(name);
1423        if (it != inputStatesByName_.end())
1424        {
1425            // exists
1426            if (activeStates_.find(it->second->getPriority()) != activeStates_.end())
1427            {
1428                // active
1429                stateLeaveRequests_.insert(it->second);
1430                return true;
1431            }
1432        }
1433        return false;
1434    }
1435
1436
1437    // ############################################################
1438    // #####                Console Commands                  #####
1439    // ##########                                        ##########
1440    // ############################################################
1441
1442    /**
1443    @brief
1444        Starts joy stick calibration.
1445    */
1446    void InputManager::calibrate()
1447    {
1448        COUT(0) << "Move all joy stick axes fully in all directions." << std::endl
1449                << "When done, put the axex in the middle position and press enter." << std::endl;
1450
1451        getInstance()._startCalibration();
1452    }
1453
1454    /**
1455    @brief
1456        Reloads the input system
1457    */
1458    void InputManager::reload(bool joyStickSupport)
1459    {
1460        getInstance().reloadInputSystem(joyStickSupport);
1461    }
1462}
Note: See TracBrowser for help on using the repository browser.