Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3141 was 3084, checked in by landauf, 16 years ago

merged netp3 branch back to trunk

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