Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/netp3/src/core/input/InputManager.cc @ 3014

Last change on this file since 3014 was 3014, checked in by scheusso, 15 years ago

console command grabMouse / ungrabMouse now working (used for a presentation hack)

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