Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Mar 31, 2010, 1:05:28 AM (15 years ago)
Author:
rgrieder
Message:

Merged revisions 6621-6661 to gamestates2.

Location:
code/branches/gamestates2
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • code/branches/gamestates2

  • code/branches/gamestates2/src/libraries/core/input/InputDevice.h

    r6417 r6662  
    159159            for (unsigned int iB = 0; iB < pressedButtons_.size(); ++iB)
    160160                for (unsigned int iS = 0; iS < inputStates_.size(); ++iS)
    161                     inputStates_[iS]->buttonEvent<ButtonEvent::THold, Traits>(
     161                    inputStates_[iS]->buttonEvent<ButtonEvent::THold, Traits::ButtonTypeParam>(
    162162                        this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(pressedButtons_[iB]));
    163163
     
    196196            // Call states
    197197            for (unsigned int i = 0; i < inputStates_.size(); ++i)
    198                 inputStates_[i]->buttonEvent<ButtonEvent::TPress, Traits>(this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(button));
     198                inputStates_[i]->buttonEvent<ButtonEvent::TPress, Traits::ButtonTypeParam>(this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(button));
    199199        }
    200200
     
    218218            // Call states
    219219            for (unsigned int i = 0; i < inputStates_.size(); ++i)
    220                 inputStates_[i]->buttonEvent<ButtonEvent::TRelease, Traits>(this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(button));
     220                inputStates_[i]->buttonEvent<ButtonEvent::TRelease, Traits::ButtonTypeParam>(this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(button));
    221221        }
    222222
  • code/branches/gamestates2/src/libraries/core/input/InputHandler.h

    r6105 r6662  
    112112        virtual ~InputHandler() { }
    113113
    114         template<class T> void buttonEvent(unsigned int device, const T& button, ButtonEvent::TPress)
     114        template<class T> void buttonEvent(unsigned int device, T button, ButtonEvent::TPress)
    115115            { this->buttonPressed(button); }
    116         template<class T> void buttonEvent(unsigned int device, const T& button, ButtonEvent::TRelease)
     116        template<class T> void buttonEvent(unsigned int device, T button, ButtonEvent::TRelease)
    117117            { this->buttonReleased(button); }
    118         template<class T> void buttonEvent(unsigned int device, const T& button, ButtonEvent::THold)
     118        template<class T> void buttonEvent(unsigned int device, T button, ButtonEvent::THold)
    119119            { this->buttonHeld(button); }
    120         void buttonEvent(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::TPress)
     120        template<> void buttonEvent<JoyStickButtonCode::ByEnum>(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::TPress)
    121121            { this->buttonPressed(device - InputDeviceEnumerator::FirstJoyStick, button); }
    122         void buttonEvent(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::TRelease)
     122        template<> void buttonEvent<JoyStickButtonCode::ByEnum>(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::TRelease)
    123123            { this->buttonReleased(device - InputDeviceEnumerator::FirstJoyStick, button); }
    124         void buttonEvent(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::THold)
     124        template<> void buttonEvent<JoyStickButtonCode::ByEnum>(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::THold)
    125125            { this->buttonHeld(device - InputDeviceEnumerator::FirstJoyStick, button); }
    126126
  • code/branches/gamestates2/src/libraries/core/input/InputManager.cc

    r6595 r6662  
    9595        CCOUT(4) << "Constructing..." << std::endl;
    9696
     97        // Allocate space for the function call buffer
     98        this->callBuffer_.reserve(16);
     99
    97100        this->setConfigValues();
    98101
     
    266269        CCOUT(3) << "Destroying..." << std::endl;
    267270
     271        // Leave all active InputStates (except "empty")
     272        while (this->activeStates_.size() > 1)
     273            this->leaveState(this->activeStates_.rbegin()->second->getName());
     274        this->activeStates_.clear();
     275
    268276        // Destroy calibrator helper handler and state
    269277        this->destroyState("calibrator");
    270278        // Destroy KeyDetector and state
    271279        calibratorCallbackHandler_->destroy();
    272         // destroy the empty InputState
     280        // Destroy the empty InputState
    273281        this->destroyStateInternal(this->emptyState_);
    274282
    275         // destroy all user InputStates
     283        // Destroy all user InputStates
    276284        while (statesByName_.size() > 0)
    277285            this->destroyStateInternal(statesByName_.rbegin()->second);
     
    335343    void InputManager::reload()
    336344    {
    337         if (internalState_ & Ticking)
    338         {
    339             // We cannot destroy OIS right now, because reload was probably
    340             // caused by a user clicking on a GUI item. The stack trace would then
    341             // include an OIS method. So it would be a very bad thing to destroy it..
    342             internalState_ |= ReloadRequest;
    343         }
    344         else if (internalState_ & Calibrating)
     345        if (internalState_ & Calibrating)
    345346            CCOUT(2) << "Warning: Cannot reload input system. Joy sticks are currently being calibrated." << std::endl;
    346347        else
     
    351352    void InputManager::reloadInternal()
    352353    {
    353         CCOUT(3) << "Reloading ..." << std::endl;
     354        CCOUT(4) << "Reloading ..." << std::endl;
    354355
    355356        this->destroyDevices();
     
    357358
    358359        internalState_ &= ~Bad;
    359         internalState_ &= ~ReloadRequest;
    360360        CCOUT(4) << "Reloading complete." << std::endl;
    361361    }
     
    370370        if (internalState_ & Bad)
    371371            ThrowException(General, "InputManager was not correctly reloaded.");
    372 
    373         else if (internalState_ & ReloadRequest)
    374             reloadInternal();
    375 
    376         // check for states to leave
    377         if (!stateLeaveRequests_.empty())
    378         {
    379             for (std::set<InputState*>::iterator it = stateLeaveRequests_.begin();
    380                 it != stateLeaveRequests_.end(); ++it)
    381             {
    382                 (*it)->left();
    383                 // just to be sure that the state actually is registered
    384                 assert(statesByName_.find((*it)->getName()) != statesByName_.end());
    385 
    386                 activeStates_.erase((*it)->getPriority());
    387                 if ((*it)->getPriority() < InputStatePriority::HighPriority)
    388                     (*it)->setPriority(0);
    389                 updateActiveStates();
    390             }
    391             stateLeaveRequests_.clear();
    392         }
    393 
    394         // check for states to enter
    395         if (!stateEnterRequests_.empty())
    396         {
    397             for (std::set<InputState*>::const_iterator it = stateEnterRequests_.begin();
    398                 it != stateEnterRequests_.end(); ++it)
    399             {
    400                 // just to be sure that the state actually is registered
    401                 assert(statesByName_.find((*it)->getName()) != statesByName_.end());
    402 
    403                 if ((*it)->getPriority() == 0)
    404                 {
    405                     // Get smallest possible priority between 1 and maxStateStackSize_s
    406                     for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin();
    407                         rit != activeStates_.rend(); ++rit)
    408                     {
    409                         if (rit->first < InputStatePriority::HighPriority)
    410                         {
    411                             (*it)->setPriority(rit->first + 1);
    412                             break;
    413                         }
    414                     }
    415                     // In case no normal handler was on the stack
    416                     if ((*it)->getPriority() == 0)
    417                         (*it)->setPriority(1);
    418                 }
    419                 activeStates_[(*it)->getPriority()] = (*it);
    420                 updateActiveStates();
    421                 (*it)->entered();
    422             }
    423             stateEnterRequests_.clear();
    424         }
    425 
    426         // check for states to destroy
    427         if (!stateDestroyRequests_.empty())
    428         {
    429             for (std::set<InputState*>::iterator it = stateDestroyRequests_.begin();
    430                 it != stateDestroyRequests_.end(); ++it)
    431             {
    432                 destroyStateInternal((*it));
    433             }
    434             stateDestroyRequests_.clear();
    435         }
    436372
    437373        // check whether a state has changed its EMPTY situation
     
    448384            updateActiveStates();
    449385
    450         // mark that we now start capturing and distributing input
    451         internalState_ |= Ticking;
    452 
    453         // Capture all the input and handle it
     386        // Capture all the input and collect the function calls
     387        // No event gets triggered here yet!
    454388        BOOST_FOREACH(InputDevice* device, devices_)
    455389            if (device != NULL)
    456390                device->update(time);
    457391
    458         // Update the states
     392        // Collect functions calls for the update
    459393        for (unsigned int i = 0; i < activeStatesTicked_.size(); ++i)
    460394            activeStatesTicked_[i]->update(time.getDeltaTime());
    461395
    462         internalState_ &= ~Ticking;
     396        // Execute all cached function calls in order
     397        // Why so complicated? The problem is that an InputHandler could trigger
     398        // a reload that would destroy the OIS devices or it could even leave and
     399        // then destroy its own InputState. That would of course lead to access
     400        // violations.
     401        // If we delay the calls, then OIS and and the InputStates are not anymore
     402        // in the call stack and can therefore be edited.
     403        for (size_t i = 0; i < this->callBuffer_.size(); ++i)
     404            this->callBuffer_[i]();
     405
     406        this->callBuffer_.clear();
    463407    }
    464408
     
    470414    void InputManager::updateActiveStates()
    471415    {
    472         assert((internalState_ & InputManager::Ticking) == 0);
    473416        // temporary resize
    474417        for (unsigned int i = 0; i < devices_.size(); ++i)
     
    622565        // get pointer from the map with all stored handlers
    623566        std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name);
    624         if (it != statesByName_.end())
    625         {
    626             // exists
    627             if (activeStates_.find(it->second->getPriority()) == activeStates_.end())
    628             {
    629                 // not active
    630                 if (stateDestroyRequests_.find(it->second) == stateDestroyRequests_.end())
     567        if (it != statesByName_.end() && activeStates_.find(it->second->getPriority()) == activeStates_.end())
     568        {
     569            // exists and not active
     570            if (it->second->getPriority() == 0)
     571            {
     572                // Get smallest possible priority between 1 and maxStateStackSize_s
     573                for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin();
     574                    rit != activeStates_.rend(); ++rit)
    631575                {
    632                     // not scheduled for destruction
    633                     // prevents a state from being added multiple times
    634                     stateEnterRequests_.insert(it->second);
    635                     return true;
     576                    if (rit->first < InputStatePriority::HighPriority)
     577                    {
     578                        it->second->setPriority(rit->first + 1);
     579                        break;
     580                    }
    636581                }
    637             }
    638             else if (this->stateLeaveRequests_.find(it->second) != this->stateLeaveRequests_.end())
    639             {
    640                 // State already scheduled for leaving --> cancel
    641                 this->stateLeaveRequests_.erase(this->stateLeaveRequests_.find(it->second));
    642             }
     582                // In case no normal handler was on the stack
     583                if (it->second->getPriority() == 0)
     584                    it->second->setPriority(1);
     585            }
     586            activeStates_[it->second->getPriority()] = it->second;
     587            updateActiveStates();
     588            it->second->entered();
     589
     590            return true;
    643591        }
    644592        return false;
     
    654602        // get pointer from the map with all stored handlers
    655603        std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name);
    656         if (it != statesByName_.end())
    657         {
    658             // exists
    659             if (activeStates_.find(it->second->getPriority()) != activeStates_.end())
    660             {
    661                 // active
    662                 stateLeaveRequests_.insert(it->second);
    663                 return true;
    664             }
    665             else if (this->stateEnterRequests_.find(it->second) != this->stateEnterRequests_.end())
    666             {
    667                 // State already scheduled for entering --> cancel
    668                 this->stateEnterRequests_.erase(this->stateEnterRequests_.find(it->second));
    669             }
     604        if (it != statesByName_.end() && activeStates_.find(it->second->getPriority()) != activeStates_.end())
     605        {
     606            // exists and active
     607
     608            it->second->left();
     609
     610            activeStates_.erase(it->second->getPriority());
     611            if (it->second->getPriority() < InputStatePriority::HighPriority)
     612                it->second->setPriority(0);
     613            updateActiveStates();
     614
     615            return true;
    670616        }
    671617        return false;
     
    682628        if (it != statesByName_.end())
    683629        {
    684             if (activeStates_.find(it->second->getPriority()) != activeStates_.end())
    685             {
    686                 // The state is still active. We have to postpone
    687                 stateLeaveRequests_.insert(it->second);
    688                 stateDestroyRequests_.insert(it->second);
    689             }
    690             else if (this->internalState_ & Ticking)
    691             {
    692                 // cannot remove state while ticking
    693                 stateDestroyRequests_.insert(it->second);
    694             }
    695             else
    696                 destroyStateInternal(it->second);
     630            this->leaveState(name);
     631            destroyStateInternal(it->second);
    697632
    698633            return true;
     
    704639    void InputManager::destroyStateInternal(InputState* state)
    705640    {
    706         assert(state && !(this->internalState_ & Ticking));
    707         std::map<int, InputState*>::iterator it = this->activeStates_.find(state->getPriority());
    708         if (it != this->activeStates_.end())
    709         {
    710             this->activeStates_.erase(it);
    711             updateActiveStates();
    712         }
     641        assert(state && this->activeStates_.find(state->getPriority()) == this->activeStates_.end());
    713642        statesByName_.erase(state->getName());
    714643        state->destroy();
  • code/branches/gamestates2/src/libraries/core/input/InputManager.h

    r6595 r6662  
    3636#include <string>
    3737#include <vector>
     38#include <boost/function.hpp>
    3839
    3940#include "util/Singleton.h"
    4041#include "util/TriBool.h"
    4142#include "core/WindowEventListener.h"
    42 #include "InputState.h"
    4343
    4444// tolua_begin
     
    7676            Nothing       = 0x00,
    7777            Bad           = 0x02,
    78             Ticking       = 0x04,
    79             Calibrating   = 0x08,
    80             ReloadRequest = 0x10,
     78            Calibrating   = 0x04,
    8179        };
    8280
     
    170168        //! Returns a pointer to the OIS InputManager. Only you if you know what you're doing!
    171169        OIS::InputManager* getOISInputManager() { return this->oisInputManager_; }
     170        //! Returns the position of the cursor as std::pair of ints
    172171        std::pair<int, int> getMousePosition() const;
     172        //! Tells whether the mouse is used exclusively to the game
     173        bool isMouseExclusive() const { return this->exclusiveMouse_; } // tolua_export
     174
     175        //-------------------------------
     176        // Function call caching
     177        //-------------------------------
     178        void pushCall(const boost::function<void ()>& function)
     179            { this->callBuffer_.push_back(function); }
    173180
    174181        static InputManager& getInstance() { return Singleton<InputManager>::getInstance(); } // tolua_export
     
    208215        std::vector<InputState*>            activeStatesTicked_;   //!< Like activeStates_, but only contains the ones that currently receive events
    209216
    210         std::set<InputState*>               stateEnterRequests_;   //!< Requests to enter a new state
    211         std::set<InputState*>               stateLeaveRequests_;   //!< Requests to leave a running state
    212         std::set<InputState*>               stateDestroyRequests_; //!< Requests to destroy a state
     217        std::vector<boost::function<void ()> > callBuffer_;        //!< Caches all calls from InputStates to be executed afterwards (see preUpdate)
    213218
    214219        static InputManager*                singletonPtr_s;        //!< Pointer reference to the singleton
  • code/branches/gamestates2/src/libraries/core/input/InputPrereqs.h

    r6417 r6662  
    4242#include <ois/OISMouse.h>
    4343#include <ois/OISJoyStick.h>
     44#include "util/OrxEnum.h"
    4445
    4546namespace orxonox
     
    448449        };
    449450    }
     451
     452    //! Enumeration wrapper for input state priorities
     453    struct InputStatePriority : OrxEnum<InputStatePriority>
     454    {
     455        OrxEnumConstructors(InputStatePriority);
     456
     457        static const int Empty        = -1;
     458        static const int Dynamic      = 0;
     459
     460        static const int HighPriority = 1000;
     461        static const int Console      = HighPriority + 0;
     462        static const int Calibrator   = HighPriority + 1;
     463        static const int Detector     = HighPriority + 2;
     464    };
    450465}
    451466
  • code/branches/gamestates2/src/libraries/core/input/InputState.h

    r6595 r6662  
    3535#include <string>
    3636#include <vector>
    37 
    38 #include "util/OrxEnum.h"
     37#include <boost/function.hpp>
     38#include <boost/bind.hpp>
     39
    3940#include "util/TriBool.h"
    4041#include "InputHandler.h"
     42#include "InputManager.h"
    4143#include "JoyStickQuantityListener.h"
     44
     45#define INPUT_STATE_PUSH_CALL(deviceIndex, functionName, ...) \
     46    InputManager::getInstance().pushCall(boost::function<void ()>(boost::bind(&InputHandler::functionName, handlers_[deviceIndex], __VA_ARGS__)))
    4247
    4348namespace orxonox
    4449{
    45     //! Enumeration wrapper for input state priorities
    46     struct InputStatePriority : OrxEnum<InputStatePriority>
    47     {
    48         OrxEnumConstructors(InputStatePriority);
    49 
    50         static const int Empty        = -1;
    51         static const int Dynamic      = 0;
    52 
    53         static const int HighPriority = 1000;
    54         static const int Console      = HighPriority + 0;
    55         static const int Calibrator   = HighPriority + 1;
    56         static const int Detector     = HighPriority + 2;
    57     };
    58 
    59 
    6050    /**
    6151    @brief
     
    144134
    145135        //! Generic function that distributes all 9 button events
    146         template <typename EventType, class Traits>
    147         void buttonEvent(unsigned int device, const typename Traits::ButtonTypeParam button);
     136        template <typename EventType, class ButtonTypeParam>
     137        void buttonEvent(unsigned int device, ButtonTypeParam button);
    148138
    149139        //! Event handler
     
    190180        for (unsigned int i = 0; i < handlers_.size(); ++i)
    191181            if (handlers_[i] != NULL)
    192                 handlers_[i]->allDevicesUpdated(dt);
     182                INPUT_STATE_PUSH_CALL(i, allDevicesUpdated, dt);
    193183    }
    194184
     
    199189        case InputDeviceEnumerator::Keyboard:
    200190            if (handlers_[keyboardIndex_s] != NULL)
    201                 handlers_[keyboardIndex_s]->keyboardUpdated(dt);
     191                INPUT_STATE_PUSH_CALL(keyboardIndex_s, keyboardUpdated, dt);
    202192            break;
    203193
    204194        case InputDeviceEnumerator::Mouse:
    205195            if (handlers_[mouseIndex_s] != NULL)
    206                 handlers_[mouseIndex_s]->mouseUpdated(dt);
     196                INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseUpdated, dt);
    207197            break;
    208198
    209199        default: // joy sticks
    210200            if (handlers_[device] != NULL)
    211                 handlers_[device]->joyStickUpdated(device - firstJoyStickIndex_s, dt);
     201                INPUT_STATE_PUSH_CALL(device, joyStickUpdated, device - firstJoyStickIndex_s, dt);
    212202            break;
    213203        }
    214204    }
    215205
    216     template <typename EventType, class Traits>
    217     FORCEINLINE void InputState::buttonEvent(unsigned int device, const typename Traits::ButtonTypeParam button)
     206    template <typename EventType, class ButtonTypeParam>
     207    FORCEINLINE void InputState::buttonEvent(unsigned int device, typename ButtonTypeParam button)
    218208    {
    219209        assert(device < handlers_.size());
    220210        if (handlers_[device] != NULL)
    221             handlers_[device]->buttonEvent(device, button, EventType());
     211        {
     212            // We have to store the function pointer to tell the compiler about its actual type because of overloading
     213            void (InputHandler::*function)(unsigned int, ButtonTypeParam, EventType) = &InputHandler::buttonEvent<ButtonTypeParam>;
     214            InputManager::getInstance().pushCall(boost::function<void ()>(boost::bind(function, handlers_[device], device, button, EventType())));
     215        }
    222216    }
    223217
     
    225219    {
    226220        if (handlers_[mouseIndex_s] != NULL)
    227             handlers_[mouseIndex_s]->mouseMoved(abs, rel, clippingSize);
     221            INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseMoved, abs, rel, clippingSize);
    228222    }
    229223
     
    231225    {
    232226        if (handlers_[mouseIndex_s] != NULL)
    233             handlers_[mouseIndex_s]->mouseScrolled(abs, rel);
     227            INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseScrolled, abs, rel);
    234228    }
    235229
     
    238232        assert(device < handlers_.size());
    239233        if (handlers_[device] != NULL)
    240             handlers_[device]->axisMoved(device - firstJoyStickIndex_s, axis, value);
     234            INPUT_STATE_PUSH_CALL(device, axisMoved, device - firstJoyStickIndex_s, axis, value);
    241235    }
    242236}
Note: See TracChangeset for help on using the changeset viewer.