[Orxonox-commit 841] r3356 - in branches/resource/src: core orxonox/gamestates

rgrieder at orxonox.net rgrieder at orxonox.net
Mon Jul 27 11:13:26 CEST 2009


Author: rgrieder
Date: 2009-07-27 11:13:25 +0200 (Mon, 27 Jul 2009)
New Revision: 3356

Modified:
   branches/resource/src/core/Core.cc
   branches/resource/src/core/Game.cc
   branches/resource/src/core/Game.h
   branches/resource/src/core/GameState.cc
   branches/resource/src/core/GameState.h
   branches/resource/src/orxonox/gamestates/GSLevel.cc
Log:
GameStates requiring graphics (Level is not one of them because it uses showsGraphics() to distinguish) are now only constructed when basic graphic support is given (GraphicsManager, InputManager and GUIManager loaded).

Modified: branches/resource/src/core/Core.cc
===================================================================
--- branches/resource/src/core/Core.cc	2009-07-26 12:15:08 UTC (rev 3355)
+++ branches/resource/src/core/Core.cc	2009-07-27 09:13:25 UTC (rev 3356)
@@ -670,10 +670,13 @@
         std::string exceptionMessage;
         try
         {
-            // process input events
-            this->inputManager_->update(time);
-            // process gui events
-            this->guiManager_->update(time);
+            if (this->bGraphicsLoaded_)
+            {
+                // process input events
+                this->inputManager_->update(time);
+                // process gui events
+                this->guiManager_->update(time);
+            }
             // process thread commands
             this->tclThreadManager_->update(time);
         }
@@ -695,8 +698,11 @@
         std::string exceptionMessage;
         try
         {
-            // Render (doesn't throw)
-            this->graphicsManager_->update(time);
+            if (this->bGraphicsLoaded_)
+            {
+                // Render (doesn't throw)
+                this->graphicsManager_->update(time);
+            }
         }
         catch (const std::exception& ex)
         { exceptionMessage = ex.what(); }

Modified: branches/resource/src/core/Game.cc
===================================================================
--- branches/resource/src/core/Game.cc	2009-07-26 12:15:08 UTC (rev 3355)
+++ branches/resource/src/core/Game.cc	2009-07-27 09:13:25 UTC (rev 3356)
@@ -69,7 +69,7 @@
     */
     struct GameStateTreeNode
     {
-        GameState* state_;
+        std::string name_;
         weak_ptr<GameStateTreeNode> parent_;
         std::vector<shared_ptr<GameStateTreeNode> > children_;
     };
@@ -137,20 +137,19 @@
         // Create the Core
         this->core_ = new Core(cmdLine);
 
-        // After the core has been created, we can safely instantiate the GameStates
+        // After the core has been created, we can safely instantiate the GameStates that don't require graphics
         for (std::map<std::string, GameStateInfo>::const_iterator it = gameStateDeclarations_s.begin();
             it != gameStateDeclarations_s.end(); ++it)
         {
-            // Only create the states appropriate for the game mode
-            //if (GameMode::showsGraphics || !it->second.bGraphicsMode)
-            gameStates_[getLowercase(it->second.stateName)] = GameStateFactory::fabricate(it->second);
+            if (!it->second.bGraphicsMode)
+                constructedStates_[it->second.stateName] = GameStateFactory::fabricate(it->second);
         }
 
         // The empty root state is ALWAYS loaded!
         this->rootStateNode_ = shared_ptr<GameStateTreeNode>(new GameStateTreeNode());
-        this->rootStateNode_->state_ = getState("emptyRootGameState");
-        this->activeStateNode_ = this->rootStateNode_;
-        this->activeStates_.push_back(this->rootStateNode_->state_);
+        this->rootStateNode_->name_ = "emptyRootGameState";
+        this->loadedTopStateNode_ = this->rootStateNode_;
+        this->loadedStates_.push_back(this->getState(rootStateNode_->name_));
 
         // Do this after the Core creation!
         this->configuration_ = new GameConfiguration();
