Index: code/trunk/src/orxonox/CMakeLists.txt
===================================================================
--- code/trunk/src/orxonox/CMakeLists.txt	(revision 7606)
+++ code/trunk/src/orxonox/CMakeLists.txt	(revision 7648)
@@ -25,4 +25,5 @@
 SET_SOURCE_FILES(ORXONOX_SRC_FILES
   Level.cc
+  LevelInfo.cc
   LevelManager.cc
   Main.cc
@@ -58,4 +59,5 @@
   TOLUA_FILES
     ChatInputHandler.h
+    LevelInfo.h
     LevelManager.h
     MoodManager.h
Index: code/trunk/src/orxonox/Level.cc
===================================================================
--- code/trunk/src/orxonox/Level.cc	(revision 7606)
+++ code/trunk/src/orxonox/Level.cc	(revision 7648)
@@ -76,5 +76,5 @@
         XMLPortObject(Level, MeshLodInformation, "lodinformation", addLodInfo, getLodInfo, xmlelement, mode);
         XMLPortObjectExtended(Level, BaseObject, "", addObject, getObject, xmlelement, mode, true, false);
-}
+    }
 
     void Level::registerVariables()
Index: code/trunk/src/orxonox/LevelInfo.cc
===================================================================
--- code/trunk/src/orxonox/LevelInfo.cc	(revision 7648)
+++ code/trunk/src/orxonox/LevelInfo.cc	(revision 7648)
@@ -0,0 +1,210 @@
+/*
+ *   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:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "LevelInfo.h"
+
+#include <sstream>
+#include <vector>
+
+#include "util/SubString.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "LevelManager.h"
+
+namespace orxonox
+{
+
+    // LevelInfoItem
+    
+    //! The list of allowed tags.
+    /*static*/ std::set<std::string> LevelInfoItem::possibleTags_s = std::set<std::string>();
+
+    /**
+    @brief
+        Default constructor.
+    */
+    LevelInfoItem::LevelInfoItem()
+    {
+
+    }
+
+    /**
+    @brief
+        Constructor. Initializes the object.
+    @param name
+        The name of the Level.
+    @param filename
+        The XML-filename of the Level.
+    */
+    LevelInfoItem::LevelInfoItem(const std::string& name, const std::string filename)
+    {
+        this->setName(name);
+        this->setXMLFilename(filename);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    LevelInfoItem::~LevelInfoItem()
+    {
+
+    }
+
+    /**
+    @brief
+        Initialize the set of allowed tags.
+    */
+    /*static*/ void LevelInfoItem::initializeTags(void)
+    {
+        if(!LevelInfoItem::initialized_s)
+        {
+            LevelInfoItem::possibleTags_s.insert("test");
+            LevelInfoItem::possibleTags_s.insert("singleplayer");
+            LevelInfoItem::possibleTags_s.insert("multiplayer");
+            LevelInfoItem::possibleTags_s.insert("showcase");
+            LevelInfoItem::possibleTags_s.insert("tutorial");
+            LevelInfoItem::possibleTags_s.insert("presentation");
+        }
+    }
+
+    /**
+    @brief
+        Set the tags the Level is tagged with.
+    @param tags
+        A comma-seperated string of all the tags to be set.
+    */
+    void LevelInfoItem::setTags(const std::string& tags)
+    {
+        SubString substr = SubString(tags, ",", " "); // Split the string into tags.
+        const std::vector<std::string>& strings = substr.getAllStrings();
+        for(std::vector<std::string>::const_iterator it = strings.begin(); it != strings.end(); it++)
+            this->addTag(*it, false);
+
+        this->tagsUpdated();
+    }
+
+    /**
+    @brief
+        Add a tag to the set of tags the Level is tagged with.
+    @param tag
+        The tag to be added.
+    @param update
+        Whether the comma-seperated string of all tags should be updated. Default is true.
+    @return
+        Returns true if the tag was successfully added, if the tag was already present it returns false.
+    */
+    bool LevelInfoItem::addTag(const std::string& tag, bool update)
+    {
+        if(!this->validateTag(tag))
+        {
+            COUT(2) << "Bad LevelInfo tag '" << tag << "' in " << this->getXMLFilename() << ". Ignoring..." << std::endl;
+            return false;
+        }
+        bool success = this->tags_.insert(*LevelInfoItem::possibleTags_s.find(tag)).second;
+        if(update && success)
+            this->tagsUpdated();
+        return success;
+    }
+
+    /**
+    @brief
+        Updates the comma-seperated string of all tags, if the set of tags has changed.
+    */
+    void LevelInfoItem::tagsUpdated(void)
+    {
+        std::stringstream stream;
+        std::set<std::string>::iterator temp;
+        for(std::set<std::string>::iterator it = this->tags_.begin(); it != this->tags_.end(); )
+        {
+            temp = it;
+            if(++it == this->tags_.end()) // If this is the last tag we don't add a comma.
+                stream << *temp;
+            else
+                stream << *temp << ", ";
+        }
+
+        this->tagsString_ = std::string(stream.str());
+    }
+
+    // LevelInfo
+
+    CreateFactory(LevelInfo);
+
+    /**
+    @brief
+
+    @param creator
+        The creator of this object.
+    */
+    LevelInfo::LevelInfo(BaseObject* creator) : BaseObject(creator)
+    {
+        RegisterObject(LevelInfo);
+
+        this->xmlfilename_ = this->getFilename();
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    LevelInfo::~LevelInfo()
+    {
+
+    }
+
+    /**
+    @brief
+        Creates a LevelInfo object through XML.
+    */
+    void LevelInfo::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(LevelInfo, XMLPort, xmlelement, mode);
+
+        XMLPortParam(LevelInfo, "description", setDescription, getDescription, xmlelement, mode);
+        XMLPortParam(LevelInfo, "tags", setTags, getTags, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Copies the contents of this LevelInfo object to a new LevelInfoItem object.
+        This is needed, because a LeveInfo object is only created within the scope of the XML-file it is loaded with and is destroyed once that is unloaded.
+    @return
+        Returns a new LevelInfoItem with the same contents as the LevelInfo object.
+    */
+    LevelInfoItem* LevelInfo::copy(void)
+    {
+        LevelInfoItem* info = new LevelInfoItem(this->BaseObject::getName(), this->getXMLFilename());
+        info->setDescription(this->getDescription());
+        info->setTags(this->getTags());
+        return info;
+    }
+
+}
+
Index: code/trunk/src/orxonox/LevelInfo.h
===================================================================
--- code/trunk/src/orxonox/LevelInfo.h	(revision 7648)
+++ code/trunk/src/orxonox/LevelInfo.h	(revision 7648)
@@ -0,0 +1,201 @@
+/*
+ *   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:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file LevelInfo.h
+    @brief Definition of the LevelInfo and LevelInfoItem class.
+    @ingroup Orxonox
+*/
+
+#ifndef _LevelInfo_H__
+#define _LevelInfo_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <set>
+#include <string>
+
+#include "core/BaseObject.h"
+#include "core/OrxonoxClass.h"
+
+namespace orxonox // tolua_export
+{ // tolua_export
+
+    /**
+    @brief
+        The LevelInfoItem class stores information regarding a @ref orxonox::Level "Level" and makes that information it accessible trough the @ref orxonox::LevelManager "LevelManager".
+        A LevelInfoItem object is commonly created from a @ref orxonox::LevelInfo "LevelInfo" object, using its <code>copy()</code> method.
+
+    @author
+        Damian 'Mozork' Frick
+    */
+    class _OrxonoxExport LevelInfoItem // tolua_export
+        : virtual public OrxonoxClass
+    { // tolua_export
+        public:
+            LevelInfoItem(); //!< Default constructor.
+            LevelInfoItem(const std::string& name, const std::string filename); //!< Constructor. Initializes the object.
+            virtual ~LevelInfoItem(); //!< Destructor.
+
+            /**
+            @brief Set the name of the Level.
+            @param name The name to be set.
+            */
+            inline void setName(const std::string& name)
+                { this->name_ = std::string(name); }
+            /**
+            @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
+
+            /**
+            @brief Set the description of the Level.
+            @param description The description to be set.
+            */
+            inline void setDescription(const std::string& description)
+                { this->description_ = std::string(description); }
+            /**
+            @brief Get the description of the Level.
+            @return Returns the description of the Level.
+            */
+            inline const std::string& getDescription() const { return this->description_; } // tolua_export
+
+            void setTags(const std::string& tags); //!< Set the tags the Level is tagged with.
+            bool addTag(const std::string& tag, bool update = true); //!< Add a tag to the set of tags the Level is tagged with.
+            /**
+            @brief Get the lis of the tags the Level is tagged with.
+            @return Returns a comma-seperated string of all the tags the Level is tagged with.
+            */
+            inline const std::string& getTags(void) const
+                { return this->tagsString_; }
+            /**
+            @brief Get whether the Level has a specific tag.
+            @param tag The tag for which is checked.
+            @return Returns true if the Level is tagged with the input tag.
+            */
+            inline bool hasTag(const std::string& tag) const { return this->tags_.find(tag) != this->tags_.end(); } // tolua_export
+
+            /**
+            @brief Get the XML-filename of the Level.
+            @return Returns the XML-filename (including *.oxw extension) of the Level.
+            */
+            inline const std::string& getXMLFilename(void) { return this->xmlfilename_; } // tolua_export
+
+        protected:
+            /**
+            @brief Set the XML-filename of the Level.
+            @param filename The XML-filename to be set.
+            */
+            inline void setXMLFilename(const std::string& filename)
+                { this->xmlfilename_ = std::string(filename); }
+
+            std::string xmlfilename_; //!< The XML-filename of the Level.
+
+        private:
+            void tagsUpdated(void); //!< Updates the comma-seperated string of all tags, if the set of tags has changed.
+
+            static void initializeTags(void); //!< Initialize the set of allowed tags.
+            /**
+            @brief Check whether an input tag is allowed.
+            @param tag The tag to check.
+            @return Returns true if the input tag is allowed, false if not.
+            */
+            static bool validateTag(const std::string& tag)
+                { LevelInfoItem::initializeTags(); return LevelInfoItem::possibleTags_s.find(tag) != LevelInfoItem::possibleTags_s.end(); }
+
+            static std::set<std::string> possibleTags_s; //!< The set of allowed tags.
+            static const bool initialized_s = false; //!< Whether the set of allowed tags has been inizialized.
+
+            std::string name_; //!< The name of the Level.
+            std::string description_; //!< The description of the Level.
+            std::set<std::string> tags_; //!< The set of tags the Level is tagged with.
+            std::string tagsString_; //!< The comma-seperated string of all the tags the Level is tagged with.
+    }; // tolua_export
+
+    /**
+    @brief
+        The LevelInfo class can be used to store information regarding a @ref orxonox::Level "Level" in its level file.
+        The following parameters can be specified:
+        - @b name The name of the level.
+        - @b description The description of the level.
+        - @b tags A comma-seperated string of tags. Allowed tags are: <em>test</em>, <em>singleplayer</em>, <em>multiplayer</em>, <em>showcase</em>, <em>tutorial</em>, <em>presentation</em>.
+
+        An example would be:
+        @code
+        <LevelInfo
+            name = "Levelname"
+            description = "This is just some awesome level."
+            tags = "test, awesome"
+        />
+        @endcode
+        The LevelInfo is best located at the top of the level file.
+
+    @author
+        Damian 'Mozork' Frick
+    */
+    class _OrxonoxExport LevelInfo : public BaseObject, public LevelInfoItem
+    {
+        public:
+            LevelInfo(BaseObject* creator);
+            virtual ~LevelInfo();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode); //!< Creates a LevelInfo object through XML.
+
+            /**
+            @brief Set the description of the Level.
+            @param description The description to be set.
+            */
+            inline void setDescription(const std::string& description)
+                { this->LevelInfoItem::setDescription(description); }
+            /**
+            @brief Get the description of the Level.
+            @return Returns the description of the Level.
+            */
+            inline const std::string& getDescription() const
+                { return this->LevelInfoItem::getDescription(); }
+
+            /**
+            @brief Set the tags the Level is tagged with.
+            @param tags A comma-seperated string of all the tags to be set.
+            */
+            inline void setTags(const std::string& tags)
+                { this->LevelInfoItem::setTags(tags); }
+            /**
+            @brief Get the lis of the tags the Level is tagged with.
+            @return Returns a comma-seperated string of all the tags the Level is tagged with.
+            */
+            inline const std::string& getTags(void) const
+                { return this->LevelInfoItem::getTags(); }
+
+            LevelInfoItem* copy(void); //!< Copies the contents of this LevelInfo object to a new LevelInfoItem object.
+
+    };
+} // tolua_export
+
+#endif /* _LevelInfo_H__ */
Index: code/trunk/src/orxonox/LevelManager.cc
===================================================================
--- code/trunk/src/orxonox/LevelManager.cc	(revision 7606)
+++ code/trunk/src/orxonox/LevelManager.cc	(revision 7648)
@@ -32,4 +32,5 @@
 
 #include "util/ScopedSingletonManager.h"
+#include "core/ClassTreeMask.h"
 #include "core/CommandLineParser.h"
 #include "core/ConfigValueIncludes.h"
@@ -37,6 +38,8 @@
 #include "core/Loader.h"
 #include "core/Resource.h"
+#include "core/XMLFile.h"
 #include "PlayerManager.h"
 #include "Level.h"
+#include "LevelInfo.h"
 
 namespace orxonox
@@ -56,4 +59,6 @@
             ModifyConfigValue(defaultLevelName_, tset, CommandLineParser::getValue("level").getString());
         }
