Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Bug fix in the InputManager.

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