@@ -165,8 +164,8 @@
         delete this->configuration_;
 
         // Destroy the GameStates (note that the nodes still point to them, but doesn't matter)
-        for (std::map<std::string, GameState*>::const_iterator it = gameStates_.begin();
-            it != gameStates_.end(); ++it)
+        for (std::map<std::string, GameState*>::const_iterator it = constructedStates_.begin();
+            it != constructedStates_.end(); ++it)
             delete it->second;
 
         // Destroy the Core and with it almost everything
@@ -207,7 +206,7 @@
         // A first item is required for the fps limiter
         StatisticsTickInfo tickInfo = {0, 0};
         statisticsTickTimes_.push_back(tickInfo);
-        while (!this->bAbort_ && (!this->activeStates_.empty() || this->requestedStateNodes_.size() > 0))
+        while (!this->bAbort_ && (!this->loadedStates_.empty() || this->requestedStateNodes_.size() > 0))
         {
             // Generate the dt
             this->gameClock_->capture();
@@ -245,9 +244,9 @@
         }
 
         // UNLOAD all remaining states
-        while (this->activeStates_.size() > 1)
-            this->unloadState(this->activeStates_.back());
-        this->activeStateNode_ = this->rootStateNode_;
+        while (this->loadedStates_.size() > 1)
+            this->unloadState(this->loadedStates_.back()->getName());
+        this->loadedTopStateNode_ = this->rootStateNode_;
         this->requestedStateNodes_.clear();
     }
 
@@ -256,18 +255,18 @@
         while (this->requestedStateNodes_.size() > 0)
         {
             shared_ptr<GameStateTreeNode> requestedStateNode = this->requestedStateNodes_.front();
-            assert(this->activeStateNode_);
-            if (!this->activeStateNode_->parent_.expired() && requestedStateNode == this->activeStateNode_->parent_.lock())
-                this->unloadState(this->activeStateNode_->state_);
+            assert(this->loadedTopStateNode_);
+            if (!this->loadedTopStateNode_->parent_.expired() && requestedStateNode == this->loadedTopStateNode_->parent_.lock())
+                this->unloadState(loadedTopStateNode_->name_);
             else // has to be child
             {
                 try
                 {
-                    this->loadState(requestedStateNode->state_);
+                    this->loadState(requestedStateNode->name_);
                 }
                 catch (const std::exception& ex)
                 {
-                    COUT(1) << "Error: Loading GameState '" << requestedStateNode->state_->getName() << "' failed: " << ex.what() << std::endl;
+                    COUT(1) << "Error: Loading GameState '" << requestedStateNode->name_ << "' failed: " << ex.what() << std::endl;
                     // All scheduled operations have now been rendered inert --> flush them and issue a warning
                     if (this->requestedStateNodes_.size() > 1)
                         COUT(1) << "All " << this->requestedStateNodes_.size() - 1 << " scheduled transitions have been ignored." << std::endl;
@@ -275,7 +274,7 @@
                     break;
                 }
             }
-            this->activeStateNode_ = requestedStateNode;
+            this->loadedTopStateNode_ = requestedStateNode;
             this->requestedStateNodes_.erase(this->requestedStateNodes_.begin());
         }
     }
