[Orxonox-commit 3108] r7802 - code/trunk/src/orxonox

dafrick at orxonox.net dafrick at orxonox.net
Sat Dec 25 20:51:18 CET 2010


Author: dafrick
Date: 2010-12-25 20:51:17 +0100 (Sat, 25 Dec 2010)
New Revision: 7802

Modified:
   code/trunk/src/orxonox/LevelInfo.h
   code/trunk/src/orxonox/LevelManager.cc
   code/trunk/src/orxonox/LevelManager.h
Log:
Making the level list in the LevelManager (and as consequence the level list displayed by the GUI) alphabetically sorted. Also some cleanup and documented LevelManager.


Modified: code/trunk/src/orxonox/LevelInfo.h
===================================================================
--- code/trunk/src/orxonox/LevelInfo.h	2010-12-22 18:24:24 UTC (rev 7801)
+++ code/trunk/src/orxonox/LevelInfo.h	2010-12-25 19:51:17 UTC (rev 7802)
@@ -39,6 +39,7 @@
 
 #include <set>
 #include <string>
+#include "util/StringUtils.h"
 
 #include "core/BaseObject.h"
 #include "core/OrxonoxClass.h"
@@ -72,7 +73,7 @@
             @brief Get the name of the Level.
             @return Returns the name of the Level.
             */
-            inline const std::string& getName(void) { return this->name_; } // tolua_export
+            inline const std::string& getName(void) const { return this->name_; } // tolua_export
 
             /**
             @brief Set the description of the Level.
@@ -149,7 +150,7 @@
         An example would be:
         @code
         <LevelInfo
-            name = "Levelname"
+            name = "Levelname"lhs->compare(rhs) < 0
             description = "This is just some awesome level."
             tags = "test, awesome"
         />
@@ -196,6 +197,17 @@
             LevelInfoItem* copy(void); //!< Copies the contents of this LevelInfo object to a new LevelInfoItem object.
 
     };
+
+    /**
+    @brief
+        Struct that overloads the compare operation between two @ref orxonox::LevelInfoItem "LevelInfoItem" pointers.
+    */
+    struct LevelInfoCompare
+    {
+        bool operator() (const LevelInfoItem* lhs, const LevelInfoItem* rhs) const
+            { return getLowercase(lhs->getName()).compare(getLowercase(rhs->getName())) < 0; }
+    };
+    
 } // tolua_export
 
 #endif /* _LevelInfo_H__ */

Modified: code/trunk/src/orxonox/LevelManager.cc
===================================================================
--- code/trunk/src/orxonox/LevelManager.cc	2010-12-22 18:24:24 UTC (rev 7801)
+++ code/trunk/src/orxonox/LevelManager.cc	2010-12-25 19:51:17 UTC (rev 7802)
@@ -22,7 +22,7 @@
  *   Author:
  *      Fabian 'x3n' Landau
  *   Co-authors:
- *      ...
+ *      Damian 'Mozork' Frick
  *
  */
 
@@ -38,9 +38,8 @@
 #include "core/Loader.h"
 #include "core/Resource.h"
 #include "core/XMLFile.h"
+#include "Level.h"
 #include "PlayerManager.h"
-#include "Level.h"
-#include "LevelInfo.h"
 
 namespace orxonox
 {
@@ -48,6 +47,10 @@
 
     ManageScopedSingleton(LevelManager, ScopeID::Root, false);
 
+    /**
+    @brief
+        Constructor. Registers the object, sets config values and initializes variables.
+    */
     LevelManager::LevelManager()
     {
         RegisterRootObject(LevelManager);
@@ -60,75 +63,117 @@
         }
 
         this->compileAvailableLevelList();
+        this->nextIndex_ = 0;
+        this->nextLevel_ = this->availableLevels_.begin();
     }
 
     LevelManager::~LevelManager()
     {
     }
 
+    /**
+    @brief
+        Set the config values for this object.
+    */
     void LevelManager::setConfigValues()
     {
         SetConfigValue(defaultLevelName_, "presentationDM.oxw")
             .description("Sets the pre selection of the level in the main menu.");
     }
 
