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_;
