Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 2358 was 2103, checked in by rgrieder, 16 years ago

Merged r2101 (objecthierarchy) to trunk.

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