[Orxonox-commit 954] r5677 - in code/branches/resource3/src: core orxonox/gamestates

rgrieder at orxonox.net rgrieder at orxonox.net
Mon Aug 24 15:03:45 CEST 2009


Author: rgrieder
Date: 2009-08-24 15:03:44 +0200 (Mon, 24 Aug 2009)
New Revision: 5677

Modified:
   code/branches/resource3/src/core/Core.cc
   code/branches/resource3/src/core/Core.h
   code/branches/resource3/src/core/GraphicsManager.cc
   code/branches/resource3/src/core/GraphicsManager.h
   code/branches/resource3/src/orxonox/gamestates/GSLevel.cc
Log:
Merged most of revision 5614 and its fixes from revisions 5628, 5658, 5662 and 5670:
- Creating Ogre::Root in non graphics mode as well. This allows to always make use of the ResourceGroupManager.
- Switched to smart pointers for the destruction code in GraphicsManager

Modified: code/branches/resource3/src/core/Core.cc
===================================================================
--- code/branches/resource3/src/core/Core.cc	2009-08-24 11:57:27 UTC (rev 5676)
+++ code/branches/resource3/src/core/Core.cc	2009-08-24 13:03:44 UTC (rev 5677)
@@ -312,6 +312,9 @@
 
         // creates the class hierarchy for all classes with factories
         Factory::createClassHierarchy();
+
+        // Load OGRE excluding the renderer and the render window
+        this->graphicsManager_.reset(new GraphicsManager(false));
     }
 
     /**
@@ -324,38 +327,44 @@
 
     void Core::loadGraphics()
     {
-        if (bGraphicsLoaded_)
-            return;
+        // Any exception should trigger this, even in upgradeToGraphics (see its remarks)
+        Loki::ScopeGuard unloader = Loki::MakeObjGuard(*this, &Core::unloadGraphics);
 
-        // Load OGRE including the render window
-        scoped_ptr<GraphicsManager> graphicsManager(new GraphicsManager());
+        // Upgrade OGRE to receive a render window
+        graphicsManager_->upgradeToGraphics();
 
         // The render window width and height are used to set up the mouse movement.
         size_t windowHnd = 0;
-        graphicsManager->getRenderWindow()->getCustomAttribute("WINDOW", &windowHnd);
+        graphicsManager_->getRenderWindow()->getCustomAttribute("WINDOW", &windowHnd);
 
         // Calls the InputManager which sets up the input devices.
-        scoped_ptr<InputManager> inputManager(new InputManager(windowHnd));
+        inputManager_.reset(new InputManager(windowHnd));
 
         // load the CEGUI interface
-        guiManager_.reset(new GUIManager(graphicsManager->getRenderWindow()));
+        guiManager_.reset(new GUIManager(graphicsManager_->getRenderWindow()));
 
-        // Dismiss scoped pointers
-        graphicsManager_.swap(graphicsManager);
-        inputManager_.swap(inputManager);
+        unloader.Dismiss();
 
         bGraphicsLoaded_ = true;
     }
 
     void Core::unloadGraphics()
     {
-        if (!bGraphicsLoaded_)
-            return;
-
         this->guiManager_.reset();;
         this->inputManager_.reset();;
         this->graphicsManager_.reset();
 
+        // Load Ogre::Root again, but without the render system
+        try
+            { this->graphicsManager_.reset(new GraphicsManager(false)); }
+        catch (...)
+        {
+            COUT(0) << "An exception occurred during 'new GraphicsManager' while "
+                    << "another exception was being handled. This will lead to undefined behaviour!" << std::endl
+                    << "Terminating the program." << std::endl;
+            abort();
+        }
+
         bGraphicsLoaded_ = false;
     }
 

Modified: code/branches/resource3/src/core/Core.h
===================================================================
--- code/branches/resource3/src/core/Core.h	2009-08-24 11:57:27 UTC (rev 5676)
+++ code/branches/resource3/src/core/Core.h	2009-08-24 13:03:44 UTC (rev 5677)
@@ -65,6 +65,7 @@
     {
         typedef Loki::ScopeGuardImpl0<void (*)()> SimpleScopeGuard;
         friend class Singleton<Core>;
+        friend class Game;
 
         public:
             /**
@@ -82,9 +83,6 @@
             bool preUpdate(const Clock& time) throw();
             bool postUpdate(const Clock& time) throw();
 
-            void loadGraphics();
-            void unloadGraphics();
-
             static int   getSoftDebugLevel(OutputHandler::OutputDevice device = OutputHandler::LD_All);
             static void  setSoftDebugLevel(OutputHandler::OutputDevice device, int level);
             static const std::string& getLanguage();
@@ -113,6 +111,9 @@
         private:
             Core(const Core&); //!< Don't use (undefined symbol)
 
+            void loadGraphics();
+            void unloadGraphics();
+
             void checkDevBuild();
             void setExecutablePath();
             void createDirectories();

Modified: code/branches/resource3/src/core/GraphicsManager.cc
===================================================================
--- code/branches/resource3/src/core/GraphicsManager.cc	2009-08-24 11:57:27 UTC (rev 5676)
+++ code/branches/resource3/src/core/GraphicsManager.cc	2009-08-24 13:03:44 UTC (rev 5677)
@@ -36,11 +36,8 @@
 #include "GraphicsManager.h"
 
 #include <fstream>
-#include <memory>
 #include <boost/filesystem.hpp>
-#include <boost/shared_ptr.hpp>
 
-#include <OgreCompositorManager.h>
 #include <OgreConfigFile.h>
 #include <OgreFrameListener.h>
 #include <OgreRoot.h>
@@ -48,7 +45,6 @@
 #include <OgreException.h>
 #include <OgreRenderWindow.h>
 #include <OgreRenderSystem.h>
-#include <OgreTextureManager.h>
 #include <OgreViewport.h>
 #include <OgreWindowEventUtilities.h>
 
@@ -67,8 +63,6 @@
 
 namespace orxonox
 {
-    using boost::shared_ptr;
-
     class OgreWindowEventListener : public Ogre::WindowEventListener
     {
     public:
@@ -88,68 +82,32 @@
     @brief
         Non-initialising constructor.
     */
