Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/archive/tutorialHS09/src/libraries/core/input/InputManager.cc

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

Added Exception::handleMessage() (copy from Game::getExceptionMessage) function that returns the exception message (if retrievable) when catching with "…"
and adjusted some exception handlers.

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