Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core5/src/libraries/core/input/InputManager.cc @ 5829

Last change on this file since 5829 was 5829, checked in by landauf, 15 years ago

replaced most occurrences of setObject(o) in combination with createFunctor(f) with the more convenient createFunctor(f, o)

  • Property svn:eol-style set to native
File size: 26.1 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Reto Grieder
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30@file
31@brief
32    Implementation of the InputManager and a static variable from the InputHandler.
33*/
34
35#include "InputManager.h"
36
37#include <cassert>
38#include <climits>
39#include <ois/OISException.h>
40#include <ois/OISInputManager.h>
41#include <boost/foreach.hpp>
42
43#include "util/Convert.h"
44#include "util/Exception.h"
45#include "util/ScopeGuard.h"
46#include "core/Clock.h"
47#include "core/CoreIncludes.h"
48#include "core/ConfigValueIncludes.h"
49#include "core/ConsoleCommand.h"
50#include "core/CommandLine.h"
51#include "core/Functor.h"
52#include "core/GraphicsManager.h"
53
54#include "InputBuffer.h"
55#include "KeyDetector.h"
56#include "JoyStick.h"
57#include "JoyStickQuantityListener.h"
58#include "Mouse.h"
59#include "Keyboard.h"
60
61namespace orxonox
62{
63    SetCommandLineSwitch(keyboard_no_grab).information("Whether not to exclusively grab the keyboard");
64
65    // Abuse of this source file for the InputHandler
66    InputHandler InputHandler::EMPTY;
67
68    InputManager* InputManager::singletonPtr_s = 0;
69
70    //! Defines the |= operator for easier use.
71    inline InputManager::State operator|=(InputManager::State& lval, InputManager::State rval)
72    {
73        return (lval = (InputManager::State)(lval | rval));
74    }
75
76    //! Defines the &= operator for easier use.
77    inline InputManager::State operator&=(InputManager::State& lval, int rval)
78    {
79        return (lval = (InputManager::State)(lval & rval));
80    }
81
82    // ############################################################
83    // #####                  Initialisation                  #####
84    // ##########                                        ##########
85    // ############################################################
86    InputManager::InputManager()
87        : internalState_(Bad)
88        , oisInputManager_(0)
89        , devices_(2)
90        , bExclusiveMouse_(false)
91        , emptyState_(0)
92        , keyDetector_(0)
93        , calibratorCallbackHandler_(0)
94    {
95        RegisterRootObject(InputManager);
96
97        CCOUT(4) << "Constructing..." << std::endl;
98
99        this->setConfigValues();
100
101        this->loadDevices();
102
103        // Lowest priority empty InputState
104        emptyState_ = createInputState("empty", false, false, InputStatePriority::Empty);
105        emptyState_->setHandler(&InputHandler::EMPTY);
106        activeStates_[emptyState_->getPriority()] = emptyState_;
107
108        // KeyDetector to evaluate a pressed key's name
109        InputState* detector = createInputState("detector", false, false, InputStatePriority::Detector);
110        // Create a callback to avoid buttonHeld events after the key has been detected
111        detector->setLeaveFunctor(createFunctor(&InputManager::clearBuffers, this));
112        keyDetector_ = new KeyDetector();
113        detector->setHandler(keyDetector_);
114
115        // Joy stick calibration helper callback
116        InputState* calibrator = createInputState("calibrator", false, false, InputStatePriority::Calibrator);
117        calibrator->setHandler(&InputHandler::EMPTY);
118        calibratorCallbackHandler_ = new InputBuffer();
119        calibratorCallbackHandler_->registerListener(this, &InputManager::stopCalibration, '\r', true);
120        calibrator->setKeyHandler(calibratorCallbackHandler_);
121
122        this->updateActiveStates();
123
124        // calibrate console command
125        this->getIdentifier()->addConsoleCommand(createConsoleCommand(createFunctor(&InputManager::calibrate, this), "calibrate"), true);
126        // reload console command
127        this->getIdentifier()->addConsoleCommand(createConsoleCommand(createFunctor(&InputManager::reload, this), "reload"), false);
128
129        CCOUT(4) << "Construction complete." << std::endl;
130        internalState_ = Nothing;
131    }
132
133    void InputManager::setConfigValues()
134    {
135    }
136
137    /**
138    @brief
139        Creates the OIS::InputMananger, the keyboard, the mouse and
140        the joys ticks. If either of the first two fail, this method throws an exception.
141    @param windowWidth
142        The width of the render window
143    @param windowHeight
144        The height of the render window
145    */
146    void InputManager::loadDevices()
147    {
148        CCOUT(4) << "Loading input devices..." << std::endl;
149
150        // When loading the devices they should not already be loaded
151        assert(internalState_ & Bad);
152        assert(devices_[InputDeviceEnumerator::Mouse] == 0);
153        assert(devices_[InputDeviceEnumerator::Keyboard] == 0);
154        assert(devices_.size() == InputDeviceEnumerator::FirstJoyStick);
155
156        // Fill parameter list
157        OIS::ParamList paramList;
158        size_t windowHnd = GraphicsManager::getInstance().getRenderWindowHandle();
159        paramList.insert(std::make_pair("WINDOW", multi_cast<std::string>(windowHnd)));
160#if defined(ORXONOX_PLATFORM_WINDOWS)
161        paramList.insert(std::make_pair("w32_keyboard", "DISCL_NONEXCLUSIVE"));
162        paramList.insert(std::make_pair("w32_keyboard", "DISCL_FOREGROUND"));
163        paramList.insert(std::make_pair("w32_mouse", "DISCL_FOREGROUND"));
164        if (bExclusiveMouse_ || GraphicsManager::getInstance().isFullScreen())
165        {
166            // Disable Windows key plus special keys (like play, stop, next, etc.)
167            paramList.insert(std::make_pair("w32_keyboard", "DISCL_NOWINKEY"));
168            paramList.insert(std::make_pair("w32_mouse", "DISCL_EXCLUSIVE"));
169        }
170        else
171            paramList.insert(std::make_pair("w32_mouse", "DISCL_NONEXCLUSIVE"));
172#elif defined(ORXONOX_PLATFORM_LINUX)
173        // Enabling this is probably a bad idea, but whenever orxonox crashes, the setting stays on
174        // Trouble might be that the Pressed event occurs a bit too often...
175        paramList.insert(std::make_pair("XAutoRepeatOn", "true"));
176
177        if (bExclusiveMouse_ || GraphicsManager::getInstance().isFullScreen())
178        {
179            if (CommandLine::getValue("keyboard_no_grab").getBool())
180                paramList.insert(std::make_pair("x11_keyboard_grab", "false"));
181            else
182                paramList.insert(std::make_pair("x11_keyboard_grab", "true"));
183            paramList.insert(std::make_pair("x11_mouse_grab",  "true"));
184            paramList.insert(std::make_pair("x11_mouse_hide", "true"));
185        }
186        else
187        {
188            paramList.insert(std::make_pair("x11_keyboard_grab", "false"));
189            paramList.insert(std::make_pair("x11_mouse_grab",  "false"));
190            paramList.insert(std::make_pair("x11_mouse_hide", "false"));
191        }
192#endif
193
194        try
195        {
196            oisInputManager_ = OIS::InputManager::createInputSystem(paramList);
197            // Exception-safety
198            Loki::ScopeGuard guard = Loki::MakeGuard(OIS::InputManager::destroyInputSystem, oisInputManager_);
199            CCOUT(ORX_DEBUG) << "Created OIS input manager." << std::endl;
200
201            if (oisInputManager_->getNumberOfDevices(OIS::OISKeyboard) > 0)
202                devices_[InputDeviceEnumerator::Keyboard] = new Keyboard(InputDeviceEnumerator::Keyboard, oisInputManager_);
203            else
204                ThrowException(InitialisationFailed, "InputManager: No keyboard found, cannot proceed!");
205
206            // Successful initialisation
207            guard.Dismiss();
208        }
209        catch (const std::exception& ex)
210        {
211            oisInputManager_ = NULL;
212            internalState_ |= Bad;
213            ThrowException(InitialisationFailed, "Could not initialise the input system: " << ex.what());
214        }
215
216        this->loadMouse();
217        this->loadJoySticks();
218
219        // Reorder states in case some joy sticks were added/removed
220        this->updateActiveStates();
221
222        CCOUT(4) << "Input devices loaded." << std::endl;
223    }
224
225    //! Creates a new orxonox::Mouse
226    void InputManager::loadMouse()
227    {
228        if (oisInputManager_->getNumberOfDevices(OIS::OISMouse) > 0)
229        {
230            try
231            {
232                devices_[InputDeviceEnumerator::Mouse] = new Mouse(InputDeviceEnumerator::Mouse, oisInputManager_);
233            }
234            catch (const std::exception& ex)
235            {
236                CCOUT(2) << "Warning: Failed to create Mouse:" << ex.what() << std::endl
237                         << "Proceeding without mouse support." << std::endl;
238            }
239        }
240        else
241            CCOUT(ORX_WARNING) << "Warning: No mouse found! Proceeding without mouse support." << std::endl;
242    }
243
244    //! Creates as many joy sticks as are available.
245    void InputManager::loadJoySticks()
246    {
247        for (int i = 0; i < oisInputManager_->getNumberOfDevices(OIS::OISJoyStick); i++)
248        {
249            try
250            {
251                devices_.push_back(new JoyStick(InputDeviceEnumerator::FirstJoyStick + i, oisInputManager_));
252            }
253            catch (const std::exception& ex)
254            {
255                CCOUT(2) << "Warning: Failed to create joy stick: " << ex.what() << std::endl;
256            }
257        }
258
259        // inform all JoyStick Device Number Listeners
260        std::vector<JoyStick*> joyStickList;
261        for (unsigned int i = InputDeviceEnumerator::FirstJoyStick; i < devices_.size(); ++i)
262            joyStickList.push_back(static_cast<JoyStick*>(devices_[i]));
263        JoyStickQuantityListener::changeJoyStickQuantity(joyStickList);
264    }
265
266    void InputManager::setKeyDetectorCallback(const std::string& command)
267    {
268        this->keyDetector_->setCallbackCommand(command);
269    }
270
271    // ############################################################
272    // #####                    Destruction                   #####
273    // ##########                                        ##########
274    // ############################################################
275
276    InputManager::~InputManager()
277    {
278        CCOUT(3) << "Destroying..." << std::endl;
279
280        // Destroy calibrator helper handler and state
281        keyDetector_->destroy();
282        this->destroyState("calibrator");
283        // Destroy KeyDetector and state
284        calibratorCallbackHandler_->destroy();
285        this->destroyState("detector");
286        // destroy the empty InputState
287        this->destroyStateInternal(this->emptyState_);
288
289        // destroy all user InputStates
290        while (statesByName_.size() > 0)
291            this->destroyStateInternal((*statesByName_.rbegin()).second);
292
293        if (!(internalState_ & Bad))
294            this->destroyDevices();
295
296        CCOUT(3) << "Destruction complete." << std::endl;
297    }
298
299    /**
300    @brief
301        Destoys all input devices (joy sticks, mouse, keyboard and OIS::InputManager)
302    @throw
303        Method does not throw
304    */
305    void InputManager::destroyDevices()
306    {
307        CCOUT(4) << "Destroying devices..." << std::endl;
308
309        BOOST_FOREACH(InputDevice*& device, devices_)
310        {
311            if (device == NULL)
312                continue;
313            std::string className = device->getClassName();
314            try
315            {
316                delete device;
317                device = 0;
318                CCOUT(4) << className << " destroyed." << std::endl;
319            }
320            catch (...)
321            {
322                COUT(1) << className << " destruction failed: " << Exception::handleMessage() << std::endl
323                        << "    Potential resource leak!" << std::endl;
324            }
325        }
326        devices_.resize(InputDeviceEnumerator::FirstJoyStick);
327
328        assert(oisInputManager_ != NULL);
329        try
330        {
331            OIS::InputManager::destroyInputSystem(oisInputManager_);
332        }
333        catch (...)
334        {
335            COUT(1) << "OIS::InputManager destruction failed" << Exception::handleMessage() << std::endl
336                    << "    Potential resource leak!" << std::endl;
337        }
338        oisInputManager_ = NULL;
339
340        internalState_ |= Bad;
341        CCOUT(4) << "Destroyed devices." << std::endl;
342    }
343
344    // ############################################################
345    // #####                     Reloading                    #####
346    // ##########                                        ##########
347    // ############################################################
348
349    void InputManager::reload()
350    {
351        if (internalState_ & Ticking)
352        {
353            // We cannot destroy OIS right now, because reload was probably
354            // caused by a user clicking on a GUI item. The stack trace would then
355            // include an OIS method. So it would be a very bad thing to destroy it..
356            internalState_ |= ReloadRequest;
357        }
358        else if (internalState_ & Calibrating)
359            CCOUT(2) << "Warning: Cannot reload input system. Joy sticks are currently being calibrated." << std::endl;
360        else
361            reloadInternal();
362    }
363
364    //! Internal reload method. Destroys the OIS devices and loads them again.
365    void InputManager::reloadInternal()
366    {
367        CCOUT(3) << "Reloading ..." << std::endl;
368
369        this->destroyDevices();
370        this->loadDevices();
371
372        internalState_ &= ~Bad;
373        internalState_ &= ~ReloadRequest;
374        CCOUT(4) << "Reloading complete." << std::endl;
375    }
376
377    // ############################################################
378    // #####                  Runtime Methods                 #####
379    // ##########                                        ##########
380    // ############################################################
381
382    void InputManager::update(const Clock& time)
383    {
384        if (internalState_ & Bad)
385            ThrowException(General, "InputManager was not correctly reloaded.");
386
387        else if (internalState_ & ReloadRequest)
388            reloadInternal();
389
390        // check for states to leave
391        if (!stateLeaveRequests_.empty())
392        {
393            for (std::set<InputState*>::iterator it = stateLeaveRequests_.begin();
394                it != stateLeaveRequests_.end(); ++it)
395            {
396                (*it)->left();
397                // just to be sure that the state actually is registered
398                assert(statesByName_.find((*it)->getName()) != statesByName_.end());
399
400                activeStates_.erase((*it)->getPriority());
401                if ((*it)->getPriority() < InputStatePriority::HighPriority)
402                    (*it)->setPriority(0);
403                updateActiveStates();
404            }
405            stateLeaveRequests_.clear();
406        }
407
408        // check for states to enter
409        if (!stateEnterRequests_.empty())
410        {
411            for (std::set<InputState*>::const_iterator it = stateEnterRequests_.begin();
412                it != stateEnterRequests_.end(); ++it)
413            {
414                // just to be sure that the state actually is registered
415                assert(statesByName_.find((*it)->getName()) != statesByName_.end());
416
417                if ((*it)->getPriority() == 0)
418                {
419                    // Get smallest possible priority between 1 and maxStateStackSize_s
420                    for(std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin();
421                        rit != activeStates_.rend(); ++rit)
422                    {
423                        if (rit->first < InputStatePriority::HighPriority)
424                        {
425                            (*it)->setPriority(rit->first + 1);
426                            break;
427                        }
428                    }
429                    // In case no normal handler was on the stack
430                    if ((*it)->getPriority() == 0)
431                        (*it)->setPriority(1);
432                }
433                activeStates_[(*it)->getPriority()] = (*it);
434                updateActiveStates();
435                (*it)->entered();
436            }
437            stateEnterRequests_.clear();
438        }
439
440        // check for states to destroy
441        if (!stateDestroyRequests_.empty())
442        {
443            for (std::set<InputState*>::iterator it = stateDestroyRequests_.begin();
444                it != stateDestroyRequests_.end(); ++it)
445            {
446                destroyStateInternal((*it));
447            }
448            stateDestroyRequests_.clear();
449        }
450
451        // check whether a state has changed its EMPTY situation
452        bool bUpdateRequired = false;
453        for (std::map<int, InputState*>::iterator it = activeStates_.begin(); it != activeStates_.end(); ++it)
454        {
455            if (it->second->hasExpired())
456            {
457                it->second->resetExpiration();
458                bUpdateRequired = true;
459            }
460        }
461        if (bUpdateRequired)
462            updateActiveStates();
463
464        // mark that we now start capturing and distributing input
465        internalState_ |= Ticking;
466
467        // Capture all the input and handle it
468        BOOST_FOREACH(InputDevice* device, devices_)
469            if (device != NULL)
470                device->update(time);
471
472        // Update the states
473        for (unsigned int i = 0; i < activeStatesTicked_.size(); ++i)
474            activeStatesTicked_[i]->update(time.getDeltaTime());
475
476        internalState_ &= ~Ticking;
477    }
478
479    /**
480    @brief
481        Updates the currently active states (according to activeStates_) for each device.
482        Also, a list of all active states (no duplicates!) is compiled for the general update().
483    */
484    void InputManager::updateActiveStates()
485    {
486        assert((internalState_ & InputManager::Ticking) == 0);
487        // temporary resize
488        for (unsigned int i = 0; i < devices_.size(); ++i)
489        {
490            if (devices_[i] == NULL)
491                continue;
492            std::vector<InputState*>& states = devices_[i]->getStateListRef();
493            bool occupied = false;
494            states.clear();
495            for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin(); rit != activeStates_.rend(); ++rit)
496            {
497                if (rit->second->isInputDeviceEnabled(i) && (!occupied || rit->second->bAlwaysGetsInput_))
498                {
499                    states.push_back(rit->second);
500                    if (!rit->second->bTransparent_)
501                        occupied = true;
502                }
503            }
504        }
505
506        // update tickables (every state will only appear once)
507        // Using a std::set to avoid duplicates
508        std::set<InputState*> tempSet;
509        for (unsigned int i = 0; i < devices_.size(); ++i)
510            if (devices_[i] != NULL)
511                for (unsigned int iState = 0; iState < devices_[i]->getStateListRef().size(); ++iState)
512                    tempSet.insert(devices_[i]->getStateListRef()[iState]);
513
514        // copy the content of the std::set back to the actual vector
515        activeStatesTicked_.clear();
516        for (std::set<InputState*>::const_iterator it = tempSet.begin();it != tempSet.end(); ++it)
517            activeStatesTicked_.push_back(*it);
518
519        // Check whether we have to change the mouse mode
520        std::vector<InputState*>& mouseStates = devices_[InputDeviceEnumerator::Mouse]->getStateListRef();
521        if (mouseStates.empty() && bExclusiveMouse_ ||
522            !mouseStates.empty() && mouseStates.front()->getIsExclusiveMouse() != bExclusiveMouse_)
523        {
524            bExclusiveMouse_ = !bExclusiveMouse_;
525            if (!GraphicsManager::getInstance().isFullScreen())
526                this->reloadInternal();
527        }
528    }
529
530    void InputManager::clearBuffers()
531    {
532        BOOST_FOREACH(InputDevice* device, devices_)
533            if (device != NULL)
534                device->clearBuffers();
535    }
536
537    void InputManager::calibrate()
538    {
539        COUT(0) << "Move all joy stick axes fully in all directions." << std::endl
540                << "When done, put the axex in the middle position and press enter." << std::endl;
541
542        BOOST_FOREACH(InputDevice* device, devices_)
543            if (device != NULL)
544                device->startCalibration();
545
546        internalState_ |= Calibrating;
547        enterState("calibrator");
548    }
549
550    //! Tells all devices to stop the calibration and evaluate it. Buffers are being cleared as well!
551    void InputManager::stopCalibration()
552    {
553        BOOST_FOREACH(InputDevice* device, devices_)
554            if (device != NULL)
555                device->stopCalibration();
556
557        // restore old input state
558        leaveState("calibrator");
559        internalState_ &= ~Calibrating;
560        // Clear buffers to prevent button hold events
561        this->clearBuffers();
562
563        COUT(0) << "Calibration has been stored." << std::endl;
564    }
565
566    //! Gets called by WindowEventListener upon focus change --> clear buffers
567    void InputManager::windowFocusChanged()
568    {
569        this->clearBuffers();
570    }
571
572    std::pair<int, int> InputManager::getMousePosition() const
573    {
574        Mouse* mouse = static_cast<Mouse*>(devices_[InputDeviceEnumerator::Mouse]);
575        if (mouse != NULL)
576        {
577            const OIS::MouseState state = mouse->getOISDevice()->getMouseState();
578            return std::make_pair(state.X.abs, state.Y.abs);
579        }
580        else
581            return std::make_pair(0, 0);
582    }
583
584    // ############################################################
585    // #####                    Input States                  #####
586    // ##########                                        ##########
587    // ############################################################
588
589    InputState* InputManager::createInputState(const std::string& name, bool bAlwaysGetsInput, bool bTransparent, InputStatePriority priority)
590    {
591        if (name == "")
592            return 0;
593        if (statesByName_.find(name) == statesByName_.end())
594        {
595            if (priority >= InputStatePriority::HighPriority || priority == InputStatePriority::Empty)
596            {
597                // Make sure we don't add two high priority states with the same priority
598                for (std::map<std::string, InputState*>::const_iterator it = this->statesByName_.begin();
599                    it != this->statesByName_.end(); ++it)
600                {
601                    if (it->second->getPriority() == priority)
602                    {
603                        COUT(2) << "Warning: Could not add an InputState with the same priority '"
604                            << static_cast<int>(priority) << "' != 0." << std::endl;
605                        return 0;
606                    }
607                }
608            }
609            InputState* state = new InputState(name, bAlwaysGetsInput, bTransparent, priority);
610            statesByName_[name] = state;
611
612            return state;
613        }
614        else
615        {
616            COUT(2) << "Warning: Could not add an InputState with the same name '" << name << "'." << std::endl;
617            return 0;
618        }
619    }
620
621    InputState* InputManager::getState(const std::string& name)
622    {
623        std::map<std::string, InputState*>::iterator it = statesByName_.find(name);
624        if (it != statesByName_.end())
625            return it->second;
626        else
627            return 0;
628    }
629
630    bool InputManager::enterState(const std::string& name)
631    {
632        // get pointer from the map with all stored handlers
633        std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name);
634        if (it != statesByName_.end())
635        {
636            // exists
637            if (activeStates_.find(it->second->getPriority()) == activeStates_.end())
638            {
639                // not active
640                if (stateDestroyRequests_.find(it->second) == stateDestroyRequests_.end())
641                {
642                    // not scheduled for destruction
643                    // prevents a state being added multiple times
644                    stateEnterRequests_.insert(it->second);
645                    return true;
646                }
647            }
648        }
649        return false;
650    }
651
652    bool InputManager::leaveState(const std::string& name)
653    {
654        if (name == "empty")
655        {
656            COUT(2) << "InputManager: Leaving the empty state is not allowed!" << std::endl;
657            return false;
658        }
659        // get pointer from the map with all stored handlers
660        std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name);
661        if (it != statesByName_.end())
662        {
663            // exists
664            if (activeStates_.find(it->second->getPriority()) != activeStates_.end())
665            {
666                // active
667                stateLeaveRequests_.insert(it->second);
668                return true;
669            }
670        }
671        return false;
672    }
673
674    bool InputManager::destroyState(const std::string& name)
675    {
676        if (name == "empty")
677        {
678            COUT(2) << "InputManager: Removing the empty state is not allowed!" << std::endl;
679            return false;
680        }
681        std::map<std::string, InputState*>::iterator it = statesByName_.find(name);
682        if (it != statesByName_.end())
683        {
684            if (activeStates_.find(it->second->getPriority()) != activeStates_.end())
685            {
686                // The state is still active. We have to postpone
687                stateLeaveRequests_.insert(it->second);
688                stateDestroyRequests_.insert(it->second);
689            }
690            else if (this->internalState_ & Ticking)
691            {
692                // cannot remove state while ticking
693                stateDestroyRequests_.insert(it->second);
694            }
695            else
696                destroyStateInternal(it->second);
697
698            return true;
699        }
700        return false;
701    }
702
703    //! Destroys an InputState internally.
704    void InputManager::destroyStateInternal(InputState* state)
705    {
706        assert(state && !(this->internalState_ & Ticking));
707        std::map<int, InputState*>::iterator it = this->activeStates_.find(state->getPriority());
708        if (it != this->activeStates_.end())
709        {
710            this->activeStates_.erase(it);
711            updateActiveStates();
712        }
713        statesByName_.erase(state->getName());
714        state->destroy();
715    }
716}
Note: See TracBrowser for help on using the repository browser.