Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

New class: KeyBinderManager (yes, it really was necessary, I'm not such a Fan of zillions of classes as well) and moved the keybind command to it from GSLevel.
This new Singleton simply maps the keybind command to the right KeyBinder, selected by KeyBinderManager::setCurrent().
There is also a default KeyBinder (with keybindings.ini as file), which should do the Trick for now. Other Keybinders should only server special purposes (like in mini games or so).

DELETE YOUR keybindings.ini FILE! =
  • Property svn:eol-style set to native
File size: 26.0 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/Clock.h"
44#include "util/Convert.h"
45#include "util/Exception.h"
46#include "util/ScopeGuard.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    // ############################################################
267    // #####                    Destruction                   #####
268    // ##########                                        ##########
269    // ############################################################
270
271    InputManager::~InputManager()
272    {
273        CCOUT(3) << "Destroying..." << std::endl;
274
275        // Destroy calibrator helper handler and state
276        keyDetector_->destroy();
277        this->destroyState("calibrator");
278        // Destroy KeyDetector and state
279        calibratorCallbackHandler_->destroy();
280        this->destroyState("detector");
281        // destroy the empty InputState
282        this->destroyStateInternal(this->emptyState_);
283
284        // destroy all user InputStates
285        while (statesByName_.size() > 0)
286            this->destroyStateInternal((*statesByName_.rbegin()).second);
287
288        if (!(internalState_ & Bad))
289            this->destroyDevices();
290
291        CCOUT(3) << "Destruction complete." << std::endl;
292    }
293
294    /**
295    @brief
296        Destoys all input devices (joy sticks, mouse, keyboard and OIS::InputManager)
297    @throw
298        Method does not throw
299    */
300    void InputManager::destroyDevices()
301    {
302        CCOUT(4) << "Destroying devices..." << std::endl;
303
304        BOOST_FOREACH(InputDevice*& device, devices_)
305        {
306            if (device == NULL)
307                continue;
308            std::string className = device->getClassName();
309            try
310            {
311                delete device;
312                device = 0;
313                CCOUT(4) << className << " destroyed." << std::endl;
314            }
315            catch (...)
316            {
317                COUT(1) << className << " destruction failed: " << Exception::handleMessage() << std::endl
318                        << "    Potential resource leak!" << std::endl;
319            }
320        }
321        devices_.resize(InputDeviceEnumerator::FirstJoyStick);
322
323        assert(oisInputManager_ != NULL);
324        try
325        {
326            OIS::InputManager::destroyInputSystem(oisInputManager_);
327        }
328        catch (...)
329        {
330            COUT(1) << "OIS::InputManager destruction failed" << Exception::handleMessage() << std::endl
331                    << "    Potential resource leak!" << std::endl;
332        }
333        oisInputManager_ = NULL;
334
335        internalState_ |= Bad;
336        CCOUT(4) << "Destroyed devices." << std::endl;
337    }
338
339    // ############################################################
340    // #####                     Reloading                    #####
341    // ##########                                        ##########
342    // ############################################################
343
344    void InputManager::reload()
345    {
346        if (internalState_ & Ticking)
347        {
348            // We cannot destroy OIS right now, because reload was probably
349            // caused by a user clicking on a GUI item. The stack trace would then
350            // include an OIS method. So it would be a very bad thing to destroy it..
351            internalState_ |= ReloadRequest;
352        }
353        else if (internalState_ & Calibrating)
354            CCOUT(2) << "Warning: Cannot reload input system. Joy sticks are currently being calibrated." << std::endl;
355        else
356            reloadInternal();
357    }
358
359    //! Internal reload method. Destroys the OIS devices and loads them again.
360    void InputManager::reloadInternal()
361    {
362        CCOUT(3) << "Reloading ..." << std::endl;
363
364        this->destroyDevices();
365        this->loadDevices();
366
367        internalState_ &= ~Bad;
368        internalState_ &= ~ReloadRequest;
369        CCOUT(4) << "Reloading complete." << std::endl;
370    }
371
372    // ############################################################
373    // #####                  Runtime Methods                 #####
374    // ##########                                        ##########
375    // ############################################################
376
377    void InputManager::update(const Clock& time)
378    {
379        if (internalState_ & Bad)
380            ThrowException(General, "InputManager was not correctly reloaded.");
381
382        else if (internalState_ & ReloadRequest)
383            reloadInternal();
384
385        // check for states to leave
386        if (!stateLeaveRequests_.empty())
387        {
388            for (std::set<InputState*>::iterator it = stateLeaveRequests_.begin();
389                it != stateLeaveRequests_.end(); ++it)
390            {
391                (*it)->left();
392                // just to be sure that the state actually is registered
393                assert(statesByName_.find((*it)->getName()) != statesByName_.end());
394
395                activeStates_.erase((*it)->getPriority());
396                if ((*it)->getPriority() < InputStatePriority::HighPriority)
397                    (*it)->setPriority(0);
398                updateActiveStates();
399            }
400            stateLeaveRequests_.clear();
401        }
402
403        // check for states to enter
404        if (!stateEnterRequests_.empty())
405        {
406            for (std::set<InputState*>::const_iterator it = stateEnterRequests_.begin();
407                it != stateEnterRequests_.end(); ++it)
408            {
409                // just to be sure that the state actually is registered
410                assert(statesByName_.find((*it)->getName()) != statesByName_.end());
411
412                if ((*it)->getPriority() == 0)
413                {
414                    // Get smallest possible priority between 1 and maxStateStackSize_s
415                    for(std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin();
416                        rit != activeStates_.rend(); ++rit)
417                    {
418                        if (rit->first < InputStatePriority::HighPriority)
419                        {
420                            (*it)->setPriority(rit->first + 1);
421                            break;
422                        }
423                    }
424                    // In case no normal handler was on the stack
425                    if ((*it)->getPriority() == 0)
426                        (*it)->setPriority(1);
427                }
428                activeStates_[(*it)->getPriority()] = (*it);
429                updateActiveStates();
430                (*it)->entered();
431            }
432            stateEnterRequests_.clear();
433        }
434
435        // check for states to destroy
436        if (!stateDestroyRequests_.empty())
437        {
438            for (std::set<InputState*>::iterator it = stateDestroyRequests_.begin();
439                it != stateDestroyRequests_.end(); ++it)
440            {
441                destroyStateInternal((*it));
442            }
443            stateDestroyRequests_.clear();
444        }
445
446        // check whether a state has changed its EMPTY situation
447        bool bUpdateRequired = false;
448        for (std::map<int, InputState*>::iterator it = activeStates_.begin(); it != activeStates_.end(); ++it)
449        {
450            if (it->second->hasExpired())
451            {
452                it->second->resetExpiration();
453                bUpdateRequired = true;
454            }
455        }
456        if (bUpdateRequired)
457            updateActiveStates();
458
459        // mark that we now start capturing and distributing input
460        internalState_ |= Ticking;
461
462        // Capture all the input and handle it
463        BOOST_FOREACH(InputDevice* device, devices_)
464            if (device != NULL)
465                device->update(time);
466
467        // Update the states
468        for (unsigned int i = 0; i < activeStatesTicked_.size(); ++i)
469            activeStatesTicked_[i]->update(time.getDeltaTime());
470
471        internalState_ &= ~Ticking;
472    }
473
474    /**
475    @brief
476        Updates the currently active states (according to activeStates_) for each device.
477        Also, a list of all active states (no duplicates!) is compiled for the general update().
478    */
479    void InputManager::updateActiveStates()
480    {
481        assert((internalState_ & InputManager::Ticking) == 0);
482        // temporary resize
483        for (unsigned int i = 0; i < devices_.size(); ++i)
484        {
485            if (devices_[i] == NULL)
486                continue;
487            std::vector<InputState*>& states = devices_[i]->getStateListRef();
488            bool occupied = false;
489            states.clear();
490            for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin(); rit != activeStates_.rend(); ++rit)
491            {
492                if (rit->second->isInputDeviceEnabled(i) && (!occupied || rit->second->bAlwaysGetsInput_))
493                {
494                    states.push_back(rit->second);
495                    if (!rit->second->bTransparent_)
496                        occupied = true;
497                }
498            }
499        }
500
501        // update tickables (every state will only appear once)
502        // Using a std::set to avoid duplicates
503        std::set<InputState*> tempSet;
504        for (unsigned int i = 0; i < devices_.size(); ++i)
505            if (devices_[i] != NULL)
506                for (unsigned int iState = 0; iState < devices_[i]->getStateListRef().size(); ++iState)
507                    tempSet.insert(devices_[i]->getStateListRef()[iState]);
508
509        // copy the content of the std::set back to the actual vector
510        activeStatesTicked_.clear();
511        for (std::set<InputState*>::const_iterator it = tempSet.begin();it != tempSet.end(); ++it)
512            activeStatesTicked_.push_back(*it);
513
514        // Check whether we have to change the mouse mode
515        std::vector<InputState*>& mouseStates = devices_[InputDeviceEnumerator::Mouse]->getStateListRef();
516        if (mouseStates.empty() && bExclusiveMouse_ ||
517            !mouseStates.empty() && mouseStates.front()->getIsExclusiveMouse() != bExclusiveMouse_)
518        {
519            bExclusiveMouse_ = !bExclusiveMouse_;
520            if (!GraphicsManager::getInstance().isFullScreen())
521                this->reloadInternal();
522        }
523    }
524
525    void InputManager::clearBuffers()
526    {
527        BOOST_FOREACH(InputDevice* device, devices_)
528            if (device != NULL)
529                device->clearBuffers();
530    }
531
532    void InputManager::calibrate()
533    {
534        COUT(0) << "Move all joy stick axes fully in all directions." << std::endl
535                << "When done, put the axex in the middle position and press enter." << std::endl;
536
537        BOOST_FOREACH(InputDevice* device, devices_)
538            if (device != NULL)
539                device->startCalibration();
540
541        internalState_ |= Calibrating;
542        enterState("calibrator");
543    }
544
545    //! Tells all devices to stop the calibration and evaluate it. Buffers are being cleared as well!
546    void InputManager::stopCalibration()
547    {
548        BOOST_FOREACH(InputDevice* device, devices_)
549            if (device != NULL)
550                device->stopCalibration();
551
552        // restore old input state
553        leaveState("calibrator");
554        internalState_ &= ~Calibrating;
555        // Clear buffers to prevent button hold events
556        this->clearBuffers();
557
558        COUT(0) << "Calibration has been stored." << std::endl;
559    }
560
561    //! Gets called by WindowEventListener upon focus change --> clear buffers
562    void InputManager::windowFocusChanged()
563    {
564        this->clearBuffers();
565    }
566
567    std::pair<int, int> InputManager::getMousePosition() const
568    {
569        Mouse* mouse = static_cast<Mouse*>(devices_[InputDeviceEnumerator::Mouse]);
570        if (mouse != NULL)
571        {
572            const OIS::MouseState state = mouse->getOISDevice()->getMouseState();
573            return std::make_pair(state.X.abs, state.Y.abs);
574        }
575        else
576            return std::make_pair(0, 0);
577    }
578
579    // ############################################################
580    // #####                    Input States                  #####
581    // ##########                                        ##########
582    // ############################################################
583
584    InputState* InputManager::createInputState(const std::string& name, bool bAlwaysGetsInput, bool bTransparent, InputStatePriority priority)
585    {
586        if (name == "")
587            return 0;
588        if (statesByName_.find(name) == statesByName_.end())
589        {
590            if (priority >= InputStatePriority::HighPriority || priority == InputStatePriority::Empty)
591            {
592                // Make sure we don't add two high priority states with the same priority
593                for (std::map<std::string, InputState*>::const_iterator it = this->statesByName_.begin();
594                    it != this->statesByName_.end(); ++it)
595                {
596                    if (it->second->getPriority() == priority)
597                    {
598                        COUT(2) << "Warning: Could not add an InputState with the same priority '"
599                            << static_cast<int>(priority) << "' != 0." << std::endl;
600                        return 0;
601                    }
602                }
603            }
604            InputState* state = new InputState(name, bAlwaysGetsInput, bTransparent, priority);
605            statesByName_[name] = state;
606
607            return state;
608        }
609        else
610        {
611            COUT(2) << "Warning: Could not add an InputState with the same name '" << name << "'." << std::endl;
612            return 0;
613        }
614    }
615
616    InputState* InputManager::getState(const std::string& name)
617    {
618        std::map<std::string, InputState*>::iterator it = statesByName_.find(name);
619        if (it != statesByName_.end())
620            return it->second;
621        else
622            return 0;
623    }
624
625    bool InputManager::enterState(const std::string& name)
626    {
627        // get pointer from the map with all stored handlers
628        std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name);
629        if (it != statesByName_.end())
630        {
631            // exists
632            if (activeStates_.find(it->second->getPriority()) == activeStates_.end())
633            {
634                // not active
635                if (stateDestroyRequests_.find(it->second) == stateDestroyRequests_.end())
636                {
637                    // not scheduled for destruction
638                    // prevents a state being added multiple times
639                    stateEnterRequests_.insert(it->second);
640                    return true;
641                }
642            }
643        }
644        return false;
645    }
646
647    bool InputManager::leaveState(const std::string& name)
648    {
649        if (name == "empty")
650        {
651            COUT(2) << "InputManager: Leaving the empty state is not allowed!" << std::endl;
652            return false;
653        }
654        // get pointer from the map with all stored handlers
655        std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name);
656        if (it != statesByName_.end())
657        {
658            // exists
659            if (activeStates_.find(it->second->getPriority()) != activeStates_.end())
660            {
661                // active
662                stateLeaveRequests_.insert(it->second);
663                return true;
664            }
665        }
666        return false;
667    }
668
669    bool InputManager::destroyState(const std::string& name)
670    {
671        if (name == "empty")
672        {
673            COUT(2) << "InputManager: Removing the empty state is not allowed!" << std::endl;
674            return false;
675        }
676        std::map<std::string, InputState*>::iterator it = statesByName_.find(name);
677        if (it != statesByName_.end())
678        {
679            if (activeStates_.find(it->second->getPriority()) != activeStates_.end())
680            {
681                // The state is still active. We have to postpone
682                stateLeaveRequests_.insert(it->second);
683                stateDestroyRequests_.insert(it->second);
684            }
685            else if (this->internalState_ & Ticking)
686            {
687                // cannot remove state while ticking
688                stateDestroyRequests_.insert(it->second);
689            }
690            else
691                destroyStateInternal(it->second);
692
693            return true;
694        }
695        return false;
696    }
697
698    //! Destroys an InputState internally.
699    void InputManager::destroyStateInternal(InputState* state)
700    {
701        assert(state && !(this->internalState_ & Ticking));
702        std::map<int, InputState*>::iterator it = this->activeStates_.find(state->getPriority());
703        if (it != this->activeStates_.end())
704        {
705            this->activeStates_.erase(it);
706            updateActiveStates();
707        }
708        statesByName_.erase(state->getName());
709        state->destroy();
710    }
711}
Note: See TracBrowser for help on using the repository browser.