Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 2908 was 2908, checked in by dafrick, 16 years ago

Reverted to revision 2906 (because I'm too stupid to merge correctly, 2nd try will follow shortly. ;))

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