+    /**
+    @brief
+        Request activity for the input Level.
+        The Level will be added to the list of Levels whose activity is requested. The list is accessed in a FIFO manner.
+        If the Level is the only Level in the list it will be immediately activated. If not it will be activated as soon as it reaches the front of the list.
+    @param level
+        A pointer to the Level whose activity is requested.
+    */
     void LevelManager::requestActivity(Level* level)
     {
-        assert( std::find(this->levels_s.begin(), this->levels_s.end(), level)==this->levels_s.end() );
-        if( std::find(this->levels_s.begin(), this->levels_s.end(), level)!=this->levels_s.end() )
-            return; // level is already in list
-        this->levels_s.push_back(level);
-        if (this->levels_s.size() == 1)
+        assert( std::find(this->levels_.begin(), this->levels_.end(), level)==this->levels_.end() );
+        // If the level is already in list.
+        if( std::find(this->levels_.begin(), this->levels_.end(), level)!=this->levels_.end() )
+            return;
+        // If it isn't insert it at the back.
+        this->levels_.push_back(level);
+        // If it is the only level in the list activate it.
+        if (this->levels_.size() == 1)
             this->activateNextLevel();
     }
 
+    /**
+    @brief
+        Release activity for the input Level.
+        Removes the Level from the list. If the Level was the one currently active, it is deactivated and the next Level in line is activated.
+    @param level
+        A pointer to the Level whose activity is to be released.
+    */
     void LevelManager::releaseActivity(Level* level)
     {
-        if (this->levels_s.size() > 0)
+        if (this->levels_.size() > 0)
         {
-            if (this->levels_s.front() == level)
+            // If the level is the active level in the front of the list.
+            if (this->levels_.front() == level)
             {
+                // Deactivate it, remove it from the list and activate the next level in line.
                 level->setActive(false);
-                this->levels_s.pop_front();
+                this->levels_.pop_front();
                 this->activateNextLevel();
             }
-            else
-            {
-                for (std::list<Level*>::iterator it = this->levels_s.begin(); it != this->levels_s.end(); ++it)
-                    if ((*it) == level)
-                        this->levels_s.erase(it);
-            }
+            else // Else just remove it from the list.
+                this->levels_.erase(std::find(this->levels_.begin(), this->levels_.end(), level));
         }
     }
 
+    /**
+    @brief
+        Get the currently active Level.
+    @return
+        Returns a pointer to the currently active level or NULL if there currently are no active Levels.
+    */
     Level* LevelManager::getActiveLevel()
     {
-        if (this->levels_s.size() > 0)
-            return this->levels_s.front();
+        if (this->levels_.size() > 0)
+            return this->levels_.front();
         else
             return 0;
     }
 
+    /**
+    @brief
+        Activate the next Level.
+    */
     void LevelManager::activateNextLevel()
     {
-        if (this->levels_s.size() > 0)
+        if (this->levels_.size() > 0)
         {
-            this->levels_s.front()->setActive(true);
+            // Activate the level that is the first in the list of levels whose activity has been requested. 
+            this->levels_.front()->setActive(true);
+            // Make every player enter the newly activated level.
             for (std::map<unsigned int, PlayerInfo*>::const_iterator it = PlayerManager::getInstance().getClients().begin(); it != PlayerManager::getInstance().getClients().end(); ++it)
-                this->levels_s.front()->playerEntered(it->second);
+                this->levels_.front()->playerEntered(it->second);
         }
     }
 
+    /**
+    @brief
+        Set the default Level.
+    @param levelName
+        The filename of the default Level.
+    */
     void LevelManager::setDefaultLevel(const std::string& levelName)
     {
         ModifyConfigValue(defaultLevelName_, set, levelName);
     }
 
-    const std::string& LevelManager::getDefaultLevel() const
-    {
-        return defaultLevelName_;
-    }
-
+    /**
+    @brief
+        Get the number of available Levels.
+        Also updates the list of available Levels.
+    @return
+        Returns the number of available Levels.
+    */
     unsigned int LevelManager::getNumberOfLevels()
     {
         this->updateAvailableLevelList();
@@ -136,17 +181,52 @@
         return this->availableLevels_.size();
     }
 