-    GraphicsManager::GraphicsManager()
-        : ogreRoot_(0)
-        , ogreLogger_(0)
+    GraphicsManager::GraphicsManager(bool bLoadRenderer)
+        : ogreWindowEventListener_(new OgreWindowEventListener())
         , renderWindow_(0)
         , viewport_(0)
-        , ogreWindowEventListener_(new OgreWindowEventListener())
     {
         RegisterObject(GraphicsManager);
 
         this->setConfigValues();
 
-        // Ogre setup procedure
-        setupOgre();
+        // Ogre setup procedure (creating Ogre::Root)
+        this->loadOgreRoot();
+        // load all the required plugins for Ogre
+        this->loadOgrePlugins();
+        // read resource declaration file
+        this->declareResources();
 
-        try
-        {
-            // load all the required plugins for Ogre
-            loadOgrePlugins();
-            // read resource declaration file
-            this->declareResources();
-            // Reads ogre config and creates the render window
-            this->loadRenderer();
-
-            // TODO: Spread this
-            this->initialiseResources();
-
-            // add console commands
-            FunctorMember<GraphicsManager>* functor1 = createFunctor(&GraphicsManager::printScreen);
-            functor1->setObject(this);
-            ccPrintScreen_ = createConsoleCommand(functor1, "printScreen");
-            CommandExecutor::addConsoleCommandShortcut(ccPrintScreen_);
-        }
-        catch (...)
-        {
-            // clean up
-            delete this->ogreRoot_;
-            delete this->ogreLogger_;
-            delete this->ogreWindowEventListener_;
-            throw;
-        }
+        if (bLoadRenderer)
+            this->upgradeToGraphics();
     }
 
     /**
     @brief
-        Destroys all the Ogre related objects
+        Destruction is done by the member scoped_ptrs.
     */
     GraphicsManager::~GraphicsManager()
     {
-/*
-        delete this->ccPrintScreen_;
-*/
-
-        // unload all compositors (this is only necessary because we don't yet destroy all resources!)
-        Ogre::CompositorManager::getSingleton().removeAll();
-
-        // Delete OGRE main control organ
-        delete this->ogreRoot_;
-
-        // delete the logManager (since we have created it in the first place).
-        delete this->ogreLogger_;
-
-        delete this->ogreWindowEventListener_;
     }
 
     void GraphicsManager::setConfigValues()
@@ -172,47 +130,29 @@
             .description("Corresponding orxonox debug level for ogre Critical");
     }
 