+
+        this->compileAvailableLevelList();
     }
 
@@ -125,24 +130,63 @@
     }
 
-    const std::string& LevelManager::getAvailableLevelListItem(unsigned int index) const
+    unsigned int LevelManager::getNumberOfLevels()
     {
-        if (index >= availableLevels_.size())
-            return BLANKSTRING;
+        this->updateAvailableLevelList();
+
+        return this->availableLevels_.size();
+    }
+
+    LevelInfoItem* LevelManager::getAvailableLevelListItem(unsigned int index) const
+    {
+        if (index >= this->availableLevels_.size())
+            return NULL;
         else
-            return availableLevels_[index];
+        {
+            std::map<std::string, LevelInfoItem*>::const_iterator it = this->infos_.find(this->availableLevels_[index]);
+            return it->second;
+        }
     }
 
     void LevelManager::compileAvailableLevelList()
     {
-        this->availableLevels_.clear();
         Ogre::StringVectorPtr levels = Resource::findResourceNames("*.oxw");
+        // Iterate over all *.oxw level files.
         for (Ogre::StringVector::const_iterator it = levels->begin(); it != levels->end(); ++it)
         {
+            //TODO: Replace with tag,
             if (it->find("old/") != 0)
             {
                 size_t pos = it->find(".oxw");
+
+                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);
+                for(ObjectList<LevelInfo>::iterator item = ObjectList<LevelInfo>::begin(); item != ObjectList<LevelInfo>::end(); ++item)
+                {
+                    LevelInfoItem* info = item->copy();
+                    if(info->getXMLFilename() == *it)
+                    {
+                        this->infos_.insert(std::pair<std::string, LevelInfoItem*>(it->substr(0, pos),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));
             }
         }
     }
+
+    void LevelManager::updateAvailableLevelList(void)
+    {
+        //TODO: Implement some kind of update?
+    }
 }