-    LevelInfoItem* LevelManager::getAvailableLevelListItem(unsigned int index) const
+    /**
+    @brief
+        Get the LevelInfoItem at the given index in the list of available Levels.
+        The LevelInfoItems are sorted in alphabetical order accoridng to the name of the Level.
+        This method is most efficiently called with consecutive indices (or at least ascending indices).
+    @return
+        Returns a pointer to the LevelInfoItem at the given index.
+    */
+    LevelInfoItem* LevelManager::getAvailableLevelListItem(unsigned int index)
     {
         if (index >= this->availableLevels_.size())
             return NULL;
+
+        // If this index directly follows the last we can optimize a lot.
+        if(index == this->nextIndex_)
+        {
+            this->nextIndex_++;
+            std::set<LevelInfoItem*, LevelInfoCompare>::iterator it = this->nextLevel_;
+            this->nextLevel_++;
+            return *it;
+        }
         else
         {
-            std::map<std::string, LevelInfoItem*>::const_iterator it = this->infos_.find(this->availableLevels_[index]);
-            return it->second;
+            // If this index is bigger than the last, we can optimize a little.
+            if(index > this->nextIndex_)
+            {
+                this->nextIndex_ = 0;
+                this->nextLevel_ = this->availableLevels_.begin();
+            }
+            while(this->nextIndex_ != index)
+            {
+                this->nextIndex_++;
+                this->nextLevel_++;
+            }
+            this->nextIndex_++;
+            std::set<LevelInfoItem*, LevelInfoCompare>::iterator it = this->nextLevel_;
+            this->nextLevel_++;
+            return *it;
         }
     }
 
+    /**
+    @brief
+        Compile the list of available Levels.
+        Iterates over all *.oxw files, loads the LevelInfo objects in them and from that it creates the LevelInfoItems which are inserted in a list.
+    */
     void LevelManager::compileAvailableLevelList()
     {
         Ogre::StringVectorPtr levels = Resource::findResourceNames("*.oxw");
@@ -154,38 +234,39 @@
         COUT(3) << "Loading LevelInfos..." << std::endl;
         for (Ogre::StringVector::const_iterator it = levels->begin(); it != levels->end(); ++it)
         {
-            //TODO: Replace with tag,
+            //TODO: Replace with tag?
             if (it->find("old/") != 0)
             {
                 size_t pos = it->find(".oxw");
 
+                // Load the LevelInfo object from the level file.
                 bool infoExists = false;
-                // Load the LevelInfo object from the level file.
                 XMLFile file = XMLFile(*it);
                 ClassTreeMask mask = ClassTreeMask();
                 mask.exclude(ClassIdentifier<BaseObject>::getIdentifier());
                 mask.include(ClassIdentifier<LevelInfo>::getIdentifier());
                 Loader::load(&file, mask, false);
+                // Iterate over all LevelInfos.
                 for(ObjectList<LevelInfo>::iterator item = ObjectList<LevelInfo>::begin(); item != ObjectList<LevelInfo>::end(); ++item)
                 {
                     LevelInfoItem* info = item->copy();
-                    if(info->getXMLFilename() == *it)
+                    if(info->getXMLFilename() == *it) // If the LevelInfo for this level exists we insert it into the list of available levels.
                     {
-                        this->infos_.insert(std::pair<std::string, LevelInfoItem*>(it->substr(0, pos),info));
+                        this->availableLevels_.insert(info);
                         infoExists = true;
                     }
                 }
                 Loader::unload(&file, mask);
-                if(!infoExists)
-                {
-                    this->infos_.insert(std::pair<std::string, LevelInfoItem*>(it->substr(0, pos), new LevelInfoItem(it->substr(0, pos), *it)));
-                }
-
-                this->availableLevels_.push_back(it->substr(0, pos));
+                if(!infoExists) // If the LevelInfo for this level doesn't exist, we create a new one and insert it into the list of available levels.
+                    this->availableLevels_.insert(new LevelInfoItem(it->substr(0, pos), *it));
             }
         }
     }
 
