Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core7/src/libraries/core/input/InputManager.cc @ 10464

Last change on this file since 10464 was 10380, checked in by landauf, 9 years ago

registered missing classes.
WorldEntityCollisionShape is the only class which was really missing, all other classes are singletons or part of the framework.

  • Property svn:eol-style set to native
File size: 24.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>
[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"
[5695]48#include "core/GraphicsManager.h"
[9667]49#include "core/config/ConfigValueIncludes.h"
[10345]50#include "core/commandline/CommandLineIncludes.h"
[10347]51#include "core/command/ConsoleCommandIncludes.h"
[7284]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
[10380]88    RegisterAbstractClass(InputManager).inheritsFrom<WindowEventListener>();
89
[1755]90    // ############################################################
91    // #####                  Initialisation                  #####
92    // ##########                                        ##########
93    // ############################################################
[5695]94    InputManager::InputManager()
[3327]95        : internalState_(Bad)
96        , oisInputManager_(0)
97        , devices_(2)
[8729]98        , exclusiveMouse_(false)
[3327]99        , emptyState_(0)
100        , calibratorCallbackHandler_(0)
[918]101    {
[9667]102        RegisterObject(InputManager);
[1219]103
[8858]104        orxout(internal_status, context::input) << "InputManager: Constructing..." << endl;
[3327]105
[6746]106        // Allocate space for the function call buffer
107        this->callBuffer_.reserve(16);
108
[3327]109        this->setConfigValues();
110
[5929]111        if (GraphicsManager::getInstance().isFullScreen())
[8729]112            exclusiveMouse_ = true;
[5695]113        this->loadDevices();
[3327]114
115        // Lowest priority empty InputState
116        emptyState_ = createInputState("empty", false, false, InputStatePriority::Empty);
117        emptyState_->setHandler(&InputHandler::EMPTY);
118        activeStates_[emptyState_->getPriority()] = emptyState_;
119
120        // Joy stick calibration helper callback
121        InputState* calibrator = createInputState("calibrator", false, false, InputStatePriority::Calibrator);
122        calibrator->setHandler(&InputHandler::EMPTY);
123        calibratorCallbackHandler_ = new InputBuffer();
124        calibratorCallbackHandler_->registerListener(this, &InputManager::stopCalibration, '\r', true);
125        calibrator->setKeyHandler(calibratorCallbackHandler_);
126
127        this->updateActiveStates();
128
[7284]129        ModifyConsoleCommand(__CC_InputManager_name, __CC_calibrate_name).setObject(this);
130        ModifyConsoleCommand(__CC_InputManager_name, __CC_reload_name).setObject(this);
[3327]131
[8858]132        orxout(internal_status, context::input) << "InputManager: Construction complete." << endl;
[3327]133        internalState_ = Nothing;
[1755]134    }
[918]135
[2662]136    void InputManager::setConfigValues()
137    {
138    }
139
140    /**
141    @brief
[1755]142        Creates the OIS::InputMananger, the keyboard, the mouse and
[3327]143        the joys ticks. If either of the first two fail, this method throws an exception.
[1755]144    */
[5695]145    void InputManager::loadDevices()
[1755]146    {
[8858]147        orxout(verbose, context::input) << "InputManager: Loading input devices..." << endl;
[1755]148
[3327]149        // When loading the devices they should not already be loaded
150        assert(internalState_ & Bad);
151        assert(devices_[InputDeviceEnumerator::Mouse] == 0);
152        assert(devices_[InputDeviceEnumerator::Keyboard] == 0);
153        assert(devices_.size() == InputDeviceEnumerator::FirstJoyStick);
[1755]154
[8351]155        typedef std::pair<std::string, std::string> StringPair;
156
[5695]157        // Fill parameter list
[3327]158        OIS::ParamList paramList;
[5695]159        size_t windowHnd = GraphicsManager::getInstance().getRenderWindowHandle();
[8351]160        paramList.insert(StringPair("WINDOW", multi_cast<std::string>(windowHnd)));
[3280]161#if defined(ORXONOX_PLATFORM_WINDOWS)
[8351]162        paramList.insert(StringPair("w32_keyboard", "DISCL_NONEXCLUSIVE"));
163        paramList.insert(StringPair("w32_keyboard", "DISCL_FOREGROUND"));
164        paramList.insert(StringPair("w32_mouse", "DISCL_FOREGROUND"));
[8729]165        if (exclusiveMouse_ || GraphicsManager::getInstance().isFullScreen())
[5695]166        {
167            // Disable Windows key plus special keys (like play, stop, next, etc.)
[8351]168            paramList.insert(StringPair("w32_keyboard", "DISCL_NOWINKEY"));
169            paramList.insert(StringPair("w32_mouse", "DISCL_EXCLUSIVE"));
[5695]170        }
171        else
[8351]172            paramList.insert(StringPair("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...
[8351]176        paramList.insert(StringPair("XAutoRepeatOn", "true"));
[5695]177
[8729]178        if (exclusiveMouse_ || GraphicsManager::getInstance().isFullScreen())
[5695]179        {
[9550]180            if (CommandLineParser::getValue("keyboard_no_grab").get<bool>())
[8351]181                paramList.insert(StringPair("x11_keyboard_grab", "false"));
[5695]182            else
[8351]183                paramList.insert(StringPair("x11_keyboard_grab", "true"));
184            paramList.insert(StringPair("x11_mouse_grab",  "true"));
185            paramList.insert(StringPair("x11_mouse_hide", "true"));
[5695]186        }
[3327]187        else
[5695]188        {
[8351]189            paramList.insert(StringPair("x11_keyboard_grab", "false"));
190            paramList.insert(StringPair("x11_mouse_grab",  "false"));
191            paramList.insert(StringPair("x11_mouse_hide", "false"));
[5695]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_);
[8858]200            orxout(verbose, context::input) << "Created OIS input manager." << 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
[8858]223        orxout(verbose, context::input) << "Input devices loaded." << 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            {
[8858]237                orxout(user_warning, context::input) << "Failed to create Mouse:" << ex.what() << '\n'
238                                                     << "Proceeding without mouse support." << endl;
[1755]239            }
[1219]240        }
[3327]241        else
[8858]242            orxout(user_warning, context::input) << "No mouse found! Proceeding without mouse support." << 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            {
[8858]256                orxout(user_warning, context::input) << "Failed to create joy stick: " << ex.what() << 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    {
[8858]274        orxout(internal_status, context::input) << "InputManager: Destroying..." << 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
[9667]284        delete calibratorCallbackHandler_;
[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
[7284]295        // Reset console commands
296        ModifyConsoleCommand(__CC_InputManager_name, __CC_calibrate_name).setObject(0);
297        ModifyConsoleCommand(__CC_InputManager_name, __CC_reload_name).setObject(0);
298
[8858]299        orxout(internal_status, context::input) << "InputManager: Destruction complete." << 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    {
[8858]310        orxout(verbose, context::input) << "InputManager: Destroying devices..." << 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;
[8858]319            orxout(verbose, context::input) << className << " destroyed." << 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        {
[8858]330            orxout(internal_error, context::input) << "OIS::InputManager destruction failed" << ex.eText << '\n'
331                                                   << "Potential resource leak!" << endl;
[3280]332        }
[3327]333        oisInputManager_ = NULL;
[1219]334
[3327]335        internalState_ |= Bad;
[8858]336        orxout(verbose, context::input) << "Destroyed devices." << 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)
[8858]347            orxout(internal_warning, context::input) << "Cannot reload input system. Joy sticks are currently being calibrated." << 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    {
[8858]355        orxout(verbose, context::input) << "InputManager: Reloading ..." << endl;
[1502]356
[3327]357        this->destroyDevices();
[5695]358        this->loadDevices();
[1502]359
[3327]360        internalState_ &= ~Bad;
[8858]361        orxout(verbose, context::input) << "InputManager: Reloading complete." << 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
[8729]451        tribool requestedMode = dontcare;
[5695]452        std::vector<InputState*>& mouseStates = devices_[InputDeviceEnumerator::Mouse]->getStateListRef();
[5929]453        if (mouseStates.empty())
[8729]454            requestedMode = false;
[6417]455        else
[6746]456            requestedMode = mouseStates.front()->getMouseExclusive();
[8729]457        if (requestedMode != dontcare && exclusiveMouse_ != requestedMode)
[5695]458        {
[8729]459            assert(requestedMode != dontcare);
460            exclusiveMouse_ = (requestedMode == true);
[5695]461            if (!GraphicsManager::getInstance().isFullScreen())
462                this->reloadInternal();
463        }
[1755]464    }
[1219]465
[1878]466    void InputManager::clearBuffers()
467    {
[3327]468        BOOST_FOREACH(InputDevice* device, devices_)
469            if (device != NULL)
470                device->clearBuffers();
[1878]471    }
[1502]472
[3327]473    void InputManager::calibrate()
[1219]474    {
[8858]475        orxout(message) << "Move all joy stick axes fully in all directions." << '\n'
476                        << "When done, put the axex in the middle position and press enter." << endl;
[1219]477
[3327]478        BOOST_FOREACH(InputDevice* device, devices_)
479            if (device != NULL)
480                device->startCalibration();
[1219]481
[3327]482        internalState_ |= Calibrating;
483        enterState("calibrator");
[1349]484    }
[1755]485
[3327]486    //! Tells all devices to stop the calibration and evaluate it. Buffers are being cleared as well!
487    void InputManager::stopCalibration()
[1349]488    {
[3327]489        BOOST_FOREACH(InputDevice* device, devices_)
490            if (device != NULL)
491                device->stopCalibration();
[1502]492
[3327]493        // restore old input state
494        leaveState("calibrator");
495        internalState_ &= ~Calibrating;
496        // Clear buffers to prevent button hold events
497        this->clearBuffers();
[1293]498
[8858]499        orxout(message) << "Calibration has been stored." << endl;
[1755]500    }
[1502]501
[6417]502    //! Gets called by WindowEventListener upon focus change --> clear buffers
[7874]503    void InputManager::windowFocusChanged(bool bFocus)
[1755]504    {
[3327]505        this->clearBuffers();
[1755]506    }
[1502]507
[5695]508    std::pair<int, int> InputManager::getMousePosition() const
509    {
510        Mouse* mouse = static_cast<Mouse*>(devices_[InputDeviceEnumerator::Mouse]);
511        if (mouse != NULL)
512        {
513            const OIS::MouseState state = mouse->getOISDevice()->getMouseState();
514            return std::make_pair(state.X.abs, state.Y.abs);
515        }
516        else
517            return std::make_pair(0, 0);
518    }
519
[1755]520    // ############################################################
[5695]521    // #####                    Input States                  #####
[1755]522    // ##########                                        ##########
523    // ############################################################
[1219]524
[3327]525    InputState* InputManager::createInputState(const std::string& name, bool bAlwaysGetsInput, bool bTransparent, InputStatePriority priority)
[1219]526    {
[6417]527        if (name.empty())
[3327]528            return 0;
529        if (statesByName_.find(name) == statesByName_.end())
[1755]530        {
[2896]531            if (priority >= InputStatePriority::HighPriority || priority == InputStatePriority::Empty)
[1755]532            {
[2896]533                // Make sure we don't add two high priority states with the same priority
[3327]534                for (std::map<std::string, InputState*>::const_iterator it = this->statesByName_.begin();
535                    it != this->statesByName_.end(); ++it)
[2896]536                {
537                    if (it->second->getPriority() == priority)
538                    {
[8858]539                        orxout(internal_warning, context::input) << "Could not add an InputState with the same priority '"
540                            << static_cast<int>(priority) << "' != 0." << endl;
[3327]541                        return 0;
[2896]542                    }
543                }
544            }
[3327]545            InputState* state = new InputState(name, bAlwaysGetsInput, bTransparent, priority);
546            statesByName_[name] = state;
547
548            return state;
[1755]549        }
550        else
551        {
[8858]552            orxout(internal_warning, context::input) << "Could not add an InputState with the same name '" << name << "'." << endl;
[3327]553            return 0;
[1755]554        }
[1219]555    }
556
[1755]557    InputState* InputManager::getState(const std::string& name)
[1219]558    {
[3327]559        std::map<std::string, InputState*>::iterator it = statesByName_.find(name);
560        if (it != statesByName_.end())
[1755]561            return it->second;
562        else
563            return 0;
[1219]564    }
565
[3327]566    bool InputManager::enterState(const std::string& name)
[1219]567    {
[1755]568        // get pointer from the map with all stored handlers
[3327]569        std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name);
[6746]570        if (it != statesByName_.end() && activeStates_.find(it->second->getPriority()) == activeStates_.end())
[1755]571        {
[6746]572            // exists and not active
573            if (it->second->getPriority() == 0)
[1755]574            {
[6746]575                // Get smallest possible priority between 1 and maxStateStackSize_s
576                for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin();
577                    rit != activeStates_.rend(); ++rit)
[1755]578                {
[6746]579                    if (rit->first < InputStatePriority::HighPriority)
580                    {
581                        it->second->setPriority(rit->first + 1);
582                        break;
583                    }
[1755]584                }
[6746]585                // In case no normal handler was on the stack
586                if (it->second->getPriority() == 0)
587                    it->second->setPriority(1);
[1755]588            }
[6746]589            activeStates_[it->second->getPriority()] = it->second;
590            updateActiveStates();
591            it->second->entered();
592
593            return true;
[1755]594        }
595        return false;
[1219]596    }
597
[3327]598    bool InputManager::leaveState(const std::string& name)
[1219]599    {
[2896]600        if (name == "empty")
601        {
[8858]602            orxout(internal_warning, context::input) << "InputManager: Leaving the empty state is not allowed!" << endl;
[2896]603            return false;
604        }
[1755]605        // get pointer from the map with all stored handlers
[3327]606        std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name);
[6746]607        if (it != statesByName_.end() && activeStates_.find(it->second->getPriority()) != activeStates_.end())
[1755]608        {
[6746]609            // exists and active
610
611            it->second->left();
612
613            activeStates_.erase(it->second->getPriority());
614            if (it->second->getPriority() < InputStatePriority::HighPriority)
615                it->second->setPriority(0);
616            updateActiveStates();
617
618            return true;
[1755]619        }
620        return false;
[1219]621    }
622
[3327]623    bool InputManager::destroyState(const std::string& name)
[1219]624    {
[3327]625        if (name == "empty")
626        {
[8858]627            orxout(internal_warning, context::input) << "InputManager: Removing the empty state is not allowed!" << endl;
[3327]628            return false;
629        }
630        std::map<std::string, InputState*>::iterator it = statesByName_.find(name);
631        if (it != statesByName_.end())
632        {
[6746]633            this->leaveState(name);
634            destroyStateInternal(it->second);
[2662]635
[3327]636            return true;
637        }
638        return false;
[1219]639    }
640
[3327]641    //! Destroys an InputState internally.
642    void InputManager::destroyStateInternal(InputState* state)
[1219]643    {
[6746]644        assert(state && this->activeStates_.find(state->getPriority()) == this->activeStates_.end());
[3327]645        statesByName_.erase(state->getName());
[9667]646        delete state;
[1219]647    }
[8079]648
[8729]649    bool InputManager::setMouseExclusive(const std::string& name, tribool value)
[8079]650    {
651        if (name == "empty")
652        {
[8858]653            orxout(internal_warning, context::input) << "InputManager: Changing the empty state is not allowed!" << endl;
[8079]654            return false;
655        }
656        std::map<std::string, InputState*>::iterator it = statesByName_.find(name);
657        if (it != statesByName_.end())
658        {
659            it->second->setMouseExclusive(value);
660            return true;
661        }
662        return false;
663    }
[918]664}
Note: See TracBrowser for help on using the repository browser.