Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/pch/src/core/input/InputManager.cc @ 3148

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

Another clean up in core/input

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