Index: code/trunk/src/libraries/core/CMakeLists.txt
===================================================================
--- code/trunk/src/libraries/core/CMakeLists.txt	(revision 7958)
+++ code/trunk/src/libraries/core/CMakeLists.txt	(revision 8079)
@@ -35,5 +35,4 @@
   OrxonoxClass.cc
   Resource.cc
-  WindowEventListener.cc
 
   # hierarchy
@@ -49,5 +48,10 @@
   Template.cc
   XMLPort.cc
+
+COMPILATION_BEGIN ListenerCompilation.cc
+  ViewportEventListener.cc
+  WindowEventListener.cc
   XMLNameListener.cc
+COMPILATION_END
 
 COMPILATION_BEGIN FilesystemCompilation.cc
@@ -76,4 +80,5 @@
     Game.h
     GameMode.h
+    GraphicsManager.h
     GUIManager.h
     Loader.h
Index: code/trunk/src/libraries/core/Core.cc
===================================================================
--- code/trunk/src/libraries/core/Core.cc	(revision 7958)
+++ code/trunk/src/libraries/core/Core.cc	(revision 8079)
@@ -208,6 +208,10 @@
 #ifdef ORXONOX_RELEASE
         const unsigned int defaultLevelLogFile = 3;
+        SetConfigValue(bDevMode_, false)
+            .description("Developer mode. If not set, hides some things from the user to not confuse him.");
 #else
         const unsigned int defaultLevelLogFile = 4;
+        SetConfigValue(bDevMode_, true)
+            .description("Developer mode. If not set, hides some things from the user to not confuse him.");
 #endif
         SetConfigValueExternal(softDebugLevelLogFile_, "OutputHandler", "softDebugLevelLogFile", defaultLevelLogFile)
Index: code/trunk/src/libraries/core/Core.h
===================================================================
--- code/trunk/src/libraries/core/Core.h	(revision 7958)
+++ code/trunk/src/libraries/core/Core.h	(revision 8079)
@@ -91,4 +91,7 @@
                 { return this->ogreConfigTimestamp_; }
 
+            inline bool inDevMode(void) const
+                { return this->bDevMode_; }
+
         private:
             Core(const Core&); //!< Don't use (undefined symbol)
@@ -130,4 +133,5 @@
             long long                     lastLevelTimestamp_;         ///< Timestamp when the last level was started
             long long                     ogreConfigTimestamp_;        ///< Timestamp wehen the ogre config level was modified
+            bool                          bDevMode_;                   //!< Developers bit. If set to false, some options are not available as to not confuse the normal user.
 
             static Core*                  singletonPtr_s;
Index: code/trunk/src/libraries/core/CorePrereqs.h
===================================================================
--- code/trunk/src/libraries/core/CorePrereqs.h	(revision 7958)
+++ code/trunk/src/libraries/core/CorePrereqs.h	(revision 8079)
@@ -182,4 +182,5 @@
     class Thread;
     class ThreadPool;
+    class ViewportEventListener;
     template <class T>
     class WeakPtr;
Index: code/trunk/src/libraries/core/GUIManager.cc
===================================================================
--- code/trunk/src/libraries/core/GUIManager.cc	(revision 7958)
+++ code/trunk/src/libraries/core/GUIManager.cc	(revision 8079)
@@ -32,7 +32,5 @@
 #include <boost/bind.hpp>
 #include <memory>
-extern "C" {
-#include <lua.h>
-}
+
 #include <CEGUIDefaultLogger.h>
 #include <CEGUIExceptions.h>
@@ -107,4 +105,5 @@
     SetConsoleCommand("showGUI", &GUIManager::showGUI).defaultValue(1, false).defaultValue(2, false);
     SetConsoleCommand("hideGUI", &GUIManager::hideGUI);
+    SetConsoleCommand("toggleGUI", &GUIManager::toggleGUI).defaultValue(1, false).defaultValue(2, false);
 
     /**
@@ -284,4 +283,27 @@
     {
         GUIManager::getInstance().executeCode("hideMenuSheet(\"" + name + "\")");
+    }
+
+    /**
+    @brief
+        Toggles specified GUI.
+        If the GUI with the input name is already shown and on the top, it is hidden, else it is shown.
+    */
+    /*static*/ void GUIManager::toggleGUI(const std::string& name, bool bHidePrevious, bool bNoInput)
+    {
+        GUIManager::getInstance().executeCode("getGUIFirstActive(\"" + name + "\", " + multi_cast<std::string>(bHidePrevious) + ", " + multi_cast<std::string>(bNoInput) + ")");
+    }
+
+    /**
+    @brief
+        Helper method to toggle a specified GUI.
+        Is called by lua.
+    */
+    void GUIManager::toggleGUIHelper(const std::string& name, bool bHidePrevious, bool bNoInput, bool show)
+    {
+        if(show)
+            GUIManager::showGUI(name, bHidePrevious, bNoInput);
+        else
+            GUIManager::hideGUI(name);
     }
 
@@ -512,9 +534,9 @@
     void GUIManager::windowResized(unsigned int newWidth, unsigned int newHeight)
     {
-        this->guiRenderer_->setDisplaySize(CEGUI::Size(newWidth, newHeight));
-    }
-
-    /**
-        @brief Notify CEGUI if the windows loses the focus (stops higlight of menu items, etc).
+        this->guiRenderer_->setDisplaySize(CEGUI::Size((float)newWidth, (float)newHeight));
+    }
+
+    /**
+        @brief Notify CEGUI if the windows loses the focus (stops highlighting of menu items, etc).
     */
     void GUIManager::windowFocusChanged(bool bFocus)
Index: code/trunk/src/libraries/core/GUIManager.h
===================================================================
--- code/trunk/src/libraries/core/GUIManager.h	(revision 7958)
+++ code/trunk/src/libraries/core/GUIManager.h	(revision 8079)
@@ -49,4 +49,5 @@
 #include "util/Singleton.h"
 #include "input/InputHandler.h"
+#include "Core.h"
 #include "OrxonoxClass.h"
 #include "WindowEventListener.h"
@@ -88,7 +89,15 @@
         void showGUIExtra(const std::string& name, const std::string& ptr, bool bHidePrevious = false, bool bNoInput = false);
         static void hideGUI(const std::string& name);
+        static void toggleGUI(const std::string& name, bool bHidePrevious = false, bool bNoInput = false);
+        void toggleGUIHelper(const std::string& name, bool bHidePrevious, bool bNoInput, bool show); // tolua_export
         void keyESC();
         void setBackgroundImage(const std::string& imageSet, const std::string imageName); // tolua_export
         void setBackgroundImage(const std::string& image);
+
+        /**
+        @brief Helper method to get the developer's mode without having to export Core.h.
+        @see Core::inDevMode
+        */
+        static bool inDevMode(void) { return Core::getInstance().inDevMode(); } // tolua_export
 
         //! Creates a new InputState to be used with a GUI Sheet
Index: code/trunk/src/libraries/core/Game.cc
===================================================================
--- code/trunk/src/libraries/core/Game.cc	(revision 7958)
+++ code/trunk/src/libraries/core/Game.cc	(revision 8079)
@@ -50,4 +50,5 @@
 #include "GameMode.h"
 #include "GameState.h"
+#include "GraphicsManager.h"
 #include "GUIManager.h"
 #include "command/ConsoleCommand.h"
@@ -60,8 +61,8 @@
     static void printFPS()
         { COUT(0) << Game::getInstance().getAvgFPS() << std::endl; }
-    SetConsoleCommand("printFPS", &printFPS);
+    SetConsoleCommand("Stats", "printFPS", &printFPS);
     static void printTickTime()
         { COUT(0) << Game::getInstance().getAvgTickTime() << std::endl; }
-    SetConsoleCommand("printTickTime", &printTickTime);
+    SetConsoleCommand("Stats", "printTickTime", &printTickTime);
 
     std::map<std::string, GameStateInfo> Game::gameStateDeclarations_s;
@@ -142,5 +143,6 @@
         SetConfigValue(statisticsAvgLength_, 1000000)
             .description("Sets the time in microseconds interval at which average fps, etc. gets calculated.");
-        SetConfigValue(fpsLimit_, 50)
+
+        SetConfigValueExternal(fpsLimit_, "GraphicsSettings", "fpsLimit", 50)
             .description("Sets the desired frame rate (0 for no limit).");
     }
@@ -207,5 +209,7 @@
 
             // Limit frame rate
-            this->updateFPSLimiter();
+            static bool hasVSync = GraphicsManager::getInstance().hasVSyncEnabled(); // can be static since changes of VSync currently require a restart
+            if (this->fpsLimit_ > 0 && !hasVSync)
+                this->updateFPSLimiter();
         }
 
Index: code/trunk/src/libraries/core/GraphicsManager.cc
===================================================================
--- code/trunk/src/libraries/core/GraphicsManager.cc	(revision 7958)
+++ code/trunk/src/libraries/core/GraphicsManager.cc	(revision 8079)
@@ -49,4 +49,5 @@
 #include "SpecialConfig.h"
 #include "util/Clock.h"
+#include "util/Convert.h"
 #include "util/Exception.h"
 #include "util/StringUtils.h"
@@ -57,13 +58,24 @@
 #include "Game.h"
 #include "GameMode.h"
+#include "GUIManager.h"
 #include "Loader.h"
 #include "MemoryArchive.h"
 #include "PathConfig.h"
+#include "ViewportEventListener.h"
 #include "WindowEventListener.h"
 #include "XMLFile.h"
 #include "command/ConsoleCommand.h"
