Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/gamestates2/src/libraries/core/input/InputManager.cc @ 6662

Last change on this file since 6662 was 6662, checked in by rgrieder, 14 years ago

Merged revisions 6621-6661 to gamestates2.

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