Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Jul 12, 2009, 11:08:50 PM (15 years ago)
Author:
rgrieder
Message:

Heavy clean up in the InputManager; not many real code changes though.
And temporary hack-fixed a problem in the Keybinder with std::vector.reserve(1000) ;)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • code/branches/core4/src/core/input/InputManager.cc

    r3276 r3279  
    3636#include "InputManager.h"
    3737
     38#include <cassert>
    3839#include <climits>
    39 #include <cassert>
    4040#include <ois/OISException.h>
    4141#include <ois/OISInputManager.h>
    4242#include <boost/foreach.hpp>
    4343
    44 #include "util/Convert.h"
    4544#include "util/Exception.h"
    4645#include "util/ScopeGuard.h"
     
    5453#include "InputBuffer.h"
    5554#include "KeyDetector.h"
    56 #include "InputHandler.h"
    57 #include "InputState.h"
     55#include "JoyStick.h"
    5856#include "JoyStickQuantityListener.h"
    59 #include "JoyStick.h"
    6057#include "Mouse.h"
    6158#include "Keyboard.h"
     
    6360namespace orxonox
    6461{
    65     SetConsoleCommand(InputManager, calibrate, true);
    66     SetConsoleCommand(InputManager, reload, false);
     62    // TODO: Add console commands again as member commands
     63    //SetConsoleCommand(InputManager, calibrate, true);
     64    //SetConsoleCommand(InputManager, reload, false);
    6765    SetCommandLineSwitch(keyboard_no_grab).information("Whether not to exclusively grab the keyboard");
    6866
     67    // Abuse of this source file for the InputHandler
    6968    InputHandler InputHandler::EMPTY;
     69
    7070    InputManager* InputManager::singletonRef_s = 0;
    7171
     
    7474        Defines the |= operator for easier use.
    7575    */
    76     inline InputManager::InputManagerState operator|=(InputManager::InputManagerState& lval,
    77                                                       InputManager::InputManagerState rval)
    78     {
    79         return (lval = (InputManager::InputManagerState)(lval | rval));
     76    inline InputManager::State operator|=(InputManager::State& lval, InputManager::State rval)
     77    {
     78        return (lval = (InputManager::State)(lval | rval));
    8079    }
    8180
     
    8483        Defines the &= operator for easier use.
    8584    */
    86     inline InputManager::InputManagerState operator&=(InputManager::InputManagerState& lval, int rval)
    87     {
    88         return (lval = (InputManager::InputManagerState)(lval & rval));
     85    inline InputManager::State operator&=(InputManager::State& lval, int rval)
     86    {
     87        return (lval = (InputManager::State)(lval & rval));
    8988    }
    9089
     
    9392    // ##########                                        ##########
    9493    // ############################################################
    95 
    9694    /**
    9795    @brief
     
    10098    */
    10199    InputManager::InputManager(size_t windowHnd, unsigned int windowWidth, unsigned int windowHeight)
    102         : inputSystem_(0)
     100        : internalState_(Bad)
     101        , oisInputManager_(0)
    103102        , devices_(2)
    104103        , windowHnd_(0)
    105         , internalState_(Uninitialised)
    106         , stateEmpty_(0)
     104        , emptyState_(0)
    107105        , keyDetector_(0)
    108         , calibratorCallbackBuffer_(0)
     106        , calibratorCallbackHandler_(0)
    109107    {
    110108        RegisterRootObject(InputManager);
     
    113111        singletonRef_s = this;
    114112
    115         setConfigValues();
    116 
    117         initialise(windowHnd, windowWidth, windowHeight);
     113        CCOUT(4) << "Constructing..." << std::endl;
     114
     115        this->setConfigValues();
     116
     117        this->loadDevices(windowHnd, windowWidth, windowHeight);
     118
     119        // Lowest priority empty InputState
     120        emptyState_ = createInputState("empty", false, false, InputStatePriority::Empty);
     121        emptyState_->setHandler(&InputHandler::EMPTY);
     122        activeStates_[emptyState_->getPriority()] = emptyState_;
     123
     124        // KeyDetector to evaluate a pressed key's name
     125        InputState* detector = createInputState("detector", false, false, InputStatePriority::Detector);
     126        // Create a callback to avoid buttonHeld events after the key has been detected
     127        FunctorMember<InputManager>* bufferFunctor = createFunctor(&InputManager::clearBuffers);
     128        bufferFunctor->setObject(this);
     129        detector->setLeaveFunctor(bufferFunctor);
     130        keyDetector_ = new KeyDetector();
     131        detector->setHandler(keyDetector_);
     132
     133        // Joy stick calibration helper callback
     134        InputState* calibrator = createInputState("calibrator", false, false, InputStatePriority::Calibrator);
     135        calibrator->setHandler(&InputHandler::EMPTY);
     136        calibratorCallbackHandler_ = new InputBuffer();
     137        calibratorCallbackHandler_->registerListener(this, &InputManager::stopCalibration, '\r', true);
     138        calibrator->setKeyHandler(calibratorCallbackHandler_);
     139
     140        this->updateActiveStates();
     141
     142        {
     143            // calibrate console command
     144            FunctorMember<InputManager>* functor = createFunctor(&InputManager::calibrate);
     145            functor->setObject(this);
     146            this->getIdentifier()->addConsoleCommand(createConsoleCommand(functor, "calibrate"), true);
     147        }
     148        {
     149            // reload console command
     150            FunctorMember<InputManager>* functor = createFunctor(&InputManager::reload);
     151            functor->setObject(this);
     152            this->getIdentifier()->addConsoleCommand(createConsoleCommand(functor, "reload"), false);
     153        }
     154
     155        internalState_ = Nothing;
     156        CCOUT(4) << "Construction complete." << std::endl;
    118157    }
    119158
     
    137176        The height of the render window
    138177    */
    139     void InputManager::initialise(size_t windowHnd, unsigned int windowWidth, unsigned int windowHeight)
    140     {
    141         CCOUT(3) << "Initialising Input System..." << std::endl;
    142 
    143         if (!(internalState_ & OISReady))
    144         {
    145             CCOUT(4) << "Initialising OIS components..." << std::endl;
    146 
    147             // store handle internally so we can reload OIS
    148             windowHnd_ = windowHnd;
    149 
    150             OIS::ParamList paramList;
    151             std::ostringstream windowHndStr;
    152 
    153             // Fill parameter list
    154             windowHndStr << (unsigned int)windowHnd_;
    155             paramList.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
     178    void InputManager::loadDevices(size_t windowHnd, unsigned int windowWidth, unsigned int windowHeight)
     179    {
     180        CCOUT(3) << "Loading input devices..." << std::endl;
     181
     182        // When loading the devices they should not already be loaded
     183        assert(internalState_ & Bad);
     184        assert(devices_[InputDeviceEnumerator::Mouse] == 0);
     185        assert(devices_[InputDeviceEnumerator::Keyboard] == 0);
     186        assert(devices_.size() == InputDeviceEnumerator::FirstJoyStick);
     187
     188        // store handle internally so we can reload OIS
     189        windowHnd_ = windowHnd;
     190
     191        OIS::ParamList paramList;
     192        std::ostringstream windowHndStr;
     193
     194        // Fill parameter list
     195        windowHndStr << (unsigned int)windowHnd_;
     196        paramList.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
    156197#if defined(ORXONOX_PLATFORM_WINDOWS)
    157             //paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_NONEXCLUSIVE")));
    158             //paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_FOREGROUND")));
    159             //paramList.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_NONEXCLUSIVE")));
    160             //paramList.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_FOREGROUND")));
     198        //paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_NONEXCLUSIVE")));
     199        //paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_FOREGROUND")));
     200        //paramList.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_NONEXCLUSIVE")));
     201        //paramList.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_FOREGROUND")));
    161202#elif defined(ORXONOX_PLATFORM_LINUX)
    162             paramList.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true")));
    163             paramList.insert(std::make_pair(std::string("x11_mouse_grab"), "true"));
    164             paramList.insert(std::make_pair(std::string("x11_mouse_hide"), "true"));
    165             bool kbNoGrab;
    166             CommandLine::getValue("keyboard_no_grab", &kbNoGrab);
    167             if (kbNoGrab)
    168                 paramList.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("false")));
     203        paramList.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true")));
     204        paramList.insert(std::make_pair(std::string("x11_mouse_grab"), "true"));
     205        paramList.insert(std::make_pair(std::string("x11_mouse_hide"), "true"));
     206        bool kbNoGrab;
     207        CommandLine::getValue("keyboard_no_grab", &kbNoGrab);
     208        if (kbNoGrab)
     209            paramList.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("false")));
     210        else
     211            paramList.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("true")));
     212#endif
     213
     214        try
     215        {
     216            oisInputManager_ = OIS::InputManager::createInputSystem(paramList);
     217            // Exception-safety
     218            Loki::ScopeGuard guard = Loki::MakeGuard(OIS::InputManager::destroyInputSystem, oisInputManager_);
     219            CCOUT(ORX_DEBUG) << "Created OIS input manager." << std::endl;
     220
     221            if (oisInputManager_->getNumberOfDevices(OIS::OISKeyboard) > 0)
     222                devices_[InputDeviceEnumerator::Keyboard] = new Keyboard(InputDeviceEnumerator::Keyboard);
    169223            else
    170                 paramList.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("true")));
    171 #endif
    172 
    173             // TODO: clean this up
    174             try
    175             {
    176                 inputSystem_ = OIS::InputManager::createInputSystem(paramList);
    177                 // Exception-safety
    178                 Loki::ScopeGuard guard = Loki::MakeGuard(OIS::InputManager::destroyInputSystem, inputSystem_);
    179                 CCOUT(ORX_DEBUG) << "Created OIS input system" << std::endl;
    180 
    181                 _initialiseKeyboard();
    182 
    183                 // Nothing below should throw anymore, dismiss the guard
    184                 guard.Dismiss();
    185             }
    186             catch (OIS::Exception& ex)
    187             {
    188                 ThrowException(InitialisationFailed, "Could not initialise the input system: " << ex.what());
    189             }
    190 
    191             // TODO: Remove the two parameters
    192             _initialiseMouse(windowWidth, windowHeight);
    193 
    194             _initialiseJoySticks();
    195 
    196             // clear all buffers
    197             clearBuffers();
    198 
    199             internalState_ |= OISReady;
    200 
    201             CCOUT(ORX_DEBUG) << "Initialising OIS components done." << std::endl;
    202         }
    203         else
    204         {
    205             CCOUT(2) << "Warning: OIS compoments already initialised, skipping" << std::endl;
    206         }
    207 
    208         if (!(internalState_ & InternalsReady))
    209         {
    210             CCOUT(4) << "Initialising InputStates components..." << std::endl;
    211 
    212             // Lowest priority empty InputState
    213             stateEmpty_ = createInputState("empty", false, false, InputStatePriority::Empty);
    214             stateEmpty_->setHandler(&InputHandler::EMPTY);
    215             activeStates_[stateEmpty_->getPriority()] = stateEmpty_;
    216 
    217             // KeyDetector to evaluate a pressed key's name
    218             InputState* detector = createInputState("detector", false, false, InputStatePriority::Detector);
    219             FunctorMember<InputManager>* bufferFunctor = createFunctor(&InputManager::clearBuffers);
    220             bufferFunctor->setObject(this);
    221             detector->setLeaveFunctor(bufferFunctor);
    222             keyDetector_ = new KeyDetector();
    223             detector->setHandler(keyDetector_);
    224 
    225             // Joy stick calibration helper callback
    226             InputState* calibrator = createInputState("calibrator", false, false, InputStatePriority::Calibrator);
    227             calibrator->setHandler(&InputHandler::EMPTY);
    228             calibratorCallbackBuffer_ = new InputBuffer();
    229             calibratorCallbackBuffer_->registerListener(this, &InputManager::_stopCalibration, '\r', true);
    230             calibrator->setKeyHandler(calibratorCallbackBuffer_);
    231 
    232             internalState_ |= InternalsReady;
    233 
    234             CCOUT(4) << "Initialising InputStates complete." << std::endl;
    235         }
    236 
    237         _updateActiveStates();
    238 
    239         CCOUT(3) << "Initialising complete." << std::endl;
    240     }
    241 
    242     void InputManager::_initialiseKeyboard()
    243     {
    244         assert(devices_[InputDeviceEnumerator::Keyboard] == 0);
    245         if (inputSystem_->getNumberOfDevices(OIS::OISKeyboard) > 0)
    246             devices_[InputDeviceEnumerator::Keyboard] = new Keyboard(InputDeviceEnumerator::Keyboard);
    247         else
    248             ThrowException(InitialisationFailed, "InputManager: No keyboard found, cannot proceed!");
    249     }
    250 
    251     void InputManager::_initialiseMouse(unsigned int windowWidth, unsigned int windowHeight)
    252     {
    253         assert(devices_[InputDeviceEnumerator::Mouse] == 0);
    254         if (inputSystem_->getNumberOfDevices(OIS::OISMouse) > 0)
     224                ThrowException(InitialisationFailed, "InputManager: No keyboard found, cannot proceed!");
     225
     226            // Successful initialisation
     227            guard.Dismiss();
     228        }
     229        catch (std::exception& ex)
     230        {
     231            oisInputManager_ = NULL;
     232            internalState_ |= Bad;
     233            ThrowException(InitialisationFailed, "Could not initialise the input system: " << ex.what());
     234        }
     235
     236        // TODO: Remove the two parameters
     237        this->loadMouse(windowWidth, windowHeight);
     238        this->loadJoySticks();
     239
     240        // Reorder states in case some joy sticks were added/removed
     241        this->updateActiveStates();
     242
     243        CCOUT(3) << "Input devices loaded." << std::endl;
     244    }
     245
     246    void InputManager::loadMouse(unsigned int windowWidth, unsigned int windowHeight)
     247    {
     248        if (oisInputManager_->getNumberOfDevices(OIS::OISMouse) > 0)
    255249        {
    256250            try
     
    274268        False joy stick stay uninitialised, true otherwise.
    275269    */
    276     void InputManager::_initialiseJoySticks()
    277     {
    278         assert(devices_.size() == InputDeviceEnumerator::FirstJoyStick);
    279 
    280         for (int i = 0; i < inputSystem_->getNumberOfDevices(OIS::OISJoyStick); i++)
     270    void InputManager::loadJoySticks()
     271    {
     272        for (int i = 0; i < oisInputManager_->getNumberOfDevices(OIS::OISJoyStick); i++)
    281273        {
    282274            try
     
    295287    }
    296288
    297     void InputManager::_startCalibration()
    298     {
    299         BOOST_FOREACH(InputDevice* device, devices_)
    300             device->startCalibration();
    301 
    302         getInstance().internalState_ |= Calibrating;
    303         getInstance().requestEnterState("calibrator");
    304     }
    305 
    306     void InputManager::_stopCalibration()
    307     {
    308         BOOST_FOREACH(InputDevice* device, devices_)
    309             device->stopCalibration();
    310 
    311         // restore old input state
    312         requestLeaveState("calibrator");
    313         internalState_ &= ~Calibrating;
    314         // Clear buffers to prevent button hold events
    315         this->clearBuffers();
     289    /**
     290    @brief
     291        Checks whether there is already a joy stick with the given ID string.
     292    @return
     293        Returns true if ID is ok (unique), false otherwise.
     294    */
     295    bool InputManager::checkJoyStickID(const std::string& idString) const
     296    {
     297        for (unsigned int i = InputDeviceEnumerator::FirstJoyStick; i < devices_.size(); ++i)
     298            if (static_cast<JoyStick*>(devices_[i])->getIDString() == idString)
     299                return false;
     300        return true;
     301    }
     302
     303    /**
     304    @brief
     305        Sets the the name of the command used by the KeyDetector as callback.
     306    @param command
     307        Command name as string
     308    */
     309    void InputManager::setKeyDetectorCallback(const std::string& command)
     310    {
     311        this->keyDetector_->setCallbackCommand(command);
    316312    }
    317313
     
    328324    InputManager::~InputManager()
    329325    {
    330         if (internalState_ != Uninitialised)
    331         {
    332             CCOUT(3) << "Destroying ..." << std::endl;
    333 
    334             // Destroy calibrator helper handler and state
    335             delete keyDetector_;
    336             requestDestroyState("calibrator");
    337             // Destroy KeyDetector and state
    338             delete calibratorCallbackBuffer_;
    339             requestDestroyState("detector");
    340             // destroy the empty InputState
    341             _destroyState(this->stateEmpty_);
    342 
    343             // destroy all user InputStates
    344             while (inputStatesByName_.size() > 0)
    345                 _destroyState((*inputStatesByName_.rbegin()).second);
    346 
    347             // destroy the devices
    348             BOOST_FOREACH(InputDevice*& device, devices_)
    349             {
    350                 std::string className = device->getClassName();
    351                 try
    352                 {
    353                     if (device)
    354                         delete device;
    355                     device = 0;
    356                     CCOUT(4) << className << " destroyed." << std::endl;
    357                 }
    358                 catch (...)
    359                 {
    360                     CCOUT(1) << className << " destruction failed! Potential resource leak!" << std::endl;
    361                 }
    362             }
    363             devices_.resize(InputDeviceEnumerator::FirstJoyStick);
    364 
     326        CCOUT(4) << "Destroying..." << std::endl;
     327
     328        // Destroy calibrator helper handler and state
     329        delete keyDetector_;
     330        this->destroyState("calibrator");
     331        // Destroy KeyDetector and state
     332        delete calibratorCallbackHandler_;
     333        this->destroyState("detector");
     334        // destroy the empty InputState
     335        this->destroyStateInternal(this->emptyState_);
     336
     337        // destroy all user InputStates
     338        while (statesByName_.size() > 0)
     339            this->destroyStateInternal((*statesByName_.rbegin()).second);
     340
     341        if (!(internalState_ & Bad))
     342            this->destroyDevices();
     343
     344        CCOUT(4) << "Destruction complete." << std::endl;
     345        singletonRef_s = 0;
     346    }
     347
     348    void InputManager::destroyDevices()
     349    {
     350        CCOUT(3) << "Destroying devices..." << std::endl;
     351
     352        BOOST_FOREACH(InputDevice*& device, devices_)
     353        {
     354            if (device == NULL)
     355                continue;
     356            std::string className = device->getClassName();
    365357            try
    366358            {
    367                 OIS::InputManager::destroyInputSystem(inputSystem_);
     359                delete device;
     360                device = 0;
     361                CCOUT(4) << className << " destroyed." << std::endl;
    368362            }
    369363            catch (...)
    370364            {
    371                 CCOUT(1) << "OIS::InputManager destruction failed! Potential resource leak!" << std::endl;
    372             }
    373         }
    374 
    375         singletonRef_s = 0;
    376     }
    377 
    378     /**
    379     @brief
    380         Removes and destroys an InputState.
    381     @return
    382         True if state was removed immediately, false if postponed.
    383     */
    384     void InputManager::_destroyState(InputState* state)
    385     {
    386         assert(state && !(this->internalState_ & Ticking));
    387         std::map<int, InputState*>::iterator it = this->activeStates_.find(state->getPriority());
    388         if (it != this->activeStates_.end())
    389         {
    390             this->activeStates_.erase(it);
    391             _updateActiveStates();
    392         }
    393         inputStatesByName_.erase(state->getName());
    394         delete state;
     365                CCOUT(1) << className << " destruction failed! Potential resource leak!" << std::endl;
     366            }
     367        }
     368        devices_.resize(InputDeviceEnumerator::FirstJoyStick);
     369
     370        assert(oisInputManager_ != NULL);
     371        try
     372        {
     373            OIS::InputManager::destroyInputSystem(oisInputManager_);
     374        }
     375        catch (...)
     376        {
     377            CCOUT(1) << "OIS::InputManager destruction failed! Potential resource leak!" << std::endl;
     378        }
     379        oisInputManager_ = NULL;
     380
     381        internalState_ |= Bad;
     382        CCOUT(3) << "Destroyed devices." << std::endl;
    395383    }
    396384
     
    405393        include the update() method.
    406394    */
    407     void InputManager::reloadInputSystem()
     395    void InputManager::reload()
    408396    {
    409397        if (internalState_ & Ticking)
    410398        {
    411399            // We cannot destroy OIS right now, because reload was probably
    412             // caused by a user clicking on a GUI item. The backtrace would then
     400            // caused by a user clicking on a GUI item. The stack trace would then
    413401            // include an OIS method. So it would be a very bad thing to destroy it..
    414402            internalState_ |= ReloadRequest;
    415403        }
    416         else if (internalState_ & OISReady)
    417             _reload();
     404        else if (internalState_ & Calibrating)
     405            CCOUT(2) << "Warning: Cannot reload input system. Joy sticks are currently being calibrated." << std::endl;
    418406        else
    419         {
    420             CCOUT(2) << "Warning: Cannot reload OIS. May not yet be initialised or"
    421                      << "joy sticks are currently calibrating." << std::endl;
    422         }
     407            reloadInternal();
    423408    }
    424409
     
    427412        Internal reload method. Destroys the OIS devices and loads them again.
    428413    */
    429     void InputManager::_reload()
    430     {
    431         try
    432         {
    433             CCOUT(3) << "Reloading ..." << std::endl;
    434 
    435             // Save mouse clipping size
    436             int mouseWidth  = static_cast<Mouse*>(devices_[InputDeviceEnumerator::Mouse])->getClippingWidth();
    437             int mouseHeight = static_cast<Mouse*>(devices_[InputDeviceEnumerator::Mouse])->getClippingHeight();
    438 
    439             internalState_ &= ~OISReady;
    440 
    441             // destroy the devices
    442             // destroy the devices
    443             BOOST_FOREACH(InputDevice*& device, devices_)
    444             {
    445                 try
    446                 {
    447                     if (device)
    448                         delete device;
    449                     device = 0;
    450                     CCOUT(4) << device->getClassName() << " destroyed." << std::endl;
    451                 }
    452                 catch (...)
    453                 {
    454                     CCOUT(1) << device->getClassName() << " destruction failed! Potential resource leak!" << std::endl;
    455                 }
    456             }
    457             devices_.resize(InputDeviceEnumerator::FirstJoyStick);
    458 
    459             OIS::InputManager::destroyInputSystem(inputSystem_);
    460             inputSystem_ = 0;
    461 
    462             // clear all buffers containing input information
    463             clearBuffers();
    464 
    465             initialise(windowHnd_, mouseWidth, mouseHeight);
    466 
    467             CCOUT(3) << "Reloading done." << std::endl;
    468         }
    469         catch (OIS::Exception& ex)
    470         {
    471             CCOUT(1) << "An exception has occured while reloading:\n" << ex.what() << std::endl;
    472         }
     414    void InputManager::reloadInternal()
     415    {
     416        CCOUT(3) << "Reloading ..." << std::endl;
     417
     418        // Save mouse clipping size
     419        int clippingWidth = 800;
     420        int clippingHeight = 600;
     421        if (devices_[InputDeviceEnumerator::Mouse])
     422        {
     423            int clippingWidth  = static_cast<Mouse*>(devices_[InputDeviceEnumerator::Mouse])->getClippingWidth();
     424            int clippingHeight = static_cast<Mouse*>(devices_[InputDeviceEnumerator::Mouse])->getClippingHeight();
     425        }
     426
     427        this->destroyDevices();
     428        this->loadDevices(windowHnd_, clippingWidth, clippingHeight);
     429
     430        internalState_ &= ~Bad;
     431        internalState_ &= ~ReloadRequest;
     432        CCOUT(3) << "Reloading complete." << std::endl;
    473433    }
    474434
     
    486446    void InputManager::update(const Clock& time)
    487447    {
    488         if (internalState_ == Uninitialised)
    489             return;
     448        if (internalState_ & Bad)
     449            ThrowException(General, "InputManager was not correctly reloaded.");
     450
    490451        else if (internalState_ & ReloadRequest)
    491         {
    492             _reload();
    493             internalState_ &= ~ReloadRequest;
    494         }
     452            reloadInternal();
    495453
    496454        // check for states to leave
     
    502460                (*it)->left();
    503461                // just to be sure that the state actually is registered
    504                 assert(inputStatesByName_.find((*it)->getName()) != inputStatesByName_.end());
     462                assert(statesByName_.find((*it)->getName()) != statesByName_.end());
    505463
    506464                activeStates_.erase((*it)->getPriority());
    507465                if ((*it)->getPriority() < InputStatePriority::HighPriority)
    508466                    (*it)->setPriority(0);
    509                 _updateActiveStates();
     467                updateActiveStates();
    510468            }
    511469            stateLeaveRequests_.clear();
     
    519477            {
    520478                // just to be sure that the state actually is registered
    521                 assert(inputStatesByName_.find((*it)->getName()) != inputStatesByName_.end());
     479                assert(statesByName_.find((*it)->getName()) != statesByName_.end());
    522480
    523481                if ((*it)->getPriority() == 0)
     
    538496                }
    539497                activeStates_[(*it)->getPriority()] = (*it);
    540                 _updateActiveStates();
     498                updateActiveStates();
    541499                (*it)->entered();
    542500            }
     
    550508                it != stateDestroyRequests_.end(); ++it)
    551509            {
    552                 _destroyState((*it));
     510                destroyStateInternal((*it));
    553511            }
    554512            stateDestroyRequests_.clear();
     
    566524        }
    567525        if (bUpdateRequired)
    568             _updateActiveStates();
     526            updateActiveStates();
    569527
    570528        // mark that we now start capturing and distributing input
    571529        internalState_ |= Ticking;
    572530
    573         // Capture all the input. This calls the event handlers in InputManager.
     531        // Capture all the input and handle it
    574532        BOOST_FOREACH(InputDevice* device, devices_)
    575             device->update(time);
    576 
    577         if (!(internalState_ & Calibrating))
    578         {
    579             // update the states with a general tick afterwards
    580             for (unsigned int i = 0; i < activeStatesTicked_.size(); ++i)
    581                 activeStatesTicked_[i]->update(time.getDeltaTime());
    582         }
     533            if (device != NULL)
     534                device->update(time);
     535
     536        // Update the states
     537        for (unsigned int i = 0; i < activeStatesTicked_.size(); ++i)
     538            activeStatesTicked_[i]->update(time.getDeltaTime());
    583539
    584540        internalState_ &= ~Ticking;
     
    590546        Also, a list of all active states (no duplicates!) is compiled for the general update().
    591547    */
    592     void InputManager::_updateActiveStates()
     548    void InputManager::updateActiveStates()
    593549    {
    594550        // temporary resize
    595551        for (unsigned int i = 0; i < devices_.size(); ++i)
    596552        {
     553            if (devices_[i] == NULL)
     554                continue;
    597555            std::vector<InputState*>& states = devices_[i]->getStateListRef();
    598556            bool occupied = false;
     
    613571        std::set<InputState*> tempSet;
    614572        for (unsigned int i = 0; i < devices_.size(); ++i)
    615             for (unsigned int iState = 0; iState < devices_[i]->getStateListRef().size(); ++iState)
    616                 tempSet.insert(devices_[i]->getStateListRef()[iState]);
     573            if (devices_[i] != NULL)
     574                for (unsigned int iState = 0; iState < devices_[i]->getStateListRef().size(); ++iState)
     575                    tempSet.insert(devices_[i]->getStateListRef()[iState]);
    617576
    618577        // copy the content of the std::set back to the actual vector
     
    629588    {
    630589        BOOST_FOREACH(InputDevice* device, devices_)
    631             device->clearBuffers();
    632     }
    633 
    634 
    635     // ############################################################
    636     // #####                Friend functions                  #####
     590            if (device != NULL)
     591                device->clearBuffers();
     592    }
     593
     594    /**
     595    @brief
     596        Starts joy stick calibration.
     597    */
     598    void InputManager::calibrate()
     599    {
     600        COUT(0) << "Move all joy stick axes fully in all directions." << std::endl
     601                << "When done, put the axex in the middle position and press enter." << std::endl;
     602
     603        BOOST_FOREACH(InputDevice* device, devices_)
     604            if (device != NULL)
     605                device->startCalibration();
     606
     607        internalState_ |= Calibrating;
     608        enterState("calibrator");
     609    }
     610
     611    void InputManager::stopCalibration()
     612    {
     613        BOOST_FOREACH(InputDevice* device, devices_)
     614            if (device != NULL)
     615                device->stopCalibration();
     616
     617        // restore old input state
     618        leaveState("calibrator");
     619        internalState_ &= ~Calibrating;
     620        // Clear buffers to prevent button hold events
     621        this->clearBuffers();
     622    }
     623
     624    // ############################################################
     625    // #####                    Iput States                   #####
    637626    // ##########                                        ##########
    638627    // ############################################################
    639 
    640     /**
    641     @brief
    642         Checks whether there is already a joy stick with the given ID string.
    643     @return
    644         Returns true if ID is ok (unique), false otherwise.
    645     */
    646     bool InputManager::checkJoyStickID(const std::string& idString) const
    647     {
    648         for (unsigned int i = InputDeviceEnumerator::FirstJoyStick; i < devices_.size(); ++i)
    649             if (static_cast<JoyStick*>(devices_[i])->getIDString() == idString)
    650                 return false;
    651         return true;
    652     }
    653 
    654 
    655     // ############################################################
    656     // #####         Other Public Interface Methods           #####
    657     // ##########                                        ##########
    658     // ############################################################
    659 
    660     /**
    661     @brief
    662         Sets the the name of the command used by the KeyDetector as callback.
    663     @param command
    664         Command name as string
    665     */
    666     void InputManager::setKeyDetectorCallback(const std::string& command)
    667     {
    668         this->keyDetector_->setCallbackCommand(command);
    669     }
    670 
    671     // ###### InputStates ######
    672628
    673629    /**
     
    689645    {
    690646        InputState* state = new InputState;
    691         if (_configureInputState(state, name, bAlwaysGetsInput, bTransparent, priority))
     647        if (configureInputState(state, name, bAlwaysGetsInput, bTransparent, priority))
    692648            return state;
    693649        else
     
    712668        True if added, false if name or priority already existed.
    713669    */
    714     bool InputManager::_configureInputState(InputState* state, const std::string& name, bool bAlwaysGetsInput, bool bTransparent, int priority)
     670    bool InputManager::configureInputState(InputState* state, const std::string& name, bool bAlwaysGetsInput, bool bTransparent, int priority)
    715671    {
    716672        if (name == "")
     
    718674        if (!state)
    719675            return false;
    720         if (inputStatesByName_.find(name) == inputStatesByName_.end())
     676        if (statesByName_.find(name) == statesByName_.end())
    721677        {
    722678            if (priority >= InputStatePriority::HighPriority || priority == InputStatePriority::Empty)
    723679            {
    724680                // Make sure we don't add two high priority states with the same priority
    725                 for (std::map<std::string, InputState*>::const_iterator it = this->inputStatesByName_.begin();
    726                     it != this->inputStatesByName_.end(); ++it)
     681                for (std::map<std::string, InputState*>::const_iterator it = this->statesByName_.begin();
     682                    it != this->statesByName_.end(); ++it)
    727683                {
    728684                    if (it->second->getPriority() == priority)
     
    734690                }
    735691            }
    736             inputStatesByName_[name] = state;
     692            statesByName_[name] = state;
    737693            state->JoyStickQuantityChanged(devices_.size() - InputDeviceEnumerator::FirstJoyStick);
    738694            state->setName(name);
     
    752708    /**
    753709    @brief
    754         Removes and destroys an input state internally.
    755     @param name
    756         Name of the handler.
    757     @return
    758         True if removal was successful, false if name was not found.
    759     @remarks
    760         You can't remove the internal states "empty", "calibrator" and "detector".
    761         The removal process is being postponed if InputManager::update() is currently running.
    762     */
    763     bool InputManager::requestDestroyState(const std::string& name)
    764     {
    765         if (name == "empty")
    766         {
    767             COUT(2) << "InputManager: Removing the empty state is not allowed!" << std::endl;
    768             return false;
    769         }
    770         std::map<std::string, InputState*>::iterator it = inputStatesByName_.find(name);
    771         if (it != inputStatesByName_.end())
    772         {
    773             if (activeStates_.find(it->second->getPriority()) != activeStates_.end())
    774             {
    775                 // The state is still active. We have to postpone
    776                 stateLeaveRequests_.insert(it->second);
    777                 stateDestroyRequests_.insert(it->second);
    778             }
    779             else if (this->internalState_ & Ticking)
    780             {
    781                 // cannot remove state while ticking
    782                 stateDestroyRequests_.insert(it->second);
    783             }
    784             else
    785                 _destroyState(it->second);
    786 
    787             return true;
    788         }
    789         return false;
    790     }
    791 
    792     /**
    793     @brief
    794710        Returns the pointer to the requested InputState.
    795711    @param name
     
    800716    InputState* InputManager::getState(const std::string& name)
    801717    {
    802         std::map<std::string, InputState*>::iterator it = inputStatesByName_.find(name);
    803         if (it != inputStatesByName_.end())
     718        std::map<std::string, InputState*>::iterator it = statesByName_.find(name);
     719        if (it != statesByName_.end())
    804720            return it->second;
    805721        else
    806722            return 0;
    807     }
    808 
    809     /**
    810     @brief
    811         Returns the current input state (there might be others active too!)
    812     @return
    813         The current highest prioritised active input state.
    814     */
    815     InputState* InputManager::getCurrentState()
    816     {
    817         return (*activeStates_.rbegin()).second;
    818723    }
    819724
     
    827732        False if name was not found, true otherwise.
    828733    */
    829     bool InputManager::requestEnterState(const std::string& name)
     734    bool InputManager::enterState(const std::string& name)
    830735    {
    831736        // get pointer from the map with all stored handlers
    832         std::map<std::string, InputState*>::const_iterator it = inputStatesByName_.find(name);
    833         if (it != inputStatesByName_.end())
     737        std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name);
     738        if (it != statesByName_.end())
    834739        {
    835740            // exists
     
    857762        False if name was not found, true otherwise.
    858763    */
    859     bool InputManager::requestLeaveState(const std::string& name)
     764    bool InputManager::leaveState(const std::string& name)
    860765    {
    861766        if (name == "empty")
     
    865770        }
    866771        // get pointer from the map with all stored handlers
    867         std::map<std::string, InputState*>::const_iterator it = inputStatesByName_.find(name);
    868         if (it != inputStatesByName_.end())
     772        std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name);
     773        if (it != statesByName_.end())
    869774        {
    870775            // exists
     
    879784    }
    880785
    881 
    882     // ############################################################
    883     // #####                Console Commands                  #####
    884     // ##########                                        ##########
    885     // ############################################################
    886 
    887     /**
    888     @brief
    889         Starts joy stick calibration.
    890     */
    891     void InputManager::calibrate()
    892     {
    893         COUT(0) << "Move all joy stick axes fully in all directions." << std::endl
    894                 << "When done, put the axex in the middle position and press enter." << std::endl;
    895 
    896         getInstance()._startCalibration();
    897     }
    898 
    899     /**
    900     @brief
    901         Reloads the input system
    902     */
    903     void InputManager::reload()
    904     {
    905         getInstance().reloadInputSystem();
     786    /**
     787    @brief
     788        Removes and destroys an input state.
     789    @param name
     790        Name of the handler.
     791    @return
     792        True if removal was successful, false if name was not found.
     793    @remarks
     794        You can't remove the internal states "empty", "calibrator" and "detector".
     795        The removal process is being postponed if InputManager::update() is currently running.
     796    */
     797    bool InputManager::destroyState(const std::string& name)
     798    {
     799        if (name == "empty")
     800        {
     801            COUT(2) << "InputManager: Removing the empty state is not allowed!" << std::endl;
     802            return false;
     803        }
     804        std::map<std::string, InputState*>::iterator it = statesByName_.find(name);
     805        if (it != statesByName_.end())
     806        {
     807            if (activeStates_.find(it->second->getPriority()) != activeStates_.end())
     808            {
     809                // The state is still active. We have to postpone
     810                stateLeaveRequests_.insert(it->second);
     811                stateDestroyRequests_.insert(it->second);
     812            }
     813            else if (this->internalState_ & Ticking)
     814            {
     815                // cannot remove state while ticking
     816                stateDestroyRequests_.insert(it->second);
     817            }
     818            else
     819                destroyStateInternal(it->second);
     820
     821            return true;
     822        }
     823        return false;
     824    }
     825
     826    /**
     827    @brief
     828        Destroys an InputState internally
     829    */
     830    void InputManager::destroyStateInternal(InputState* state)
     831    {
     832        assert(state && !(this->internalState_ & Ticking));
     833        std::map<int, InputState*>::iterator it = this->activeStates_.find(state->getPriority());
     834        if (it != this->activeStates_.end())
     835        {
     836            this->activeStates_.erase(it);
     837            updateActiveStates();
     838        }
     839        statesByName_.erase(state->getName());
     840        delete state;
    906841    }
    907842}
Note: See TracChangeset for help on using the changeset viewer.