Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/core/input/InputManager.cc @ 2833

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

Merged presentation branch back to trunk.

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