Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/consolecommands/src/libraries/core/input/InputManager.cc @ 6372

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

Added preUpdate and postUpdate methods for all classes inheriting Singleton. Replaced update() with preUpdate except for the GraphicsManager (postUpdate).
However this does not apply to the Client and Server singletons in the network library. We should think about putting them in a scope as well.

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