Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/input/InputManager.cc @ 7401

Last change on this file since 7401 was 7401, checked in by landauf, 14 years ago

merged doc branch back to trunk

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