+#include "input/InputManager.h"
 
 namespace orxonox
 {
+    static const std::string __CC_GraphicsManager_group = "GraphicsManager";
+    static const std::string __CC_setScreenResolution_name = "setScreenResolution";
+    static const std::string __CC_setFSAA_name = "setFSAA";
+    static const std::string __CC_setVSync_name = "setVSync";
+    DeclareConsoleCommand(__CC_GraphicsManager_group, __CC_setScreenResolution_name, &prototype::string__uint_uint_bool);
+    DeclareConsoleCommand(__CC_GraphicsManager_group, __CC_setFSAA_name, &prototype::string__string);
+    DeclareConsoleCommand(__CC_GraphicsManager_group, __CC_setVSync_name, &prototype::string__bool);
+
     static const std::string __CC_printScreen_name = "printScreen";
     DeclareConsoleCommand(__CC_printScreen_name, &prototype::void__void);
@@ -95,4 +107,6 @@
         , renderWindow_(0)
         , viewport_(0)
+        , lastFrameStartTime_(0.0f)
+        , lastFrameEndTime_(0.0f)
     {
         RegisterObject(GraphicsManager);
@@ -136,4 +150,7 @@
         Ogre::WindowEventUtilities::removeWindowEventListener(renderWindow_, ogreWindowEventListener_.get());
         ModifyConsoleCommand(__CC_printScreen_name).resetFunction();
+        ModifyConsoleCommand(__CC_GraphicsManager_group, __CC_setScreenResolution_name).resetFunction();
+        ModifyConsoleCommand(__CC_GraphicsManager_group, __CC_setFSAA_name).resetFunction();
+        ModifyConsoleCommand(__CC_GraphicsManager_group, __CC_setVSync_name).resetFunction();
 
         // Undeclare the resources
@@ -304,5 +321,9 @@
         CCOUT(4) << "Configuring Renderer" << std::endl;
 
-        if (!ogreRoot_->restoreConfig() || Core::getInstance().getOgreConfigTimestamp() > Core::getInstance().getLastLevelTimestamp())
+        bool updatedConfig = Core::getInstance().getOgreConfigTimestamp() > Core::getInstance().getLastLevelTimestamp();
+        if (updatedConfig)
+            COUT(2) << "Ogre config file has changed, but no level was started since then. Displaying config dialogue again to verify the changes." << std::endl;
+
+        if (!ogreRoot_->restoreConfig() || updatedConfig)
         {
             if (!ogreRoot_->showConfigDialog())
@@ -330,4 +351,7 @@
         // add console commands
         ModifyConsoleCommand(__CC_printScreen_name).setFunction(&GraphicsManager::printScreen, this);
+        ModifyConsoleCommand(__CC_GraphicsManager_group, __CC_setScreenResolution_name).setFunction(&GraphicsManager::setScreenResolution, this);
+        ModifyConsoleCommand(__CC_GraphicsManager_group, __CC_setFSAA_name).setFunction(&GraphicsManager::setFSAA, this);
+        ModifyConsoleCommand(__CC_GraphicsManager_group, __CC_setVSync_name).setFunction(&GraphicsManager::setVSync, this);
     }
 
@@ -343,17 +367,21 @@
     @note
         A note about the Ogre::FrameListener: Even though we don't use them,
-        they still get called. However, the delta times are not correct (except
-        for timeSinceLastFrame, which is the most important). A little research
-        as shown that there is probably only one FrameListener that doesn't even
-        need the time. So we shouldn't run into problems.
+        they still get called.
     */
     void GraphicsManager::postUpdate(const Clock& time)
     {
+        // Time before rendering
+        uint64_t timeBeforeTick = time.getRealMicroseconds();
+
+        // Ogre's time keeping object
         Ogre::FrameEvent evt;
-        evt.timeSinceLastFrame = time.getDeltaTime();
-        evt.timeSinceLastEvent = time.getDeltaTime(); // note: same time, but shouldn't matter anyway
-
-        // don't forget to call _fireFrameStarted to OGRE to make sure
-        // everything goes smoothly
+
+        // Translate to Ogre float times before the update
+        float temp = lastFrameStartTime_;
+        lastFrameStartTime_ = (float)timeBeforeTick * 0.000001f;
+        evt.timeSinceLastFrame = lastFrameStartTime_ - temp;
+        evt.timeSinceLastEvent = lastFrameStartTime_ - lastFrameEndTime_;
+
+        // Ogre requires the time too
         ogreRoot_->_fireFrameStarted(evt);
 
@@ -361,10 +389,7 @@
         // This calls the WindowEventListener objects.
         Ogre::WindowEventUtilities::messagePump();
-        // make sure the window stays active even when not focused
+        // Make sure the window stays active even when not focused
         // (probably only necessary on windows)
         this->renderWindow_->setActive(true);
-
-        // Time before rendering
-        uint64_t timeBeforeTick = time.getRealMicroseconds();
 
         // Render frame
@@ -375,11 +400,23 @@
         Game::getInstance().subtractTickTime((int32_t)(timeAfterTick - timeBeforeTick));
 
-        // again, just to be sure OGRE works fine
-        ogreRoot_->_fireFrameEnded(evt); // note: uses the same time as _fireFrameStarted
+        // Translate to Ogre float times after the update
+        temp = lastFrameEndTime_;
+        lastFrameEndTime_ = (float)timeBeforeTick * 0.000001f;
+        evt.timeSinceLastFrame = lastFrameEndTime_ - temp;
+        evt.timeSinceLastEvent = lastFrameEndTime_ - lastFrameStartTime_;
+
+        // Ogre also needs the time after the frame finished
+        ogreRoot_->_fireFrameEnded(evt);
     }
 
     void GraphicsManager::setCamera(Ogre::Camera* camera)
     {
+        Ogre::Camera* oldCamera = this->viewport_->getCamera();
+
         this->viewport_->setCamera(camera);
+        GUIManager::getInstance().setCamera(camera);
+
+        for (ObjectList<ViewportEventListener>::iterator it = ObjectList<ViewportEventListener>::begin(); it != ObjectList<ViewportEventListener>::end(); ++it)
+            it->cameraChanged(this->viewport_, oldCamera);
     }
 
@@ -440,17 +477,104 @@
     bool GraphicsManager::isFullScreen() const
     {
+        return this->renderWindow_->isFullScreen();
+    }
+
+    unsigned int GraphicsManager::getWindowWidth() const
+    {
+        return this->renderWindow_->getWidth();
+    }
+
+    unsigned int GraphicsManager::getWindowHeight() const
+    {
+        return this->renderWindow_->getHeight();
+    }
+
+    bool GraphicsManager::hasVSyncEnabled() const
+    {
         Ogre::ConfigOptionMap& options = ogreRoot_->getRenderSystem()->getConfigOptions();
-        if (options.find("Full Screen") != options.end())
-        {
-            if (options["Full Screen"].currentValue == "Yes")
-                return true;
-            else
-                return false;
-        }
+        Ogre::ConfigOptionMap::iterator it = options.find("VSync");
+        if (it != options.end())
+            return (it->second.currentValue == "Yes");
         else
-        {
-            COUT(0) << "Could not find 'Full Screen' render system option. Fix This!!!" << std::endl;
             return false;
-        }
+    }
+
+    std::string GraphicsManager::getFSAAMode() const
+    {
+        Ogre::ConfigOptionMap& options = ogreRoot_->getRenderSystem()->getConfigOptions();
+        Ogre::ConfigOptionMap::iterator it = options.find("FSAA");
+        if (it != options.end())
+            return it->second.currentValue;
+        else
+            return "";
+    }
+
+    std::string GraphicsManager::setScreenResolution(unsigned int width, unsigned int height, bool fullscreen)
+    {
+        // workaround to detect if the colour depth should be written to the config file
+        bool bWriteColourDepth = false;
+        Ogre::ConfigOptionMap& options = ogreRoot_->getRenderSystem()->getConfigOptions();
+        Ogre::ConfigOptionMap::iterator it = options.find("Video Mode");
+        if (it != options.end())
+            bWriteColourDepth = (it->second.currentValue.find('@') != std::string::npos);
+
+        if (bWriteColourDepth)
+        {
+            this->ogreRoot_->getRenderSystem()->setConfigOption("Video Mode", multi_cast<std::string>(width)
+                                                                    + " x " + multi_cast<std::string>(height)
+                                                                    + " @ " + multi_cast<std::string>(this->getRenderWindow()->getColourDepth()) + "-bit colour");
+        }
+        else
+        {
+            this->ogreRoot_->getRenderSystem()->setConfigOption("Video Mode", multi_cast<std::string>(width)
+                                                                    + " x " + multi_cast<std::string>(height));
+        }
+
+        this->ogreRoot_->getRenderSystem()->setConfigOption("Full Screen", fullscreen ? "Yes" : "No");
+
+        std::string validate = this->ogreRoot_->getRenderSystem()->validateConfigOptions();
+
+        if (validate == "")
+        {
+            GraphicsManager::getInstance().getRenderWindow()->setFullscreen(fullscreen, width, height);
+            this->ogreRoot_->saveConfig();
+            Core::getInstance().updateOgreConfigTimestamp();
+            // Also reload the input devices
+            InputManager::getInstance().reload();
+        }
+
+        return validate;
+    }
+
+    std::string GraphicsManager::setFSAA(const std::string& mode)
+    {
+        this->ogreRoot_->getRenderSystem()->setConfigOption("FSAA", mode);
+
+        std::string validate = this->ogreRoot_->getRenderSystem()->validateConfigOptions();
+
+        if (validate == "")
+        {
+            //this->ogreRoot_->getRenderSystem()->reinitialise(); // can't use this that easily, because it recreates the render window, invalidating renderWindow_
+            this->ogreRoot_->saveConfig();
+            Core::getInstance().updateOgreConfigTimestamp();
+        }
+
+        return validate;
+    }
+
+    std::string GraphicsManager::setVSync(bool vsync)
+    {
+        this->ogreRoot_->getRenderSystem()->setConfigOption("VSync", vsync ? "Yes" : "No");
+
+        std::string validate = this->ogreRoot_->getRenderSystem()->validateConfigOptions();
+
+        if (validate == "")
+        {
+            //this->ogreRoot_->getRenderSystem()->reinitialise(); // can't use this that easily, because it recreates the render window, invalidating renderWindow_
+            this->ogreRoot_->saveConfig();
+            Core::getInstance().updateOgreConfigTimestamp();
+        }
+
+        return validate;
     }
 
Index: code/trunk/src/libraries/core/GraphicsManager.h
===================================================================
--- code/trunk/src/libraries/core/GraphicsManager.h	(revision 7958)
+++ code/trunk/src/libraries/core/GraphicsManager.h	(revision 8079)
@@ -54,4 +54,5 @@
 #include "OrxonoxClass.h"
 
+// tolua_begin
 namespace orxonox
 {
@@ -60,6 +61,8 @@
         Graphics engine manager class
     */
-    class _CoreExport GraphicsManager : public Singleton<GraphicsManager>, public OrxonoxClass, public Ogre::LogListener
-    {
+    class _CoreExport GraphicsManager
+// tolua_end
+        : public Singleton<GraphicsManager>, public OrxonoxClass, public Ogre::LogListener
+    { // tolua_export
         friend class Singleton<GraphicsManager>;
     public:
@@ -74,5 +77,15 @@
         Ogre::RenderWindow* getRenderWindow() { return this->renderWindow_; }
         size_t getRenderWindowHandle();
+
+// tolua_begin
+        static GraphicsManager& getInstance() { return Singleton<GraphicsManager>::getInstance(); } // tolua_export
+
         bool isFullScreen() const;
+        unsigned int getWindowWidth() const;
+        unsigned int getWindowHeight() const;
+
+        bool hasVSyncEnabled() const;
+        std::string getFSAAMode() const;
+// tolua_end
 
         void upgradeToGraphics();
@@ -96,4 +109,7 @@
         // console commands
         void printScreen();
+        std::string setScreenResolution(unsigned int width, unsigned int height, bool fullscreen);
+        std::string setFSAA(const std::string& mode);
+        std::string setVSync(bool vsync);
 
         scoped_ptr<OgreWindowEventListener> ogreWindowEventListener_; //!< Pimpl to hide OgreWindowUtilities.h
@@ -105,4 +121,6 @@
         Ogre::RenderWindow* renderWindow_;             //!< the one and only render window
         Ogre::Viewport*     viewport_;                 //!< default full size viewport
+        float               lastFrameStartTime_;       //!< Time stamp of the beginning of the last frame
+        float               lastFrameEndTime_;         //!< Time stamp of the end of the last frame
 
         // XML files for the resources and the debug overlay
@@ -121,6 +139,8 @@
 
         static GraphicsManager* singletonPtr_s;        //!< Pointer to the Singleton
+// tolua_begin
     };
 }
+// tolua_end
 
 #endif /* _GraphicsManager_H__ */
Index: code/trunk/src/libraries/core/Loader.cc
===================================================================
--- code/trunk/src/libraries/core/Loader.cc	(revision 7958)
+++ code/trunk/src/libraries/core/Loader.cc	(revision 8079)
@@ -147,5 +147,5 @@
         Returns true if successful.
     */
-    bool Loader::load(const XMLFile* file, const ClassTreeMask& mask, bool verbose)
+    bool Loader::load(const XMLFile* file, const ClassTreeMask& mask, bool verbose, bool bRemoveLuaTags)
     {
         if (!file)
@@ -155,5 +155,5 @@
 
         std::string xmlInput;
-        if (file->getLuaSupport())
+        if (file->getLuaSupport() && !bRemoveLuaTags)
         {
             // Use the LuaState to replace the XML tags (calls our function)
@@ -172,4 +172,13 @@
             }
             xmlInput = Resource::open(file->getFilename())->getAsString();
+
+            if (bRemoveLuaTags)
+            {
+                // Remove all Lua code.
+                // Note: we only need this to speed up parsing of level files at the
+                // start of the program.
+                // Assumption: the LevelInfo tag does not use Lua scripting
+                xmlInput = removeLuaTags(xmlInput);
+            }
         }
 
@@ -271,8 +280,7 @@
     }
 
-    std::string Loader::replaceLuaTags(const std::string& text)
-    {
-        // create map with all Lua tags
-        std::map<size_t, bool> luaTags;
+    bool Loader::getLuaTags(const std::string& text, std::map<size_t, bool>& luaTags)
+    {
+        // fill map with all Lua tags
         {
             size_t pos = 0;
@@ -328,8 +336,18 @@
             {
                 COUT(2) << "Warning: Error in level file" << std::endl;
-                // todo: errorhandling
-                return "";
-            }
-        }
+                // TODO: error handling
+                return false; 
+            }
+        }
+
+        return true;
+    }
+
+    std::string Loader::replaceLuaTags(const std::string& text)
+    {
+        // create a map with all lua tags
+        std::map<size_t, bool> luaTags;
+        if (!getLuaTags(text, luaTags))
+            return "";
 
         // Use a stringstream object to speed up the parsing
@@ -421,3 +439,41 @@
         return output.str();
     }
+
+    std::string Loader::removeLuaTags(const std::string& text)
+    {
+        // create a map with all lua tags
+        std::map<size_t, bool> luaTags;
+        if (!getLuaTags(text, luaTags))
+            return "";
+
+        // Use a stringstream object to speed up the concatenation
+        std::ostringstream output;
+
+        // cut the original string into pieces and only write the non Lua parts
+        std::map<size_t, bool>::iterator it = luaTags.begin();
+        bool bLuaCode = false;
+        size_t start = 0;
+        size_t end = 0;
+
+        do
+        {
+            if (it != luaTags.end())
+                end = (it++)->first;
+            else
+                end = std::string::npos;
+
+            if (!bLuaCode)
+            {
+                output << text.substr(start, end - start);
+                start = end + 5;
+            }
+            else
+                start = end + 2;
+
+            bLuaCode = !bLuaCode;
+        }
+        while (end != std::string::npos);
+
+        return output.str();
+    }
 }
