Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Renamed stupid omni_cast to multi_cast. It still eats about anything ;)

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