Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/consolecommands3/src/libraries/core/input/InputManager.cc @ 7236

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

replaced the temporary names of all ConsoleCommand related classes and functions by their real names

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