Index: code/trunk/src/orxonox/LevelManager.h
===================================================================
--- code/trunk/src/orxonox/LevelManager.h	(revision 7606)
+++ code/trunk/src/orxonox/LevelManager.h	(revision 7648)
@@ -34,4 +34,5 @@
 #include <cassert>
 #include <list>
+#include <map>
 #include <string>
 
@@ -59,6 +60,6 @@
             void setDefaultLevel(const std::string& levelName); //tolua_export
             const std::string& getDefaultLevel() const; //tolua_export
-            void compileAvailableLevelList(); //tolua_export
-            const std::string& getAvailableLevelListItem(unsigned int index) const; //tolua_export
+            unsigned int getNumberOfLevels(void); //tolua_export
+            LevelInfoItem* getAvailableLevelListItem(unsigned int index) const; //tolua_export
 
             static LevelManager& getInstance()    { return Singleton<LevelManager>::getInstance(); } // tolua_export
@@ -69,6 +70,10 @@
             void activateNextLevel();
 
+            void compileAvailableLevelList(void);
+            void updateAvailableLevelList(void);
+
             std::list<Level*> levels_s;
             std::vector<std::string> availableLevels_;
+            std::map<std::string, LevelInfoItem*> infos_;
 
             // config values
Index: code/trunk/src/orxonox/OrxonoxPrereqs.h
===================================================================
--- code/trunk/src/orxonox/OrxonoxPrereqs.h	(revision 7606)
+++ code/trunk/src/orxonox/OrxonoxPrereqs.h	(revision 7648)
@@ -67,4 +67,6 @@
     class CameraManager;
     class Level;
+    class LevelInfo;
+    class LevelInfoItem;
     class LevelManager;
     class PawnManager;