+    /**
+    @brief
+        Update the list of available Levels.
+    */
     void LevelManager::updateAvailableLevelList(void)
     {
         //TODO: Implement some kind of update?

Modified: code/trunk/src/orxonox/LevelManager.h
===================================================================
--- code/trunk/src/orxonox/LevelManager.h	2010-12-22 18:24:24 UTC (rev 7801)
+++ code/trunk/src/orxonox/LevelManager.h	2010-12-25 19:51:17 UTC (rev 7802)
@@ -22,7 +22,7 @@
  *   Author:
  *      Fabian 'x3n' Landau
  *   Co-authors:
- *      ...
+ *      Damian 'Mozork' Frick
  *
  */
 
@@ -36,12 +36,25 @@
 #include <map>
 #include <string>
 
+#include "LevelInfo.h"
+
 #include "util/Singleton.h"
 #include "core/OrxonoxClass.h"
 
 // tolua_begin
 namespace orxonox
 {
+
+    /**
+    @brief
+        The LevelManager keeps track of @ref orxonox::Level "Levels" whose activity has been requested and serves as an access point to get a list of all available @ref orxonox::Level "Levels" (or rather their respective @ref orxonox::LevelInfoItem "LevelInfoItems").
+
+    @author
+        Fabian 'x3n' Landau
+
+    @author
+        Damian 'Mozork' Frick
+    */
     class _OrxonoxExport LevelManager
     // tolua_end
         : public Singleton<LevelManager>, public OrxonoxClass
@@ -51,31 +64,46 @@
             LevelManager();
             virtual ~LevelManager();
 
-            void setConfigValues();
+            void setConfigValues(); //!< Set the config values for this object.
 
-            void requestActivity(Level* level);
-            void releaseActivity(Level* level);
-            Level* getActiveLevel();
+            void requestActivity(Level* level); //!< Request activity for the input Level.
+            void releaseActivity(Level* level); //!< Release activity for the input Level.
+            Level* getActiveLevel(); //!< Get the currently active Level.
 
-            void setDefaultLevel(const std::string& levelName); //tolua_export
-            const std::string& getDefaultLevel() const; //tolua_export
-            unsigned int getNumberOfLevels(void); //tolua_export
-            LevelInfoItem* getAvailableLevelListItem(unsigned int index) const; //tolua_export
+            // tolua_begin
+            void setDefaultLevel(const std::string& levelName); //!< Set the default Level.
+            /**
+            @brief Get the default level.
+            @return Returns the filename of the default level.
+            */
+            const std::string& getDefaultLevel() const
+                { return defaultLevelName_; }
+            unsigned int getNumberOfLevels(void);
+            LevelInfoItem* getAvailableLevelListItem(unsigned int index); //!< Get the LevelInfoItem at the given index in the list of available Levels.
 
-            static LevelManager& getInstance()    { return Singleton<LevelManager>::getInstance(); } // tolua_export
+            /**
+            @brief Get the instance of the LevelManager.
+            @return Returns the instance of the LevelManager.
+            */
+            static LevelManager& getInstance()
+                { return Singleton<LevelManager>::getInstance(); }
+            // tolua_end
 
         private:
             LevelManager(const LevelManager&);
 
-            void activateNextLevel();
+            void activateNextLevel(); //!< Activate the next level.
 
-            void compileAvailableLevelList(void);
-            void updateAvailableLevelList(void);
+            void compileAvailableLevelList(void); //!< Compile the list of available Levels.
+            void updateAvailableLevelList(void); //!< Update the list of available Levels.
 
-            std::list<Level*> levels_s;
-            std::vector<std::string> availableLevels_;
-            std::map<std::string, LevelInfoItem*> infos_;
+            std::list<Level*> levels_; //!< A list of all the Levels whose activity has been requested, in the order in which they will become active.
+            std::set<LevelInfoItem*, LevelInfoCompare> availableLevels_; //!< The set of available Levels sorted alphabetically according to the name of the Level.
 
+            // Helpers to allow fast access to the availableLevels list.
+            unsigned int nextIndex_; //! The next expected index to be accessed.
+            std::set<LevelInfoItem*, LevelInfoCompare>::iterator nextLevel_; //! The nex expected Level to be accessed.
+
             // config values
             std::string defaultLevelName_;
 




More information about the Orxonox-commit mailing list