@@ -283,8 +282,8 @@
     void Game::updateGameStates()
     {
         // Note: The first element is the empty root state, which doesn't need ticking
-        for (std::vector<GameState*>::const_iterator it = this->activeStates_.begin() + 1;
-            it != this->activeStates_.end(); ++it)
+        for (std::vector<GameState*>::const_iterator it = this->loadedStates_.begin() + 1;
+            it != this->loadedStates_.end(); ++it)
         {
             std::string exceptionMessage;
             try
@@ -306,8 +305,11 @@
                 COUT(1) << "An exception occurred while updating '" << (*it)->getName() << "': " << exceptionMessage << std::endl;
                 COUT(1) << "This should really never happen!" << std::endl;
                 COUT(1) << "Unloading all GameStates depending on the one that crashed." << std::endl;
-                if ((*it)->getParent() != NULL)
-                    this->requestState((*it)->getParent()->getName());
+                shared_ptr<GameStateTreeNode> current = this->loadedTopStateNode_;
+                while (current->name_ != (*it)->getName() && current)
+                    current = current->parent_.lock();
+                if (current && current->parent_.lock())
+                    this->requestState(current->parent_.lock()->name_);
                 else
                     this->stop();
                 break;
@@ -381,9 +383,11 @@
 
     void Game::requestState(const std::string& name)
     {
-        GameState* state = this->getState(name);
-        if (state == NULL)
+        if (!this->checkState(name))
+        {
+            COUT(2) << "Warning: GameState named '" << name << "' doesn't exist!" << std::endl;
             return;
+        }
 
         //if (this->bChangingState_)
         //{
@@ -393,10 +397,10 @@
 
         shared_ptr<GameStateTreeNode> lastRequestedNode;
         if (this->requestedStateNodes_.empty())
-            lastRequestedNode = this->activeStateNode_;
+            lastRequestedNode = this->loadedTopStateNode_;
         else
             lastRequestedNode = this->requestedStateNodes_.back();
-        if (state == lastRequestedNode->state_)
+        if (name == lastRequestedNode->name_)
         {
             COUT(2) << "Warning: Requesting the currently active state! Ignoring." << std::endl;
             return;
@@ -406,7 +410,7 @@
         std::vector<shared_ptr<GameStateTreeNode> > requestedNodes;
         for (unsigned int i = 0; i < lastRequestedNode->children_.size(); ++i)
         {
-            if (lastRequestedNode->children_[i]->state_ == state)
+            if (lastRequestedNode->children_[i]->name_ == name)
             {
                 requestedNodes.push_back(lastRequestedNode->children_[i]);
                 break;
@@ -419,7 +423,7 @@
             shared_ptr<GameStateTreeNode> currentNode = lastRequestedNode;
             while (currentNode != NULL)
             {
-                if (currentNode->state_ == state)
+                if (currentNode->name_ == name)
                     break;
                 currentNode = currentNode->parent_.lock();
                 requestedNodes.push_back(currentNode);
@@ -443,23 +447,27 @@
     {
         shared_ptr<GameStateTreeNode> lastRequestedNode;
         if (this->requestedStateNodes_.empty())
-            lastRequestedNode = this->activeStateNode_;
+            lastRequestedNode = this->loadedTopStateNode_;
         else
             lastRequestedNode = this->requestedStateNodes_.back();
         if (lastRequestedNode != this->rootStateNode_)
-            this->requestState(lastRequestedNode->parent_.lock()->state_->getName());
+            this->requestState(lastRequestedNode->parent_.lock()->name_);
         else
             COUT(2) << "Warning: Can't pop the internal dummy root GameState" << std::endl;
     }
 
     GameState* Game::getState(const std::string& name)
     {
-        std::map<std::string, GameState*>::const_iterator it = gameStates_.find(getLowercase(name));
-        if (it != gameStates_.end())
+        std::map<std::string, GameState*>::const_iterator it = constructedStates_.find(name);
+        if (it != constructedStates_.end())
             return it->second;
         else
         {
-            COUT(1) << "Error: Could not find GameState '" << name << "'. Ignoring." << std::endl;
+            std::map<std::string, GameStateInfo>::const_iterator it = gameStateDeclarations_s.find(name);
+            if (it != gameStateDeclarations_s.end())
+                COUT(1) << "Error: GameState '" << name << "' has not yet been loaded." << std::endl;
+            else
+                COUT(1) << "Error: Could not find GameState '" << name << "'." << std::endl;
             return 0;
         }
     }
@@ -486,13 +494,12 @@
         {
             std::string newStateName = it->first;
             unsigned newLevel = it->second + 1; // empty root is 0
-            GameState* newState = this->getState(newStateName);
-            if (!newState)
+            if (!this->checkState(newStateName))
                 ThrowException(GameState, "GameState with name '" << newStateName << "' not found!");
-            if (newState == this->rootStateNode_->state_)
+            if (newStateName == this->rootStateNode_->name_)
                 ThrowException(GameState, "You shouldn't use 'emptyRootGameState' in the hierarchy...");
             shared_ptr<GameStateTreeNode> newNode(new GameStateTreeNode);
-            newNode->state_ = newState;
+            newNode->name_ = newStateName;
 
             if (newLevel <= currentLevel)
             {
@@ -505,7 +512,6 @@
                 // Add the child
                 newNode->parent_ = currentNode;
                 currentNode->children_.push_back(newNode);
-                currentNode->state_->addChild(newNode->state_);
             }
             else
                 ThrowException(GameState, "Indentation error while parsing the hierarchy.");
@@ -522,6 +528,18 @@
         {
             core_->loadGraphics();
             GameMode::bShowsGraphics_s = true;
+
+            // Construct all the GameStates that require graphics
+            for (std::map<std::string, GameStateInfo>::const_iterator it = gameStateDeclarations_s.begin();
+                it != gameStateDeclarations_s.end(); ++it)
+            {
+                if (it->second.bGraphicsMode)
+                {
+                    if (!constructedStates_.insert(std::make_pair(
+                        it->second.stateName, GameStateFactory::fabricate(it->second))).second)
+                        assert(false); // GameState was already created!
+                }
+            }
         }
     }
 
@@ -529,45 +547,68 @@
     {
         if (GameMode::bShowsGraphics_s)
         {
+            // Destroy all the GameStates that require graphics
+            for (std::map<std::string, GameState*>::iterator it = constructedStates_.begin(); it != constructedStates_.end();)
+            {
+                if (it->second->getInfo().bGraphicsMode)
+                {
+                    delete it->second;
+                    it = constructedStates_.erase(it);
+                }
+                else
+                    ++it;
+            }
+
             core_->unloadGraphics();
             GameMode::bShowsGraphics_s = false;
         }
     }
 
-    void Game::loadState(GameState* state)
+    bool Game::checkState(const std::string& name) const
     {
+        std::map<std::string, GameStateInfo>::const_iterator it = gameStateDeclarations_s.find(name);
+        if (it == gameStateDeclarations_s.end())
+            return false;
+        else
+            return true;
+    }
+
+    void Game::loadState(const std::string& name)
+    {
         this->bChangingState_ = true;
         // If state requires graphics, load it
-        if (state->getInfo().bGraphicsMode)
+        if (gameStateDeclarations_s[name].bGraphicsMode)
             this->loadGraphics();
+        GameState* state = this->getState(name);
         state->activate();
-        if (!this->activeStates_.empty())
-            this->activeStates_.back()->activity_.topState = false;
-        this->activeStates_.push_back(state);
+        if (!this->loadedStates_.empty())
+            this->loadedStates_.back()->activity_.topState = false;
+        this->loadedStates_.push_back(state);
         state->activity_.topState = true;
         this->bChangingState_ = false;
     }
 
-    void Game::unloadState(orxonox::GameState* state)
+    void Game::unloadState(const std::string& name)
     {
+        GameState* state = this->getState(name);
         this->bChangingState_ = true;
         state->activity_.topState = false;
-        this->activeStates_.pop_back();
-        if (!this->activeStates_.empty())
-            this->activeStates_.back()->activity_.topState = true;
+        this->loadedStates_.pop_back();
+        if (!this->loadedStates_.empty())
+            this->loadedStates_.back()->activity_.topState = true;
         try
         {
             state->deactivate();
             // Check if graphis is still required
             bool graphicsRequired = false;
-            for (unsigned i = 0; i < activeStates_.size(); ++i)
-                graphicsRequired |= activeStates_[i]->getInfo().bGraphicsMode;
+            for (unsigned i = 0; i < loadedStates_.size(); ++i)
+                graphicsRequired |= loadedStates_[i]->getInfo().bGraphicsMode;
             if (!graphicsRequired)
                 this->unloadGraphics();
         }
         catch (const std::exception& ex)
         {
-            COUT(2) << "Warning: Unloading GameState '" << state->getName() << "' threw an exception: " << ex.what() << std::endl;
+            COUT(2) << "Warning: Unloading GameState '" << name << "' threw an exception: " << ex.what() << std::endl;
             COUT(2) << "         There might be potential resource leaks involved! To avoid this, improve exception-safety." << std::endl;
         }
         this->bChangingState_ = false;

Modified: branches/resource/src/core/Game.h
===================================================================
--- branches/resource/src/core/Game.h	2009-07-26 12:15:08 UTC (rev 3355)
+++ branches/resource/src/core/Game.h	2009-07-27 09:13:25 UTC (rev 3356)
@@ -46,7 +46,6 @@
 #include <boost/preprocessor/cat.hpp>
 
 #include "util/Debug.h"
-#include "util/StringUtils.h"
 
 /**
 @def
@@ -75,6 +74,7 @@
     */
     class _CoreExport Game
     {
+        typedef boost::shared_ptr<GameStateTreeNode> GameStateTreeNodePtr;
     public:
         Game(const std::string& cmdLine);
         ~Game();
@@ -133,8 +133,9 @@
         void loadGraphics();
         void unloadGraphics();
 
-        void loadState(GameState* state);
-        void unloadState(GameState* state);
+        bool checkState(const std::string& name) const;
+        void loadState(const std::string& name);
+        void unloadState(const std::string& name);
 
         // Main loop structuring
         void updateGameStateStack();
@@ -142,28 +143,28 @@
         void updateStatistics();
         void updateFPSLimiter();
 
-        std::map<std::string, GameState*>    gameStates_;
-        std::vector<GameState*>              activeStates_;
-        boost::shared_ptr<GameStateTreeNode> rootStateNode_;
-        boost::shared_ptr<GameStateTreeNode> activeStateNode_;
-        std::vector<boost::shared_ptr<GameStateTreeNode> > requestedStateNodes_;
+        std::map<std::string, GameState*>  constructedStates_;
+        std::vector<GameState*>            loadedStates_;
+        GameStateTreeNodePtr               rootStateNode_;
+        GameStateTreeNodePtr               loadedTopStateNode_;
+        std::vector<GameStateTreeNodePtr > requestedStateNodes_;
 
-        Core*                           core_;
-        Clock*                          gameClock_;
-        GameConfiguration*              configuration_;
+        Core*                              core_;
+        Clock*                             gameClock_;
+        GameConfiguration*                 configuration_;
 
-        bool                            bChangingState_;
-        bool                            bAbort_;
+        bool                               bChangingState_;
+        bool                               bAbort_;
 
         // variables for time statistics
-        uint64_t                        statisticsStartTime_;
-        std::list<StatisticsTickInfo>   statisticsTickTimes_;
-        uint32_t                        periodTime_;
-        uint32_t                        periodTickTime_;
-        float                           avgFPS_;
-        float                           avgTickTime_;
-        int                             excessSleepTime_;
-        unsigned int                    minimumSleepTime_;
+        uint64_t                           statisticsStartTime_;
+        std::list<StatisticsTickInfo>      statisticsTickTimes_;
+        uint32_t                           periodTime_;
+        uint32_t                           periodTickTime_;
+        float                              avgFPS_;
+        float                              avgTickTime_;
+        int                                excessSleepTime_;
+        unsigned int                       minimumSleepTime_;
 
         static std::map<std::string, GameStateInfo> gameStateDeclarations_s;
         static Game* singletonRef_s;        //!< Pointer to the Singleton
@@ -172,10 +173,10 @@
     template <class T>
     /*static*/ bool Game::declareGameState(const std::string& className, const std::string& stateName, bool bIgnoreTickTime, bool bGraphicsMode)
     {
-        std::map<std::string, GameStateInfo>::const_iterator it = gameStateDeclarations_s.find(getLowercase(stateName));
+        std::map<std::string, GameStateInfo>::const_iterator it = gameStateDeclarations_s.find(stateName);
         if (it == gameStateDeclarations_s.end())
         {
-            GameStateInfo& info = gameStateDeclarations_s[getLowercase(stateName)];
+            GameStateInfo& info = gameStateDeclarations_s[stateName];
             info.stateName = stateName;
             info.className = className;
             info.bIgnoreTickTime = bIgnoreTickTime;

Modified: branches/resource/src/core/GameState.cc
===================================================================
--- branches/resource/src/core/GameState.cc	2009-07-26 12:15:08 UTC (rev 3355)
+++ branches/resource/src/core/GameState.cc	2009-07-27 09:13:25 UTC (rev 3356)
@@ -47,7 +47,6 @@
     */
     GameState::GameState(const GameStateInfo& info)
         : info_(info)
-        , parent_(0)
     {
         this->activity_.activating   = false;
         this->activity_.active       = false;
@@ -71,51 +70,6 @@
         return info_.stateName;
     }
 
-    /**
-    @brief
-        Adds a child to the current tree. The Child can contain children of its own.
-        But you cannot a state tree that already has an active state.
-    @param state
-        The state to be added.
-    */
-    void GameState::addChild(GameState* state)
-    {
-        assert(state != NULL);
-
-        std::map<std::string, GameState*>::const_iterator it = this->children_.find(state->getName());
-        if (it == this->children_.end())
-        {
-            this->children_[state->getName()] = state;
-            // mark us as parent
-            state->setParent(this);
-        }
-        else
-        {
-            ThrowException(GameState, "Cannot add two children with the same name");
-        }
-    }
-
-    /**
-    @brief
-        Removes a child by instance. This splits the tree in two parts,
-        each of them functional on its own.
-    @param state
-        GameState by instance pointer
-    */
-    void GameState::removeChild(GameState* state)
-    {
-        assert(state != NULL);
-
-        std::map<std::string, GameState*>::iterator it = this->children_.find(state->getName());
-        if (it != this->children_.end())
-            this->children_.erase(it);
-        else
-        {
-            ThrowException(GameState, "Game state '" + this->getName() + "' doesn't have a child named '"
-                + state->getName() + "'.");
-        }
-    }
-
     void GameState::activateInternal()
     {
         this->activity_.activating = true;

Modified: branches/resource/src/core/GameState.h
===================================================================
--- branches/resource/src/core/GameState.h	2009-07-26 12:15:08 UTC (rev 3355)
+++ branches/resource/src/core/GameState.h	2009-07-27 09:13:25 UTC (rev 3356)
@@ -81,28 +81,21 @@
 
         const std::string& getName()   const;
         State getActivity()            const { return activity_; }
-        GameState* getParent()         const { return parent_; }
         const GameStateInfo& getInfo() const { return info_; }
 
-        void addChild(GameState* state);
-        void removeChild(GameState* state);
-
     protected:
         virtual void activate() { }
         virtual void deactivate() { }
         virtual void update(const Clock& time) { }
 
     private:
-        void setParent(GameState* state) { this->parent_ = state; }
         void setActivity(State activity);
         void activateInternal();
         void deactivateInternal();
         void updateInternal(const Clock& time);
 
-        const GameStateInfo&                     info_;
-        State                                    activity_;
-        GameState*                               parent_;
-        std::map<std::string, GameState*>        children_;
+        const GameStateInfo& info_;
+        State                activity_;
     };
 }
 

Modified: branches/resource/src/orxonox/gamestates/GSLevel.cc
===================================================================
--- branches/resource/src/orxonox/gamestates/GSLevel.cc	2009-07-26 12:15:08 UTC (rev 3355)
+++ branches/resource/src/orxonox/gamestates/GSLevel.cc	2009-07-27 09:13:25 UTC (rev 3356)
@@ -54,7 +54,7 @@
 
 namespace orxonox
 {
-    DeclareGameState(GSLevel, "level", false, true);
+    DeclareGameState(GSLevel, "level", false, false);
     SetConsoleCommand(GSLevel, showIngameGUI, true);
 
     XMLFile* GSLevel::startFile_s = NULL;




More information about the Orxonox-commit mailing list