Index: code/trunk/src/libraries/core/Loader.h
===================================================================
--- code/trunk/src/libraries/core/Loader.h	(revision 7958)
+++ code/trunk/src/libraries/core/Loader.h	(revision 8079)
@@ -42,4 +42,5 @@
 #include "CorePrereqs.h"
 
+#include <map>
 #include <vector>
 #include "ClassTreeMask.h"
@@ -61,13 +62,17 @@
             static bool reload(const ClassTreeMask& mask = ClassTreeMask(), bool verbose = true);
 
-            static bool load(const XMLFile* file, const ClassTreeMask& mask = ClassTreeMask(), bool verbose = true);
+            static bool load(const XMLFile* file, const ClassTreeMask& mask = ClassTreeMask(),
+                             bool verbose = true, bool bRemoveLuaTags = false);
             static void unload(const XMLFile* file, const ClassTreeMask& mask = ClassTreeMask());
             static bool reload(const XMLFile* file, const ClassTreeMask& mask = ClassTreeMask(), bool verbose = true);
 
             static std::string replaceLuaTags(const std::string& text);
+            static std::string removeLuaTags(const std::string& text);
 
             static ClassTreeMask currentMask_s;
 
         private:
+            static bool getLuaTags(const std::string& text, std::map<size_t, bool>& luaTags);
+
             static std::vector<std::pair<const XMLFile*, ClassTreeMask> > files_s;
     };
Index: code/trunk/src/libraries/core/OrxonoxClass.h
===================================================================
--- code/trunk/src/libraries/core/OrxonoxClass.h	(revision 7958)
+++ code/trunk/src/libraries/core/OrxonoxClass.h	(revision 8079)
@@ -194,4 +194,6 @@
 
         protected:
+            virtual ~DestructionListener() {}
+
             inline void registerAsDestructionListener(OrxonoxClass* object)
                 { if (object) { object->registerDestructionListener(this); } }
Index: code/trunk/src/libraries/core/ViewportEventListener.cc
===================================================================
--- code/trunk/src/libraries/core/ViewportEventListener.cc	(revision 8079)
+++ code/trunk/src/libraries/core/ViewportEventListener.cc	(revision 8079)
@@ -0,0 +1,38 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ViewportEventListener.h"
+#include "CoreIncludes.h"
+
+namespace orxonox
+{
+    ViewportEventListener::ViewportEventListener()
+    {
+        RegisterRootObject(ViewportEventListener);
+    }
+}
Index: code/trunk/src/libraries/core/ViewportEventListener.h
===================================================================
--- code/trunk/src/libraries/core/ViewportEventListener.h	(revision 8079)
+++ code/trunk/src/libraries/core/ViewportEventListener.h	(revision 8079)
@@ -0,0 +1,50 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ViewportEventListener_H__
+#define _ViewportEventListener_H__
+
+#include "util/OgreForwardRefs.h"
+
+#include "CorePrereqs.h"
+#include "OrxonoxClass.h"
+
+namespace orxonox
+{
+    class _CoreExport ViewportEventListener : virtual public OrxonoxClass
+    {
+        public:
+            virtual void cameraChanged(Ogre::Viewport* viewport, Ogre::Camera* oldCamera) {}
+
+        protected:
+            ViewportEventListener();
+            virtual ~ViewportEventListener() {}
+    };
+}
+
+#endif /* _ViewportEventListener_H__ */
Index: code/trunk/src/libraries/core/WeakPtr.h
===================================================================
--- code/trunk/src/libraries/core/WeakPtr.h	(revision 7958)
+++ code/trunk/src/libraries/core/WeakPtr.h	(revision 8079)
@@ -129,5 +129,5 @@
 
             /// Destructor
-            inline ~WeakPtr()
+            inline virtual ~WeakPtr()
             {
                 this->unregisterAsDestructionListener(this->base_);
Index: code/trunk/src/libraries/core/command/CommandEvaluation.h
===================================================================
--- code/trunk/src/libraries/core/command/CommandEvaluation.h	(revision 7958)
+++ code/trunk/src/libraries/core/command/CommandEvaluation.h	(revision 8079)
@@ -70,9 +70,9 @@
 
         @remarks execCommand_ and hintCommand_ can be different in this case: There are multiple
-        commands avaliable, let's say "tcl", "tclexecute", and "tclquery". The user enters
-        "tcl", which is already a valid command. Now execCommand_ points to the "tcl"-command,
-        but hintCommand_ still points to the autocompletion command of CommandExecutor, because
-        the auto-completion list must still return the three possible commands, "tcl tclexecute tclquery"
-        because the user may want to execute "tclquery" and needs auto-completion.
+        commands avaliable, let's say "tcl" and "TclThreadManager". The user enters "tcl", which
+        is already a valid command. Now execCommand_ points to the "tcl"-command, but hintCommand_
+        still points to the autocompletion command of CommandExecutor, because the auto-completion
+        list must still return the two possible commands, "tcl TclThreadManager" because the user
+        may want to write "TclThreadManager ..." and needs auto-completion.
 
         @see See @ref CommandExecutorExample "this description" for an example.
Index: code/trunk/src/libraries/core/command/ConsoleCommand.h
===================================================================
--- code/trunk/src/libraries/core/command/ConsoleCommand.h	(revision 7958)
+++ code/trunk/src/libraries/core/command/ConsoleCommand.h	(revision 8079)
@@ -317,4 +317,8 @@
         inline void void__void(void) {}
         inline void void__string(const std::string&) {}
+
+        inline std::string string__bool(bool) { return ""; }
+        inline std::string string__string(const std::string&) { return ""; }
+        inline std::string string__uint_uint_bool(unsigned int, unsigned int, bool) { return ""; }
     }
 
