Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 1927 was 1887, checked in by rgrieder, 16 years ago

FIRST THINGS FIRST: Delete or rename your keybindings.ini (def_keybindings.ini already has the most important bindings) or else you won't be able to do anything!

Changes:

  • Multiple joy stick support should now fully work with KeyBinder too (only tested with 0/1 joystick)
  • Reloading the OIS Devices now works with KeyBinder too
  • Modified ConfigValueContainer to accept arbitrary section names
  • added tkeybind to temporary bind a command to a key
  • Fixed dlleport issue in ArgumentCompletionFunctions.h

Internal changes:

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