Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3022 was 2896, checked in by landauf, 16 years ago

Merged gui branch back to trunk.

I did 2 small changes in IngameManager.cc on line 777 and 888 (yes, really), because const_reverse_iterator strangely doesn't work on MinGW.

  • Property svn:eol-style set to native
File size: 53.3 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"
[2896]45#include "core/Clock.h"
[1519]46#include "core/CoreIncludes.h"
47#include "core/ConfigValueIncludes.h"
48#include "core/CommandExecutor.h"
49#include "core/ConsoleCommand.h"
[1934]50#include "core/CommandLine.h"
[1747]51#include "util/Debug.h"
[1555]52
[1219]53#include "InputBuffer.h"
[1502]54#include "KeyBinder.h"
[1520]55#include "KeyDetector.h"
56#include "CalibratorCallback.h"
[1755]57#include "InputState.h"
58#include "SimpleInputState.h"
59#include "ExtendedInputState.h"
[1887]60#include "JoyStickDeviceNumberListener.h"
[918]61
62namespace orxonox
63{
[1755]64    SetConsoleCommand(InputManager, calibrate, true);
65    SetConsoleCommand(InputManager, reload, false);
[1934]66    SetCommandLineSwitch(keyboard_no_grab);
[1502]67
[1878]68    EmptyHandler InputManager::EMPTY_HANDLER;
[1755]69    InputManager* InputManager::singletonRef_s = 0;
[1084]70
[1755]71    using namespace InputDevice;
[929]72
[1755]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    }
[919]82
[1755]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    }
[1219]91
[1755]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)
[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")));
[2896]175#if defined ORXONOX_PLATFORM_LINUX
[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
[2896]220            stateEmpty_ = createInputState<SimpleInputState>("empty", false, false, InputStatePriority::Empty);
[1878]221            stateEmpty_->setHandler(&EMPTY_HANDLER);
[1755]222            activeStates_[stateEmpty_->getPriority()] = stateEmpty_;
[1502]223
[1881]224            // KeyDetector to evaluate a pressed key's name
[2896]225            SimpleInputState* detector = createInputState<SimpleInputState>("detector", false, false, InputStatePriority::Detector);
[1881]226            keyDetector_ = new KeyDetector();
227            detector->setHandler(keyDetector_);
228
229            // Joy stick calibration helper callback
[2896]230            SimpleInputState* calibrator = createInputState<SimpleInputState>("calibrator", false, false, InputStatePriority::Calibrator);
[1881]231            calibrator->setHandler(&EMPTY_HANDLER);
232            calibratorCallbackBuffer_ = new InputBuffer();
233            calibratorCallbackBuffer_->registerListener(this, &InputManager::_completeCalibration, '\r', true);
234            calibrator->setKeyHandler(calibratorCallbackBuffer_);
235
[1755]236            internalState_ |= InternalsReady;
237
238            CCOUT(4) << "Initialising InputStates complete." << std::endl;
239        }
240
241        _updateActiveStates();
242
243        CCOUT(3) << "Initialising complete." << std::endl;
[1219]244    }
[928]245
[1755]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()
[1219]253    {
[1755]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        }
[1219]271    }
[1035]272
[1755]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()
[1219]280    {
[1755]281        if (mouse_ != 0)
282        {
283            CCOUT(2) << "Warning: Mouse already initialised, skipping." << std::endl;
284            return;
285        }
[1219]286        try
287        {
[1755]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            }
[1219]299        }
300        catch (OIS::Exception ex)
301        {
[1755]302            CCOUT(ORX_WARNING) << "Warning: Failed to create an OIS mouse\n"
303                << "OIS error message: \"" << ex.eText << "\"" << std::endl;
304            mouse_ = 0;
[1219]305        }
306    }
[1755]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()
[1219]315    {
[1755]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        }
[1219]345    }
[1035]346
[1755]347    /**
348    @brief
[2662]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
[1755]373        Sets the size of all the different lists that are dependent on the number
[2662]374        of joy stick devices created and loads the joy stick calibration.
[1755]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    */
[2662]379    void InputManager::_configureJoySticks()
[1505]380    {
[1755]381        joySticksSize_ = joySticks_.size();
[2662]382        devicesNum_    = 2 + joySticksSize_;
383        joyStickIDs_         .resize(joySticksSize_);
[1755]384        joyStickButtonsDown_ .resize(joySticksSize_);
385        povStates_           .resize(joySticksSize_);
386        sliderStates_        .resize(joySticksSize_);
[2662]387        joyStickMinValues_   .resize(joySticksSize_);
388        joyStickMaxValues_   .resize(joySticksSize_);
389        joyStickMiddleValues_.resize(joySticksSize_);
390        joyStickCalibrations_.resize(joySticksSize_);
[1502]391
[1755]392        for (unsigned int iJoyStick = 0; iJoyStick < joySticksSize_; iJoyStick++)
393        {
[2662]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)
[1755]403            {
[2662]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                }
[1755]409            }
[2662]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);
[1755]416        }
[1505]417
[2662]418        _evaluateCalibration();
419
[1755]420        // state management
[2896]421        activeStatesTriggered_.resize(devicesNum_);
[1505]422
[1755]423        // inform all states
[2896]424        for (std::map<std::string, InputState*>::const_iterator it = inputStatesByName_.begin();
425            it != inputStatesByName_.end(); ++it)
[1887]426        {
[1755]427            it->second->setNumOfJoySticks(joySticksSize_);
[1887]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
[1505]434    }
[1502]435
[2662]436    void InputManager::_evaluateCalibration()
[1219]437    {
[2662]438        for (unsigned int iJoyStick = 0; iJoyStick < this->joySticksSize_; ++iJoyStick)
[1755]439        {
[2662]440            for (unsigned int i = 0; i < this->joyStickMinValues_[iJoyStick].size(); i++)
[1755]441            {
[2662]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]);
[1755]445            }
[2662]446        }
447    }
[2896]448
[2662]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        }
[1293]461
[2662]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)
[1755]473            {
[2662]474                this->joyStickMiddleValues_[iJoyStick][iAxis++] = this->joySticks_[iJoyStick]->getJoyStickState().mSliders[i].abX;
475                this->joyStickMiddleValues_[iJoyStick][iAxis++] = this->joySticks_[iJoyStick]->getJoyStickState().mSliders[i].abY;
[1755]476            }
[2662]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)
[1755]480            {
[2662]481                this->joyStickMiddleValues_[iJoyStick][iAxis++] = this->joySticks_[iJoyStick]->getJoyStickState().mAxes[i].abs;
[1755]482            }
[1219]483
[2662]484            for (unsigned int i = 0; i < joyStickMinValues_[iJoyStick].size(); ++i)
[1755]485            {
[2662]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);
[1502]491
[2662]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);
[1755]501            }
502        }
[2662]503
504        _evaluateCalibration();
505
506        // restore old input state
507        requestLeaveState("calibrator");
508        internalState_ &= ~Calibrating;
[1219]509    }
[928]510
[1755]511    // ############################################################
512    // #####                    Destruction                   #####
513    // ##########                                        ##########
514    // ############################################################
[1219]515
[1755]516    /**
517    @brief
518        Destroys all the created input devices and states.
519    */
520    InputManager::~InputManager()
[1219]521    {
[1755]522        if (internalState_ != Uninitialised)
523        {
524            try
525            {
526                CCOUT(3) << "Destroying ..." << std::endl;
[1219]527
[1755]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                }
[1502]534
[1881]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_);
[1788]543
[1881]544                // destroy all user InputStates
[2896]545                while (inputStatesByName_.size() > 0)
546                    _destroyState((*inputStatesByName_.rbegin()).second);
[1881]547
[1755]548                // destroy the devices
549                _destroyKeyboard();
550                _destroyMouse();
551                _destroyJoySticks();
[1219]552
[1755]553                OIS::InputManager::destroyInputSystem(inputSystem_);
[1349]554
[1755]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        }
[2662]563
564        singletonRef_s = 0;
[1755]565    }
[1349]566
[1755]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    }
[1219]579
[1755]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    }
[1219]592
[1755]593    /**
594    @brief
595        Destroys all the joy sticks and resizes the lists to 0.
596    */
597    void InputManager::_destroyJoySticks()
[1022]598    {
[1755]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]);
[1219]605
[1755]606            joySticks_.clear();
[1887]607            // don't use _configureNumberOfJoySticks(), might mess with registered handler if
[1755]608            // downgrading from 2 to 1 joystick
[1887]609            //_configureNumberOfJoySticks();
[1755]610            joySticksSize_ = 0;
611        }
612        CCOUT(4) << "Joy sticks destroyed." << std::endl;
613    }
[1502]614
[1755]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    }
[1502]633
[1755]634    void InputManager::_clearBuffers()
635    {
[1502]636        keysDown_.clear();
[1755]637        keyboardModifiers_ = 0;
[1502]638        mouseButtonsDown_.clear();
[1755]639        for (unsigned int i = 0; i < joySticksSize_; ++i)
[1219]640        {
[1755]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    }
[1219]650
651
[1755]652    // ############################################################
653    // #####                     Reloading                    #####
654    // ##########                                        ##########
655    // ############################################################
[1219]656
[1755]657    /**
658    @brief
659        Public interface. Only reloads immediately if the call stack doesn't
[2896]660        include the update() method.
[1755]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;
[1219]675        }
[1755]676        else if (internalState_ & OISReady)
677        {
678            _reload(joyStickSupport);
679        }
[1502]680        else
681        {
[1755]682            CCOUT(2) << "Warning: Cannot reload OIS. May not yet be initialised or"
683                     << "joy sticks are currently calibrating." << std::endl;
[1502]684        }
[1755]685    }
[1502]686
[1755]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;
[1502]696
[1755]697            // Save mouse clipping size
698            int mouseWidth  = mouse_->getMouseState().width;
699            int mouseHeight = mouse_->getMouseState().height;
[1502]700
[1755]701            internalState_ &= ~OISReady;
[1219]702
[1755]703            // destroy the devices
704            _destroyKeyboard();
705            _destroyMouse();
706            _destroyJoySticks();
[1219]707
[1755]708            OIS::InputManager::destroyInputSystem(inputSystem_);
709            inputSystem_ = 0;
[1219]710
[1755]711            // clear all buffers containing input information
712            _clearBuffers();
[1219]713
[1755]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        }
[1502]722    }
[1219]723
[1755]724    // ############################################################
725    // #####                  Runtime Methods                 #####
726    // ##########                                        ##########
727    // ############################################################
[1555]728
[1755]729    /**
730    @brief
[2662]731        Updates the states and the InputState situation.
[2896]732    @param time
733        Clock holding the current time.
[1755]734    */
[2896]735    void InputManager::update(const Clock& time)
[1502]736    {
[1755]737        if (internalState_ == Uninitialised)
738            return;
739        else if (internalState_ & ReloadRequest)
740        {
741            _reload(internalState_ & JoyStickSupport);
742            internalState_ &= ~ReloadRequest;
743            internalState_ &= ~JoyStickSupport;
744        }
[1349]745
[1755]746        // check for states to leave
[2662]747        if (!stateLeaveRequests_.empty())
[1755]748        {
[2896]749            for (std::set<InputState*>::iterator it = stateLeaveRequests_.begin();
750                it != stateLeaveRequests_.end(); ++it)
[2662]751            {
[2896]752                (*it)->onLeave();
[2662]753                // just to be sure that the state actually is registered
[2896]754                assert(inputStatesByName_.find((*it)->getName()) != inputStatesByName_.end());
[1505]755
[2896]756                activeStates_.erase((*it)->getPriority());
757                if ((*it)->getPriority() < InputStatePriority::HighPriority)
758                    (*it)->setPriority(0);
[2662]759                _updateActiveStates();
760            }
761            stateLeaveRequests_.clear();
[1755]762        }
[1505]763
[1755]764        // check for states to enter
[2662]765        if (!stateEnterRequests_.empty())
[1755]766        {
[2896]767            for (std::set<InputState*>::const_iterator it = stateEnterRequests_.begin();
768                it != stateEnterRequests_.end(); ++it)
[2662]769            {
770                // just to be sure that the state actually is registered
[2896]771                assert(inputStatesByName_.find((*it)->getName()) != inputStatesByName_.end());
[1219]772
[2896]773                if ((*it)->getPriority() == 0)
774                {
775                    // Get smallest possible priority between 1 and maxStateStackSize_s
776#if defined( __MINGW32__ ) // Avoid the strange mingw-stl bug with const_reverse_iterator
777                    for(std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin();
778                        rit != activeStates_.rend(); ++rit)
779#else
780                    for(std::map<int, InputState*>::const_reverse_iterator rit = activeStates_.rbegin();
781                        rit != activeStates_.rend(); ++rit)
782#endif
783                    {
784                        if (rit->first < InputStatePriority::HighPriority)
785                        {
786                            (*it)->setPriority(rit->first + 1);
787                            break;
788                        }
789                    }
790                    // In case no normal handler was on the stack
791                    if ((*it)->getPriority() == 0)
792                        (*it)->setPriority(1);
793                }
794                activeStates_[(*it)->getPriority()] = (*it);
[2662]795                _updateActiveStates();
[2896]796                (*it)->onEnter();
[2662]797            }
798            stateEnterRequests_.clear();
[1755]799        }
[1219]800
[1755]801        // check for states to destroy
[2662]802        if (!stateDestroyRequests_.empty())
[1755]803        {
[2896]804            for (std::set<InputState*>::iterator it = stateDestroyRequests_.begin();
805                it != stateDestroyRequests_.end(); ++it)
[2662]806            {
[2896]807                _destroyState((*it));
[2662]808            }
809            stateDestroyRequests_.clear();
[1755]810        }
[1219]811
[1878]812        // check whether a state has changed its EMPTY_HANDLER situation
813        bool bUpdateRequired = false;
814        for (std::map<int, InputState*>::iterator it = activeStates_.begin(); it != activeStates_.end(); ++it)
815        {
816            if (it->second->handlersChanged())
817            {
818                it->second->resetHandlersChanged();
819                bUpdateRequired = true;
820            }
821        }
822        if (bUpdateRequired)
823            _updateActiveStates();
824
[2896]825        // mark that we now start capturing and distributing input
[1755]826        internalState_ |= Ticking;
[1293]827
[1755]828        // Capture all the input. This calls the event handlers in InputManager.
829        if (keyboard_)
830            keyboard_->capture();
831        if (mouse_)
832            mouse_->capture();
833        for (unsigned  int i = 0; i < joySticksSize_; i++)
834            joySticks_[i]->capture();
[1219]835
[2662]836        if (!(internalState_ & Calibrating))
[1755]837        {
838            // call all the handlers for the held key events
839            for (unsigned int iKey = 0; iKey < keysDown_.size(); iKey++)
[1788]840            {
841                KeyEvent kEvt(keysDown_[iKey], keyboardModifiers_);
[2896]842
843                for (unsigned int iState = 0; iState < activeStatesTriggered_[Keyboard].size(); ++iState)
844                    activeStatesTriggered_[Keyboard][iState]->keyHeld(kEvt);
[1788]845            }
[1219]846
[1755]847            // call all the handlers for the held mouse button events
848            for (unsigned int iButton = 0; iButton < mouseButtonsDown_.size(); iButton++)
[1788]849            {
[2896]850                for (unsigned int iState = 0; iState < activeStatesTriggered_[Mouse].size(); ++iState)
851                    activeStatesTriggered_[Mouse][iState]->mouseButtonHeld(mouseButtonsDown_[iButton]);
[1788]852            }
[1219]853
[1755]854            // call all the handlers for the held joy stick button events
855            for (unsigned int iJoyStick  = 0; iJoyStick < joySticksSize_; iJoyStick++)
856                for (unsigned int iButton   = 0; iButton   < joyStickButtonsDown_[iJoyStick].size(); iButton++)
[1788]857                {
[2896]858                    for (unsigned int iState = 0; iState < activeStatesTriggered_[JoyStick0 + iJoyStick].size(); ++iState)
859                        activeStatesTriggered_[JoyStick0 + iJoyStick][iState]->joyStickButtonHeld(iJoyStick, joyStickButtonsDown_[iJoyStick][iButton]);
[1788]860                }
[1293]861
[2896]862            // update the handlers for each active handler
[1755]863            for (unsigned int i = 0; i < devicesNum_; ++i)
[1788]864            {
[2896]865                for (unsigned int iState = 0; iState < activeStatesTriggered_[i].size(); ++iState)
866                    activeStatesTriggered_[i][iState]->updateInput(time.getDeltaTime(), i);
[1788]867            }
[1219]868
[2896]869            // update the handler with a general tick afterwards
[1755]870            for (unsigned int i = 0; i < activeStatesTicked_.size(); ++i)
[2896]871                activeStatesTicked_[i]->updateInput(time.getDeltaTime());
[1755]872        }
[1219]873
[1755]874        internalState_ &= ~Ticking;
[1293]875    }
[1219]876
[1755]877    /**
878    @brief
879        Updates the currently active states (according to activeStates_) for each device.
[2896]880        Also, a list of all active states (no duplicates!) is compiled for the general update().
[1755]881    */
882    void InputManager::_updateActiveStates()
[1293]883    {
[2896]884        for (unsigned int i = 0; i < devicesNum_; ++i)
885        {
886            bool occupied = false;
887            activeStatesTriggered_[i].clear();
888#if defined( __MINGW32__ ) // Avoid the strange mingw-stl bug with const_reverse_iterator
889            for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin(); rit != activeStates_.rend(); ++rit)
890            {
891#else
892            for (std::map<int, InputState*>::const_reverse_iterator rit = activeStates_.rbegin(); rit != activeStates_.rend(); ++rit)
893            {
894#endif
895                if (rit->second->isInputDeviceEnabled(i) && (!occupied || rit->second->bAlwaysGetsInput_))
896                {
897                    activeStatesTriggered_[i].push_back(rit->second);
898                    if (!rit->second->bTransparent_)
899                        occupied = true;
900                }
901            }
902        }
[1293]903
[1755]904        // update tickables (every state will only appear once)
905        // Using a std::set to avoid duplicates
906        std::set<InputState*> tempSet;
907        for (unsigned int i = 0; i < devicesNum_; ++i)
[2896]908            for (unsigned int iState = 0; iState < activeStatesTriggered_[i].size(); ++iState)
909                tempSet.insert(activeStatesTriggered_[i][iState]);
[1219]910
[2896]911        // copy the content of the std::set back to the actual vector
[1755]912        activeStatesTicked_.clear();
913        for (std::set<InputState*>::const_iterator it = tempSet.begin();it != tempSet.end(); ++it)
914            activeStatesTicked_.push_back(*it);
[1219]915
[1755]916        this->mouseButtonsDown_.clear();
917    }
[1219]918
[1755]919    /**
920    @brief
[2662]921        Clears all buffers that store what keys/buttons are being pressed at the moment.
[1755]922    */
[1878]923    void InputManager::clearBuffers()
924    {
925        this->keysDown_.clear();
926        this->mouseButtonsDown_.clear();
927        for (unsigned int i = 0; i < this->joySticksSize_; ++i)
928            this->joyStickButtonsDown_[i].clear();
929    }
[1502]930
[1878]931
[1755]932    // ############################################################
933    // #####                    OIS events                    #####
934    // ##########                                        ##########
935    // ############################################################
[1219]936
[1755]937    // ###### Key Events ######
[1219]938
[1755]939    /**
940    @brief
941        Event handler for the keyPressed Event.
942    @param e
943        Event information
944    */
945    bool InputManager::keyPressed(const OIS::KeyEvent &e)
[1219]946    {
[1755]947        // check whether the key already is in the list (can happen when focus was lost)
948        unsigned int iKey = 0;
[1887]949        while (iKey < keysDown_.size() && keysDown_[iKey].key != (KeyCode::ByEnum)e.key)
[1755]950            iKey++;
951        if (iKey == keysDown_.size())
952            keysDown_.push_back(Key(e));
953        else
[1788]954        {
955            // This happens when XAutoRepeat is set under linux. The KeyPressed event gets then sent
956            // continuously.
[1755]957            return true;
[1788]958        }
[1219]959
[1755]960        // update modifiers
961        if(e.key == OIS::KC_RMENU    || e.key == OIS::KC_LMENU)
962            keyboardModifiers_ |= KeyboardModifier::Alt;   // alt key
963        if(e.key == OIS::KC_RCONTROL || e.key == OIS::KC_LCONTROL)
964            keyboardModifiers_ |= KeyboardModifier::Ctrl;  // ctrl key
965        if(e.key == OIS::KC_RSHIFT   || e.key == OIS::KC_LSHIFT)
966            keyboardModifiers_ |= KeyboardModifier::Shift; // shift key
[1219]967
[1788]968        KeyEvent kEvt(e, keyboardModifiers_);
[2896]969        for (unsigned int iState = 0; iState < activeStatesTriggered_[Keyboard].size(); ++iState)
970            activeStatesTriggered_[Keyboard][iState]->keyPressed(kEvt);
[1219]971
[1755]972        return true;
[1349]973    }
[1755]974
975    /**
976    @brief
977        Event handler for the keyReleased Event.
978    @param e
979        Event information
980    */
981    bool InputManager::keyReleased(const OIS::KeyEvent &e)
[1349]982    {
[1755]983        // remove the key from the keysDown_ list
984        for (unsigned int iKey = 0; iKey < keysDown_.size(); iKey++)
985        {
[1887]986            if (keysDown_[iKey].key == (KeyCode::ByEnum)e.key)
[1755]987            {
988                keysDown_.erase(keysDown_.begin() + iKey);
989                break;
990            }
991        }
[1502]992
[1755]993        // update modifiers
994        if(e.key == OIS::KC_RMENU    || e.key == OIS::KC_LMENU)
995            keyboardModifiers_ &= ~KeyboardModifier::Alt;   // alt key
996        if(e.key == OIS::KC_RCONTROL || e.key == OIS::KC_LCONTROL)
997            keyboardModifiers_ &= ~KeyboardModifier::Ctrl;  // ctrl key
998        if(e.key == OIS::KC_RSHIFT   || e.key == OIS::KC_LSHIFT)
999            keyboardModifiers_ &= ~KeyboardModifier::Shift; // shift key
[1293]1000
[1788]1001        KeyEvent kEvt(e, keyboardModifiers_);
[2896]1002        for (unsigned int iState = 0; iState < activeStatesTriggered_[Keyboard].size(); ++iState)
1003            activeStatesTriggered_[Keyboard][iState]->keyReleased(kEvt);
[1502]1004
[1755]1005        return true;
1006    }
[1502]1007
1008
[1755]1009    // ###### Mouse Events ######
[1502]1010
[1755]1011    /**
1012    @brief
1013        Event handler for the mouseMoved Event.
1014    @param e
1015        Event information
1016    */
1017    bool InputManager::mouseMoved(const OIS::MouseEvent &e)
1018    {
1019        // check for actual moved event
1020        if (e.state.X.rel != 0 || e.state.Y.rel != 0)
1021        {
[1788]1022            IntVector2 abs(e.state.X.abs, e.state.Y.abs);
1023            IntVector2 rel(e.state.X.rel, e.state.Y.rel);
1024            IntVector2 clippingSize(e.state.width, e.state.height);
[2896]1025            for (unsigned int iState = 0; iState < activeStatesTriggered_[Mouse].size(); ++iState)
1026                activeStatesTriggered_[Mouse][iState]->mouseMoved(abs, rel, clippingSize);
[1755]1027        }
[1502]1028
[1755]1029        // check for mouse scrolled event
1030        if (e.state.Z.rel != 0)
1031        {
[2896]1032            for (unsigned int iState = 0; iState < activeStatesTriggered_[Mouse].size(); ++iState)
1033                activeStatesTriggered_[Mouse][iState]->mouseScrolled(e.state.Z.abs, e.state.Z.rel);
[1755]1034        }
[1502]1035
[1755]1036        return true;
1037    }
[1502]1038
[1755]1039    /**
1040    @brief
1041        Event handler for the mousePressed Event.
1042    @param e
1043        Event information
1044    @param id
1045        The ID of the mouse button
1046    */
1047    bool InputManager::mousePressed(const OIS::MouseEvent &e, OIS::MouseButtonID id)
1048    {
1049        // check whether the button already is in the list (can happen when focus was lost)
1050        unsigned int iButton = 0;
[1887]1051        while (iButton < mouseButtonsDown_.size() && mouseButtonsDown_[iButton] != (MouseButtonCode::ByEnum)id)
[1755]1052            iButton++;
1053        if (iButton == mouseButtonsDown_.size())
[1887]1054            mouseButtonsDown_.push_back((MouseButtonCode::ByEnum)id);
[1502]1055
[2896]1056        for (unsigned int iState = 0; iState < activeStatesTriggered_[Mouse].size(); ++iState)
1057            activeStatesTriggered_[Mouse][iState]->mouseButtonPressed((MouseButtonCode::ByEnum)id);
[1502]1058
[1755]1059        return true;
1060    }
[1502]1061
[1755]1062    /**
1063    @brief
1064        Event handler for the mouseReleased Event.
1065    @param e
1066        Event information
1067    @param id
1068        The ID of the mouse button
1069    */
1070    bool InputManager::mouseReleased(const OIS::MouseEvent &e, OIS::MouseButtonID id)
1071    {
1072        // remove the button from the keysDown_ list
1073        for (unsigned int iButton = 0; iButton < mouseButtonsDown_.size(); iButton++)
1074        {
[1887]1075            if (mouseButtonsDown_[iButton] == (MouseButtonCode::ByEnum)id)
[1755]1076            {
1077                mouseButtonsDown_.erase(mouseButtonsDown_.begin() + iButton);
1078                break;
1079            }
1080        }
[1502]1081
[2896]1082        for (unsigned int iState = 0; iState < activeStatesTriggered_[Mouse].size(); ++iState)
1083            activeStatesTriggered_[Mouse][iState]->mouseButtonReleased((MouseButtonCode::ByEnum)id);
[1219]1084
[1755]1085        return true;
1086    }
[1293]1087
[1502]1088
[1755]1089    // ###### Joy Stick Events ######
[1219]1090
[1755]1091    /**
1092    @brief
1093        Returns the joy stick ID (orxonox) according to a OIS::JoyStickEvent
1094    */
1095    inline unsigned int InputManager::_getJoystick(const OIS::JoyStickEvent& arg)
1096    {
1097        // use the device to identify which one called the method
1098        OIS::JoyStick* joyStick = (OIS::JoyStick*)arg.device;
1099        unsigned int iJoyStick = 0;
1100        while (joySticks_[iJoyStick] != joyStick)
1101            iJoyStick++;
1102        // assert: Unknown joystick fired an event.
1103        assert(iJoyStick != joySticksSize_);
1104        return iJoyStick;
1105    }
[1219]1106
[1755]1107    bool InputManager::buttonPressed(const OIS::JoyStickEvent &arg, int button)
1108    {
1109        unsigned int iJoyStick = _getJoystick(arg);
[1502]1110
[1755]1111        // check whether the button already is in the list (can happen when focus was lost)
[1887]1112        std::vector<JoyStickButtonCode::ByEnum>& buttonsDown = joyStickButtonsDown_[iJoyStick];
[1755]1113        unsigned int iButton = 0;
1114        while (iButton < buttonsDown.size() && buttonsDown[iButton] != button)
1115            iButton++;
1116        if (iButton == buttonsDown.size())
[1887]1117            buttonsDown.push_back((JoyStickButtonCode::ByEnum)button);
[1219]1118
[2896]1119        for (unsigned int iState = 0; iState < activeStatesTriggered_[2 + iJoyStick].size(); ++iState)
1120            activeStatesTriggered_[2 + iJoyStick][iState]->joyStickButtonPressed(iJoyStick, (JoyStickButtonCode::ByEnum)button);
[1502]1121
[1755]1122        return true;
1123    }
[1219]1124
[1755]1125    bool InputManager::buttonReleased(const OIS::JoyStickEvent &arg, int button)
1126    {
1127        unsigned int iJoyStick = _getJoystick(arg);
[1219]1128
[1755]1129        // remove the button from the joyStickButtonsDown_ list
[1887]1130        std::vector<JoyStickButtonCode::ByEnum>& buttonsDown = joyStickButtonsDown_[iJoyStick];
[1755]1131        for (unsigned int iButton = 0; iButton < buttonsDown.size(); iButton++)
1132        {
1133            if (buttonsDown[iButton] == button)
1134            {
1135                buttonsDown.erase(buttonsDown.begin() + iButton);
1136                break;
1137            }
1138        }
[1219]1139
[2896]1140        for (unsigned int iState = 0; iState < activeStatesTriggered_[2 + iJoyStick].size(); ++iState)
1141            activeStatesTriggered_[2 + iJoyStick][iState]->joyStickButtonReleased(iJoyStick, (JoyStickButtonCode::ByEnum)button);
[1219]1142
[1755]1143        return true;
1144    }
[1219]1145
[1755]1146    /**
1147    @brief
1148        Calls the states for a particular axis with our enumeration.
1149        Used by OIS sliders and OIS axes.
1150    */
1151    void InputManager::_fireAxis(unsigned int iJoyStick, int axis, int value)
1152    {
[2662]1153        if (internalState_ & Calibrating)
[1755]1154        {
[2662]1155            if (value < joyStickMinValues_[iJoyStick][axis])
1156                joyStickMinValues_[iJoyStick][axis] = value;
1157            if (value > joyStickMaxValues_[iJoyStick][axis])
1158                joyStickMaxValues_[iJoyStick][axis] = value;
[1755]1159        }
1160        else
1161        {
[2662]1162            float fValue = value - joyStickCalibrations_[iJoyStick].middleValue[axis];
[1755]1163            if (fValue > 0.0f)
[2662]1164                fValue *= joyStickCalibrations_[iJoyStick].positiveCoeff[axis];
[1755]1165            else
[2662]1166                fValue *= joyStickCalibrations_[iJoyStick].negativeCoeff[axis];
[1219]1167
[2896]1168            for (unsigned int iState = 0; iState < activeStatesTriggered_[2 + iJoyStick].size(); ++iState)
1169                activeStatesTriggered_[2 + iJoyStick][iState]->joyStickAxisMoved(iJoyStick, axis, fValue);
[1755]1170        }
1171    }
[1219]1172
[1755]1173    bool InputManager::axisMoved(const OIS::JoyStickEvent &arg, int axis)
1174    {
1175        unsigned int iJoyStick = _getJoystick(arg);
[1219]1176
[1755]1177        // keep in mind that the first 8 axes are reserved for the sliders
[2662]1178        _fireAxis(iJoyStick, axis + sliderAxes, arg.state.mAxes[axis].abs);
[1293]1179
[1755]1180        return true;
1181    }
[1293]1182
[1755]1183    bool InputManager::sliderMoved(const OIS::JoyStickEvent &arg, int id)
1184    {
1185        unsigned int iJoyStick = _getJoystick(arg);
[1293]1186
[1755]1187        if (sliderStates_[iJoyStick].sliderStates[id].x != arg.state.mSliders[id].abX)
1188            _fireAxis(iJoyStick, id * 2, arg.state.mSliders[id].abX);
1189        else if (sliderStates_[iJoyStick].sliderStates[id].y != arg.state.mSliders[id].abY)
1190            _fireAxis(iJoyStick, id * 2 + 1, arg.state.mSliders[id].abY);
[1219]1191
[1755]1192        return true;
1193    }
[1219]1194
[1755]1195    bool InputManager::povMoved(const OIS::JoyStickEvent &arg, int id)
[1219]1196    {
[1755]1197        unsigned int iJoyStick = _getJoystick(arg);
[918]1198
[1755]1199        // translate the POV into 8 simple buttons
[922]1200
[1755]1201        int lastState = povStates_[iJoyStick][id];
1202        if (lastState & OIS::Pov::North)
1203            buttonReleased(arg, 32 + id * 4 + 0);
1204        if (lastState & OIS::Pov::South)
1205            buttonReleased(arg, 32 + id * 4 + 1);
1206        if (lastState & OIS::Pov::East)
1207            buttonReleased(arg, 32 + id * 4 + 2);
1208        if (lastState & OIS::Pov::West)
1209            buttonReleased(arg, 32 + id * 4 + 3);
[918]1210
[1755]1211        povStates_[iJoyStick].povStates[id] = arg.state.mPOV[id].direction;
[1219]1212
[1755]1213        int currentState = povStates_[iJoyStick][id];
1214        if (currentState & OIS::Pov::North)
1215            buttonPressed(arg, 32 + id * 4 + 0);
1216        if (currentState & OIS::Pov::South)
1217            buttonPressed(arg, 32 + id * 4 + 1);
1218        if (currentState & OIS::Pov::East)
1219            buttonPressed(arg, 32 + id * 4 + 2);
1220        if (currentState & OIS::Pov::West)
1221            buttonPressed(arg, 32 + id * 4 + 3);
[1502]1222
[1755]1223        return true;
[1219]1224    }
[1066]1225
1226
[1755]1227    // ############################################################
1228    // #####         Other Public Interface Methods           #####
1229    // ##########                                        ##########
1230    // ############################################################
[1219]1231
[1755]1232    /**
1233    @brief
1234        Adjusts the mouse window metrics.
1235        This method has to be called every time the size of the window changes.
1236    @param width
1237        The new width of the render window
1238    @param^height
1239        The new height of the render window
1240    */
1241    void InputManager::setWindowExtents(const int width, const int height)
[1219]1242    {
[1755]1243        if (mouse_)
1244        {
1245            // Set mouse region (if window resizes, we should alter this to reflect as well)
1246            mouse_->getMouseState().width  = width;
1247            mouse_->getMouseState().height = height;
1248        }
[1219]1249    }
1250
[1887]1251    /**
1252    @brief
1253        Sets the the name of the command used by the KeyDetector as callback.
1254    @param command
1255        Command name as string
1256    */
1257    void InputManager::setKeyDetectorCallback(const std::string& command)
1258    {
1259        this->keyDetector_->setCallbackCommand(command);
1260    }
[1219]1261
[1755]1262    // ###### InputStates ######
[1219]1263
[1755]1264    /**
1265    @brief
1266        Adds a new key handler.
1267    @param handler
1268        Pointer to the handler object.
1269    @param name
1270        Unique name of the handler.
1271    @param priority
[2896]1272        Determines which InputState gets the input. Higher is better.
1273        Use 0 to handle it implicitely by the order of activation.
1274        Otherwise numbers larger than maxStateStackSize_s have to be used!
[1755]1275    @return
1276        True if added, false if name or priority already existed.
1277    */
[2896]1278    bool InputManager::_configureInputState(InputState* state, const std::string& name, bool bAlwaysGetsInput, bool bTransparent, int priority)
[1219]1279    {
[1755]1280        if (name == "")
1281            return false;
1282        if (!state)
1283            return false;
1284        if (inputStatesByName_.find(name) == inputStatesByName_.end())
1285        {
[2896]1286            if (priority >= InputStatePriority::HighPriority || priority == InputStatePriority::Empty)
[1755]1287            {
[2896]1288                // Make sure we don't add two high priority states with the same priority
1289                for (std::map<std::string, InputState*>::const_iterator it = this->inputStatesByName_.begin();
1290                    it != this->inputStatesByName_.end(); ++it)
1291                {
1292                    if (it->second->getPriority() == priority)
1293                    {
1294                        COUT(2) << "Warning: Could not add an InputState with the same priority '"
1295                            << priority << "' != 0." << std::endl;
1296                        return false;
1297                    }
1298                }
1299            }
1300            inputStatesByName_[name] = state;
1301            state->setNumOfJoySticks(numberOfJoySticks());
1302            state->setName(name);
1303            state->bAlwaysGetsInput_ = bAlwaysGetsInput;
1304            state->bTransparent_ = bTransparent;
1305            if (priority >= InputStatePriority::HighPriority || priority == InputStatePriority::Empty)
[1755]1306                state->setPriority(priority);
[2896]1307            return true;
[1755]1308        }
1309        else
1310        {
1311            COUT(2) << "Warning: Could not add an InputState with the same name '" << name << "'." << std::endl;
1312            return false;
1313        }
[1219]1314    }
1315
[1755]1316    /**
1317    @brief
1318        Removes and destroys an input state internally.
1319    @param name
1320        Name of the handler.
1321    @return
1322        True if removal was successful, false if name was not found.
1323    @remarks
1324        You can't remove the internal states "empty", "calibrator" and "detector".
[2896]1325        The removal process is being postponed if InputManager::update() is currently running.
[1755]1326    */
1327    bool InputManager::requestDestroyState(const std::string& name)
[1219]1328    {
[1881]1329        if (name == "empty")
[1755]1330        {
[1881]1331            COUT(2) << "InputManager: Removing the empty state is not allowed!" << std::endl;
[1755]1332            return false;
1333        }
1334        std::map<std::string, InputState*>::iterator it = inputStatesByName_.find(name);
1335        if (it != inputStatesByName_.end())
1336        {
1337            if (activeStates_.find(it->second->getPriority()) != activeStates_.end())
1338            {
1339                // The state is still active. We have to postpone
1340                stateLeaveRequests_.insert(it->second);
1341                stateDestroyRequests_.insert(it->second);
1342            }
1343            else if (this->internalState_ & Ticking)
1344            {
1345                // cannot remove state while ticking
1346                stateDestroyRequests_.insert(it->second);
1347            }
1348            else
1349                _destroyState(it->second);
[1219]1350
[1755]1351            return true;
1352        }
1353        return false;
[1219]1354    }
1355
[1755]1356    /**
1357    @brief
1358        Returns the pointer to the requested InputState.
1359    @param name
1360        Unique name of the state.
1361    @return
1362        Pointer to the instance, 0 if name was not found.
1363    */
1364    InputState* InputManager::getState(const std::string& name)
[1219]1365    {
[1755]1366        std::map<std::string, InputState*>::iterator it = inputStatesByName_.find(name);
1367        if (it != inputStatesByName_.end())
1368            return it->second;
1369        else
1370            return 0;
[1219]1371    }
1372
[1755]1373    /**
1374    @brief
1375        Returns the current input state (there might be others active too!)
1376    @return
1377        The current highest prioritised active input state.
1378    */
1379    InputState* InputManager::getCurrentState()
[1219]1380    {
[1755]1381        return (*activeStates_.rbegin()).second;
[1219]1382    }
1383
[1755]1384    /**
1385    @brief
1386        Activates a specific input state.
1387        It might not be really activated if the priority is too low!
1388    @param name
1389        Unique name of the state.
1390    @return
1391        False if name was not found, true otherwise.
1392    */
1393    bool InputManager::requestEnterState(const std::string& name)
[1219]1394    {
[1755]1395        // get pointer from the map with all stored handlers
1396        std::map<std::string, InputState*>::const_iterator it = inputStatesByName_.find(name);
1397        if (it != inputStatesByName_.end())
1398        {
1399            // exists
1400            if (activeStates_.find(it->second->getPriority()) == activeStates_.end())
1401            {
1402                // not active
1403                if (stateDestroyRequests_.find(it->second) == stateDestroyRequests_.end())
1404                {
1405                    // not scheduled for destruction
[2896]1406                    // prevents a state being added multiple times
[1755]1407                    stateEnterRequests_.insert(it->second);
1408                    return true;
1409                }
1410            }
1411        }
1412        return false;
[1219]1413    }
1414
[1755]1415    /**
1416    @brief
1417        Deactivates a specific input state.
1418    @param name
1419        Unique name of the state.
1420    @return
1421        False if name was not found, true otherwise.
1422    */
1423    bool InputManager::requestLeaveState(const std::string& name)
[1219]1424    {
[2896]1425        if (name == "empty")
1426        {
1427            COUT(2) << "InputManager: Leaving the empty state is not allowed!" << std::endl;
1428            return false;
1429        }
[1755]1430        // get pointer from the map with all stored handlers
1431        std::map<std::string, InputState*>::const_iterator it = inputStatesByName_.find(name);
1432        if (it != inputStatesByName_.end())
1433        {
1434            // exists
1435            if (activeStates_.find(it->second->getPriority()) != activeStates_.end())
1436            {
1437                // active
1438                stateLeaveRequests_.insert(it->second);
1439                return true;
1440            }
1441        }
1442        return false;
[1219]1443    }
1444
1445
[1755]1446    // ############################################################
1447    // #####                Console Commands                  #####
1448    // ##########                                        ##########
1449    // ############################################################
[1219]1450
[1755]1451    /**
1452    @brief
1453        Starts joy stick calibration.
1454    */
1455    void InputManager::calibrate()
[1219]1456    {
[2662]1457        COUT(0) << "Move all joy stick axes fully in all directions." << std::endl
1458                << "When done, put the axex in the middle position and press enter." << std::endl;
1459
1460        getInstance()._startCalibration();
[1219]1461    }
1462
[1755]1463    /**
1464    @brief
1465        Reloads the input system
1466    */
1467    void InputManager::reload(bool joyStickSupport)
[1219]1468    {
[1755]1469        getInstance().reloadInputSystem(joyStickSupport);
[1219]1470    }
[918]1471}
Note: See TracBrowser for help on using the repository browser.