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, 10 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.