Index: code/trunk/src/libraries/core/command/ConsoleCommandCompilation.cc
===================================================================
--- code/trunk/src/libraries/core/command/ConsoleCommandCompilation.cc	(revision 7958)
+++ code/trunk/src/libraries/core/command/ConsoleCommandCompilation.cc	(revision 8079)
@@ -46,11 +46,11 @@
 namespace orxonox
 {
-    SetConsoleCommand("source", source).argumentCompleter(0, autocompletion::files());
+//    SetConsoleCommand("source", source).argumentCompleter(0, autocompletion::files());  // disabled because we use the implementation in Tcl
     SetConsoleCommand("echo", echo);
-    SetConsoleCommand("puts", puts);
-
-    SetConsoleCommand("read", read).argumentCompleter(0, autocompletion::files());
-    SetConsoleCommand("append", append).argumentCompleter(0, autocompletion::files());
-    SetConsoleCommand("write", write).argumentCompleter(0, autocompletion::files());
+//    SetConsoleCommand("puts", puts);                                                    // disabled because we use the implementation in Tcl
+
+//    SetConsoleCommand("read", read).argumentCompleter(0, autocompletion::files());      // disabled because we use the implementation in Tcl
+//    SetConsoleCommand("append", append).argumentCompleter(0, autocompletion::files());  // disabled because we use the implementation in Tcl
+//    SetConsoleCommand("write", write).argumentCompleter(0, autocompletion::files());    // disabled because we use the implementation in Tcl
 
     SetConsoleCommand("calculate", calculate);
Index: code/trunk/src/libraries/core/command/Shell.cc
===================================================================
--- code/trunk/src/libraries/core/command/Shell.cc	(revision 7958)
+++ code/trunk/src/libraries/core/command/Shell.cc	(revision 8079)
@@ -46,8 +46,8 @@
 {
     SetConsoleCommand("log",     OutputHandler::log    );
-    SetConsoleCommand("error",   OutputHandler::error  );
-    SetConsoleCommand("warning", OutputHandler::warning);
-    SetConsoleCommand("info",    OutputHandler::info   );
-    SetConsoleCommand("debug",   OutputHandler::debug  );
+    SetConsoleCommand("error",   OutputHandler::error  ).hide();
+    SetConsoleCommand("warning", OutputHandler::warning).hide();
+    SetConsoleCommand("info",    OutputHandler::info   ).hide();
+    SetConsoleCommand("debug",   OutputHandler::debug  ).hide();
 
     unsigned int Shell::cacheSize_s;
Index: code/trunk/src/libraries/core/command/TclBind.cc
===================================================================
--- code/trunk/src/libraries/core/command/TclBind.cc	(revision 7958)
+++ code/trunk/src/libraries/core/command/TclBind.cc	(revision 8079)
@@ -45,5 +45,5 @@
 {
     SetConsoleCommand("tcl", &TclBind::tcl);
-    SetConsoleCommand("bgerror", &TclBind::bgerror);
+    SetConsoleCommand("bgerror", &TclBind::bgerror).hide();
 
     TclBind* TclBind::singletonPtr_s = 0;
@@ -91,13 +91,14 @@
 
             this->interpreter_->def("::orxonox::query", TclBind::tcl_query, Tcl::variadic());
+            this->interpreter_->def("::orxonox::execute", TclBind::tcl_execute, Tcl::variadic());
             this->interpreter_->def("::orxonox::crossquery", TclThreadManager::tcl_crossquery, Tcl::variadic());
-            this->interpreter_->def("execute", TclBind::tcl_execute, Tcl::variadic());
             this->interpreter_->def("::orxonox::crossexecute", TclThreadManager::tcl_crossexecute, Tcl::variadic());
 
             try
             {
-                this->interpreter_->eval("proc query        {args}    { ::orxonox::query $args }");
+                this->interpreter_->def("query", TclBind::tcl_query, Tcl::variadic());
+                this->interpreter_->def("execute", TclBind::tcl_execute, Tcl::variadic());
                 this->interpreter_->eval("proc crossquery   {id args} { ::orxonox::crossquery 0 $id $args }");
-                this->interpreter_->eval("proc crossexecute {id args} { ::orxonox::crossquery 0 $id $args }");
+                this->interpreter_->eval("proc crossexecute {id args} { ::orxonox::crossexecute 0 $id $args }");
                 this->interpreter_->eval("proc running      {}        { return 1 }");
                 this->interpreter_->eval("set id 0");
@@ -154,10 +155,33 @@
     {
         COUT(4) << "Tcl_query: " << args.get() << std::endl;
-
+        return TclBind::tcl_helper(args, true);
+    }
+
+    /**
+        @brief Callback: Used to send an Orxonox-command from Tcl to the CommandExecutor.
+    */
+    void TclBind::tcl_execute(Tcl::object const &args)
+    {
+        COUT(4) << "Tcl_execute: " << args.get() << std::endl;
+        TclBind::tcl_helper(args, false);
+    }
+
+    /**
+        @brief Helper function, used by tcl_query() and tcl_execute().
+    */
+    std::string TclBind::tcl_helper(Tcl::object const &args, bool bQuery)
+    {
         const std::string& command = stripEnclosingBraces(args.get());
 
         int error;
+        std::string result;
+
         CommandEvaluation evaluation = CommandExecutor::evaluate(command);
-        const std::string& result = evaluation.query(&error);
+
+        if (bQuery)
+            result = evaluation.query(&error).getString();
+        else
+            error = evaluation.execute();
+
         switch (error)
         {
@@ -175,18 +199,4 @@
 
     /**
-        @brief Callback: Used to send an Orxonox-command from Tcl to the CommandExecutor.
-    */
-    void TclBind::tcl_execute(Tcl::object const &args)
-    {
-        COUT(4) << "Tcl_execute: " << args.get() << std::endl;
-        const std::string& command = stripEnclosingBraces(args.get());
-
-        if (CommandExecutor::execute(command, false))
-        {
-            COUT(1) << "Error: Can't execute command \"" << command << "\"!" << std::endl;
-        }
-    }
-
-    /**
         @brief Console command, executes Tcl code. Can be used to bind Tcl-commands to a key, because native
         Tcl-commands can not be evaluated and are thus not supported by the key-binder.
@@ -198,13 +208,8 @@
             try
             {
-                const std::string& output = TclBind::getInstance().interpreter_->eval("uplevel #0 " + tclcode);
-                if (!output.empty())
-                {
-                    COUT(0) << "tcl> " << output << std::endl;
-                }
-                return output;
+                return TclBind::getInstance().interpreter_->eval("uplevel #0 " + tclcode);
             }
             catch (Tcl::tcl_error const &e)
-            {   COUT(1) << "tcl> Error: " << e.what() << std::endl;   }
+            {   COUT(1) << "Tcl error: " << e.what() << std::endl;   }
         }
 
Index: code/trunk/src/libraries/core/command/TclBind.h
===================================================================
--- code/trunk/src/libraries/core/command/TclBind.h	(revision 7958)
+++ code/trunk/src/libraries/core/command/TclBind.h	(revision 8079)
@@ -126,4 +126,6 @@
             TclBind(const TclBind& other);      ///< Copy-constructor, not implemented
 
+            static std::string tcl_helper(Tcl::object const &args, bool bQuery);
+
             Tcl::interpreter* interpreter_;     ///< The wrapped Tcl interpreter
             std::string tclDataPath_;           ///< The path to the directory that contains the Orxonox-specific Tcl-files
Index: code/trunk/src/libraries/core/command/TclThreadManager.cc
===================================================================
--- code/trunk/src/libraries/core/command/TclThreadManager.cc	(revision 7958)
+++ code/trunk/src/libraries/core/command/TclThreadManager.cc	(revision 8079)
@@ -55,6 +55,4 @@
     const float TCLTHREADMANAGER_MAX_CPU_USAGE = 0.50f;
 
-    SetConsoleCommand("tclexecute", &TclThreadManager::execute).argumentCompleter(0, autocompletion::tclthreads());
-    SetConsoleCommand("tclquery",   &TclThreadManager::query  ).argumentCompleter(0, autocompletion::tclthreads());
     SetConsoleCommand("TclThreadManager", "create",  &TclThreadManager::create);
     SetConsoleCommand("TclThreadManager", "destroy", &TclThreadManager::destroy).argumentCompleter(0, autocompletion::tclthreads());
Index: code/trunk/src/libraries/core/input/InputManager.cc
===================================================================
--- code/trunk/src/libraries/core/input/InputManager.cc	(revision 7958)
+++ code/trunk/src/libraries/core/input/InputManager.cc	(revision 8079)
@@ -641,3 +641,19 @@
         state->destroy();
     }
+
+    bool InputManager::setMouseExclusive(const std::string& name, TriBool::Value value)
+    {
+        if (name == "empty")
+        {
+            COUT(2) << "InputManager: Changing the empty state is not allowed!" << std::endl;
+            return false;
+        }
+        std::map<std::string, InputState*>::iterator it = statesByName_.find(name);
+        if (it != statesByName_.end())
+        {
+            it->second->setMouseExclusive(value);
+            return true;
+        }
+        return false;
+    }
 }
Index: code/trunk/src/libraries/core/input/InputManager.h
===================================================================
--- code/trunk/src/libraries/core/input/InputManager.h	(revision 7958)
+++ code/trunk/src/libraries/core/input/InputManager.h	(revision 8079)
@@ -163,4 +163,11 @@
         */
         bool destroyState(const std::string& name); // tolua_export
+        /**
+        @brief
+            Changes the mouse mode of an input state.
+        @return
+            True if the call was successful, fals if the name was not found
+        */
+        bool setMouseExclusive(const std::string& name, TriBool::Value value); // tolua_export
 
         //-------------------------------
Index: code/trunk/src/libraries/core/input/KeyBinder.cc
===================================================================
--- code/trunk/src/libraries/core/input/KeyBinder.cc	(revision 7958)
+++ code/trunk/src/libraries/core/input/KeyBinder.cc	(revision 8079)
@@ -431,5 +431,11 @@
                         // decrease counter
                         button->nCommands_[mode_index]--;
-                        // note: we don't replace the old array - it's not one element too large, but no one cares since nCommands_ defines the size
+                        // old array would not get deleted if nCommands_ is now 0
+                        // otherwise: nobody cares about an array that is one element too large - nCommands_ defines the size
+                        if (button->nCommands_[mode_index] == 0)
+                        {
+                            delete[] button->commands_[mode_index];
+                            button->commands_[mode_index] = 0;
+                        }
 
                         // decrement the index since we shifted the array and continue searching for more occurrences of the command
Index: code/trunk/src/libraries/core/input/Keyboard.cc
===================================================================
--- code/trunk/src/libraries/core/input/Keyboard.cc	(revision 7958)
+++ code/trunk/src/libraries/core/input/Keyboard.cc	(revision 8079)
@@ -36,16 +36,26 @@
     {
         // update modifiers
-        if (arg.key == OIS::KC_RMENU    || arg.key == OIS::KC_LMENU)
-            modifiers_ |= KeyboardModifier::Alt;   // alt key
-        if (arg.key == OIS::KC_RCONTROL || arg.key == OIS::KC_LCONTROL)
-            modifiers_ |= KeyboardModifier::Ctrl;  // ctrl key
-        if (arg.key == OIS::KC_RSHIFT   || arg.key == OIS::KC_LSHIFT)
-            modifiers_ |= KeyboardModifier::Shift; // shift key
+        switch (arg.key)
+        {
+            case OIS::KC_RMENU:
+            case OIS::KC_LMENU:
+                modifiers_ |= KeyboardModifier::Alt;   // alt key
+                break;
+            case OIS::KC_RCONTROL:
+            case OIS::KC_LCONTROL:
+                modifiers_ |= KeyboardModifier::Ctrl;  // ctrl key
+                break;
+            case OIS::KC_RSHIFT:
+            case OIS::KC_LSHIFT:
+                modifiers_ |= KeyboardModifier::Shift; // shift key
+                break;
+            case OIS::KC_TAB:
+                // Do not distribute the alt+tab event (messes with the operating system)
+                if ((modifiers_ & KeyboardModifier::Alt) != 0)
+                    return true;
+            default:;
+        }
 
-        // Do not distribute the alt+tab event (messes with the operating system)
-        if ((modifiers_ & KeyboardModifier::Alt) != 0 && arg.key == OIS::KC_TAB)
-            return true;
-
-        KeyEvent evt(arg);
+        KeyEvent evt(static_cast<KeyCode::ByEnum>(arg.key), Keyboard::getKeyText(arg), 0);
         super::buttonPressed(evt);
         return true;
@@ -56,14 +66,46 @@
     {
         // update modifiers
-        if (arg.key == OIS::KC_RMENU    || arg.key == OIS::KC_LMENU)
-            modifiers_ &= ~KeyboardModifier::Alt;   // alt key
-        if (arg.key == OIS::KC_RCONTROL || arg.key == OIS::KC_LCONTROL)
-            modifiers_ &= ~KeyboardModifier::Ctrl;  // ctrl key
-        if (arg.key == OIS::KC_RSHIFT   || arg.key == OIS::KC_LSHIFT)
-            modifiers_ &= ~KeyboardModifier::Shift; // shift key
+        switch (arg.key)
+        {
+            case OIS::KC_RMENU:
+            case OIS::KC_LMENU:
+                modifiers_ &= ~KeyboardModifier::Alt;   // alt key
+                break;
+            case OIS::KC_RCONTROL:
+            case OIS::KC_LCONTROL:
+                modifiers_ &= ~KeyboardModifier::Ctrl;  // ctrl key
+                break;
+            case OIS::KC_RSHIFT:
+            case OIS::KC_LSHIFT:
+                modifiers_ &= ~KeyboardModifier::Shift; // shift key
+                break;
+            default:;
+        }
 
-        KeyEvent evt(arg);
+        KeyEvent evt(static_cast<KeyCode::ByEnum>(arg.key), Keyboard::getKeyText(arg), 0);
         super::buttonReleased(evt);
         return true;
     }
+
+    /// A map which returns the corresponding chars for some key codes
+    unsigned int Keyboard::getKeyText(const OIS::KeyEvent& arg)
+    {
+        switch (arg.key)
+        {
+            case OIS::KC_NUMPAD0:     return static_cast<unsigned int>('0');
+            case OIS::KC_NUMPAD1:     return static_cast<unsigned int>('1');
+            case OIS::KC_NUMPAD2:     return static_cast<unsigned int>('2');
+            case OIS::KC_NUMPAD3:     return static_cast<unsigned int>('3');
+            case OIS::KC_NUMPAD4:     return static_cast<unsigned int>('4');
+            case OIS::KC_NUMPAD5:     return static_cast<unsigned int>('5');
+            case OIS::KC_NUMPAD6:     return static_cast<unsigned int>('6');
+            case OIS::KC_NUMPAD7:     return static_cast<unsigned int>('7');
+            case OIS::KC_NUMPAD8:     return static_cast<unsigned int>('8');
+            case OIS::KC_NUMPAD9:     return static_cast<unsigned int>('9');
+            case OIS::KC_DECIMAL:     return static_cast<unsigned int>('.');
+            case OIS::KC_DIVIDE:      return static_cast<unsigned int>('/');
+            case OIS::KC_NUMPADENTER: return static_cast<unsigned int>('\n');
+            default:                  return arg.text;
+        }
+    }
 }
Index: code/trunk/src/libraries/core/input/Keyboard.h
===================================================================
--- code/trunk/src/libraries/core/input/Keyboard.h	(revision 7958)
+++ code/trunk/src/libraries/core/input/Keyboard.h	(revision 8079)
@@ -83,4 +83,6 @@
         static std::string getClassNameImpl() { return "Keyboard"; }
 
+        static unsigned int getKeyText(const OIS::KeyEvent& arg);
+
         //! Bit mask representing keyboard modifiers
         int modifiers_;
Index: code/trunk/src/libraries/network/Host.cc
===================================================================
--- code/trunk/src/libraries/network/Host.cc	(revision 7958)
+++ code/trunk/src/libraries/network/Host.cc	(revision 8079)
@@ -38,8 +38,9 @@
 namespace orxonox {
 
+  static const std::string __CC_printRTT_group = "Stats";
   static const std::string __CC_printRTT_name = "printRTT";
 
   SetConsoleCommand("chat", &Host::Chat);
-  SetConsoleCommand(__CC_printRTT_name, &Host::printRTT);
+  SetConsoleCommand(__CC_printRTT_group, __CC_printRTT_name, &Host::printRTT);
 
   // Host*               Host::instance_=0;
@@ -55,5 +56,5 @@
   //   assert(instance_==0);
     instances_s.push_back(this);
-    ModifyConsoleCommand(__CC_printRTT_name).setObject(this);
+    ModifyConsoleCommand(__CC_printRTT_group, __CC_printRTT_name).setObject(this);
     this->bIsActive_ = false;
   }
@@ -67,5 +68,5 @@
     assert( std::find( instances_s.begin(), instances_s.end(), this )!=instances_s.end() );
     instances_s.erase(std::find( instances_s.begin(), instances_s.end(), this ));
-    ModifyConsoleCommand(__CC_printRTT_name).setObject(0);
+    ModifyConsoleCommand(__CC_printRTT_group, __CC_printRTT_name).setObject(0);
   }
 
Index: code/trunk/src/libraries/tools/ResourceLocation.cc
===================================================================
--- code/trunk/src/libraries/tools/ResourceLocation.cc	(revision 7958)
+++ code/trunk/src/libraries/tools/ResourceLocation.cc	(revision 8079)
@@ -30,4 +30,5 @@
 
 #include <OgreResourceGroupManager.h>
+#include <OgreException.h>
 #include <boost/filesystem.hpp>
 
Index: code/trunk/src/libraries/tools/Shader.cc
===================================================================
--- code/trunk/src/libraries/tools/Shader.cc	(revision 7958)
+++ code/trunk/src/libraries/tools/Shader.cc	(revision 8079)
@@ -30,12 +30,6 @@
 
 #include <OgreCompositorManager.h>
-#include <OgreCompositorInstance.h>
-#include <OgreSceneManager.h>
 #include <OgreRoot.h>
 #include <OgrePlugin.h>
-#include <OgreMaterial.h>
-#include <OgreTechnique.h>
-#include <OgrePass.h>
-#include <OgreMaterialManager.h>
 
 #include "core/CoreIncludes.h"
@@ -45,7 +39,7 @@
 namespace orxonox
 {
-    bool Shader::bLoadedCgPlugin_s = false;
-    Shader::MaterialMap Shader::parameters_s;
-
+    /**
+        @brief Initializes the values and sets the scene manager.
+    */
     Shader::Shader(Ogre::SceneManager* scenemanager) : compositorInstance_(0)
     {
@@ -53,277 +47,195 @@
 
         this->scenemanager_ = scenemanager;
-        this->compositorInstance_ = 0;
         this->bVisible_ = true;
         this->bLoadCompositor_ = GameMode::showsGraphics();
-        this->bViewportInitialized_ = false;
-
-        if (this->bLoadCompositor_ && Ogre::Root::getSingletonPtr())
-        {
-            Shader::bLoadedCgPlugin_s = false;
+        this->registeredAsListener_ = false;
+
+        static bool hasCgProgramManager = Shader::hasCgProgramManager();
+
+        this->bLoadCompositor_ &= hasCgProgramManager;
+    }
+
+    /**
+        @brief Removes the compositor and frees the resources.
+    */
+    Shader::~Shader()
+    {
+        if (this->compositorInstance_ && GraphicsManager::getInstance().getViewport())
+            Ogre::CompositorManager::getSingleton().removeCompositor(GraphicsManager::getInstance().getViewport(), this->compositorName_);
+    }
+
+    /**
+        @brief Inherited from ViewportEventListener - called if the camera changes.
+
+        Since the new camera could be in a different scene, the shader has to make sure
+        it deactivates or activates itself accordingly.
+
+        Additionally the shader has to be turned off and on even if the camera stays in
+        the same scene to fix a weird behavior of Ogre.
+    */
+    void Shader::cameraChanged(Ogre::Viewport* viewport, Ogre::Camera* oldCamera)
+    {
+        if (!this->bLoadCompositor_ || !this->scenemanager_)
+            return;
+
+        // load the compositor if not already done
+        if (!this->compositorName_.empty() && !this->compositorInstance_)
+            this->changedCompositorName(viewport);
+
+        // update compositor in viewport (shader should only be active if the current camera is in the same scene as the shader)
+
+        // Note:
+        // The shader needs also to be switched off and on after changing the camera in the
+        // same scene to avoid weird behaviour with active compositors while switching the
+        // camera (like freezing the image)
+        //
+        // Last known Ogre version needing this workaround:
+        // 1.4.8
+        // 1.7.2
+
+        if (oldCamera && this->scenemanager_ == oldCamera->getSceneManager())
+            Ogre::CompositorManager::getSingleton().setCompositorEnabled(viewport, this->compositorName_, false);
+
+        if (viewport->getCamera() && this->scenemanager_ == viewport->getCamera()->getSceneManager())
+            Ogre::CompositorManager::getSingleton().setCompositorEnabled(viewport, this->compositorName_, this->isVisible());
+    }
+
+    /**
+        @brief Changes the compositor - default viewport.
+    */
+    void Shader::changedCompositorName()
+    {
+        // For the moment, we get the viewport always from the graphics manager
+        // TODO: Try to support multiple viewports - note however that scenemanager_->getCurrentViewport() returns NULL
+        //       after switching to a camera in a different scene (only for the first time this scene is displayed though)
+        this->changedCompositorName(GraphicsManager::getInstance().getViewport());
+    }
+
+    /**
+        @brief Changes the compositor.
+    */
+    void Shader::changedCompositorName(Ogre::Viewport* viewport)
+    {
+        if (this->bLoadCompositor_)
+        {
+            assert(viewport);
+            if (this->compositorInstance_)
+            {
+                // remove the old compositor, remove the listener
+                Ogre::CompositorManager::getSingleton().removeCompositor(viewport, this->oldcompositorName_);
+                this->compositorInstance_->removeListener(this);
+                this->compositorInstance_ = 0;
+            }
+            if (!this->compositorName_.empty())
+            {
+                // add the new compositor
+                this->compositorInstance_ = Ogre::CompositorManager::getSingleton().addCompositor(viewport, this->compositorName_);
+                if (this->compositorInstance_)
+                {
+                    // register as listener if required
+                    if (this->registeredAsListener_)
+                        this->compositorInstance_->addListener(this);
+                    // set visibility according to the isVisible() and the camera/viewport
+                    if (viewport->getCamera())
+                        Ogre::CompositorManager::getSingleton().setCompositorEnabled(viewport, this->compositorName_, this->isVisible() && viewport->getCamera() && this->scenemanager_ == viewport->getCamera()->getSceneManager());
+                }
+                else
+                    COUT(2) << "Warning: Couldn't load compositor with name \"" << this->compositorName_ << "\"." << std::endl;
+            }
+            this->oldcompositorName_ = this->compositorName_;
+        }
+    }
+
+    /**
+        @brief Changes the visibility of the shader. Doesn't free any resources if set to invisible.
+    */
+    void Shader::updateVisibility()
+    {
+        if (this->compositorInstance_)
+            Ogre::CompositorManager::getSingleton().setCompositorEnabled(GraphicsManager::getInstance().getViewport(), this->compositorName_, this->isVisible());
+    }
+
+    /**
+        @brief Defines a new integer value for a given parameter. The parameter will be updated if the compositor is rendered the next time.
+    */
+    void Shader::setParameter(size_t technique, size_t pass, const std::string& parameter, int value)
+    {
+        ParameterContainer container = {technique, pass, parameter, value, 0.0f, MT_Type::Int};
+        this->parameters_.push_back(container);
+        this->addAsListener();
+    }
+
+    /**
+        @brief Defines a new float value for a given parameter. The parameter will be updated if the compositor is rendered the next time.
+    */
+    void Shader::setParameter(size_t technique, size_t pass, const std::string& parameter, float value)
+    {
+        ParameterContainer container = {technique, pass, parameter, 0, value, MT_Type::Float};
+        this->parameters_.push_back(container);
+        this->addAsListener();
+    }
+
+    /**
+        @brief Registers the shader as CompositorInstance::Listener at the compositor. Used to change parameters.
+    */
+    void Shader::addAsListener()
+    {
+        if (!this->registeredAsListener_)
+        {
+            this->registeredAsListener_ = true;
+            if (this->compositorInstance_)
+                this->compositorInstance_->addListener(this);
+        }
+    }
+
+    /**
+        @brief Inherited by Ogre::CompositorInstance::Listener, called whenever the material is rendered. Used to change parameters.
+    */
+    void Shader::notifyMaterialRender(Ogre::uint32 pass_id, Ogre::MaterialPtr& materialPtr)
+    {
+        // iterate through the list of parameters
+        for (std::list<ParameterContainer>::iterator it = this->parameters_.begin(); it != this->parameters_.end(); ++it)
+        {
+            Ogre::Technique* techniquePtr = materialPtr->getTechnique(it->technique_);
+            if (techniquePtr)
+            {
+                Ogre::Pass* passPtr = techniquePtr->getPass(it->pass_);
+                if (passPtr)
+                {
+                    // change the value of the parameter depending on its type
+                    switch (it->valueType_)
+                    {
+                        case MT_Type::Int:
+                            passPtr->getFragmentProgramParameters()->setNamedConstant(it->parameter_, it->valueInt_);
+                            break;
+                        case MT_Type::Float:
+                            passPtr->getFragmentProgramParameters()->setNamedConstant(it->parameter_, it->valueFloat_);
+                            break;
+                        default:
+                            break;
+                    }
+                }
+                else
+                    COUT(2) << "Warning: No pass " << it->pass_ << " in technique " << it->technique_ << " in compositor \"" << this->compositorName_ << "\" or pass has no shader." << std::endl;
+            }
+            else
+                COUT(2) << "Warning: No technique " << it->technique_ << " in compositor \"" << this->compositorName_ << "\" or technique has no pass with shader." << std::endl;
+        }
+        this->parameters_.clear();
+    }
+
+    /**
+        @brief Detects if the Cg program manager plugin is active.
+    */
+    /* static */ bool Shader::hasCgProgramManager()
+    {
+        if (Ogre::Root::getSingletonPtr())
+        {
             const Ogre::Root::PluginInstanceList& plugins = Ogre::Root::getSingleton().getInstalledPlugins();
             for (size_t i = 0; i < plugins.size(); ++i)
-            {
                 if (plugins[i]->getName() == "Cg Program Manager")
-                {
-                    Shader::bLoadedCgPlugin_s = true;
-                    break;
-                }
-            }
-        }
-
-        this->bLoadCompositor_ &= Shader::bLoadedCgPlugin_s;
-    }
-
-    Shader::~Shader()
-    {
-        if (this->compositorInstance_ && this->bLoadCompositor_)
-        {
-            Ogre::Viewport* viewport = GraphicsManager::getInstance().getViewport();
-            assert(viewport);
-            Ogre::CompositorManager::getSingleton().removeCompositor(viewport, this->compositor_);
-        }
-
-    }
-
-    void Shader::setSceneManager(Ogre::SceneManager* scenemanager)
-    {
-        this->scenemanager_ = scenemanager;
-        this->bViewportInitialized_ = false;
-    }
-
-    void Shader::tick(float dt)
-    {
-        SUPER(Shader, tick, dt);
-
-        if (this->bLoadCompositor_ && !this->bViewportInitialized_ && this->scenemanager_ && this->scenemanager_->getCurrentViewport())
-        {
-            this->bViewportInitialized_ = true;
-            this->updateVisibility();
-        }
-    }
-
-    void Shader::changedCompositor()
-    {
-        if (this->bLoadCompositor_)
-        {
-            Ogre::Viewport* viewport = GraphicsManager::getInstance().getViewport();
-            assert(viewport);
-            if (!this->oldcompositor_.empty())
-            {
-                Ogre::CompositorManager::getSingleton().removeCompositor(viewport, this->oldcompositor_);
-                this->compositorInstance_ = 0;
-            }
-            if (!this->compositor_.empty())
-            {
-                this->compositorInstance_ = Ogre::CompositorManager::getSingleton().addCompositor(viewport, this->compositor_);
-                if (!this->compositorInstance_)
-                    COUT(2) << "Warning: Couldn't load compositor with name \"" << this->compositor_ << "\"." << std::endl;
-                Ogre::CompositorManager::getSingleton().setCompositorEnabled(viewport, this->compositor_, this->bViewportInitialized_ && this->isVisible());
-            }
-            this->oldcompositor_ = this->compositor_;
-        }
-    }
-
-    void Shader::updateVisibility()
-    {
-        if (this->compositorInstance_ && this->scenemanager_)
-            this->compositorInstance_->setEnabled(this->scenemanager_->getCurrentViewport() && this->isVisible());
-    }
-
-    void Shader::setParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter, float value)
-    {
-        if (Shader::_setParameter(material, technique, pass, parameter, value))
-        {
-            if (this->bViewportInitialized_ && this->compositorInstance_ && this->isVisible())
-            {
-                this->compositorInstance_->setEnabled(false);
-                this->compositorInstance_->setEnabled(true);
-            }
-        }
-    }
-
-    void Shader::setParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter, int value)
-    {
-        if (Shader::_setParameter(material, technique, pass, parameter, value))
-        {
-            if (this->bViewportInitialized_ && this->compositorInstance_ && this->isVisible())
-            {
-                this->compositorInstance_->setEnabled(false);
-                this->compositorInstance_->setEnabled(true);
-            }
-        }
-    }
-
-    bool Shader::_setParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter, float value)
-    {
-        ParameterPointer* pointer = Shader::getParameterPointer(material, technique, pass, parameter);
-        if (pointer)
-        {
-            if (pointer->first)
-            {
-                if ((*static_cast<float*>(pointer->second)) != value)
-                {
-                    (*static_cast<float*>(pointer->second)) = value;
                     return true;
-                }
-            }
-            else
-            {
-                if ((*static_cast<int*>(pointer->second)) != static_cast<int>(value))
-                {
-                    (*static_cast<int*>(pointer->second)) = static_cast<int>(value);
-                    return true;
-                }
-            }
         }
         return false;
     }
-
-    bool Shader::_setParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter, int value)
-    {
-        ParameterPointer* pointer = Shader::getParameterPointer(material, technique, pass, parameter);
-        if (pointer)
-        {
-            if (pointer->first)
-            {
-                if ((*static_cast<float*>(pointer->second)) != static_cast<float>(value))
-                {
-                    (*static_cast<float*>(pointer->second)) = static_cast<float>(value);
-                    return true;
-                }
-            }
-            else
-            {
-                if ((*static_cast<int*>(pointer->second)) != value)
-                {
-                    (*static_cast<int*>(pointer->second)) = value;
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    float Shader::getParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter)
-    {
-        ParameterPointer* pointer = Shader::getParameterPointer(material, technique, pass, parameter);
-        if (pointer)
-        {
-            if (pointer->first)
-                return (*static_cast<float*>(pointer->second));
-            else
-                return static_cast<float>(*static_cast<int*>(pointer->second));
-        }
-        else
-            return 0;
-    }
-
-    bool Shader::getParameterIsFloat(const std::string& material, size_t technique, size_t pass, const std::string& parameter)
-    {
-        ParameterPointer* pointer = Shader::getParameterPointer(material, technique, pass, parameter);
-        if (pointer)
-            return pointer->first;
-        else
-            return false;
-    }
-
-    bool Shader::getParameterIsInt(const std::string& material, size_t technique, size_t pass, const std::string& parameter)
-    {
-        ParameterPointer* pointer = Shader::getParameterPointer(material, technique, pass, parameter);
-        if (pointer)
-            return (!pointer->first);
-        else
-            return false;
-    }
-
-    Shader::ParameterPointer* Shader::getParameterPointer(const std::string& material, size_t technique, size_t pass, const std::string& parameter)
-    {
-        if (!GameMode::showsGraphics() || !Shader::bLoadedCgPlugin_s)
-            return 0;
-
-        MaterialMap::iterator material_iterator = Shader::parameters_s.find(material);
-        if (material_iterator != Shader::parameters_s.end())
-        {
-            TechniqueVector& technique_vector = material_iterator->second;
-            if (technique < technique_vector.size())
-            {
-                PassVector& pass_vector = technique_vector[technique];
-                if (pass < pass_vector.size())
-                {
-                    ParameterMap& parameter_map = pass_vector[pass];
-                    ParameterMap::iterator parameter_iterator = parameter_map.find(parameter);
-
-                    if (parameter_iterator != parameter_map.end())
-                        return (&parameter_iterator->second);
-                    else
-                        COUT(2) << "Warning: No shader parameter \"" << parameter << "\" in pass " << pass << " in technique " << technique << " in material \"" << material << "\"." << std::endl;
-                }
-                else
-                    COUT(2) << "Warning: No pass " << pass << " in technique " << technique << " in material \"" << material << "\" or pass has no shader." << std::endl;
-            }
-            else
-                COUT(2) << "Warning: No technique " << technique << " in material \"" << material << "\" or technique has no pass with shader." << std::endl;
-        }
-        else
-        {
-            bool foundAtLeastOneShaderParameter = false;
-            Ogre::MaterialManager::ResourceMapIterator iterator = Ogre::MaterialManager::getSingleton().getResourceIterator();
-            Ogre::Material* material_pointer = 0;
-
-            while (iterator.hasMoreElements())
-            {
-                Ogre::Resource* resource = iterator.getNext().get();
-                if (resource->getName() == material)
-                    material_pointer = (Ogre::Material*)resource;
-            }
-
-            if (!material_pointer)
-            {
-                COUT(2) << "Warning: No material with name \"" << material << "\" found." << std::endl;
-                return 0;
-            }
-
-            for (unsigned int t = 0; t < material_pointer->getNumTechniques(); ++t)
-            {
-                Ogre::Technique* technique_pointer = material_pointer->getTechnique(t);
-                if (!technique_pointer)
-                    continue;
-
-                for (unsigned int p = 0; p < technique_pointer->getNumPasses(); ++p)
-                {
-                    Ogre::Pass* pass_pointer = technique_pointer->getPass(p);
-                    if (!pass_pointer)
-                        continue;
-
-                    if (!pass_pointer->getFragmentProgramName().empty())
-                    {
-                        Ogre::GpuProgramParameters* parameter_pointer = pass_pointer->getFragmentProgramParameters().get();
-                        if (!parameter_pointer)
-                            continue;
-
-                        const Ogre::GpuConstantDefinitionMap& constant_definitions = parameter_pointer->getConstantDefinitions().map;
-                        for (Ogre::GpuConstantDefinitionMap::const_iterator definition_iterator = constant_definitions.begin(); definition_iterator != constant_definitions.end(); ++definition_iterator)
-                        {
-                            void* temp = (definition_iterator->second.isFloat())
-                                            ? static_cast<void*>(parameter_pointer->getFloatPointer(definition_iterator->second.physicalIndex))
-                                            : static_cast<void*>(parameter_pointer->getIntPointer(definition_iterator->second.physicalIndex));
-                            ParameterPointer parameter_pointer = ParameterPointer(definition_iterator->second.isFloat(), temp);
-
-                            TechniqueVector& technique_vector = Shader::parameters_s[material];
-                            technique_vector.resize(technique + 1);
-                            PassVector& pass_vector = technique_vector[technique];
-                            pass_vector.resize(pass + 1);
-                            pass_vector[pass][definition_iterator->first] = parameter_pointer;
-                            foundAtLeastOneShaderParameter = true;
-                        }
-                    }
-                }
-            }
-
-            // recursive call if the material was added to the map
-            if (foundAtLeastOneShaderParameter)
-                return Shader::getParameterPointer(material, technique, pass, parameter);
-        }
-        return 0;
-    }
 }
Index: code/trunk/src/libraries/tools/Shader.h
===================================================================
--- code/trunk/src/libraries/tools/Shader.h	(revision 7958)
+++ code/trunk/src/libraries/tools/Shader.h	(revision 8079)
@@ -36,23 +36,23 @@
 #include <vector>
 
+#include <OgreCompositorInstance.h>
+
+#include "util/MultiType.h"
 #include "util/OgreForwardRefs.h"
-#include "tools/interfaces/Tickable.h"
+#include "core/ViewportEventListener.h"
 
 namespace orxonox
 {
-    class _ToolsExport Shader : public Tickable
+    /**
+        @brief Shader is a wrapper class around Ogre::CompositorInstance. It provides some
+        functions to easily change the visibility and parameters for shader programs.
+    */
+    class _ToolsExport Shader : public ViewportEventListener, public Ogre::CompositorInstance::Listener
     {
-        typedef std::pair<bool, void*>                  ParameterPointer;
-        typedef std::map<std::string, ParameterPointer> ParameterMap;
-        typedef std::vector<ParameterMap>               PassVector;
-        typedef std::vector<PassVector>                 TechniqueVector;
-        typedef std::map<std::string, TechniqueVector>  MaterialMap;
-
         public:
             Shader(Ogre::SceneManager* scenemanager = 0);
             virtual ~Shader();
 
-            virtual void tick(float dt);
-
+            /// Defines if the shader is visible or not.
             inline void setVisible(bool bVisible)
             {
@@ -63,45 +63,66 @@
                 }
             }
+            /// Returns whether or not the shader is visible.
             inline bool isVisible() const
                 { return this->bVisible_; }
             void updateVisibility();
 
-            inline void setCompositor(const std::string& compositor)
+            /// Defines the compositor's name (located in a .compositor file).
+            inline void setCompositorName(const std::string& name)
             {
-                if (this->compositor_ != compositor)
+                if (this->compositorName_ != name)
                 {
-                    this->compositor_ = compositor;
-                    this->changedCompositor();
+                    this->compositorName_ = name;
+                    this->changedCompositorName();
                 }
             }
-            inline const std::string& getCompositor() const
-                { return this->compositor_; }
-            void changedCompositor();
+            /// Returns the compositor's name.
+            inline const std::string& getCompositorName() const
+                { return this->compositorName_; }
+            void changedCompositorName();
+            void changedCompositorName(Ogre::Viewport* viewport);
 
-            void setSceneManager(Ogre::SceneManager* scenemanager);
+            /// Sets the scenemanager (usually provided in the constructor, but can be set later). Shouldn't be changed once it's set.
+            inline void setSceneManager(Ogre::SceneManager* scenemanager)
+                { this->scenemanager_ = scenemanager; }
+            /// Returns the scene manager.
             inline Ogre::SceneManager* getSceneManager() const
                 { return this->scenemanager_; }
 
-            void setParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter, float value);
-            void setParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter, int value);
+            virtual void cameraChanged(Ogre::Viewport* viewport, Ogre::Camera* oldCamera);
 
-            static bool _setParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter, float value);
-            static bool _setParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter, int value);
-            static float getParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter);
-            static bool  getParameterIsFloat(const std::string& material, size_t technique, size_t pass, const std::string& parameter);
-            static bool  getParameterIsInt  (const std::string& material, size_t technique, size_t pass, const std::string& parameter);
-            static ParameterPointer* getParameterPointer(const std::string& material, size_t technique, size_t pass, const std::string& parameter);
+            void setParameter(size_t technique, size_t pass, const std::string& parameter, float value);
+            void setParameter(size_t technique, size_t pass, const std::string& parameter, int value);
+
+            virtual void notifyMaterialRender(Ogre::uint32 pass_id, Ogre::MaterialPtr& materialPtr);
 
         private:
-            Ogre::SceneManager* scenemanager_;
-            Ogre::CompositorInstance* compositorInstance_;
-            bool bVisible_;
-            bool bLoadCompositor_;
-            bool bViewportInitialized_;
-            std::string compositor_;
-            std::string oldcompositor_;
+            static bool hasCgProgramManager();
 
-            static MaterialMap parameters_s;
-            static bool bLoadedCgPlugin_s;
+            Ogre::SceneManager* scenemanager_;              ///< The scenemanager for which the shader is active
+            Ogre::CompositorInstance* compositorInstance_;  ///< The compositor instance representing the wrapped compositor
+            bool bVisible_;                                 ///< True if the shader should be visible
+            bool bLoadCompositor_;                          ///< True if the compositor should be loaded (usually false if no graphics)
+            std::string compositorName_;                    ///< The name of the current compositor
+            std::string oldcompositorName_;                 ///< The name of the previous compositor (used to unregister)
+
+        private:
+            void addAsListener();
+
+            /// Helper struct to store parameters for shader programs.
+            struct ParameterContainer
+            {
+                size_t technique_;          ///< The ID of the technique
+                size_t pass_;               ///< The ID of the pass
+                std::string parameter_;     ///< The name of the parameter
+
+                int valueInt_;              ///< The desired int value of the parameter
+                float valueFloat_;          ///< The desired float value of the parameter
+
+                MT_Type::Value valueType_;  ///< The type of the parameter (currently only int or float)
+            };
+
+            std::list<ParameterContainer> parameters_;  ///< The list of parameters that should be set on the next update
+            bool registeredAsListener_;                 ///< True if the shader should register itself as listener at the compositor
     };
 }