-    void GraphicsManager::update(const Clock& time)
+    /**
+    @brief
+        Loads the renderer and creates the render window if not yet done so.
+    @remarks
+        This operation is irreversible without recreating the GraphicsManager!
+        So if it throws you HAVE to recreate the GraphicsManager!!!
+        It therefore offers almost no exception safety.
+    */
+    void GraphicsManager::upgradeToGraphics()
     {
-        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
-        ogreRoot_->_fireFrameStarted(evt);
-
-        // Pump messages in all registered RenderWindows
-        // This calls the WindowEventListener objects.
-        Ogre::WindowEventUtilities::messagePump();
-        // 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
-        ogreRoot_->_updateAllRenderTargets();
-
-        uint64_t timeAfterTick = time.getRealMicroseconds();
-        // Subtract the time used for rendering from the tick time counter
-        Game::getInstance().subtractTickTime(timeAfterTick - timeBeforeTick);
-
-        // again, just to be sure OGRE works fine
-        ogreRoot_->_fireFrameEnded(evt); // note: uses the same time as _fireFrameStarted
+        if (renderWindow_ == NULL)
+        {
+            // Reads the ogre config and creates the render window
+            this->loadRenderer();
+            this->initialiseResources();
+        }
     }
 
-    void GraphicsManager::setCamera(Ogre::Camera* camera)
-    {
-        this->viewport_->setCamera(camera);
-    }
-
     /**
     @brief
         Creates the Ogre Root object and sets up the ogre log.
     */
-    void GraphicsManager::setupOgre()
+    void GraphicsManager::loadOgreRoot()
     {
         COUT(3) << "Setting up Ogre..." << std::endl;
 
@@ -232,12 +172,12 @@
 
         // create a new logManager
         // Ogre::Root will detect that we've already created a Log
-        std::auto_ptr<Ogre::LogManager> logger(new Ogre::LogManager());
+        ogreLogger_.reset(new Ogre::LogManager());
         COUT(4) << "Ogre LogManager created" << std::endl;
 
         // create our own log that we can listen to
         Ogre::Log *myLog;
-        myLog = logger->createLog(ogreLogFilepath.string(), true, false, false);
+        myLog = ogreLogger_->createLog(ogreLogFilepath.string(), true, false, false);
         COUT(4) << "Ogre Log created" << std::endl;
 
         myLog->setLogDetail(Ogre::LL_BOREME);
@@ -255,9 +195,7 @@
         }
 
         // Leave plugins file empty. We're going to do that part manually later
-        ogreRoot_ = new Ogre::Root("", ogreConfigFilepath.string(), ogreLogFilepath.string());
-        // In case that new Root failed the logger gets destroyed because of the std::auto_ptr
-        ogreLogger_ = logger.release();
+        ogreRoot_.reset(new Ogre::Root("", ogreConfigFilepath.string(), ogreLogFilepath.string()));
 
         COUT(3) << "Ogre set up done." << std::endl;
     }
@@ -339,14 +277,21 @@
         CCOUT(4) << "Creating render window" << std::endl;
 
         this->renderWindow_ = ogreRoot_->initialise(true, "Orxonox");
+        // Propagate the size of the new winodw
         this->ogreWindowEventListener_->windowResized(renderWindow_);
 
-        Ogre::WindowEventUtilities::addWindowEventListener(this->renderWindow_, ogreWindowEventListener_);
+        Ogre::WindowEventUtilities::addWindowEventListener(this->renderWindow_, ogreWindowEventListener_.get());
 
-        Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(0);
-
         // create a full screen default viewport
+        // Note: This may throw when adding a viewport with an existing z-order!
+        //       But in our case we only have one viewport for now anyway, therefore
+        //       no ScopeGuards or anything to handle exceptions.
         this->viewport_ = this->renderWindow_->addViewport(0, 0);
+
+        // add console commands
+        FunctorMember<GraphicsManager>* functor1 = createFunctor(&GraphicsManager::printScreen);
+        ccPrintScreen_ = createConsoleCommand(functor1->setObject(this), "printScreen");
+        CommandExecutor::addConsoleCommandShortcut(ccPrintScreen_);
     }
 
     void GraphicsManager::initialiseResources()
@@ -369,6 +314,42 @@
         //}
     }
 
