Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 9550 was 9550, checked in by landauf, 11 years ago

merged testing branch back to trunk. unbelievable it took me 13 months to finish this chore…

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