Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Apr 16, 2010, 2:50:16 PM (15 years ago)
Author:
rgrieder
Message:

Merged gamestates2 branch back to trunk.
This brings in some heavy changes in the GUI framework.
It should also fix problems with triggered asserts in the InputManager.

Note: PickupInventory does not seem to work —> Segfault when showing because before, the owner in GUIOverlay::setGUIName is already NULL.
I haven't tested it before, so I can't tell whether it's my changes.

Location:
code/trunk
Files:
20 edited

Legend:

Unmodified
Added
Removed
  • code/trunk

  • code/trunk/src/libraries/core/Core.cc

    r6417 r6746  
    7878
    7979    SetCommandLineArgument(settingsFile, "orxonox.ini").information("THE configuration file");
     80    SetCommandLineSwitch(noIOConsole).information("Use this if you don't want to use the IOConsole (for instance for Lua debugging)");
    8081#ifdef ORXONOX_PLATFORM_WINDOWS
    8182    SetCommandLineArgument(limitToCPU, 1).information("Limits the program to one CPU/core (1, 2, 3, etc.). Default is the first core (faster than off)");
     
    8889        , consoleCommandDestroyer_(CommandExecutor::destroyExternalCommands)
    8990        , bGraphicsLoaded_(false)
     91        , bStartIOConsole_(true)
    9092    {
    9193        // Set the hard coded fixed paths
     
    149151
    150152        // create persistent io console
    151         this->ioConsole_.reset(new IOConsole());
     153        if (CommandLineParser::getValue("noIOConsole").getBool())
     154        {
     155            ModifyConfigValue(bStartIOConsole_, tset, false);
     156        }
     157        if (this->bStartIOConsole_)
     158            this->ioConsole_.reset(new IOConsole());
    152159
    153160        // creates the class hierarchy for all classes with factories
     
    193200            .description("If true, all random actions are different each time you start the game")
    194201            .callback(this, &Core::initRandomNumberGenerator);
     202        SetConfigValue(bStartIOConsole_, true)
     203            .description("Set to false if you don't want to use the IOConsole (for Lua debugging for instance)");
    195204    }
    196205
     
    225234
    226235        // Load the CEGUI interface
    227         guiManager_.reset(new GUIManager(graphicsManager_->getRenderWindow(),
    228             inputManager_->getMousePosition(), graphicsManager_->isFullScreen()));
     236        guiManager_.reset(new GUIManager(inputManager_->getMousePosition()));
    229237
    230238        bGraphicsLoaded_ = true;
     
    328336        }
    329337        // Process console events and status line
    330         this->ioConsole_->preUpdate(time);
     338        if (this->ioConsole_ != NULL)
     339            this->ioConsole_->preUpdate(time);
    331340        // Process thread commands
    332341        this->tclThreadManager_->preUpdate(time);
  • code/trunk/src/libraries/core/Core.h

    r6417 r6746  
    3838#include "util/ScopeGuard.h"
    3939#include "util/Singleton.h"
    40 #include "core/OrxonoxClass.h"
     40#include "OrxonoxClass.h"
    4141
    4242namespace orxonox
     
    9797            scoped_ptr<TclBind>           tclBind_;
    9898            scoped_ptr<TclThreadManager>  tclThreadManager_;
    99             scoped_ptr<Scope<ScopeID::Root> >     rootScope_;
     99            scoped_ptr<Scope<ScopeID::Root> > rootScope_;
    100100            // graphical
    101101            scoped_ptr<GraphicsManager>   graphicsManager_;     //!< Interface to OGRE
     
    108108            std::string                   language_;                   //!< The language
    109109            bool                          bInitRandomNumberGenerator_; //!< If true, srand(time(0)) is called
     110            bool                          bStartIOConsole_;            //!< Set to false if you don't want to use the IOConsole
    110111
    111112            static Core*                  singletonPtr_s;
  • code/trunk/src/libraries/core/GUIManager.cc

    r6502 r6746  
    3030#include "GUIManager.h"
    3131
     32#include <boost/bind.hpp>
    3233#include <memory>
    3334extern "C" {
     
    4142#include <CEGUISystem.h>
    4243#include <CEGUIWindow.h>
     44#include <CEGUIWindowManager.h>
    4345#include <ogreceguirenderer/OgreCEGUIRenderer.h>
    4446
     
    5759#include "ConsoleCommand.h"
    5860#include "Core.h"
     61#include "GraphicsManager.h"
    5962#include "LuaState.h"
    6063#include "PathConfig.h"
    6164#include "Resource.h"
     65#include "input/InputManager.h"
     66#include "input/InputState.h"
     67#include "input/KeyBinderManager.h"
    6268
    6369namespace orxonox
     
    108114    @return true if success, otherwise false
    109115    */
    110     GUIManager::GUIManager(Ogre::RenderWindow* renderWindow, const std::pair<int, int>& mousePosition, bool bFullScreen)
    111         : renderWindow_(renderWindow)
    112         , resourceProvider_(0)
     116    GUIManager::GUIManager(const std::pair<int, int>& mousePosition)
     117        : resourceProvider_(NULL)
    113118        , camera_(NULL)
    114         , bShowIngameGUI_(false)
    115119    {
    116120        using namespace CEGUI;
     
    119123
    120124        // Note: No SceneManager specified yet
    121         guiRenderer_.reset(new OgreCEGUIRenderer(renderWindow_, Ogre::RENDER_QUEUE_OVERLAY, false, 3000));
     125        guiRenderer_.reset(new OgreCEGUIRenderer(GraphicsManager::getInstance().getRenderWindow(), Ogre::RENDER_QUEUE_OVERLAY, false, 3000));
    122126        resourceProvider_ = guiRenderer_->createResourceProvider();
    123127        resourceProvider_->setDefaultResourceGroup("GUI");
     
    141145        guiSystem_.reset(new System(guiRenderer_.get(), resourceProvider_, 0, scriptModule_.get()));
    142146
    143         // Initialise the basic Lua code
    144         this->luaState_->doFile("InitialiseGUI.lua");
    145 
    146147        // Align CEGUI mouse with OIS mouse
    147148        guiSystem_->injectMousePosition((float)mousePosition.first, (float)mousePosition.second);
    148149
    149         // Hide the mouse cursor unless playing in full screen mode
    150         if (!bFullScreen)
    151             CEGUI::MouseCursor::getSingleton().hide();
     150        // Initialise the Lua framework and load the schemes
     151        this->luaState_->doFile("InitialiseGUI.lua");
     152
     153        // Create the root nodes
     154        this->rootWindow_ = CEGUI::WindowManager::getSingleton().createWindow("MenuWidgets/StaticImage", "AbsoluteRootWindow");
     155        this->rootWindow_->setProperty("FrameEnabled", "False");
     156        this->hudRootWindow_ = CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow", "HUDRootWindow");
     157        this->menuRootWindow_ = CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow", "MenuRootWindow");
     158        // And connect them
     159        CEGUI::System::getSingleton().setGUISheet(this->rootWindow_);
     160        this->rootWindow_->addChildWindow(this->hudRootWindow_);
     161        this->rootWindow_->addChildWindow(this->menuRootWindow_);
     162
     163        // Set up the sheet manager in the Lua framework
     164        this->luaState_->doFile("SheetManager.lua");
    152165    }
    153166
     
    173186    {
    174187        assert(guiSystem_);
    175         guiSystem_->injectTimePulse(time.getDeltaTime());
     188        this->protectedCall(boost::bind(&CEGUI::System::injectTimePulse, _1, time.getDeltaTime()));
    176189    }
    177190
     
    200213    @param str
    201214        reference to string object holding the Lua code which is to be executed
    202 
    203         This function gives total access to the GUI. You can execute ANY Lua code here.
    204215    */
    205216    void GUIManager::executeCode(const std::string& str)
    206217    {
    207218        this->luaState_->doString(str, rootFileInfo_);
     219    }
     220
     221    /** Loads a GUI sheet by Lua script
     222    @param name
     223        The name of the GUI (like the script name, but without the extension)
     224    */
     225    void GUIManager::loadGUI(const std::string& name)
     226    {
     227        this->executeCode("loadSheet(\"" + name + "\")");
    208228    }
    209229
     
    215235
    216236        The function executes the Lua function with the same name in case the GUIManager is ready.
    217         For more details check out loadGUI_2.lua where the function presides.
    218     */
    219     /*static*/ void GUIManager::showGUI(const std::string& name, bool hidePrevious, bool showCursor)
    220     {
    221         GUIManager::getInstance().executeCode("showGUI(\"" + name + "\", " + multi_cast<std::string>(hidePrevious) + ", " + multi_cast<std::string>(showCursor) + ")");
     237    */
     238    /*static*/ void GUIManager::showGUI(const std::string& name, bool bHidePrevious)
     239    {
     240        GUIManager::getInstance().executeCode("showMenuSheet(\"" + name + "\", " + multi_cast<std::string>(bHidePrevious) + ")");
    222241    }
    223242
     
    226245        Hack-ish. Needed for GUIOverlay.
    227246    */
    228     void GUIManager::showGUIExtra(const std::string& name, const std::string& ptr, bool hidePrevious, bool showCursor)
    229     {
    230         this->executeCode("showGUI(\"" + name + "\", " + multi_cast<std::string>(hidePrevious) + ", " + multi_cast<std::string>(showCursor) + ", " + ptr + ")");
     247    void GUIManager::showGUIExtra(const std::string& name, const std::string& ptr, bool bHidePrevious)
     248    {
     249        this->executeCode("showMenuSheet(\"" + name + "\", " + multi_cast<std::string>(bHidePrevious) + ", " + ptr + ")");
    231250    }
    232251
     
    239258    /*static*/ void GUIManager::hideGUI(const std::string& name)
    240259    {
    241         GUIManager::getInstance().executeCode("hideGUI(\"" + name + "\")");
     260        GUIManager::getInstance().executeCode("hideMenuSheet(\"" + name + "\")");
     261    }
     262
     263    const std::string& GUIManager::createInputState(const std::string& name, TriBool::Value showCursor, TriBool::Value useKeyboard, bool bBlockJoyStick)
     264    {
     265        InputState* state = InputManager::getInstance().createInputState(name);
     266
     267        /* Table that maps isFullScreen() and showCursor to mouseExclusive
     268        isFullscreen / showCursor | True  | False | Dontcare
     269        ----------------------------------------------------
     270        true                      | True  | True  | Dontcare
     271        ----------------------------------------------------
     272        false                     | False | True  | Dontcare
     273        */
     274        if (showCursor == TriBool::Dontcare)
     275            state->setMouseExclusive(TriBool::Dontcare);
     276        else if (GraphicsManager::getInstance().isFullScreen() || showCursor == TriBool::False)
     277            state->setMouseExclusive(TriBool::True);
     278        else
     279            state->setMouseExclusive(TriBool::False);
     280
     281        if (showCursor == TriBool::True)
     282            state->setMouseHandler(this);
     283        else if (showCursor == TriBool::False)
     284            state->setMouseHandler(&InputHandler::EMPTY);
     285
     286        if (useKeyboard == TriBool::True)
     287            state->setKeyHandler(this);
     288        else if (useKeyboard == TriBool::False)
     289            state->setKeyHandler(&InputHandler::EMPTY);
     290
     291        if (bBlockJoyStick)
     292            state->setJoyStickHandler(&InputHandler::EMPTY);
     293
     294        return state->getName();
    242295    }
    243296
     
    247300    }
    248301
    249     void GUIManager::setBackground(const std::string& name)
    250     {
    251         this->executeCode("setBackground(\"" + name + "\")");
     302    void GUIManager::setBackgroundImage(const std::string& imageSet, const std::string imageName)
     303    {
     304        if (imageSet.empty() || imageName.empty())
     305            this->setBackgroundImage("");
     306        else
     307            this->setBackgroundImage("set: " + imageSet + " image: " + imageName);
     308    }
     309
     310    void GUIManager::setBackgroundImage(const std::string& image)
     311    {
     312        if (image.empty())
     313            this->rootWindow_->setProperty("Alpha", "0.0");
     314        else
     315            this->rootWindow_->setProperty("Alpha", "1.0");
     316        this->rootWindow_->setProperty("Image", image);
    252317    }
    253318
    254319    void GUIManager::keyPressed(const KeyEvent& evt)
    255320    {
    256         guiSystem_->injectKeyDown(evt.getKeyCode());
    257         guiSystem_->injectChar(evt.getText());
    258     }
     321        this->protectedCall(boost::bind(&CEGUI::System::injectKeyDown, _1, evt.getKeyCode()));
     322        this->protectedCall(boost::bind(&CEGUI::System::injectChar, _1, evt.getText()));
     323    }
     324
    259325    void GUIManager::keyReleased(const KeyEvent& evt)
    260326    {
    261         guiSystem_->injectKeyUp(evt.getKeyCode());
     327        this->protectedCall(boost::bind(&CEGUI::System::injectKeyUp, _1, evt.getKeyCode()));
    262328    }
    263329
     
    273339    void GUIManager::buttonPressed(MouseButtonCode::ByEnum id)
    274340    {
    275         try
    276         {
    277             guiSystem_->injectMouseButtonDown(convertButton(id));
    278         }
    279         catch (CEGUI::ScriptException& ex)
    280         {
    281             // We simply ignore the exception and proceed
    282             COUT(1) << ex.getMessage() << std::endl;
    283         }
     341        this->protectedCall(boost::bind(&CEGUI::System::injectMouseButtonDown, _1, convertButton(id)));
    284342    }
    285343
     
    295353    void GUIManager::buttonReleased(MouseButtonCode::ByEnum id)
    296354    {
    297         try
    298         {
    299             guiSystem_->injectMouseButtonUp(convertButton(id));
    300         }
    301         catch (CEGUI::ScriptException& ex)
    302         {
    303             // We simply ignore the exception and proceed
    304             COUT(1) << ex.getMessage() << std::endl;
    305         }
     355        this->protectedCall(boost::bind(&CEGUI::System::injectMouseButtonUp, _1, convertButton(id)));
    306356    }
    307357
    308358    void GUIManager::mouseMoved(IntVector2 abs, IntVector2 rel, IntVector2 clippingSize)
    309359    {
    310         guiSystem_->injectMousePosition(static_cast<float>(abs.x), static_cast<float>(abs.y));
    311     }
     360        this->protectedCall(boost::bind(&CEGUI::System::injectMousePosition, _1, (float)abs.x, (float)abs.y));
     361    }
     362
    312363    void GUIManager::mouseScrolled(int abs, int rel)
    313364    {
    314         guiSystem_->injectMouseWheelChange(static_cast<float>(rel));
     365        this->protectedCall(boost::bind(&CEGUI::System::injectMouseWheelChange, _1, (float)rel));
    315366    }
    316367
     
    349400    }
    350401
     402    /** Executes a CEGUI function normally, but catches CEGUI::ScriptException.
     403        When a ScriptException occurs, the error message will be displayed and
     404        the program carries on.
     405    @remarks
     406        The exception behaviour may pose problems if the code is not written
     407        exception-safe (and you can forget about that in Lua). The program might
     408        be left in an undefined state. But otherwise one script error would
     409        terminate the whole program...
     410    @note
     411        Your life gets easier if you use boost::bind to create the object/function.
     412    @param function
     413        Any callable object/function that takes this->guiSystem_ as its only parameter.
     414    @return
     415        True if input was handled, false otherwise. A caught exception yields true.
     416    */
     417    template <typename FunctionType>
     418    bool GUIManager::protectedCall(FunctionType function)
     419    {
     420        try
     421        {
     422            return function(this->guiSystem_);
     423        }
     424        catch (CEGUI::ScriptException& ex)
     425        {
     426            // Display the error and proceed. See @remarks why this can be dangerous.
     427            COUT(1) << ex.getMessage() << std::endl;
     428            return true;
     429        }
     430    }
     431
    351432    void GUIManager::subscribeEventHelper(CEGUI::Window* window, const std::string& event, const std::string& function)
    352433    {
  • code/trunk/src/libraries/core/GUIManager.h

    r6417 r6746  
    4141
    4242#include "util/OgreForwardRefs.h"
     43#include "util/TriBool.h"
    4344#include "util/Singleton.h"
    4445#include "input/InputHandler.h"
     46
     47// Tolua includes (have to be relative to the current directory)
     48/*
     49$cfile "../util/TriBool.h" // tolua_export
     50*/
    4551
    4652namespace orxonox // tolua_export
     
    5460
    5561        The GUIManager is a singleton and can be called anywhere when access on the GUI is needed.
    56         Creation of the GUIManager is therefore not possible and the cunstructor is private.
    5762
    5863        Since the GUI needs user input, the GUIManager implements the functions needed to act as a key and/or mouse handler.
     
    6469        friend class Singleton<GUIManager>;
    6570    public:
    66         GUIManager(Ogre::RenderWindow* renderWindow, const std::pair<int, int>& mousePosition, bool bFullScreen);
     71        GUIManager(const std::pair<int, int>& mousePosition);
    6772        ~GUIManager();
    6873
    6974        void preUpdate(const Clock& time);
    7075
    71         static void showGUI(const std::string& name, bool hidePrevious=false, bool showCursor=true);
    72         void showGUIExtra(const std::string& name, const std::string& ptr, bool hidePrevious=false, bool showCursor=true);
     76        void loadGUI(const std::string& name);
     77        static void showGUI(const std::string& name, bool bHidePrevious = false);
     78        void showGUIExtra(const std::string& name, const std::string& ptr, bool bHidePrevious = false);
    7379        static void hideGUI(const std::string& name);
    7480        void keyESC();
    75         void setBackground(const std::string& name);
     81        void setBackgroundImage(const std::string& imageSet, const std::string imageName); // tolua_export
     82        void setBackgroundImage(const std::string& image);
     83
     84        //! Creates a new InputState to be used with a GUI Sheet
     85        const std::string& createInputState(const std::string& name, TriBool::Value showCursor = TriBool::True, TriBool::Value useKeyboard = TriBool::True, bool bBlockJoyStick = false); // tolua_export
     86
     87        //! Returns the root window for all menu sheets
     88        CEGUI::Window* getMenuRootWindow() { return this->menuRootWindow_; } // tolua_export
     89        //! Returns the root window for all HUD sheets
     90        CEGUI::Window* getHUDRootWindow() { return this->hudRootWindow_; } // tolua_export
    7691
    7792        void setCamera(Ogre::Camera* camera);
    7893        Ogre::Camera* getCamera() { return this->camera_; }
    79 
    80         static GUIManager* getInstancePtr() { return singletonPtr_s; }
    8194
    8295        inline void setPlayer(const std::string& guiname, PlayerInfo* player)
     
    88101        static void subscribeEventHelper(CEGUI::Window* window, const std::string& event, const std::string& function); //tolua_export
    89102
     103        static GUIManager& getInstance() { return Singleton<GUIManager>::getInstance(); } // tolua_export
     104
    90105    private:
    91106        GUIManager(const GUIManager& instance); //!< private and undefined copy c'tor (this is a singleton class)
    92107
    93108        void executeCode(const std::string& str);
     109
     110        template <typename FunctionType>
     111        bool protectedCall(FunctionType function);
    94112
    95113        // keyHandler functions
     
    102120        void mouseMoved    (IntVector2 abs, IntVector2 rel, IntVector2 clippingSize);
    103121        void mouseScrolled (int abs, int rel);
    104 
    105122        scoped_ptr<CEGUI::OgreCEGUIRenderer> guiRenderer_;      //!< CEGUI's interface to the Ogre Engine
    106123        scoped_ptr<LuaState>                 luaState_;         //!< LuaState, access point to the Lua engine
     
    108125        scoped_ptr<CEGUI::System>            guiSystem_;        //!< CEGUI's main system
    109126        shared_ptr<ResourceInfo>             rootFileInfo_;     //!< Resource information about the root script
    110         Ogre::RenderWindow*                  renderWindow_;     //!< Ogre's render window to give CEGUI access to it
    111127        CEGUI::ResourceProvider*             resourceProvider_; //!< CEGUI's resource provider
    112128        CEGUI::Logger*                       ceguiLogger_;      //!< CEGUI's logger to be able to log CEGUI errors in our log
    113         std::map<std::string, PlayerInfo*>   players_;          //!< Stores the player (owner) for each gui
     129        CEGUI::Window*                       rootWindow_;       //!< Root node for all windows
     130        CEGUI::Window*                       hudRootWindow_;    //!< Root node for the HUD sheets
     131        CEGUI::Window*                       menuRootWindow_;   //!< Root node for the menu sheets (used by Lua)
     132        std::map<std::string, PlayerInfo*>   players_;          //!< Stores the player (owner) for each GUI
    114133        Ogre::Camera*                        camera_;           //!< Camera used to render the scene with the GUI
    115134
    116135        static GUIManager*                   singletonPtr_s;    //!< Singleton reference to GUIManager
    117         bool                                 bShowIngameGUI_;
    118136
    119137    }; // tolua_export
  • code/trunk/src/libraries/core/Game.h

    r6417 r6746  
    5050#include "util/ScopeGuard.h"
    5151#include "util/Singleton.h"
    52 #include "core/OrxonoxClass.h"
     52#include "OrxonoxClass.h"
    5353
    5454/**
  • code/trunk/src/libraries/core/IOConsole.cc

    r6422 r6746  
    3535#include "util/Clock.h"
    3636#include "util/Math.h"
    37 #include "core/Game.h"
    38 #include "core/input/InputBuffer.h"
     37#include "Game.h"
     38#include "input/InputBuffer.h"
    3939
    4040// ##########################
  • code/trunk/src/libraries/core/IOConsole.h

    r6417 r6746  
    3737#include <vector>
    3838#include "util/Singleton.h"
    39 #include "core/Shell.h"
     39#include "Shell.h"
    4040
    4141#ifdef ORXONOX_PLATFORM_UNIX
  • code/trunk/src/libraries/core/LuaState.cc

    r6417 r6746  
    3737
    3838#include "util/Debug.h"
     39#include "util/Exception.h"
     40#include "util/ScopeGuard.h"
     41#include "IOConsole.h"
    3942#include "Resource.h"
    4043#include "ToluaBindCore.h"
     
    5457        // Create new lua state and configure it
    5558        luaState_ = lua_open();
     59        Loki::ScopeGuard luaStateGuard = Loki::MakeGuard(&lua_close, luaState_);
    5660#if LUA_VERSION_NUM == 501
    5761        luaL_openlibs(luaState_);
     
    7882
    7983        // Parse init script
    80         this->doFile("LuaStateInit.lua");
     84        if (!this->doFile("LuaStateInit.lua"))
     85            ThrowException(InitialisationFailed, "Running LuaStateInit.lua failed");
     86
     87        luaStateGuard.Dismiss();
    8188    }
    8289
     
    96103    }
    97104
    98     void LuaState::includeFile(const std::string& filename)
     105    bool LuaState::includeFile(const std::string& filename)
    99106    {
    100107        shared_ptr<ResourceInfo> sourceInfo = this->getFileInfo(filename);
    101108        if (sourceInfo != NULL)
    102             this->includeString(Resource::open(sourceInfo)->getAsString(), sourceInfo);
    103         else
    104             COUT(2) << "LuaState: Cannot include file '" << filename << "'." << std::endl;
    105     }
    106 
    107     void LuaState::includeString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo)
     109            return this->includeString(Resource::open(sourceInfo)->getAsString(), sourceInfo);
     110        else
     111        {
     112            COUT(2) << "LuaState: Cannot include file '" << filename << "' (not found)." << std::endl;
     113            return false;
     114        }
     115    }
     116
     117    bool LuaState::includeString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo)
    108118    {
    109119        // Parse string with provided include parser (otherwise don't preparse at all)
     
    114124            luaInput = code;
    115125
    116         this->doString(luaInput, sourceFileInfo);
    117     }
    118 
    119     void LuaState::doFile(const std::string& filename)
     126        if (sourceFileInfo != NULL)
     127        {
     128            // Also fill a map with the actual source code. This is just for the include* commands
     129            // where the content of sourceFileInfo->filename doesn't match 'code'
     130            this->sourceCodeMap_[sourceFileInfo->filename] = code;
     131        }
     132
     133        bool returnValue = this->doString(luaInput, sourceFileInfo);
     134
     135        if (sourceFileInfo != NULL)
     136        {
     137            // Delete source code entry
     138            if (sourceFileInfo != NULL)
     139                this->sourceCodeMap_.erase(sourceFileInfo->filename);
     140        }
     141
     142        return returnValue;
     143    }
     144
     145    bool LuaState::doFile(const std::string& filename)
    120146    {
    121147        shared_ptr<ResourceInfo> sourceInfo = this->getFileInfo(filename);
    122148        if (sourceInfo != NULL)
    123             this->doString(Resource::open(sourceInfo)->getAsString(), sourceInfo);
    124         else
    125             COUT(2) << "LuaState: Cannot do file '" << filename << "'." << std::endl;
    126     }
    127 
    128     void LuaState::doString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo)
     149            return this->doString(Resource::open(sourceInfo)->getAsString(), sourceInfo);
     150        else
     151        {
     152            COUT(2) << "LuaState: Cannot do file '" << filename << "' (not found)." << std::endl;
     153            return false;
     154        }
     155    }
     156
     157    bool LuaState::doString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo)
    129158    {
    130159        // Save the old source file info
     
    134163            sourceFileInfo_ = sourceFileInfo;
    135164
    136         int error = 0;
     165        std::string chunkname;
     166        if (sourceFileInfo != NULL)
     167        {
     168            // Provide lua_load with the filename for debug purposes
     169            // The '@' is a Lua convention to identify the chunk name as filename
     170            chunkname = '@' + sourceFileInfo->filename;
     171        }
     172        else
     173        {
     174            // Use the code string to identify the chunk
     175            chunkname = code;
     176        }
     177
     178        // Push custom error handler that uses the debugger
     179        lua_getglobal(this->luaState_, "errorHandler");
     180        int errorHandler = lua_gettop(luaState_);
     181        if (lua_isnil(this->luaState_, -1))
     182        {
     183            lua_pop(this->luaState_, 1);
     184            errorHandler = 0;
     185        }
     186
    137187#if LUA_VERSION_NUM != 501
    138188        LoadS ls;
    139189        ls.s = code.c_str();
    140190        ls.size = code.size();
    141         error = lua_load(luaState_, &orxonox::LuaState::lua_Chunkreader, &ls, code.c_str());
     191        int error = lua_load(luaState_, &orxonox::LuaState::lua_Chunkreader, &ls, chunkname.c_str());
    142192#else
    143         error = luaL_loadstring(luaState_, code.c_str());
     193        int error = luaL_loadbuffer(luaState_, code.c_str(), code.size(), chunkname.c_str());
    144194#endif
    145195
    146         // execute the chunk
     196        switch (error)
     197        {
     198        case LUA_ERRSYNTAX: // Syntax error
     199            COUT(1) << "Lua syntax error: " << lua_tostring(luaState_, -1) << std::endl;
     200            break;
     201        case LUA_ERRMEM:    // Memory allocation error
     202            COUT(1) << "Lua memory allocation error: Consult your dentist immediately!" << std::endl;
     203            break;
     204        }
     205
    147206        if (error == 0)
    148             error = lua_pcall(luaState_, 0, 1, 0);
     207        {
     208            // Execute the chunk in protected mode with an error handler function (stack index)
     209            error = lua_pcall(luaState_, 0, 1, errorHandler);
     210
     211            switch (error)
     212            {
     213            case LUA_ERRRUN: // Runtime error
     214                if (errorHandler)
     215                {
     216                    // Do nothing (we already display the error in the
     217                    // 'errorHandler' Lua function in LuaStateInit.lua)
     218                }
     219                else
     220                {
     221                    std::string errorString = lua_tostring(this->luaState_, -1);
     222                    if (errorString.find("Error propagation") == std::string::npos)
     223                        COUT(1) << "Lua runtime error: " << errorString << std::endl;
     224                }
     225                break;
     226            case LUA_ERRERR: // Error in the error handler
     227                COUT(1) << "Lua error in error handler. No message available." << std::endl;
     228                break;
     229            case LUA_ERRMEM: // Memory allocation error
     230                COUT(1) << "Lua memory allocation error: Consult your dentist immediately!" << std::endl;
     231                break;
     232            }
     233        }
     234
    149235        if (error != 0)
    150236        {
    151             std::string origin;
    152             if (sourceFileInfo != NULL)
    153                 origin = " originating from " + sourceFileInfo_->filename;
    154             COUT(1) << "Error in Lua-script" << origin << ": " << lua_tostring(luaState_, -1) << std::endl;
    155             // return value is nil
    156             lua_pushnil(luaState_);
    157         }
    158         // push return value because it will get lost since the return value of this function is void
     237            lua_pop(luaState_, 1);  // Remove error message
     238            lua_pushnil(luaState_); // Push a nil return value
     239        }
     240
     241        if (errorHandler != 0)
     242            lua_remove(luaState_, errorHandler); // Remove error handler from stack
     243
     244        // Set return value to a global variable because we cannot return a table in this function
     245        // here. It would work for numbers, pointers and strings, but certainly not for Lua tables.
    159246        lua_setglobal(luaState_, "LuaStateReturnValue");
    160247
    161248        // Load the old info again
    162249        sourceFileInfo_ = oldSourceFileInfo;
     250
     251        return (error == 0);
    163252    }
    164253
     
    180269        else
    181270            return true;
     271    }
     272
     273    //! Returns the content of a file
     274    std::string LuaState::getSourceCode(const std::string& filename)
     275    {
     276        // Try the internal map first to get the actual Lua code
     277        // and not just some pseudo Lua-XML code when using include* commands
     278        std::map<std::string, std::string>::const_iterator it = this->sourceCodeMap_.find(filename);
     279        if (it != this->sourceCodeMap_.end())
     280            return it->second;
     281        shared_ptr<ResourceInfo> info = Resource::getInfo(filename);
     282        if (info == NULL)
     283            return "";
     284        else
     285            return Resource::open(info)->getAsString();
     286    }
     287
     288    bool LuaState::usingIOConsole() const
     289    {
     290        return IOConsole::exists();
    182291    }
    183292
  • code/trunk/src/libraries/core/LuaState.h

    r6417 r6746  
    4040
    4141#include "util/ScopeGuard.h"
    42 #include "core/Functor.h"
     42#include "Functor.h"
    4343#include "ToluaInterface.h"
    4444
     
    7171        ~LuaState();
    7272
    73         void doFile(const std::string& filename); // tolua_export
    74         void doString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo = shared_ptr<ResourceInfo>());
     73        bool doFile(const std::string& filename); // tolua_export
     74        bool doString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo = shared_ptr<ResourceInfo>());
    7575
    76         void includeFile(const std::string& filename); // tolua_export
    77         void includeString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo = shared_ptr<ResourceInfo>());
     76        bool includeFile(const std::string& filename); // tolua_export
     77        bool includeString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo = shared_ptr<ResourceInfo>());
    7878
    7979        void luaPrint(const std::string& str); // tolua_export
    8080        void luaLog(unsigned int level, const std::string& message); // tolua_export
    8181        bool fileExists(const std::string& filename); // tolua_export
     82        std::string getSourceCode(const std::string& filename); // tolua_export
    8283
    8384        const std::stringstream& getOutput() const { return output_; }
     
    9192
    9293        Functor* createLuaFunctor(const std::string& code) { return new LuaFunctor(code, this); } // tolua_export
     94        //! Tells about whether IOConsole was activated. The Lua debugger only works with a normal console.
     95        bool usingIOConsole() const; // tolua_export
    9396
    9497        static bool addToluaInterface(int (*function)(lua_State*), const std::string& name);
     
    114117        bool bIsRunning_;
    115118        shared_ptr<ResourceInfo> sourceFileInfo_;
     119        std::map<std::string, std::string> sourceCodeMap_;
    116120        std::string (*includeParseFunction_)(const std::string&);
    117121
  • code/trunk/src/libraries/core/Resource.cc

    r6501 r6746  
    2929#include "Resource.h"
    3030
     31#include <boost/filesystem/path.hpp>
    3132#include <OgreException.h>
     33#include <OgreFileSystem.h>
    3234#include <OgreResourceGroupManager.h>
    3335
     
    8991                ptr->group = group;
    9092                ptr->size = it->uncompressedSize;
     93                if (dynamic_cast<Ogre::FileSystemArchive*>(it->archive) != NULL)
     94                {
     95                    boost::filesystem::path base(it->archive->getName());
     96                    base /= it->filename;
     97                    ptr->fileSystemPath = base.string();
     98                }
    9199                return ptr;
    92100            }
  • code/trunk/src/libraries/core/Resource.h

    r6417 r6746  
    5757        //! Uncompressed size
    5858        size_t size;
     59        //! Absolute file path ("" for files not on filesystem)
     60        std::string fileSystemPath;
    5961    };
    6062
  • code/trunk/src/libraries/core/Template.cc

    r6417 r6746  
    3333
    3434#include "util/Debug.h"
    35 #include "core/CoreIncludes.h"
    36 #include "core/XMLPort.h"
     35#include "CoreIncludes.h"
     36#include "XMLPort.h"
    3737
    3838namespace orxonox
  • code/trunk/src/libraries/core/input/InputDevice.h

    r6417 r6746  
    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, typename 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, typename 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, typename Traits::ButtonTypeParam>(this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(button));
    221221        }
    222222
  • code/trunk/src/libraries/core/input/InputHandler.h

    r6105 r6746  
    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)
    121             { this->buttonPressed(device - InputDeviceEnumerator::FirstJoyStick, button); }
    122         void buttonEvent(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::TRelease)
    123             { this->buttonReleased(device - InputDeviceEnumerator::FirstJoyStick, button); }
    124         void buttonEvent(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::THold)
    125             { this->buttonHeld(device - InputDeviceEnumerator::FirstJoyStick, button); }
    126120
    127121        virtual void buttonPressed (const KeyEvent& evt) { }
     
    149143        static InputHandler EMPTY;
    150144    };
     145
     146    template<> inline void InputHandler::buttonEvent<JoyStickButtonCode::ByEnum>(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::TPress)
     147        { this->buttonPressed(device - InputDeviceEnumerator::FirstJoyStick, button); }
     148    template<> inline void InputHandler::buttonEvent<JoyStickButtonCode::ByEnum>(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::TRelease)
     149        { this->buttonReleased(device - InputDeviceEnumerator::FirstJoyStick, button); }
     150    template<> inline void InputHandler::buttonEvent<JoyStickButtonCode::ByEnum>(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::THold)
     151        { this->buttonHeld(device - InputDeviceEnumerator::FirstJoyStick, button); }
    151152}
    152153
  • code/trunk/src/libraries/core/input/InputManager.cc

    r6422 r6746  
    8787        , oisInputManager_(0)
    8888        , devices_(2)
    89         , mouseMode_(MouseMode::Nonexclusive)
     89        , exclusiveMouse_(TriBool::False)
    9090        , emptyState_(0)
    9191        , calibratorCallbackHandler_(0)
     
    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
    99102        if (GraphicsManager::getInstance().isFullScreen())
    100             mouseMode_ = MouseMode::Exclusive;
     103            exclusiveMouse_ = TriBool::True;
    101104        this->loadDevices();
    102105
     
    155158        paramList.insert(std::make_pair("w32_keyboard", "DISCL_FOREGROUND"));
    156159        paramList.insert(std::make_pair("w32_mouse", "DISCL_FOREGROUND"));
    157         if (mouseMode_ == MouseMode::Exclusive || GraphicsManager::getInstance().isFullScreen())
     160        if (exclusiveMouse_ == TriBool::True || GraphicsManager::getInstance().isFullScreen())
    158161        {
    159162            // Disable Windows key plus special keys (like play, stop, next, etc.)
     
    168171        paramList.insert(std::make_pair("XAutoRepeatOn", "true"));
    169172
    170         if (mouseMode_ == MouseMode::Exclusive || GraphicsManager::getInstance().isFullScreen())
     173        if (exclusiveMouse_ == TriBool::True || GraphicsManager::getInstance().isFullScreen())
    171174        {
    172175            if (CommandLineParser::getValue("keyboard_no_grab").getBool())
     
    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 function 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);
    473         // temporary resize
     416        // Calculate the stack of input states
     417        // and assign it to the corresponding device
    474418        for (unsigned int i = 0; i < devices_.size(); ++i)
    475419        {
     
    490434        }
    491435
    492         // update tickables (every state will only appear once)
    493         // Using a std::set to avoid duplicates
     436        // See that we only update each InputState once for each device
     437        // Using an std::set to avoid duplicates
    494438        std::set<InputState*> tempSet;
    495439        for (unsigned int i = 0; i < devices_.size(); ++i)
     
    498442                    tempSet.insert(devices_[i]->getStateListRef()[iState]);
    499443
    500         // copy the content of the std::set back to the actual vector
     444        // Copy the content of the std::set back to the actual vector
    501445        activeStatesTicked_.clear();
    502446        for (std::set<InputState*>::const_iterator it = tempSet.begin();it != tempSet.end(); ++it)
     
    504448
    505449        // Check whether we have to change the mouse mode
    506         MouseMode::Value requestedMode = MouseMode::Dontcare;
     450        TriBool::Value requestedMode = TriBool::Dontcare;
    507451        std::vector<InputState*>& mouseStates = devices_[InputDeviceEnumerator::Mouse]->getStateListRef();
    508452        if (mouseStates.empty())
    509             requestedMode = MouseMode::Nonexclusive;
    510         else
    511             requestedMode = mouseStates.front()->getMouseMode();
    512         if (requestedMode != MouseMode::Dontcare && mouseMode_ != requestedMode)
    513         {
    514             mouseMode_ = requestedMode;
     453            requestedMode = TriBool::False;
     454        else
     455            requestedMode = mouseStates.front()->getMouseExclusive();
     456        if (requestedMode != TriBool::Dontcare && exclusiveMouse_ != requestedMode)
     457        {
     458            exclusiveMouse_ = requestedMode;
    515459            if (!GraphicsManager::getInstance().isFullScreen())
    516460                this->reloadInternal();
     
    622566        // get pointer from the map with all stored handlers
    623567        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())
     568        if (it != statesByName_.end() && activeStates_.find(it->second->getPriority()) == activeStates_.end())
     569        {
     570            // exists and not active
     571            if (it->second->getPriority() == 0)
     572            {
     573                // Get smallest possible priority between 1 and maxStateStackSize_s
     574                for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin();
     575                    rit != activeStates_.rend(); ++rit)
    631576                {
    632                     // not scheduled for destruction
    633                     // prevents a state from being added multiple times
    634                     stateEnterRequests_.insert(it->second);
    635                     return true;
     577                    if (rit->first < InputStatePriority::HighPriority)
     578                    {
     579                        it->second->setPriority(rit->first + 1);
     580                        break;
     581                    }
    636582                }
    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             }
     583                // In case no normal handler was on the stack
     584                if (it->second->getPriority() == 0)
     585                    it->second->setPriority(1);
     586            }
     587            activeStates_[it->second->getPriority()] = it->second;
     588            updateActiveStates();
     589            it->second->entered();
     590
     591            return true;
    643592        }
    644593        return false;
     
    654603        // get pointer from the map with all stored handlers
    655604        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             }
     605        if (it != statesByName_.end() && activeStates_.find(it->second->getPriority()) != activeStates_.end())
     606        {
     607            // exists and active
     608
     609            it->second->left();
     610
     611            activeStates_.erase(it->second->getPriority());
     612            if (it->second->getPriority() < InputStatePriority::HighPriority)
     613                it->second->setPriority(0);
     614            updateActiveStates();
     615
     616            return true;
    670617        }
    671618        return false;
     
    682629        if (it != statesByName_.end())
    683630        {
    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);
     631            this->leaveState(name);
     632            destroyStateInternal(it->second);
    697633
    698634            return true;
     
    704640    void InputManager::destroyStateInternal(InputState* state)
    705641    {
    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         }
     642        assert(state && this->activeStates_.find(state->getPriority()) == this->activeStates_.end());
    713643        statesByName_.erase(state->getName());
    714644        state->destroy();
  • code/trunk/src/libraries/core/input/InputManager.h

    r6417 r6746  
    3636#include <string>
    3737#include <vector>
     38#include <boost/function.hpp>
    3839
    3940#include "util/Singleton.h"
     41#include "util/TriBool.h"
    4042#include "core/WindowEventListener.h"
    41 #include "InputState.h"
    4243
    4344// tolua_begin
     
    7576            Nothing       = 0x00,
    7677            Bad           = 0x02,
    77             Ticking       = 0x04,
    78             Calibrating   = 0x08,
    79             ReloadRequest = 0x10,
     78            Calibrating   = 0x04,
    8079        };
    8180
     
    159158            - The removal process is being postponed if InputManager::preUpdate() is currently running.
    160159        */
    161         bool destroyState(const std::string& name);
     160        bool destroyState(const std::string& name); // tolua_export
    162161
    163162        //-------------------------------
     
    169168        //! Returns a pointer to the OIS InputManager. Only you if you know what you're doing!
    170169        OIS::InputManager* getOISInputManager() { return this->oisInputManager_; }
     170        //! Returns the position of the cursor as std::pair of ints
    171171        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); }
    172180
    173181        static InputManager& getInstance() { return Singleton<InputManager>::getInstance(); } // tolua_export
     
    196204        OIS::InputManager*                  oisInputManager_;      //!< OIS input manager
    197205        std::vector<InputDevice*>           devices_;              //!< List of all input devices (keyboard, mouse, joy sticks)
    198         MouseMode::Value                    mouseMode_;            //!< Currently applied mouse mode
     206        TriBool::Value                      exclusiveMouse_;       //!< Currently applied mouse mode
    199207
    200208        // some internally handled states and handlers
     
    207215        std::vector<InputState*>            activeStatesTicked_;   //!< Like activeStates_, but only contains the ones that currently receive events
    208216
    209         std::set<InputState*>               stateEnterRequests_;   //!< Requests to enter a new state
    210         std::set<InputState*>               stateLeaveRequests_;   //!< Requests to leave a running state
    211         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)
    212218
    213219        static InputManager*                singletonPtr_s;        //!< Pointer reference to the singleton
  • code/trunk/src/libraries/core/input/InputPrereqs.h

    r6417 r6746  
    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/trunk/src/libraries/core/input/InputState.cc

    r6417 r6746  
    3737        , bAlwaysGetsInput_(bAlwaysGetsInput)
    3838        , bTransparent_(bTransparent)
    39         , mouseMode_(MouseMode::Dontcare)
     39        , exclusiveMouse_(TriBool::Dontcare)
    4040        , bExpired_(true)
    4141        , handlers_(2)
  • code/trunk/src/libraries/core/input/InputState.h

    r5929 r6746  
    3535#include <string>
    3636#include <vector>
    37 
    38 #include "util/OrxEnum.h"
     37#include <boost/function.hpp>
     38#include <boost/bind.hpp>
     39
     40#include "util/TriBool.h"
    3941#include "InputHandler.h"
     42#include "InputManager.h"
    4043#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__)))
    4147
    4248namespace orxonox
    4349{
    44     //! Enumeration wrapper for input state priorities
    45     struct InputStatePriority : OrxEnum<InputStatePriority>
    46     {
    47         OrxEnumConstructors(InputStatePriority);
    48 
    49         static const int Empty        = -1;
    50         static const int Dynamic      = 0;
    51 
    52         static const int HighPriority = 1000;
    53         static const int Console      = HighPriority + 0;
    54         static const int Calibrator   = HighPriority + 1;
    55         static const int Detector     = HighPriority + 2;
    56     };
    57 
    58     namespace MouseMode
    59     {
    60         enum Value
    61         {
    62             Exclusive,
    63             Nonexclusive,
    64             Dontcare
    65         };
    66     }
    67 
    6850    /**
    6951    @brief
     
    7355        that stack and only the top one gets the input events. This is done for
    7456        every device (keyboard, mouse, all joy sticks) separately to allow
    75         for intance keyboard input capturing for the console while you can still
     57        for instance keyboard input capturing for the console while you can still
    7658        steer a ship with the mouse.
    7759        There are two exceptions to this behaviour though:
     
    8365          the state will always receive input as long as it is activated.
    8466        - Note: If you mark an InputState with both parameters on, then it will
    85           not influence ony other InputState at all.
     67          not influence only other InputState at all.
    8668
    8769    @par Priorities
     
    9577    @par Exclusive/Non-Exclusive mouse Mode
    9678        You can select a specific mouse mode that tells whether the application
    97         should have exclusive accessto it or not.
     79        should have exclusive access to it or not.
    9880        When in non-exclusive mode, you can move the mouse out of the window
    9981        like with any other normal window (only for windowed mode!).
     
    130112        void setHandler        (InputHandler* handler);
    131113
    132         void setMouseMode(MouseMode::Value value) { mouseMode_ = value; this->bExpired_ = true; }
    133         MouseMode::Value getMouseMode() const { return mouseMode_; }
     114        void setMouseExclusive(TriBool::Value value) { exclusiveMouse_ = value; this->bExpired_ = true; }
     115        TriBool::Value getMouseExclusive() const { return exclusiveMouse_; }
    134116
    135117        //! Returns the name of the state (which is unique!)
     
    152134
    153135        //! Generic function that distributes all 9 button events
    154         template <typename EventType, class Traits>
    155         void buttonEvent(unsigned int device, const typename Traits::ButtonTypeParam button);
     136        template <typename EventType, class ButtonTypeParam>
     137        void buttonEvent(unsigned int device, ButtonTypeParam button);
    156138
    157139        //! Event handler
     
    184166        const bool                  bAlwaysGetsInput_;      //!< See class declaration for explanation
    185167        const bool                  bTransparent_;          //!< See class declaration for explanation
    186         MouseMode::Value            mouseMode_;             //!< See class declaration for explanation
     168        TriBool::Value              exclusiveMouse_;        //!< See class declaration for explanation
    187169        int                         priority_;              //!< Current priority (might change)
    188170        bool                        bExpired_;              //!< See hasExpired()
     
    198180        for (unsigned int i = 0; i < handlers_.size(); ++i)
    199181            if (handlers_[i] != NULL)
    200                 handlers_[i]->allDevicesUpdated(dt);
     182                INPUT_STATE_PUSH_CALL(i, allDevicesUpdated, dt);
    201183    }
    202184
     
    207189        case InputDeviceEnumerator::Keyboard:
    208190            if (handlers_[keyboardIndex_s] != NULL)
    209                 handlers_[keyboardIndex_s]->keyboardUpdated(dt);
     191                INPUT_STATE_PUSH_CALL(keyboardIndex_s, keyboardUpdated, dt);
    210192            break;
    211193
    212194        case InputDeviceEnumerator::Mouse:
    213195            if (handlers_[mouseIndex_s] != NULL)
    214                 handlers_[mouseIndex_s]->mouseUpdated(dt);
     196                INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseUpdated, dt);
    215197            break;
    216198
    217199        default: // joy sticks
    218200            if (handlers_[device] != NULL)
    219                 handlers_[device]->joyStickUpdated(device - firstJoyStickIndex_s, dt);
     201                INPUT_STATE_PUSH_CALL(device, joyStickUpdated, device - firstJoyStickIndex_s, dt);
    220202            break;
    221203        }
    222204    }
    223205
    224     template <typename EventType, class Traits>
    225     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, ButtonTypeParam button)
    226208    {
    227209        assert(device < handlers_.size());
    228210        if (handlers_[device] != NULL)
    229             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        }
    230216    }
    231217
     
    233219    {
    234220        if (handlers_[mouseIndex_s] != NULL)
    235             handlers_[mouseIndex_s]->mouseMoved(abs, rel, clippingSize);
     221            INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseMoved, abs, rel, clippingSize);
    236222    }
    237223
     
    239225    {
    240226        if (handlers_[mouseIndex_s] != NULL)
    241             handlers_[mouseIndex_s]->mouseScrolled(abs, rel);
     227            INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseScrolled, abs, rel);
    242228    }
    243229
     
    246232        assert(device < handlers_.size());
    247233        if (handlers_[device] != NULL)
    248             handlers_[device]->axisMoved(device - firstJoyStickIndex_s, axis, value);
     234            INPUT_STATE_PUSH_CALL(device, axisMoved, device - firstJoyStickIndex_s, axis, value);
    249235    }
    250236}
Note: See TracChangeset for help on using the changeset viewer.