+    void GraphicsManager::update(const Clock& time)
+    {
+        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
+        ogreRoot_->_fireFrameStarted(evt);
+
+        // Pump messages in all registered RenderWindows
+        // This calls the WindowEventListener objects.
+        Ogre::WindowEventUtilities::messagePump();
+        // 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
+        ogreRoot_->_updateAllRenderTargets();
+
+        uint64_t timeAfterTick = time.getRealMicroseconds();
+        // Subtract the time used for rendering from the tick time counter
+        Game::getInstance().subtractTickTime(timeAfterTick - timeBeforeTick);
+
+        // again, just to be sure OGRE works fine
+        ogreRoot_->_fireFrameEnded(evt); // note: uses the same time as _fireFrameStarted
+    }
+
+    void GraphicsManager::setCamera(Ogre::Camera* camera)
+    {
+        this->viewport_->setCamera(camera);
+    }
+
     /**
     @brief
         Method called by the LogListener interface from Ogre.

Modified: code/branches/resource3/src/core/GraphicsManager.h
===================================================================
--- code/branches/resource3/src/core/GraphicsManager.h	2009-08-24 11:57:27 UTC (rev 5676)
+++ code/branches/resource3/src/core/GraphicsManager.h	2009-08-24 13:03:44 UTC (rev 5677)
@@ -41,11 +41,15 @@
 #include <cassert>
 #include <string>
 #include <OgreLog.h>
+#include <boost/scoped_ptr.hpp>
+
 #include "util/Singleton.h"
 #include "OrxonoxClass.h"
 
 namespace orxonox
 {
+    using boost::scoped_ptr;
+
     /**
     @brief
         Graphics engine manager class
@@ -54,25 +58,26 @@
     {
         friend class Singleton<GraphicsManager>;
     public:
-        GraphicsManager();
+        GraphicsManager(bool bLoadRenderer = true);
         ~GraphicsManager();
 
         void setConfigValues();
 
         void update(const Clock& time);
 
-        inline Ogre::Viewport* getViewport()
-            { return this->viewport_; }
-        inline Ogre::RenderWindow* getRenderWindow()
-            { return this->renderWindow_; }
+        Ogre::Viewport* getViewport()         { return this->viewport_; }
+        Ogre::RenderWindow* getRenderWindow() { return this->renderWindow_; }
 
+        void upgradeToGraphics();
+        bool rendererLoaded() const { return renderWindow_ != NULL; }
+
         void setCamera(Ogre::Camera* camera);
 
     private:
         GraphicsManager(GraphicsManager&); // don't mess with singletons
 
         // OGRE initialisation
-        void setupOgre();
+        void loadOgreRoot();
         void loadOgrePlugins();
         void declareResources();
         void loadRenderer();
@@ -86,11 +91,11 @@
         void printScreen();
 
     private:
-        Ogre::Root*         ogreRoot_;                 //!< Ogre's root
-        Ogre::LogManager*   ogreLogger_;
+        scoped_ptr<OgreWindowEventListener> ogreWindowEventListener_; //!< Pimpl to hide OgreWindowUtilities.h
+        scoped_ptr<Ogre::LogManager>        ogreLogger_;
+        scoped_ptr<Ogre::Root>              ogreRoot_;                //!< Ogre's root
         Ogre::RenderWindow* renderWindow_;             //!< the one and only render window
         Ogre::Viewport*     viewport_;                 //!< default full size viewport
-        OgreWindowEventListener* ogreWindowEventListener_; //!< Pimpl to hide OgreWindowUtilities.h
 
         // config values
         std::string         resourceFile_;             //!< resources file name

Modified: code/branches/resource3/src/orxonox/gamestates/GSLevel.cc
===================================================================
--- code/branches/resource3/src/orxonox/gamestates/GSLevel.cc	2009-08-24 11:57:27 UTC (rev 5676)
+++ code/branches/resource3/src/orxonox/gamestates/GSLevel.cc	2009-08-24 13:03:44 UTC (rev 5677)
@@ -29,6 +29,8 @@
 
 #include "GSLevel.h"
 
+#include <OgreCompositorManager.h>
+
 #include "core/input/InputManager.h"
 #include "core/input/InputState.h"
 #include "core/input/KeyBinder.h"
@@ -169,6 +171,11 @@
         }
 */
 
+        if (GameMode::showsGraphics())
+        {
+            // unload all compositors (this is only necessary because we don't yet destroy all resources!)
+            Ogre::CompositorManager::getSingleton().removeAll();
+        }
 
         // this call will delete every BaseObject!
         // But currently this will call methods of objects that exist no more




More information about the Orxonox-commit mailing list