Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3280 was 3280, checked in by rgrieder, 15 years ago

Merged most of the core4 revisions back to the trunk except for:

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