Index: code/trunk/src/libraries/tools/Timer.cc
===================================================================
--- code/trunk/src/libraries/tools/Timer.cc	(revision 7958)
+++ code/trunk/src/libraries/tools/Timer.cc	(revision 8079)
@@ -35,4 +35,6 @@
 
 #include <set>
+
+#include <boost/bimap.hpp>
 
 #include "util/Clock.h"
@@ -41,25 +43,54 @@
 #include "core/command/CommandExecutor.h"
 #include "core/command/Functor.h"
+#include "tools/interfaces/TimeFactorListener.h"
 
 namespace orxonox
 {
     SetConsoleCommand("delay", &delay).argumentCompleter(1, autocompletion::command());
+    SetConsoleCommand("delayreal", &delayreal).argumentCompleter(1, autocompletion::command());
+    SetConsoleCommand("killdelay", &killdelay);
     SetConsoleCommand("killdelays", &killdelays);
 
-    static std::set<Timer*> delaytimerset;
-
-    /**
-        @brief Console-command: Calls another console command after @a delay seconds.
+    static boost::bimap<unsigned int, Timer*> delaytimers;
+    static unsigned int delayHandleCounter = 0;
+
+    /**
+        @brief Console-command: Calls another console command after @a delay seconds (game time).
         @param delay The delay in seconds
         @param command The console command
-    */
-    void delay(float delay, const std::string& command)
-    {
-        Timer* delaytimer = new Timer();
-        delaytimerset.insert(delaytimer);
+        @return The handle of the delayed command, can be used as argument for killdelay()
+    */
+    unsigned int delay(float delay, const std::string& command)
+    {
+        return addDelayedCommand(new Timer(), delay, command);
+    }
+
+    /**
+        @brief Console-command: Calls another console command after @a delay seconds (real time)
+        @param delay The delay in seconds
+        @param command The console command
+        @return The handle of the delayed command, can be used as argument for killdelay()
+    */
+    unsigned int delayreal(float delay, const std::string& command)
+    {
+        return addDelayedCommand(new RealTimer(), delay, command);
+    }
+
+    /**
+        @brief Helper function, used by delay() and delayreal() to add a delayed command.
+        @param timer The timer which will execute the command
+        @param delay The delay in seconds
+        @param command The console command
+        @return The handle of the delayed command, can be used as argument for killdelay()
+    */
+    unsigned int addDelayedCommand(Timer* timer, float delay, const std::string& command)
+    {
+        delaytimers.insert(boost::bimap<unsigned int, Timer*>::value_type(++delayHandleCounter, timer));
 
         const ExecutorStaticPtr& delayexecutor = createExecutor(createFunctor(&executeDelayedCommand));
-        delayexecutor->setDefaultValues(delaytimer, command);
-        delaytimer->setTimer(delay, false, delayexecutor);
+        delayexecutor->setDefaultValues(timer, command);
+        timer->setTimer(delay, false, delayexecutor);
+
+        return delayHandleCounter;
     }
 
@@ -73,5 +104,5 @@
         CommandExecutor::execute(command);
         timer->destroy();
-        delaytimerset.erase(timer);
+        delaytimers.right.erase(timer);
     }
 
@@ -81,8 +112,21 @@
     void killdelays()
     {
-        for (std::set<Timer*>::iterator it = delaytimerset.begin(); it != delaytimerset.end(); ++it)
-            (*it)->destroy();
-
-        delaytimerset.clear();
+        for (boost::bimap<unsigned int, Timer*>::left_map::iterator it = delaytimers.left.begin(); it != delaytimers.left.end(); ++it)
+            it->second->destroy();
+
+        delaytimers.clear();
+    }
+
+    /**
+        @brief Console-command: Kills a delayed command with given handle.
+    */
+    void killdelay(unsigned int handle)
+    {
+        boost::bimap<unsigned int, Timer*>::left_map::iterator it = delaytimers.left.find(handle);
+        if (it != delaytimers.left.end())
+        {
+            it->second->destroy();
+            delaytimers.left.erase(it);
+        }
     }
 
@@ -93,5 +137,5 @@
     {
         this->init();
-        RegisterObject(Timer);
+        RegisterRootObject(Timer);
     }
 
@@ -106,5 +150,5 @@
     {
         this->init();
-        RegisterObject(Timer);
+        RegisterRootObject(Timer);
 
         this->setTimer(interval, bLoop, executor, bKillAfterCall);
@@ -123,4 +167,12 @@
 
         this->time_ = 0;
+    }
+
+    /**
+        @brief Returns the current time factor of the game.
+    */
+    float Timer::getTimeFactor()
+    {
+        return TimeFactorListener::getTimeFactor();
     }
 
@@ -168,3 +220,24 @@
         }
     }
