Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/testing/src/libraries/core/input/InputManager.cc @ 9524

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

fixed build on linux

  • 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        {
[9524]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.