Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 2800 was 2800, checked in by rgrieder, 15 years ago

Renaming "tick" to "update" for all those classes not inheriting from Tickable to avoid confusions.
GameState::ticked still exists, but that's going to change anyway.

  • Property svn:eol-style set to native
File size: 50.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
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 OIS_LINUX_PLATFORM
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", -1);
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", 101);
232            keyDetector_ = new KeyDetector();
233            detector->setHandler(keyDetector_);
234
235            // Joy stick calibration helper callback
236            SimpleInputState* calibrator = createInputState<SimpleInputState>("calibrator", 100);
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<int, InputState*>::const_iterator it = inputStatesByPriority_.begin();
431            it != inputStatesByPriority_.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 (inputStatesByPriority_.size() > 0)
558                    _destroyState((*inputStatesByPriority_.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        inputStatesByPriority_.erase(state->getPriority());
643        inputStatesByName_.erase(state->getName());
644        delete state;
645    }
646
647    void InputManager::_clearBuffers()
648    {
649        keysDown_.clear();
650        keyboardModifiers_ = 0;
651        mouseButtonsDown_.clear();
652        for (unsigned int i = 0; i < joySticksSize_; ++i)
653        {
654            joyStickButtonsDown_[i].clear();
655            for (int j = 0; j < 4; ++j)
656            {
657                sliderStates_[i].sliderStates[j].x = 0;
658                sliderStates_[i].sliderStates[j].y = 0;
659                povStates_[i][j] = 0;
660            }
661        }
662    }
663
664
665    // ############################################################
666    // #####                     Reloading                    #####
667    // ##########                                        ##########
668    // ############################################################
669
670    /**
671    @brief
672        Public interface. Only reloads immediately if the call stack doesn't
673        include the update() method.
674    @param joyStickSupport
675        Whether or not to initialise joy sticks as well.
676    */
677    void InputManager::reloadInputSystem(bool joyStickSupport)
678    {
679        if (internalState_ & Ticking)
680        {
681            // We cannot destroy OIS right now, because reload was probably
682            // caused by a user clicking on a GUI item. The backtrace would then
683            // include an OIS method. So it would be a very bad thing to destroy it..
684            internalState_ |= ReloadRequest;
685            // Misuse of internalState_: We can easily store the joyStickSupport bool.
686            // use Uninitialised as 0 value in order to make use of the overloaded |= operator
687            internalState_ |= joyStickSupport ? JoyStickSupport : Uninitialised;
688        }
689        else if (internalState_ & OISReady)
690        {
691            _reload(joyStickSupport);
692        }
693        else
694        {
695            CCOUT(2) << "Warning: Cannot reload OIS. May not yet be initialised or"
696                     << "joy sticks are currently calibrating." << std::endl;
697        }
698    }
699
700    /**
701    @brief
702        Internal reload method. Destroys the OIS devices and loads them again.
703    */
704    void InputManager::_reload(bool joyStickSupport)
705    {
706        try
707        {
708            CCOUT(3) << "Reloading ..." << std::endl;
709
710            // Save mouse clipping size
711            int mouseWidth  = mouse_->getMouseState().width;
712            int mouseHeight = mouse_->getMouseState().height;
713
714            internalState_ &= ~OISReady;
715
716            // destroy the devices
717            _destroyKeyboard();
718            _destroyMouse();
719            _destroyJoySticks();
720
721            OIS::InputManager::destroyInputSystem(inputSystem_);
722            inputSystem_ = 0;
723
724            // clear all buffers containing input information
725            _clearBuffers();
726
727            initialise(windowHnd_, mouseWidth, mouseHeight, joyStickSupport);
728
729            CCOUT(3) << "Reloading done." << std::endl;
730        }
731        catch (OIS::Exception& ex)
732        {
733            CCOUT(1) << "An exception has occured while reloading:\n" << ex.what() << std::endl;
734        }
735    }
736
737    // ############################################################
738    // #####                  Runtime Methods                 #####
739    // ##########                                        ##########
740    // ############################################################
741
742    /**
743    @brief
744        Updates the states and the InputState situation.
745    @param time
746        Clock holding the current time.
747    */
748    void InputManager::update(const Clock& time)
749    {
750        if (internalState_ == Uninitialised)
751            return;
752        else if (internalState_ & ReloadRequest)
753        {
754            _reload(internalState_ & JoyStickSupport);
755            internalState_ &= ~ReloadRequest;
756            internalState_ &= ~JoyStickSupport;
757        }
758
759        // check for states to leave
760        if (!stateLeaveRequests_.empty())
761        {
762            for (std::set<InputState*>::reverse_iterator rit = stateLeaveRequests_.rbegin();
763                rit != stateLeaveRequests_.rend(); ++rit)
764            {
765                (*rit)->onLeave();
766                // just to be sure that the state actually is registered
767                assert(inputStatesByName_.find((*rit)->getName()) != inputStatesByName_.end());
768
769                activeStates_.erase((*rit)->getPriority());
770                _updateActiveStates();
771            }
772            stateLeaveRequests_.clear();
773        }
774
775        // check for states to enter
776        if (!stateEnterRequests_.empty())
777        {
778            for (std::set<InputState*>::reverse_iterator rit = stateEnterRequests_.rbegin();
779                rit != stateEnterRequests_.rend(); ++rit)
780            {
781                // just to be sure that the state actually is registered
782                assert(inputStatesByName_.find((*rit)->getName()) != inputStatesByName_.end());
783
784                activeStates_[(*rit)->getPriority()] = (*rit);
785                _updateActiveStates();
786                (*rit)->onEnter();
787            }
788            stateEnterRequests_.clear();
789        }
790
791        // check for states to destroy
792        if (!stateDestroyRequests_.empty())
793        {
794            for (std::set<InputState*>::reverse_iterator rit = stateDestroyRequests_.rbegin();
795                rit != stateDestroyRequests_.rend(); ++rit)
796            {
797                _destroyState((*rit));
798            }
799            stateDestroyRequests_.clear();
800        }
801
802        // check whether a state has changed its EMPTY_HANDLER situation
803        bool bUpdateRequired = false;
804        for (std::map<int, InputState*>::iterator it = activeStates_.begin(); it != activeStates_.end(); ++it)
805        {
806            if (it->second->handlersChanged())
807            {
808                it->second->resetHandlersChanged();
809                bUpdateRequired = true;
810            }
811        }
812        if (bUpdateRequired)
813            _updateActiveStates();
814
815        // mark that we capture and distribute input
816        internalState_ |= Ticking;
817
818        // Capture all the input. This calls the event handlers in InputManager.
819        if (keyboard_)
820            keyboard_->capture();
821        if (mouse_)
822            mouse_->capture();
823        for (unsigned  int i = 0; i < joySticksSize_; i++)
824            joySticks_[i]->capture();
825
826        if (!(internalState_ & Calibrating))
827        {
828            // call all the handlers for the held key events
829            for (unsigned int iKey = 0; iKey < keysDown_.size(); iKey++)
830            {
831                KeyEvent kEvt(keysDown_[iKey], keyboardModifiers_);
832                activeStatesTop_[Keyboard]->keyHeld(kEvt);
833                stateMaster_->keyHeld(kEvt);
834            }
835
836            // call all the handlers for the held mouse button events
837            for (unsigned int iButton = 0; iButton < mouseButtonsDown_.size(); iButton++)
838            {
839                activeStatesTop_[Mouse]->mouseButtonHeld(mouseButtonsDown_[iButton]);
840                stateMaster_->mouseButtonHeld(mouseButtonsDown_[iButton]);
841            }
842
843            // call all the handlers for the held joy stick button events
844            for (unsigned int iJoyStick  = 0; iJoyStick < joySticksSize_; iJoyStick++)
845                for (unsigned int iButton   = 0; iButton   < joyStickButtonsDown_[iJoyStick].size(); iButton++)
846                {
847                    activeStatesTop_[JoyStick0 + iJoyStick]
848                        ->joyStickButtonHeld(iJoyStick, joyStickButtonsDown_[iJoyStick][iButton]);
849                    stateMaster_->joyStickButtonHeld(iJoyStick, joyStickButtonsDown_[iJoyStick][iButton]);
850                }
851
852            // update the handlers for each active handler
853            for (unsigned int i = 0; i < devicesNum_; ++i)
854            {
855                activeStatesTop_[i]->updateInput(time.getDeltaTime(), i);
856                if (stateMaster_->isInputDeviceEnabled(i))
857                    stateMaster_->updateInput(time.getDeltaTime(), i);
858            }
859
860            // update the handler with a general tick afterwards
861            for (unsigned int i = 0; i < activeStatesTicked_.size(); ++i)
862                activeStatesTicked_[i]->updateInput(time.getDeltaTime());
863            stateMaster_->updateInput(time.getDeltaTime());
864        }
865
866        internalState_ &= ~Ticking;
867    }
868
869    /**
870    @brief
871        Updates the currently active states (according to activeStates_) for each device.
872        Also, a list of all active states (no duplicates!) is compiled for the general update().
873    */
874    void InputManager::_updateActiveStates()
875    {
876        for (std::map<int, InputState*>::const_iterator it = activeStates_.begin(); it != activeStates_.end(); ++it)
877            for (unsigned int i = 0; i < devicesNum_; ++i)
878                if (it->second->isInputDeviceEnabled(i))
879                    activeStatesTop_[i] = it->second;
880
881        // update tickables (every state will only appear once)
882        // Using a std::set to avoid duplicates
883        std::set<InputState*> tempSet;
884        for (unsigned int i = 0; i < devicesNum_; ++i)
885            tempSet.insert(activeStatesTop_[i]);
886
887        // copy the content of the set back to the actual vector
888        activeStatesTicked_.clear();
889        for (std::set<InputState*>::const_iterator it = tempSet.begin();it != tempSet.end(); ++it)
890            activeStatesTicked_.push_back(*it);
891
892        this->mouseButtonsDown_.clear();
893    }
894
895    /**
896    @brief
897        Clears all buffers that store what keys/buttons are being pressed at the moment.
898    */
899    void InputManager::clearBuffers()
900    {
901        this->keysDown_.clear();
902        this->mouseButtonsDown_.clear();
903        for (unsigned int i = 0; i < this->joySticksSize_; ++i)
904            this->joyStickButtonsDown_[i].clear();
905    }
906
907
908    // ############################################################
909    // #####                    OIS events                    #####
910    // ##########                                        ##########
911    // ############################################################
912
913    // ###### Key Events ######
914
915    /**
916    @brief
917        Event handler for the keyPressed Event.
918    @param e
919        Event information
920    */
921    bool InputManager::keyPressed(const OIS::KeyEvent &e)
922    {
923        // check whether the key already is in the list (can happen when focus was lost)
924        unsigned int iKey = 0;
925        while (iKey < keysDown_.size() && keysDown_[iKey].key != (KeyCode::ByEnum)e.key)
926            iKey++;
927        if (iKey == keysDown_.size())
928            keysDown_.push_back(Key(e));
929        else
930        {
931            // This happens when XAutoRepeat is set under linux. The KeyPressed event gets then sent
932            // continuously.
933            return true;
934        }
935
936        // update modifiers
937        if(e.key == OIS::KC_RMENU    || e.key == OIS::KC_LMENU)
938            keyboardModifiers_ |= KeyboardModifier::Alt;   // alt key
939        if(e.key == OIS::KC_RCONTROL || e.key == OIS::KC_LCONTROL)
940            keyboardModifiers_ |= KeyboardModifier::Ctrl;  // ctrl key
941        if(e.key == OIS::KC_RSHIFT   || e.key == OIS::KC_LSHIFT)
942            keyboardModifiers_ |= KeyboardModifier::Shift; // shift key
943
944        KeyEvent kEvt(e, keyboardModifiers_);
945        activeStatesTop_[Keyboard]->keyPressed(kEvt);
946        stateMaster_->keyPressed(kEvt);
947
948        return true;
949    }
950
951    /**
952    @brief
953        Event handler for the keyReleased Event.
954    @param e
955        Event information
956    */
957    bool InputManager::keyReleased(const OIS::KeyEvent &e)
958    {
959        // remove the key from the keysDown_ list
960        for (unsigned int iKey = 0; iKey < keysDown_.size(); iKey++)
961        {
962            if (keysDown_[iKey].key == (KeyCode::ByEnum)e.key)
963            {
964                keysDown_.erase(keysDown_.begin() + iKey);
965                break;
966            }
967        }
968
969        // update modifiers
970        if(e.key == OIS::KC_RMENU    || e.key == OIS::KC_LMENU)
971            keyboardModifiers_ &= ~KeyboardModifier::Alt;   // alt key
972        if(e.key == OIS::KC_RCONTROL || e.key == OIS::KC_LCONTROL)
973            keyboardModifiers_ &= ~KeyboardModifier::Ctrl;  // ctrl key
974        if(e.key == OIS::KC_RSHIFT   || e.key == OIS::KC_LSHIFT)
975            keyboardModifiers_ &= ~KeyboardModifier::Shift; // shift key
976
977        KeyEvent kEvt(e, keyboardModifiers_);
978        activeStatesTop_[Keyboard]->keyReleased(kEvt);
979        stateMaster_->keyReleased(kEvt);
980
981        return true;
982    }
983
984
985    // ###### Mouse Events ######
986
987    /**
988    @brief
989        Event handler for the mouseMoved Event.
990    @param e
991        Event information
992    */
993    bool InputManager::mouseMoved(const OIS::MouseEvent &e)
994    {
995        // check for actual moved event
996        if (e.state.X.rel != 0 || e.state.Y.rel != 0)
997        {
998            IntVector2 abs(e.state.X.abs, e.state.Y.abs);
999            IntVector2 rel(e.state.X.rel, e.state.Y.rel);
1000            IntVector2 clippingSize(e.state.width, e.state.height);
1001            activeStatesTop_[Mouse]->mouseMoved(abs, rel, clippingSize);
1002            stateMaster_->mouseMoved(abs, rel, clippingSize);
1003        }
1004
1005        // check for mouse scrolled event
1006        if (e.state.Z.rel != 0)
1007        {
1008            activeStatesTop_[Mouse]->mouseScrolled(e.state.Z.abs, e.state.Z.rel);
1009            stateMaster_->mouseScrolled(e.state.Z.abs, e.state.Z.rel);
1010        }
1011
1012        return true;
1013    }
1014
1015    /**
1016    @brief
1017        Event handler for the mousePressed Event.
1018    @param e
1019        Event information
1020    @param id
1021        The ID of the mouse button
1022    */
1023    bool InputManager::mousePressed(const OIS::MouseEvent &e, OIS::MouseButtonID id)
1024    {
1025        // check whether the button already is in the list (can happen when focus was lost)
1026        unsigned int iButton = 0;
1027        while (iButton < mouseButtonsDown_.size() && mouseButtonsDown_[iButton] != (MouseButtonCode::ByEnum)id)
1028            iButton++;
1029        if (iButton == mouseButtonsDown_.size())
1030            mouseButtonsDown_.push_back((MouseButtonCode::ByEnum)id);
1031
1032        activeStatesTop_[Mouse]->mouseButtonPressed((MouseButtonCode::ByEnum)id);
1033        stateMaster_->mouseButtonPressed((MouseButtonCode::ByEnum)id);
1034
1035        return true;
1036    }
1037
1038    /**
1039    @brief
1040        Event handler for the mouseReleased Event.
1041    @param e
1042        Event information
1043    @param id
1044        The ID of the mouse button
1045    */
1046    bool InputManager::mouseReleased(const OIS::MouseEvent &e, OIS::MouseButtonID id)
1047    {
1048        // remove the button from the keysDown_ list
1049        for (unsigned int iButton = 0; iButton < mouseButtonsDown_.size(); iButton++)
1050        {
1051            if (mouseButtonsDown_[iButton] == (MouseButtonCode::ByEnum)id)
1052            {
1053                mouseButtonsDown_.erase(mouseButtonsDown_.begin() + iButton);
1054                break;
1055            }
1056        }
1057
1058        activeStatesTop_[Mouse]->mouseButtonReleased((MouseButtonCode::ByEnum)id);
1059        stateMaster_->mouseButtonReleased((MouseButtonCode::ByEnum)id);
1060
1061        return true;
1062    }
1063
1064
1065    // ###### Joy Stick Events ######
1066
1067    /**
1068    @brief
1069        Returns the joy stick ID (orxonox) according to a OIS::JoyStickEvent
1070    */
1071    inline unsigned int InputManager::_getJoystick(const OIS::JoyStickEvent& arg)
1072    {
1073        // use the device to identify which one called the method
1074        OIS::JoyStick* joyStick = (OIS::JoyStick*)arg.device;
1075        unsigned int iJoyStick = 0;
1076        while (joySticks_[iJoyStick] != joyStick)
1077            iJoyStick++;
1078        // assert: Unknown joystick fired an event.
1079        assert(iJoyStick != joySticksSize_);
1080        return iJoyStick;
1081    }
1082
1083    bool InputManager::buttonPressed(const OIS::JoyStickEvent &arg, int button)
1084    {
1085        unsigned int iJoyStick = _getJoystick(arg);
1086
1087        // check whether the button already is in the list (can happen when focus was lost)
1088        std::vector<JoyStickButtonCode::ByEnum>& buttonsDown = joyStickButtonsDown_[iJoyStick];
1089        unsigned int iButton = 0;
1090        while (iButton < buttonsDown.size() && buttonsDown[iButton] != button)
1091            iButton++;
1092        if (iButton == buttonsDown.size())
1093            buttonsDown.push_back((JoyStickButtonCode::ByEnum)button);
1094
1095        activeStatesTop_[2 + iJoyStick]->joyStickButtonPressed(iJoyStick, (JoyStickButtonCode::ByEnum)button);
1096        stateMaster_->joyStickButtonPressed(iJoyStick, (JoyStickButtonCode::ByEnum)button);
1097
1098        return true;
1099    }
1100
1101    bool InputManager::buttonReleased(const OIS::JoyStickEvent &arg, int button)
1102    {
1103        unsigned int iJoyStick = _getJoystick(arg);
1104
1105        // remove the button from the joyStickButtonsDown_ list
1106        std::vector<JoyStickButtonCode::ByEnum>& buttonsDown = joyStickButtonsDown_[iJoyStick];
1107        for (unsigned int iButton = 0; iButton < buttonsDown.size(); iButton++)
1108        {
1109            if (buttonsDown[iButton] == button)
1110            {
1111                buttonsDown.erase(buttonsDown.begin() + iButton);
1112                break;
1113            }
1114        }
1115
1116        activeStatesTop_[2 + iJoyStick]->joyStickButtonReleased(iJoyStick, (JoyStickButtonCode::ByEnum)button);
1117        stateMaster_->joyStickButtonReleased(iJoyStick, (JoyStickButtonCode::ByEnum)button);
1118
1119        return true;
1120    }
1121
1122    /**
1123    @brief
1124        Calls the states for a particular axis with our enumeration.
1125        Used by OIS sliders and OIS axes.
1126    */
1127    void InputManager::_fireAxis(unsigned int iJoyStick, int axis, int value)
1128    {
1129        if (internalState_ & Calibrating)
1130        {
1131            if (value < joyStickMinValues_[iJoyStick][axis])
1132                joyStickMinValues_[iJoyStick][axis] = value;
1133            if (value > joyStickMaxValues_[iJoyStick][axis])
1134                joyStickMaxValues_[iJoyStick][axis] = value;
1135        }
1136        else
1137        {
1138            float fValue = value - joyStickCalibrations_[iJoyStick].middleValue[axis];
1139            if (fValue > 0.0f)
1140                fValue *= joyStickCalibrations_[iJoyStick].positiveCoeff[axis];
1141            else
1142                fValue *= joyStickCalibrations_[iJoyStick].negativeCoeff[axis];
1143
1144            activeStatesTop_[2 + iJoyStick]->joyStickAxisMoved(iJoyStick, axis, fValue);
1145            stateMaster_->joyStickAxisMoved(iJoyStick, axis, fValue);
1146        }
1147    }
1148
1149    bool InputManager::axisMoved(const OIS::JoyStickEvent &arg, int axis)
1150    {
1151        unsigned int iJoyStick = _getJoystick(arg);
1152
1153        // keep in mind that the first 8 axes are reserved for the sliders
1154        _fireAxis(iJoyStick, axis + sliderAxes, arg.state.mAxes[axis].abs);
1155
1156        return true;
1157    }
1158
1159    bool InputManager::sliderMoved(const OIS::JoyStickEvent &arg, int id)
1160    {
1161        unsigned int iJoyStick = _getJoystick(arg);
1162
1163        if (sliderStates_[iJoyStick].sliderStates[id].x != arg.state.mSliders[id].abX)
1164            _fireAxis(iJoyStick, id * 2, arg.state.mSliders[id].abX);
1165        else if (sliderStates_[iJoyStick].sliderStates[id].y != arg.state.mSliders[id].abY)
1166            _fireAxis(iJoyStick, id * 2 + 1, arg.state.mSliders[id].abY);
1167
1168        return true;
1169    }
1170
1171    bool InputManager::povMoved(const OIS::JoyStickEvent &arg, int id)
1172    {
1173        unsigned int iJoyStick = _getJoystick(arg);
1174
1175        // translate the POV into 8 simple buttons
1176
1177        int lastState = povStates_[iJoyStick][id];
1178        if (lastState & OIS::Pov::North)
1179            buttonReleased(arg, 32 + id * 4 + 0);
1180        if (lastState & OIS::Pov::South)
1181            buttonReleased(arg, 32 + id * 4 + 1);
1182        if (lastState & OIS::Pov::East)
1183            buttonReleased(arg, 32 + id * 4 + 2);
1184        if (lastState & OIS::Pov::West)
1185            buttonReleased(arg, 32 + id * 4 + 3);
1186
1187        povStates_[iJoyStick].povStates[id] = arg.state.mPOV[id].direction;
1188
1189        int currentState = povStates_[iJoyStick][id];
1190        if (currentState & OIS::Pov::North)
1191            buttonPressed(arg, 32 + id * 4 + 0);
1192        if (currentState & OIS::Pov::South)
1193            buttonPressed(arg, 32 + id * 4 + 1);
1194        if (currentState & OIS::Pov::East)
1195            buttonPressed(arg, 32 + id * 4 + 2);
1196        if (currentState & OIS::Pov::West)
1197            buttonPressed(arg, 32 + id * 4 + 3);
1198
1199        return true;
1200    }
1201
1202
1203    // ############################################################
1204    // #####         Other Public Interface Methods           #####
1205    // ##########                                        ##########
1206    // ############################################################
1207
1208    /**
1209    @brief
1210        Adjusts the mouse window metrics.
1211        This method has to be called every time the size of the window changes.
1212    @param width
1213        The new width of the render window
1214    @param^height
1215        The new height of the render window
1216    */
1217    void InputManager::setWindowExtents(const int width, const int height)
1218    {
1219        if (mouse_)
1220        {
1221            // Set mouse region (if window resizes, we should alter this to reflect as well)
1222            mouse_->getMouseState().width  = width;
1223            mouse_->getMouseState().height = height;
1224        }
1225    }
1226
1227    /**
1228    @brief
1229        Sets the the name of the command used by the KeyDetector as callback.
1230    @param command
1231        Command name as string
1232    */
1233    void InputManager::setKeyDetectorCallback(const std::string& command)
1234    {
1235        this->keyDetector_->setCallbackCommand(command);
1236    }
1237
1238    // ###### InputStates ######
1239
1240    /**
1241    @brief
1242        Adds a new key handler.
1243    @param handler
1244        Pointer to the handler object.
1245    @param name
1246        Unique name of the handler.
1247    @param priority
1248        Unique integer number. Higher means more prioritised.
1249    @return
1250        True if added, false if name or priority already existed.
1251    */
1252    bool InputManager::_configureInputState(InputState* state, const std::string& name, int priority)
1253    {
1254        if (name == "")
1255            return false;
1256        if (!state)
1257            return false;
1258        if (inputStatesByName_.find(name) == inputStatesByName_.end())
1259        {
1260            if (inputStatesByPriority_.find(priority)
1261                == inputStatesByPriority_.end())
1262            {
1263                inputStatesByName_[name] = state;
1264                inputStatesByPriority_[priority] = state;
1265                state->setNumOfJoySticks(numberOfJoySticks());
1266                state->setName(name);
1267                state->setPriority(priority);
1268                return true;
1269            }
1270            else
1271            {
1272                COUT(2) << "Warning: Could not add an InputState with the same priority '"
1273                    << priority << "'." << std::endl;
1274                return false;
1275            }
1276        }
1277        else
1278        {
1279            COUT(2) << "Warning: Could not add an InputState with the same name '" << name << "'." << std::endl;
1280            return false;
1281        }
1282    }
1283
1284    /**
1285    @brief
1286        Removes and destroys an input state internally.
1287    @param name
1288        Name of the handler.
1289    @return
1290        True if removal was successful, false if name was not found.
1291    @remarks
1292        You can't remove the internal states "empty", "calibrator" and "detector".
1293        The removal process is being postponed if InputManager::update() is currently running.
1294    */
1295    bool InputManager::requestDestroyState(const std::string& name)
1296    {
1297        if (name == "empty")
1298        {
1299            COUT(2) << "InputManager: Removing the empty state is not allowed!" << std::endl;
1300            return false;
1301        }
1302        std::map<std::string, InputState*>::iterator it = inputStatesByName_.find(name);
1303        if (it != inputStatesByName_.end())
1304        {
1305            if (activeStates_.find(it->second->getPriority()) != activeStates_.end())
1306            {
1307                // The state is still active. We have to postpone
1308                stateLeaveRequests_.insert(it->second);
1309                stateDestroyRequests_.insert(it->second);
1310            }
1311            else if (this->internalState_ & Ticking)
1312            {
1313                // cannot remove state while ticking
1314                stateDestroyRequests_.insert(it->second);
1315            }
1316            else
1317                _destroyState(it->second);
1318
1319            return true;
1320        }
1321        return false;
1322    }
1323
1324    /**
1325    @brief
1326        Returns the pointer to the requested InputState.
1327    @param name
1328        Unique name of the state.
1329    @return
1330        Pointer to the instance, 0 if name was not found.
1331    */
1332    InputState* InputManager::getState(const std::string& name)
1333    {
1334        std::map<std::string, InputState*>::iterator it = inputStatesByName_.find(name);
1335        if (it != inputStatesByName_.end())
1336            return it->second;
1337        else
1338            return 0;
1339    }
1340
1341    /**
1342    @brief
1343        Returns the current input state (there might be others active too!)
1344    @return
1345        The current highest prioritised active input state.
1346    */
1347    InputState* InputManager::getCurrentState()
1348    {
1349        return (*activeStates_.rbegin()).second;
1350    }
1351
1352    /**
1353    @brief
1354        Activates a specific input state.
1355        It might not be really activated if the priority is too low!
1356    @param name
1357        Unique name of the state.
1358    @return
1359        False if name was not found, true otherwise.
1360    */
1361    bool InputManager::requestEnterState(const std::string& name)
1362    {
1363        // get pointer from the map with all stored handlers
1364        std::map<std::string, InputState*>::const_iterator it = inputStatesByName_.find(name);
1365        if (it != inputStatesByName_.end())
1366        {
1367            // exists
1368            if (activeStates_.find(it->second->getPriority()) == activeStates_.end())
1369            {
1370                // not active
1371                if (stateDestroyRequests_.find(it->second) == stateDestroyRequests_.end())
1372                {
1373                    // not scheduled for destruction
1374                    // set prevents a state being added multiple times
1375                    stateEnterRequests_.insert(it->second);
1376                    return true;
1377                }
1378            }
1379        }
1380        return false;
1381    }
1382
1383    /**
1384    @brief
1385        Deactivates a specific input state.
1386    @param name
1387        Unique name of the state.
1388    @return
1389        False if name was not found, true otherwise.
1390    */
1391    bool InputManager::requestLeaveState(const std::string& name)
1392    {
1393        // get pointer from the map with all stored handlers
1394        std::map<std::string, InputState*>::const_iterator it = inputStatesByName_.find(name);
1395        if (it != inputStatesByName_.end())
1396        {
1397            // exists
1398            if (activeStates_.find(it->second->getPriority()) != activeStates_.end())
1399            {
1400                // active
1401                stateLeaveRequests_.insert(it->second);
1402                return true;
1403            }
1404        }
1405        return false;
1406    }
1407
1408
1409    // ############################################################
1410    // #####                Console Commands                  #####
1411    // ##########                                        ##########
1412    // ############################################################
1413
1414    /**
1415    @brief
1416        Starts joy stick calibration.
1417    */
1418    void InputManager::calibrate()
1419    {
1420        COUT(0) << "Move all joy stick axes fully in all directions." << std::endl
1421                << "When done, put the axex in the middle position and press enter." << std::endl;
1422
1423        getInstance()._startCalibration();
1424    }
1425
1426    /**
1427    @brief
1428        Reloads the input system
1429    */
1430    void InputManager::reload(bool joyStickSupport)
1431    {
1432        getInstance().reloadInputSystem(joyStickSupport);
1433    }
1434}
Note: See TracBrowser for help on using the repository browser.