+
+    ///////////////
+    // RealTimer //
+    ///////////////
+    /// @copydoc Timer::Timer
+    RealTimer::RealTimer()
+    {
+        RegisterObject(RealTimer);
+    }
+
+    /// @copydoc Timer::Timer(float, bool, const ExecutorPtr&, bool)
+    RealTimer::RealTimer(float interval, bool bLoop, const ExecutorPtr& executor, bool bKillAfterCall) : Timer(interval, bLoop, executor, bKillAfterCall)
+    {
+        RegisterObject(RealTimer);
+    }
+
+    /// Returns always 1 because RealTimer doesn't depend on the game time.
+    float RealTimer::getTimeFactor()
+    {
+        return 1;
+    }
 }
Index: code/trunk/src/libraries/tools/Timer.h
===================================================================
--- code/trunk/src/libraries/tools/Timer.h	(revision 7958)
+++ code/trunk/src/libraries/tools/Timer.h	(revision 8079)
@@ -81,18 +81,26 @@
 #include "core/OrxonoxClass.h"
 #include "core/command/Executor.h"
-#include "tools/interfaces/TimeFactorListener.h"
 
 namespace orxonox
 {
-    void delay(float delay, const std::string& command);
-    void killdelays();
+    unsigned int delay(float delay, const std::string& command);
+    unsigned int delayreal(float delay, const std::string& command);
+
+    unsigned int addDelayedCommand(Timer* timer, float delay, const std::string& command);
     void executeDelayedCommand(Timer* timer, const std::string& command);
 
+    void killdelay(unsigned int handle);
+    void killdelays();
+
     /**
-        @brief Timer is a helper class that executes a function after a given amount of time.
+        @brief Timer is a helper class that executes a function after a given amount of seconds in game-time.
 
         @see See @ref TimerExample "Timer.h" for an example.
+
+        The time interval of Timer depends on the game time, hence it stops if the game is paused or runs
+        slower/faster if the game-speed is modified. See RealTimer for a timer class which doesn't depend
+        on the game time.
     */
-    class _ToolsExport Timer : public TimeFactorListener
+    class _ToolsExport Timer : virtual public OrxonoxClass
     {
         public:
@@ -123,26 +131,26 @@
             void run();
 
-            /// Re-starts the Timer: The executor will be called after @a interval seconds.
+            /// Re-starts the timer: The executor will be called after @a interval seconds.
             inline void startTimer()
                 { this->bActive_ = true; this->time_ = this->interval_; }
-            /// Stops the Timer.
+            /// Stops the timer.
             inline void stopTimer()
                 { this->bActive_ = false; this->time_ = this->interval_; }
-            /// Pauses the Timer - it will continue with the actual state if you call unpauseTimer().
+            /// Pauses the timer - it will continue with the actual state if you call unpauseTimer().
             inline void pauseTimer()
                 { this->bActive_ = false; }
-            /// Unpauses the Timer - continues with the given state.
+            /// Unpauses the timer - continues with the given state.
             inline void unpauseTimer()
                 { this->bActive_ = true; }
-            /// Returns true if the Timer is active (neither stopped nor paused).
+            /// Returns true if the timer is active (neither stopped nor paused).
             inline bool isActive() const
                 { return this->bActive_; }
-            /// Returns the remaining time until the Timer calls the executor.
+            /// Returns the remaining time until the timer calls the executor.
             inline float getRemainingTime() const
                 { return static_cast<float>(this->time_ / 1000000.0f); }
-            /// Increases the remaining time of the Timer by the given amount of time (in seconds).
+            /// Increases the remaining time of the timer by the given amount of time (in seconds).
             inline void addTime(float time)
                 { if (time > 0.0f) this->time_ += static_cast<long long>(time * 1000000.0f); }
-            /// Decreases the remaining time of the Timer by the given amount of time (in seconds)
+            /// Decreases the remaining time of the timer by the given amount of time (in seconds)
             inline void removeTime(float time)
                 { if (time > 0.0f) this->time_ -= static_cast<long long>(time * 1000000.0f); }
@@ -156,4 +164,7 @@
             void tick(const Clock& time);
 
+        protected:
+            virtual float getTimeFactor();
+
         private:
             void init();
@@ -163,9 +174,25 @@
             long long interval_;    //!< The time-interval in micro seconds
             bool bLoop_;            //!< If true, the executor gets called every @a interval seconds
-            bool bActive_;          //!< If true, the Timer ticks and calls the executor if the time's up
+            bool bActive_;          //!< If true, the timer ticks and calls the executor if the time's up
             bool bKillAfterCall_;   //!< If true the timer gets deleted after it expired and called the executor
 
             long long time_;        //!< Internal variable, counting the time untill the next executor-call
     };
+
+    /**
+        @brief RealTimer is a helper class that executes a function after a given amount of seconds in real-time.
+
+        The time interval of RealTimer doesn't depend on the game time, it will also call the function
+        if the game is paused. See Timer for a timer class that depends on the game time.
+    */
+    class _ToolsExport RealTimer : public Timer
+    {
+        public:
+            RealTimer();
+            RealTimer(float interval, bool bLoop, const ExecutorPtr& executor, bool bKillAfterCall = false);
+
+        protected:
+            virtual float getTimeFactor();
+    };
 }
 
Index: code/trunk/src/libraries/tools/ToolsPrereqs.h
===================================================================
--- code/trunk/src/libraries/tools/ToolsPrereqs.h	(revision 7958)
+++ code/trunk/src/libraries/tools/ToolsPrereqs.h	(revision 8079)
@@ -85,4 +85,5 @@
     class Mesh;
     class ParticleInterface;
+    class RealTimer;
     class ResourceCollection;
     class ResourceLocation;
