Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/resource/src/core/input/InputManager.cc @ 3458

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

Derived all singletons implemented in a usual manner from orxonox::Singleton<T>.
This resolves inconsistencies with the singletonPtr_s variable in case of exceptions (asserts were being triggered then).
And while at it replaced singletonRef_s with singletonPtr_s for it to be less misleading (as fabian has already pointed out).

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