Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/wiimote/src/libraries/core/input/InputManager.cc @ 9856

Last change on this file since 9856 was 9856, checked in by georgr, 10 years ago

still trying to get quicker reaction to button presses

  • Property svn:eol-style set to native
File size: 26.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"
50#include "core/config/CommandLineParser.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
[9723]60#include "WiiMote.h"
61
[9790]62
[918]63namespace orxonox
64{
[3280]65    SetCommandLineSwitch(keyboard_no_grab).information("Whether not to exclusively grab the keyboard");
[1502]66
[7284]67    static const std::string __CC_InputManager_name = "InputManager";
68    static const std::string __CC_calibrate_name = "calibrate";
69    static const std::string __CC_reload_name = "reload";
70
71    SetConsoleCommand(__CC_InputManager_name, __CC_calibrate_name, &InputManager::calibrate).addShortcut();
72    SetConsoleCommand(__CC_InputManager_name, __CC_reload_name,    &InputManager::reload   );
73
[3327]74    // Abuse of this source file for the InputHandler
75    InputHandler InputHandler::EMPTY;
76
[3370]77    InputManager* InputManager::singletonPtr_s = 0;
[1084]78
[3327]79    //! Defines the |= operator for easier use.
80    inline InputManager::State operator|=(InputManager::State& lval, InputManager::State rval)
[1755]81    {
[3327]82        return (lval = (InputManager::State)(lval | rval));
[1755]83    }
[919]84
[3327]85    //! Defines the &= operator for easier use.
86    inline InputManager::State operator&=(InputManager::State& lval, int rval)
[1755]87    {
[3327]88        return (lval = (InputManager::State)(lval & rval));
[1755]89    }
[1219]90
[1755]91    // ############################################################
92    // #####                  Initialisation                  #####
93    // ##########                                        ##########
94    // ############################################################
[5695]95    InputManager::InputManager()
[3327]96        : internalState_(Bad)
97        , oisInputManager_(0)
98        , devices_(2)
[8729]99        , exclusiveMouse_(false)
[3327]100        , emptyState_(0)
101        , calibratorCallbackHandler_(0)
[918]102    {
[9667]103        RegisterObject(InputManager);
[1219]104
[8858]105        orxout(internal_status, context::input) << "InputManager: Constructing..." << endl;
[3327]106
[6746]107        // Allocate space for the function call buffer
108        this->callBuffer_.reserve(16);
109
[3327]110        this->setConfigValues();
111
[5929]112        if (GraphicsManager::getInstance().isFullScreen())
[8729]113            exclusiveMouse_ = true;
[5695]114        this->loadDevices();
[3327]115
116        // Lowest priority empty InputState
117        emptyState_ = createInputState("empty", false, false, InputStatePriority::Empty);
118        emptyState_->setHandler(&InputHandler::EMPTY);
119        activeStates_[emptyState_->getPriority()] = emptyState_;
120
121        // Joy stick calibration helper callback
122        InputState* calibrator = createInputState("calibrator", false, false, InputStatePriority::Calibrator);
123        calibrator->setHandler(&InputHandler::EMPTY);
124        calibratorCallbackHandler_ = new InputBuffer();
125        calibratorCallbackHandler_->registerListener(this, &InputManager::stopCalibration, '\r', true);
126        calibrator->setKeyHandler(calibratorCallbackHandler_);
127
128        this->updateActiveStates();
129
[7284]130        ModifyConsoleCommand(__CC_InputManager_name, __CC_calibrate_name).setObject(this);
131        ModifyConsoleCommand(__CC_InputManager_name, __CC_reload_name).setObject(this);
[3327]132
[8858]133        orxout(internal_status, context::input) << "InputManager: Construction complete." << endl;
[3327]134        internalState_ = Nothing;
[1755]135    }
[918]136
[2662]137    void InputManager::setConfigValues()
138    {
139    }
140
141    /**
142    @brief
[1755]143        Creates the OIS::InputMananger, the keyboard, the mouse and
[3327]144        the joys ticks. If either of the first two fail, this method throws an exception.
[1755]145    */
[5695]146    void InputManager::loadDevices()
[1755]147    {
[8858]148        orxout(verbose, context::input) << "InputManager: Loading input devices..." << endl;
[1755]149
[3327]150        // When loading the devices they should not already be loaded
151        assert(internalState_ & Bad);
152        assert(devices_[InputDeviceEnumerator::Mouse] == 0);
153        assert(devices_[InputDeviceEnumerator::Keyboard] == 0);
154        assert(devices_.size() == InputDeviceEnumerator::FirstJoyStick);
[1755]155
[8351]156        typedef std::pair<std::string, std::string> StringPair;
157
[5695]158        // Fill parameter list
[3327]159        OIS::ParamList paramList;
[5695]160        size_t windowHnd = GraphicsManager::getInstance().getRenderWindowHandle();
[8351]161        paramList.insert(StringPair("WINDOW", multi_cast<std::string>(windowHnd)));
[3280]162#if defined(ORXONOX_PLATFORM_WINDOWS)
[8351]163        paramList.insert(StringPair("w32_keyboard", "DISCL_NONEXCLUSIVE"));
164        paramList.insert(StringPair("w32_keyboard", "DISCL_FOREGROUND"));
165        paramList.insert(StringPair("w32_mouse", "DISCL_FOREGROUND"));
[8729]166        if (exclusiveMouse_ || GraphicsManager::getInstance().isFullScreen())
[5695]167        {
168            // Disable Windows key plus special keys (like play, stop, next, etc.)
[8351]169            paramList.insert(StringPair("w32_keyboard", "DISCL_NOWINKEY"));
170            paramList.insert(StringPair("w32_mouse", "DISCL_EXCLUSIVE"));
[5695]171        }
172        else
[8351]173            paramList.insert(StringPair("w32_mouse", "DISCL_NONEXCLUSIVE"));
[3280]174#elif defined(ORXONOX_PLATFORM_LINUX)
[5695]175        // Enabling this is probably a bad idea, but whenever orxonox crashes, the setting stays on
176        // Trouble might be that the Pressed event occurs a bit too often...
[8351]177        paramList.insert(StringPair("XAutoRepeatOn", "true"));
[5695]178
[8729]179        if (exclusiveMouse_ || GraphicsManager::getInstance().isFullScreen())
[5695]180        {
[9550]181            if (CommandLineParser::getValue("keyboard_no_grab").get<bool>())
[8351]182                paramList.insert(StringPair("x11_keyboard_grab", "false"));
[5695]183            else
[8351]184                paramList.insert(StringPair("x11_keyboard_grab", "true"));
185            paramList.insert(StringPair("x11_mouse_grab",  "true"));
186            paramList.insert(StringPair("x11_mouse_hide", "true"));
[5695]187        }
[3327]188        else
[5695]189        {
[8351]190            paramList.insert(StringPair("x11_keyboard_grab", "false"));
191            paramList.insert(StringPair("x11_mouse_grab",  "false"));
192            paramList.insert(StringPair("x11_mouse_hide", "false"));
[5695]193        }
[1735]194#endif
[928]195
[3327]196        try
197        {
198            oisInputManager_ = OIS::InputManager::createInputSystem(paramList);
199            // Exception-safety
200            Loki::ScopeGuard guard = Loki::MakeGuard(OIS::InputManager::destroyInputSystem, oisInputManager_);
[8858]201            orxout(verbose, context::input) << "Created OIS input manager." << endl;
[1219]202
[3327]203            if (oisInputManager_->getNumberOfDevices(OIS::OISKeyboard) > 0)
204                devices_[InputDeviceEnumerator::Keyboard] = new Keyboard(InputDeviceEnumerator::Keyboard, oisInputManager_);
205            else
206                ThrowException(InitialisationFailed, "InputManager: No keyboard found, cannot proceed!");
[1219]207
[3327]208            // Successful initialisation
209            guard.Dismiss();
[1755]210        }
[3331]211        catch (const std::exception& ex)
[1755]212        {
[3327]213            oisInputManager_ = NULL;
214            internalState_ |= Bad;
215            ThrowException(InitialisationFailed, "Could not initialise the input system: " << ex.what());
[1755]216        }
[1502]217
[3327]218        this->loadMouse();
219        this->loadJoySticks();
[9790]220        this->loadWiiMote();
[3327]221        // Reorder states in case some joy sticks were added/removed
222        this->updateActiveStates();
[9790]223
[8858]224        orxout(verbose, context::input) << "Input devices loaded." << endl;
[1219]225    }
[9790]226
[9723]227    void InputManager::loadWiiMote()
228    {
[9790]229
[9840]230
231
232        static CWii wii; // Defaults to 4 remotes; static because else it will get deleted during InternalReload
[9790]233        std::vector< ::CWiimote>::iterator i;
234        int reloadWiimotes = 0;
235        int index;
236
237        // Find and connect to the wiimotes
[9840]238        static std::vector<CWiimote>& wiimotes = wii.FindAndConnect(10); //CWiimotes are kept in here in case of InternalReload calls
[9790]239        if (!wiimotes.size())
[9723]240        {
[9790]241                cout << "No wiimotes found." << endl;
[9813]242                return;
[9790]243                }
244
245            // Setup the wiimotes
246            for(index = 0, i = wiimotes.begin(); i != wiimotes.end(); ++i, ++index)
247            {
248                // Use a reference to make working with the iterator handy.
249            CWiimote & wiimote = *i;
250
251            //Set Leds
252            int LED_MAP[4] =
253              {CWiimote::LED_1, CWiimote::LED_2,
254               CWiimote::LED_3, CWiimote::LED_4};
255            wiimote.SetLEDs(LED_MAP[index]);
[9816]256            try
257                       {
258                         orxout()<< "Size of devices vector before wiimote insertion:" << devices_.size() << std::endl;
[9838]259                         devices_.push_back(new WiiMote((unsigned int)devices_.size(), *i, wii));
[9816]260                         //devices_[2] = new WiiMote(devices_.size(), *(new CWiimote()));
261                         orxout()<< "Size of devices vector after wiimote insertion:" << devices_.size() << std::endl;
[9856]262                         wiimote.SetMotionSensingMode(CWiimote::ON);
[9790]263
[9816]264                       }
265                       catch(std::exception& e)  //gotta catch em all
266                       {
267                         orxout()<<"Exception loading WiiMote!!!1!11!";
268                       }
[9790]269
[9816]270
[9819]271
[9723]272        }
[9790]273
274
[9723]275    }
[3327]276    //! Creates a new orxonox::Mouse
277    void InputManager::loadMouse()
[1219]278    {
[3327]279        if (oisInputManager_->getNumberOfDevices(OIS::OISMouse) > 0)
[1755]280        {
[3327]281            try
[1755]282            {
[3327]283                devices_[InputDeviceEnumerator::Mouse] = new Mouse(InputDeviceEnumerator::Mouse, oisInputManager_);
[1755]284            }
[3331]285            catch (const std::exception& ex)
[1755]286            {
[8858]287                orxout(user_warning, context::input) << "Failed to create Mouse:" << ex.what() << '\n'
288                                                     << "Proceeding without mouse support." << endl;
[1755]289            }
[1219]290        }
[3327]291        else
[8858]292            orxout(user_warning, context::input) << "No mouse found! Proceeding without mouse support." << endl;
[1219]293    }
[1755]294
[3327]295    //! Creates as many joy sticks as are available.
296    void InputManager::loadJoySticks()
[1219]297    {
[3327]298        for (int i = 0; i < oisInputManager_->getNumberOfDevices(OIS::OISJoyStick); i++)
[1755]299        {
[3327]300            try
[1755]301            {
[3327]302                devices_.push_back(new JoyStick(InputDeviceEnumerator::FirstJoyStick + i, oisInputManager_));
[1755]303            }
[3331]304            catch (const std::exception& ex)
[1755]305            {
[8858]306                orxout(user_warning, context::input) << "Failed to create joy stick: " << ex.what() << endl;
[1755]307            }
308        }
[1505]309
[1887]310        // inform all JoyStick Device Number Listeners
[3327]311        std::vector<JoyStick*> joyStickList;
312        for (unsigned int i = InputDeviceEnumerator::FirstJoyStick; i < devices_.size(); ++i)
313            joyStickList.push_back(static_cast<JoyStick*>(devices_[i]));
314        JoyStickQuantityListener::changeJoyStickQuantity(joyStickList);
[1505]315    }
[1502]316
[3327]317    // ############################################################
318    // #####                    Destruction                   #####
319    // ##########                                        ##########
320    // ############################################################
[1293]321
[3327]322    InputManager::~InputManager()
[2662]323    {
[8858]324        orxout(internal_status, context::input) << "InputManager: Destroying..." << endl;
[1219]325
[6746]326        // Leave all active InputStates (except "empty")
327        while (this->activeStates_.size() > 1)
328            this->leaveState(this->activeStates_.rbegin()->second->getName());
329        this->activeStates_.clear();
330
[3327]331        // Destroy calibrator helper handler and state
332        this->destroyState("calibrator");
333        // Destroy KeyDetector and state
[9667]334        delete calibratorCallbackHandler_;
[6746]335        // Destroy the empty InputState
[3327]336        this->destroyStateInternal(this->emptyState_);
[1502]337
[6746]338        // Destroy all user InputStates
[3327]339        while (statesByName_.size() > 0)
[6417]340            this->destroyStateInternal(statesByName_.rbegin()->second);
[2662]341
[3327]342        if (!(internalState_ & Bad))
343            this->destroyDevices();
[2662]344
[7284]345        // Reset console commands
346        ModifyConsoleCommand(__CC_InputManager_name, __CC_calibrate_name).setObject(0);
347        ModifyConsoleCommand(__CC_InputManager_name, __CC_reload_name).setObject(0);
348
[8858]349        orxout(internal_status, context::input) << "InputManager: Destruction complete." << endl;
[1219]350    }
[928]351
[1755]352    /**
353    @brief
[3327]354        Destoys all input devices (joy sticks, mouse, keyboard and OIS::InputManager)
355    @throw
356        Method does not throw
[1755]357    */
[3327]358    void InputManager::destroyDevices()
[1219]359    {
[8858]360        orxout(verbose, context::input) << "InputManager: Destroying devices..." << endl;
[3327]361
362        BOOST_FOREACH(InputDevice*& device, devices_)
[1755]363        {
[3327]364            if (device == NULL)
365                continue;
[6417]366            const std::string& className = device->getClassName();
[7174]367            delete device;
368            device = 0;
[8858]369            orxout(verbose, context::input) << className << " destroyed." << endl;
[1755]370        }
[3327]371        devices_.resize(InputDeviceEnumerator::FirstJoyStick);
[2662]372
[3327]373        assert(oisInputManager_ != NULL);
[3280]374        try
375        {
[3327]376            OIS::InputManager::destroyInputSystem(oisInputManager_);
[3280]377        }
[7174]378        catch (const OIS::Exception& ex)
[3280]379        {
[8858]380            orxout(internal_error, context::input) << "OIS::InputManager destruction failed" << ex.eText << '\n'
381                                                   << "Potential resource leak!" << endl;
[3280]382        }
[3327]383        oisInputManager_ = NULL;
[1219]384
[3327]385        internalState_ |= Bad;
[8858]386        orxout(verbose, context::input) << "Destroyed devices." << endl;
[1755]387    }
[1219]388
[1755]389    // ############################################################
390    // #####                     Reloading                    #####
391    // ##########                                        ##########
392    // ############################################################
[1219]393
[3327]394    void InputManager::reload()
[1755]395    {
[6746]396        if (internalState_ & Calibrating)
[8858]397            orxout(internal_warning, context::input) << "Cannot reload input system. Joy sticks are currently being calibrated." << endl;
[1502]398        else
[3327]399            reloadInternal();
[1755]400    }
[1502]401
[3327]402    //! Internal reload method. Destroys the OIS devices and loads them again.
403    void InputManager::reloadInternal()
[1755]404    {
[8858]405        orxout(verbose, context::input) << "InputManager: Reloading ..." << endl;
[1502]406
[3327]407        this->destroyDevices();
[5695]408        this->loadDevices();
[1502]409
[3327]410        internalState_ &= ~Bad;
[8858]411        orxout(verbose, context::input) << "InputManager: Reloading complete." << endl;
[1502]412    }
[1219]413
[1755]414    // ############################################################
415    // #####                  Runtime Methods                 #####
416    // ##########                                        ##########
417    // ############################################################
[1555]418
[6417]419    void InputManager::preUpdate(const Clock& time)
[1502]420    {
[3327]421        if (internalState_ & Bad)
422            ThrowException(General, "InputManager was not correctly reloaded.");
423
424        // check whether a state has changed its EMPTY situation
[1878]425        bool bUpdateRequired = false;
426        for (std::map<int, InputState*>::iterator it = activeStates_.begin(); it != activeStates_.end(); ++it)
427        {
[3327]428            if (it->second->hasExpired())
[1878]429            {
[3327]430                it->second->resetExpiration();
[1878]431                bUpdateRequired = true;
432            }
433        }
434        if (bUpdateRequired)
[3327]435            updateActiveStates();
[1878]436
[6746]437        // Capture all the input and collect the function calls
438        // No event gets triggered here yet!
[3327]439        BOOST_FOREACH(InputDevice* device, devices_)
440            if (device != NULL)
441                device->update(time);
[1219]442
[6746]443        // Collect function calls for the update
[3327]444        for (unsigned int i = 0; i < activeStatesTicked_.size(); ++i)
445            activeStatesTicked_[i]->update(time.getDeltaTime());
[2896]446
[6746]447        // Execute all cached function calls in order
448        // Why so complicated? The problem is that an InputHandler could trigger
449        // a reload that would destroy the OIS devices or it could even leave and
450        // then destroy its own InputState. That would of course lead to access
451        // violations.
452        // If we delay the calls, then OIS and and the InputStates are not anymore
453        // in the call stack and can therefore be edited.
454        for (size_t i = 0; i < this->callBuffer_.size(); ++i)
455            this->callBuffer_[i]();
456
457        this->callBuffer_.clear();
[1293]458    }
[1219]459
[1755]460    /**
461    @brief
462        Updates the currently active states (according to activeStates_) for each device.
[6417]463        Also, a list of all active states (no duplicates!) is compiled for the general preUpdate().
[1755]464    */
[3327]465    void InputManager::updateActiveStates()
[1293]466    {
[6746]467        // Calculate the stack of input states
468        // and assign it to the corresponding device
[3327]469        for (unsigned int i = 0; i < devices_.size(); ++i)
[2896]470        {
[3327]471            if (devices_[i] == NULL)
472                continue;
473            std::vector<InputState*>& states = devices_[i]->getStateListRef();
[2896]474            bool occupied = false;
[3327]475            states.clear();
[2896]476            for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin(); rit != activeStates_.rend(); ++rit)
477            {
[9790]478                orxout() << "Checking ID " << i <<std::endl;
479                orxout() << "Checking condition 1: " << rit->second->isInputDeviceEnabled(i) <<std::endl;
480                orxout() << "Checking condition 2: " << rit->second->bAlwaysGetsInput_ <<std::endl;
481                orxout() << "Checking condition 3: " << !occupied <<std::endl;
482                if (rit->second->isInputDeviceEnabled(i) && (!occupied || rit->second->bAlwaysGetsInput_))
[2896]483                {
[9805]484                    orxout() << "Success with ID " << i <<std::endl;
[3327]485                    states.push_back(rit->second);
[2896]486                    if (!rit->second->bTransparent_)
487                        occupied = true;
488                }
489            }
490        }
[1293]491
[6746]492        // See that we only update each InputState once for each device
493        // Using an std::set to avoid duplicates
[1755]494        std::set<InputState*> tempSet;
[3327]495        for (unsigned int i = 0; i < devices_.size(); ++i)
496            if (devices_[i] != NULL)
497                for (unsigned int iState = 0; iState < devices_[i]->getStateListRef().size(); ++iState)
498                    tempSet.insert(devices_[i]->getStateListRef()[iState]);
[1219]499
[6746]500        // Copy the content of the std::set back to the actual vector
[1755]501        activeStatesTicked_.clear();
502        for (std::set<InputState*>::const_iterator it = tempSet.begin();it != tempSet.end(); ++it)
503            activeStatesTicked_.push_back(*it);
[5695]504
505        // Check whether we have to change the mouse mode
[8729]506        tribool requestedMode = dontcare;
[5695]507        std::vector<InputState*>& mouseStates = devices_[InputDeviceEnumerator::Mouse]->getStateListRef();
[5929]508        if (mouseStates.empty())
[8729]509            requestedMode = false;
[6417]510        else
[6746]511            requestedMode = mouseStates.front()->getMouseExclusive();
[8729]512        if (requestedMode != dontcare && exclusiveMouse_ != requestedMode)
[5695]513        {
[8729]514            assert(requestedMode != dontcare);
515            exclusiveMouse_ = (requestedMode == true);
[5695]516            if (!GraphicsManager::getInstance().isFullScreen())
517                this->reloadInternal();
518        }
[1755]519    }
[1219]520
[1878]521    void InputManager::clearBuffers()
522    {
[3327]523        BOOST_FOREACH(InputDevice* device, devices_)
524            if (device != NULL)
525                device->clearBuffers();
[1878]526    }
[1502]527
[3327]528    void InputManager::calibrate()
[1219]529    {
[8858]530        orxout(message) << "Move all joy stick axes fully in all directions." << '\n'
531                        << "When done, put the axex in the middle position and press enter." << endl;
[1219]532
[3327]533        BOOST_FOREACH(InputDevice* device, devices_)
534            if (device != NULL)
535                device->startCalibration();
[1219]536
[3327]537        internalState_ |= Calibrating;
538        enterState("calibrator");
[1349]539    }
[1755]540
[3327]541    //! Tells all devices to stop the calibration and evaluate it. Buffers are being cleared as well!
542    void InputManager::stopCalibration()
[1349]543    {
[3327]544        BOOST_FOREACH(InputDevice* device, devices_)
545            if (device != NULL)
546                device->stopCalibration();
[1502]547
[3327]548        // restore old input state
549        leaveState("calibrator");
550        internalState_ &= ~Calibrating;
551        // Clear buffers to prevent button hold events
552        this->clearBuffers();
[1293]553
[8858]554        orxout(message) << "Calibration has been stored." << endl;
[1755]555    }
[1502]556
[6417]557    //! Gets called by WindowEventListener upon focus change --> clear buffers
[7874]558    void InputManager::windowFocusChanged(bool bFocus)
[1755]559    {
[3327]560        this->clearBuffers();
[1755]561    }
[1502]562
[5695]563    std::pair<int, int> InputManager::getMousePosition() const
564    {
565        Mouse* mouse = static_cast<Mouse*>(devices_[InputDeviceEnumerator::Mouse]);
566        if (mouse != NULL)
567        {
568            const OIS::MouseState state = mouse->getOISDevice()->getMouseState();
569            return std::make_pair(state.X.abs, state.Y.abs);
570        }
571        else
572            return std::make_pair(0, 0);
573    }
574
[1755]575    // ############################################################
[5695]576    // #####                    Input States                  #####
[1755]577    // ##########                                        ##########
578    // ############################################################
[1219]579
[3327]580    InputState* InputManager::createInputState(const std::string& name, bool bAlwaysGetsInput, bool bTransparent, InputStatePriority priority)
[1219]581    {
[6417]582        if (name.empty())
[3327]583            return 0;
584        if (statesByName_.find(name) == statesByName_.end())
[1755]585        {
[2896]586            if (priority >= InputStatePriority::HighPriority || priority == InputStatePriority::Empty)
[1755]587            {
[2896]588                // Make sure we don't add two high priority states with the same priority
[3327]589                for (std::map<std::string, InputState*>::const_iterator it = this->statesByName_.begin();
590                    it != this->statesByName_.end(); ++it)
[2896]591                {
592                    if (it->second->getPriority() == priority)
593                    {
[8858]594                        orxout(internal_warning, context::input) << "Could not add an InputState with the same priority '"
595                            << static_cast<int>(priority) << "' != 0." << endl;
[3327]596                        return 0;
[2896]597                    }
598                }
599            }
[3327]600            InputState* state = new InputState(name, bAlwaysGetsInput, bTransparent, priority);
601            statesByName_[name] = state;
602
603            return state;
[1755]604        }
605        else
606        {
[8858]607            orxout(internal_warning, context::input) << "Could not add an InputState with the same name '" << name << "'." << endl;
[3327]608            return 0;
[1755]609        }
[1219]610    }
611
[1755]612    InputState* InputManager::getState(const std::string& name)
[1219]613    {
[3327]614        std::map<std::string, InputState*>::iterator it = statesByName_.find(name);
615        if (it != statesByName_.end())
[1755]616            return it->second;
617        else
618            return 0;
[1219]619    }
620
[3327]621    bool InputManager::enterState(const std::string& name)
[1219]622    {
[1755]623        // get pointer from the map with all stored handlers
[3327]624        std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name);
[6746]625        if (it != statesByName_.end() && activeStates_.find(it->second->getPriority()) == activeStates_.end())
[1755]626        {
[6746]627            // exists and not active
628            if (it->second->getPriority() == 0)
[1755]629            {
[6746]630                // Get smallest possible priority between 1 and maxStateStackSize_s
631                for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin();
632                    rit != activeStates_.rend(); ++rit)
[1755]633                {
[6746]634                    if (rit->first < InputStatePriority::HighPriority)
635                    {
636                        it->second->setPriority(rit->first + 1);
637                        break;
638                    }
[1755]639                }
[6746]640                // In case no normal handler was on the stack
641                if (it->second->getPriority() == 0)
642                    it->second->setPriority(1);
[1755]643            }
[6746]644            activeStates_[it->second->getPriority()] = it->second;
645            updateActiveStates();
646            it->second->entered();
647
648            return true;
[1755]649        }
650        return false;
[1219]651    }
652
[3327]653    bool InputManager::leaveState(const std::string& name)
[1219]654    {
[2896]655        if (name == "empty")
656        {
[8858]657            orxout(internal_warning, context::input) << "InputManager: Leaving the empty state is not allowed!" << endl;
[2896]658            return false;
659        }
[1755]660        // get pointer from the map with all stored handlers
[3327]661        std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name);
[6746]662        if (it != statesByName_.end() && activeStates_.find(it->second->getPriority()) != activeStates_.end())
[1755]663        {
[6746]664            // exists and active
665
666            it->second->left();
667
668            activeStates_.erase(it->second->getPriority());
669            if (it->second->getPriority() < InputStatePriority::HighPriority)
670                it->second->setPriority(0);
671            updateActiveStates();
672
673            return true;
[1755]674        }
675        return false;
[1219]676    }
677
[3327]678    bool InputManager::destroyState(const std::string& name)
[1219]679    {
[3327]680        if (name == "empty")
681        {
[8858]682            orxout(internal_warning, context::input) << "InputManager: Removing the empty state is not allowed!" << endl;
[3327]683            return false;
684        }
685        std::map<std::string, InputState*>::iterator it = statesByName_.find(name);
686        if (it != statesByName_.end())
687        {
[6746]688            this->leaveState(name);
689            destroyStateInternal(it->second);
[2662]690
[3327]691            return true;
692        }
693        return false;
[1219]694    }
695
[3327]696    //! Destroys an InputState internally.
697    void InputManager::destroyStateInternal(InputState* state)
[1219]698    {
[6746]699        assert(state && this->activeStates_.find(state->getPriority()) == this->activeStates_.end());
[3327]700        statesByName_.erase(state->getName());
[9667]701        delete state;
[1219]702    }
[8079]703
[8729]704    bool InputManager::setMouseExclusive(const std::string& name, tribool value)
[8079]705    {
706        if (name == "empty")
707        {
[8858]708            orxout(internal_warning, context::input) << "InputManager: Changing the empty state is not allowed!" << endl;
[8079]709            return false;
710        }
711        std::map<std::string, InputState*>::iterator it = statesByName_.find(name);
712        if (it != statesByName_.end())
713        {
714            it->second->setMouseExclusive(value);
715            return true;
716        }
717        return false;
718    }
[918]719}
Note: See TracBrowser for help on using the repository browser.