Index: /code/trunk/data/gui/layouts/MultiplayerMenu.layout
===================================================================
--- /code/trunk/data/gui/layouts/MultiplayerMenu.layout	(revision 7647)
+++ /code/trunk/data/gui/layouts/MultiplayerMenu.layout	(revision 7648)
@@ -15,5 +15,5 @@
             <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
             <Property Name="VertFormatting" Value="TopAligned" />
-            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.2875,0},{0.75,0},{0.6375,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.2875,0},{0.75,0},{0.7,0}}" />
             <Window Type="MenuWidgets/Listbox" Name="orxonox/MultiplayerListbox" >
                 <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
@@ -23,5 +23,5 @@
                 <Property Name="Text" Value="Join" />
                 <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
-                <Property Name="UnifiedAreaRect" Value="{{0.1,0},{0.85,0},{0.3,0},{0.95,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.1,0},{0.81,0},{0.3,0},{0.89,0}}" />
                 <Event Name="SelectStateChanged" Function="MultiplayerMenu.MultiplayerJoinButton_clicked"/>
             </Window>
@@ -29,5 +29,5 @@
                 <Property Name="Text" Value="Host" />
                 <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
-                <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.85,0},{0.6,0},{0.95,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.81,0},{0.6,0},{0.89,0}}" />
                 <Event Name="SelectStateChanged" Function="MultiplayerMenu.MultiplayerHostButton_clicked"/>
             </Window>
@@ -35,6 +35,13 @@
                 <Property Name="Text" Value="Dedicated" />
                 <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
-                <Property Name="UnifiedAreaRect" Value="{{0.7,0},{0.85,0},{0.9,0},{0.95,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.7,0},{0.81,0},{0.9,0},{0.89,0}}" />
                 <Event Name="SelectStateChanged" Function="MultiplayerMenu.MultiplayerDedicatedButton_clicked"/>
+            </Window>
+            <Window Type="MenuWidgets/Checkbox" Name="orxonox/MultiplayerShowAllCheckbox" >
+                <Property Name="Text" Value="show all" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.65,0},{0.89,0},{0.8,0},{0.99,0}}" />
+                <Property Name="Disabled" Value="True" />
+                <Event Name="CheckStateChanged" Function="MultiplayerMenu.MultiplayerShowAll_clicked"/>
             </Window>
         </Window>
@@ -42,5 +49,5 @@
             <Property Name="Text" Value="Start" />
             <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
-            <Property Name="UnifiedAreaRect" Value="{{0.2875,0},{0.6625,0},{0.4875,0},{0.7125,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.2875,0},{0.725,0},{0.4875,0},{0.775,0}}" />
             <Event Name="Clicked" Function="MultiplayerMenu.MultiplayerStartButton_clicked"/>
         </Window>
@@ -48,5 +55,5 @@
             <Property Name="Text" Value="Back" />
             <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
-            <Property Name="UnifiedAreaRect" Value="{{0.5125,0},{0.6625,0},{0.7125,0},{0.7125,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.5125,0},{0.725,0},{0.7125,0},{0.775,0}}" />
             <Event Name="Clicked" Function="MultiplayerMenu.MultiplayerBackButton_clicked"/>
         </Window>
Index: /code/trunk/data/gui/layouts/SingleplayerMenu.layout
===================================================================
--- /code/trunk/data/gui/layouts/SingleplayerMenu.layout	(revision 7647)
+++ /code/trunk/data/gui/layouts/SingleplayerMenu.layout	(revision 7648)
@@ -15,8 +15,14 @@
             <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
             <Property Name="VertFormatting" Value="TopAligned" />
-            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.2875,0},{0.75,0},{0.6375,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.2875,0},{0.75,0},{0.7,0}}" />
             <Window Type="MenuWidgets/Listbox" Name="orxonox/SingleplayerLevelListbox" >
                 <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
-                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.15,0},{0.95,0},{0.92,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.15,0},{0.95,0},{0.85,0}}" />
+            </Window>
+            <Window Type="MenuWidgets/Checkbox" Name="orxonox/SingleplayerShowAllCheckbox" >
+                <Property Name="Text" Value="show all" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.65,0},{0.87,0},{0.8,0},{.97,0}}" />
+                <Event Name="CheckStateChanged" Function="SingleplayerMenu.SingleplayerShowAll_clicked"/>
             </Window>
         </Window>
@@ -24,5 +30,5 @@
             <Property Name="Text" Value="Start" />
             <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
-            <Property Name="UnifiedAreaRect" Value="{{0.2875,0},{0.6625,0},{0.4875,0},{0.7125,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.2875,0},{0.725,0},{0.4875,0},{0.775,0}}" />
             <Event Name="Clicked" Function="SingleplayerMenu.SingleplayerStartButton_clicked"/>
         </Window>
@@ -30,5 +36,5 @@
             <Property Name="Text" Value="Back" />
             <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
-            <Property Name="UnifiedAreaRect" Value="{{0.5125,0},{0.6625,0},{0.7125,0},{0.7125,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.5125,0},{0.725,0},{0.7125,0},{0.775,0}}" />
             <Event Name="Clicked" Function="SingleplayerMenu.SingleplayerBackButton_clicked"/>
         </Window>
Index: /code/trunk/data/gui/scripts/MultiplayerMenu.lua
===================================================================
--- /code/trunk/data/gui/scripts/MultiplayerMenu.lua	(revision 7647)
+++ /code/trunk/data/gui/scripts/MultiplayerMenu.lua	(revision 7648)
@@ -2,4 +2,8 @@
 
 local P = createMenuSheet("MultiplayerMenu")
+
+P.levelList = {}
+P.itemList = {}
+P.showAll = false
 
 function P.onLoad()
@@ -12,4 +16,6 @@
         local button = tolua.cast(window,"CEGUI::RadioButton")
         button:setSelected(true)
+        local checkbox = winMgr:getWindow("orxonox/MultiplayerShowAllCheckbox")
+        checkbox:setProperty("Disabled", "True")
         P.showServerList()
     end
@@ -18,4 +24,6 @@
         local button = tolua.cast(window,"CEGUI::RadioButton")
         button:setSelected(true)
+        local checkbox = winMgr:getWindow("orxonox/MultiplayerShowAllCheckbox")
+        checkbox:setProperty("Disabled", "False")
         P.showLevelList()
     end
@@ -24,4 +32,6 @@
         local button = tolua.cast(window,"CEGUI::RadioButton")
         button:setSelected(true)
+        local checkbox = winMgr:getWindow("orxonox/MultiplayerShowAllCheckbox")
+        checkbox:setProperty("Disabled", "True")
         P.showLevelList()
     end
@@ -30,4 +40,6 @@
 function P.MultiplayerJoinButton_clicked(e)
     P.multiplayerMode = "startClient"
+    local checkbox = winMgr:getWindow("orxonox/MultiplayerShowAllCheckbox")
+    checkbox:setProperty("Disabled", "True")
     P.showServerList()
 end
@@ -35,4 +47,6 @@
 function P.MultiplayerHostButton_clicked(e)
     P.multiplayerMode = "startServer"
+    local checkbox = winMgr:getWindow("orxonox/MultiplayerShowAllCheckbox")
+    checkbox:setProperty("Disabled", "False")
     P.showLevelList()
 end
@@ -40,5 +54,16 @@
 function P.MultiplayerDedicatedButton_clicked(e)
     P.multiplayerMode = "startDedicated"
+    local checkbox = winMgr:getWindow("orxonox/MultiplayerShowAllCheckbox")
+    checkbox:setProperty("Disabled", "True")
     P.showLevelList()
+end
+
+function P.MultiplayerShowAll_clicked(e)
+    local checkbox = tolua.cast(winMgr:getWindow("orxonox/MultiplayerShowAllCheckbox"), "CEGUI::Checkbox")
+    local show = checkbox:isSelected()
+    if show ~= P.showAll then
+        P.showAll = show
+        P.createLevelList()
+    end
 end
 
@@ -69,33 +94,40 @@
 
 function P.showLevelList()
-    local listbox = winMgr:getWindow("orxonox/MultiplayerListbox")
-    CEGUI.toListbox(listbox):resetList()
+    P.createLevelList()
+end
+
+function P.createLevelList()
+    P.levelList = {}
+    P.itemList = {}
+    local listbox = CEGUI.toListbox(winMgr:getWindow("orxonox/MultiplayerListbox"))
+    listbox:resetList()
+    orxonox.GUIManager:setItemTooltipsEnabledHelper(listbox, true)
     local preselect = orxonox.LevelManager:getInstance():getDefaultLevel()
-    orxonox.LevelManager:getInstance():compileAvailableLevelList()
-    local levelList = {}
+    local size = orxonox.LevelManager:getInstance():getNumberOfLevels()
     local index = 0
-    local level = ""
-    while true do
+    local level = nil
+    while index < size do
         level = orxonox.LevelManager:getInstance():getAvailableLevelListItem(index)
-        if level == "" then
-            break
+        if level ~= nil then
+            if P.showAll or not level:hasTag("test") then
+                table.insert(P.levelList, level)
+            end
         end
-        table.insert(levelList, level)
         index = index + 1
     end
-    table.sort(levelList)
-    index = 1
-    for k,v in pairs(levelList) do
-        local item = CEGUI.createListboxTextItem(v)
+    --TODO: Reintroduce sorting, if needed. At the moment it's sorted by filename.
+    --table.sort(levelList)
+    for k,v in pairs(P.levelList) do
+        local item = CEGUI.createListboxTextItem(v:getName())
         item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
-        item:setID(index)
-        index = index + 1
-        CEGUI.toListbox(listbox):addItem(item)
-        if v .. ".oxw" == preselect then
+        listbox:addItem(item)
+        if v:getXMLFilename() == preselect then
             listbox:setItemSelectState(item, true)
         end
+        P.itemList[k] = listbox:getListboxItemFromIndex(k-1)
+        orxonox.GUIManager:setTooltipTextHelper(P.itemList[k], v:getDescription())
     end
-    end
-    
+end
+
 function P.showServerList()
     local listbox = winMgr:getWindow("orxonox/MultiplayerListbox")
Index: /code/trunk/data/gui/scripts/SingleplayerMenu.lua
===================================================================
--- /code/trunk/data/gui/scripts/SingleplayerMenu.lua	(revision 7647)
+++ /code/trunk/data/gui/scripts/SingleplayerMenu.lua	(revision 7648)
@@ -3,38 +3,69 @@
 local P = createMenuSheet("SingleplayerMenu")
 
+P.levelList = {}
+P.itemList = {}
+P.showAll = false
+
 function P.onLoad()
-    listbox = winMgr:getWindow("orxonox/SingleplayerLevelListbox")
-    preselect = orxonox.LevelManager:getInstance():getDefaultLevel()
-    orxonox.LevelManager:getInstance():compileAvailableLevelList()
-    local levelList = {}
+    local window = winMgr:getWindow("orxonox/SingleplayerShowAllCheckbox")
+    local button = tolua.cast(window,"CEGUI::Checkbox")
+    button:setSelected(false)
+    P.createLevelList()
+end
+
+function P.createLevelList()
+    P.levelList = {}
+    P.itemList = {}
+    local listbox = CEGUI.toListbox(winMgr:getWindow("orxonox/SingleplayerLevelListbox"))
+    listbox:resetList()
+    orxonox.GUIManager:setItemTooltipsEnabledHelper(listbox, true)
+    local preselect = orxonox.LevelManager:getInstance():getDefaultLevel()
+    local size = orxonox.LevelManager:getInstance():getNumberOfLevels()
     local index = 0
-    local level = ""
-    while true do
-      level = orxonox.LevelManager:getInstance():getAvailableLevelListItem(index)
-      if level == "" then
-        break
-      end
-      table.insert(levelList, level)
-      index = index + 1
+    local level = nil
+    while index < size do
+        level = orxonox.LevelManager:getInstance():getAvailableLevelListItem(index)
+        if level ~= nil then
+            if P.showAll or not level:hasTag("test") then
+                table.insert(P.levelList, level)
+            end
+        end
+        index = index + 1
     end
-    table.sort(levelList)
-    for k,v in pairs(levelList) do
-        item = CEGUI.createListboxTextItem(v)
+    --TODO: Reintroduce sorting, if needed. At the moment it's sorted by filename.
+    --table.sort(levelList)
+    for k,v in pairs(P.levelList) do
+        local item = CEGUI.createListboxTextItem(v:getName())
         item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
-        CEGUI.toListbox(listbox):addItem(item)
-        if v .. ".oxw" == preselect then
+        listbox:addItem(item)
+        if v:getXMLFilename() == preselect then
             listbox:setItemSelectState(item, true)
         end
+        P.itemList[k] = listbox:getListboxItemFromIndex(k-1)
+        orxonox.GUIManager:setTooltipTextHelper(P.itemList[k], v:getDescription())
     end
-
 end
 
 function P.SingleplayerStartButton_clicked(e)
-    local choice = CEGUI.toListbox(winMgr:getWindow("orxonox/SingleplayerLevelListbox")):getFirstSelectedItem()
-    if choice then
-        orxonox.LevelManager:getInstance():setDefaultLevel(choice:getText() .. ".oxw")
-        orxonox.execute("startGame")
-        hideAllMenuSheets()
+    local listbox = CEGUI.toListbox(winMgr:getWindow("orxonox/SingleplayerLevelListbox"))
+    local choice = listbox:getFirstSelectedItem()
+    if choice ~= nil then
+        local index = listbox:getItemIndex(choice)
+        local level = P.levelList[index+1]
+        if level ~= nil then
+            orxonox.LevelManager:getInstance():setDefaultLevel(level:getXMLFilename())
+            orxonox.execute("startGame")
+            hideAllMenuSheets()
+        end
     end
+end
+
+function P.SingleplayerShowAll_clicked(e)
+    local checkbox = tolua.cast(winMgr:getWindow("orxonox/SingleplayerShowAllCheckbox"), "CEGUI::Checkbox")
+    local show = checkbox:isSelected()
+    if show ~= P.showAll then
+        P.showAll = show
+        P.createLevelList()
+   end
 end
 
Index: /code/trunk/data/levels/Fight in our Back.oxw
===================================================================
--- /code/trunk/data/levels/Fight in our Back.oxw	(revision 7647)
+++ /code/trunk/data/levels/Fight in our Back.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+  name = "Fight in our Back"
+  description = "Our fleet is far ahead of us. We need to get rid of all the enemies in its back, because we do not want our enemies to attack from everywhere. So let us clear this Sector!"
+  tags = "" 
+/>
+
 <?lua
     include("stats.oxo")
Index: /code/trunk/data/levels/Quest_PirateAttack.oxw
===================================================================
--- /code/trunk/data/levels/Quest_PirateAttack.oxw	(revision 7647)
+++ /code/trunk/data/levels/Quest_PirateAttack.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Pirate Attack"
+ description = "Dani's Testlevel"
+ tags = "test"
+/>
+
 <?lua
   include("hudtemplates3.oxo")
Index: /code/trunk/data/levels/The Time Machine.oxw
===================================================================
--- /code/trunk/data/levels/The Time Machine.oxw	(revision 7647)
+++ /code/trunk/data/levels/The Time Machine.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "The Time Machine"
+ description = "A simple level. The only goal is to defeat as much enemies as you can."
+ tags = ""
+/>
+
 <?lua 
     include("stats.oxo")
Index: /code/trunk/data/levels/empty_level.oxw
===================================================================
--- /code/trunk/data/levels/empty_level.oxw	(revision 7647)
+++ /code/trunk/data/levels/empty_level.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Empty level"
+ description = "A level with absolutely nothing in it."
+ tags = "test"
+/>
+
 <?lua
   include("stats.oxo")
Index: /code/trunk/data/levels/events.oxw
===================================================================
--- /code/trunk/data/levels/events.oxw	(revision 7647)
+++ /code/trunk/data/levels/events.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+  name = "Events showcase"
+  description = "Level to test and showcase events."
+  tags = "test, showcase" 
+/>
+
 <?lua
   include("hudtemplates3.oxo")
Index: /code/trunk/data/levels/fps_test.oxw
===================================================================
--- /code/trunk/data/levels/fps_test.oxw	(revision 7647)
+++ /code/trunk/data/levels/fps_test.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "FPS testlevel"
+ description = "Level to test First Person Shooter"
+ tags = "test"
+/>
+
 <?lua
   include("hudtemplates3.oxo")
Index: /code/trunk/data/levels/notifications.oxw
===================================================================
--- /code/trunk/data/levels/notifications.oxw	(revision 7647)
+++ /code/trunk/data/levels/notifications.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Notifications showcase"
+ description = "Level to test and showcase notifications."
+ tags = "test, showcase"
+/>
+
 <?lua
   include("hudtemplates3.oxo")
Index: /code/trunk/data/levels/pickups.oxw
===================================================================
--- /code/trunk/data/levels/pickups.oxw	(revision 7647)
+++ /code/trunk/data/levels/pickups.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Pickups showcase"
+ description = "Level to test and showcase pickups."
+ tags = "test, showcase"
+/>
+
 <?lua
   include("stats.oxo")
Index: /code/trunk/data/levels/presentation.oxw
===================================================================
--- /code/trunk/data/levels/presentation.oxw	(revision 7647)
+++ /code/trunk/data/levels/presentation.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Presentation"
+ description = "Presentation Level"
+ tags = "presentation"
+/>
+
 <?lua
   include("hudtemplates3.oxo")
Index: /code/trunk/data/levels/presentation09.oxw
===================================================================
--- /code/trunk/data/levels/presentation09.oxw	(revision 7647)
+++ /code/trunk/data/levels/presentation09.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Presentation X"
+ description = "1st Presentation level for Orxonox Convention X"
+ tags = "presentation"
+/>
+
 <?lua
   include("hudtemplates3.oxo")
Index: /code/trunk/data/levels/presentation09b.oxw
===================================================================
--- /code/trunk/data/levels/presentation09b.oxw	(revision 7647)
+++ /code/trunk/data/levels/presentation09b.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Presentation X2"
+ description = "2nd Presentation level for Orxonox Convention X"
+ tags = "presentation"
+/>
+
 <?lua
   include("hudtemplates3.oxo")
Index: /code/trunk/data/levels/presentationFS10.oxw
===================================================================
--- /code/trunk/data/levels/presentationFS10.oxw	(revision 7647)
+++ /code/trunk/data/levels/presentationFS10.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Presentation XI"
+ description = "1st Presentation level for Orxonox Convention XI"
+ tags = "presentation"
+/>
+
 <?lua
   include("stats.oxo")
Index: /code/trunk/data/levels/presentationHS09.oxw
===================================================================
--- /code/trunk/data/levels/presentationHS09.oxw	(revision 7647)
+++ /code/trunk/data/levels/presentationHS09.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Presentation X"
+ description = "1st Presentation level for Orxonox Convention X"
+ tags = "presentation"
+/>
+
 <?lua
   include("hudtemplates3.oxo")
Index: /code/trunk/data/levels/presentationHS09b.oxw
===================================================================
--- /code/trunk/data/levels/presentationHS09b.oxw	(revision 7647)
+++ /code/trunk/data/levels/presentationHS09b.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Presentation X"
+ description = "2nd Presentation level for Orxonox Convention X"
+ tags = "presentation"
+/>
+
 <?lua
   include("stats.oxo")
Index: /code/trunk/data/levels/presentation_FS10.oxw
===================================================================
--- /code/trunk/data/levels/presentation_FS10.oxw	(revision 7647)
+++ /code/trunk/data/levels/presentation_FS10.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Presentation XI FPS"
+ description = "2nd Presentation level for Orxonox Convention XI, FPS"
+ tags = "presentation"
+/>
+
 <?lua
   include("hudtemplates3.oxo")
Index: /code/trunk/data/levels/presentation_FS10_ed.oxw
===================================================================
--- /code/trunk/data/levels/presentation_FS10_ed.oxw	(revision 7647)
+++ /code/trunk/data/levels/presentation_FS10_ed.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Presentation XI FPS"
+ description = "3rd Presentation level for Orxonox Convention XI, FPS"
+ tags = "presentation"
+/>
+
 <?lua
   include("hudtemplates3.oxo")
Index: /code/trunk/data/levels/presentation_dm.oxw
===================================================================
--- /code/trunk/data/levels/presentation_dm.oxw	(revision 7647)
+++ /code/trunk/data/levels/presentation_dm.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Presentation DM"
+ description = "Presentation Level"
+ tags = "presentation"
+/>
+
 <?lua
   include("hudtemplates3.oxo")
Index: /code/trunk/data/levels/princessaeryn.oxw
===================================================================
--- /code/trunk/data/levels/princessaeryn.oxw	(revision 7647)
+++ /code/trunk/data/levels/princessaeryn.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "The Tale of Princess Aeryn"
+ description = "The Tale of the elusive but beautiful Princess Aeryn"
+ tags = ""
+/>
+
 <?lua
   include("hudtemplates3.oxo")
Index: /code/trunk/data/levels/screenshot.oxw
===================================================================
--- /code/trunk/data/levels/screenshot.oxw	(revision 7647)
+++ /code/trunk/data/levels/screenshot.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Screenshot"
+ description = "Level to make awesome screenshots in."
+ tags = "test"
+/>
+
 <?lua
   include("hudtemplates3.oxo")
Index: /code/trunk/data/levels/sound.oxw
===================================================================
--- /code/trunk/data/levels/sound.oxw	(revision 7647)
+++ /code/trunk/data/levels/sound.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Sound showcase"
+ description = "Level to test and showcase sound."
+ tags = "test"
+/>
+
 <?lua
   include("stats.oxo")
Index: /code/trunk/data/levels/teambasematchlevel.oxw
===================================================================
--- /code/trunk/data/levels/teambasematchlevel.oxw	(revision 7647)
+++ /code/trunk/data/levels/teambasematchlevel.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Teambase Match"
+ description = "Fight for the bases."
+ tags = ""
+/>
+
 <?lua
   include("hudtemplates3.oxo")
Index: /code/trunk/data/levels/teamdeathmatch.oxw
===================================================================
--- /code/trunk/data/levels/teamdeathmatch.oxw	(revision 7647)
+++ /code/trunk/data/levels/teamdeathmatch.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Team Deathmatch"
+ description = "Fight against each other in teams."
+ tags = ""
+/>
+
 <?lua
   include("hudtemplates3.oxo")
Index: /code/trunk/data/levels/test_stars.oxw
===================================================================
--- /code/trunk/data/levels/test_stars.oxw	(revision 7647)
+++ /code/trunk/data/levels/test_stars.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Stars Testlevel"
+ description = "Level to test stars"
+ tags = "test"
+/>
+
 <?lua
   include("stats.oxo")
Index: /code/trunk/data/levels/test_swallow.oxw
===================================================================
--- /code/trunk/data/levels/test_swallow.oxw	(revision 7647)
+++ /code/trunk/data/levels/test_swallow.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Swallow Testlevel"
+ description = "Level to test the swallow spaceship."
+ tags = "test"
+/>
+
 <?lua
   include("hudtemplates3.oxo")
Index: /code/trunk/data/levels/tutorial.oxw
===================================================================
--- /code/trunk/data/levels/tutorial.oxw	(revision 7647)
+++ /code/trunk/data/levels/tutorial.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Coding Tutorial"
+ description = "Level for the coding tutorial."
+ tags = "tutorial"
+/>
+
 <?lua
   include("hudtemplates3.oxo")
Index: /code/trunk/data/levels/waypoints.oxw
===================================================================
--- /code/trunk/data/levels/waypoints.oxw	(revision 7647)
+++ /code/trunk/data/levels/waypoints.oxw	(revision 7648)
@@ -1,2 +1,8 @@
+<LevelInfo
+ name = "Waypoints Testlevel"
+ description = "Testing waypoings for AI controlled spaceships."
+ tags = "test"
+/>
+
 <?lua
   include("hudtemplates3.oxo")
Index: /code/trunk/src/libraries/core/GUIManager.cc
===================================================================
--- /code/trunk/src/libraries/core/GUIManager.cc	(revision 7647)
+++ /code/trunk/src/libraries/core/GUIManager.cc	(revision 7648)
@@ -43,4 +43,6 @@
 #include <CEGUIWindow.h>
 #include <CEGUIWindowManager.h>
+#include <elements/CEGUIListbox.h>
+#include <elements/CEGUIListboxItem.h>
 #include <ogreceguirenderer/OgreCEGUIRenderer.h>
 
@@ -436,7 +438,45 @@
     }
 
+    /**
+    @brief
+        Subscribe the input function to the input event for the input window.
+        This is a helper to be used in lua, because subscribeScriptedEvent() doesn't work in lua.
+    @param window
+        The window for which the event is subscribed.
+    @param event
+        The type of event to which we subscribe.
+    @param function
+        The function that is called when the event occurs.
+    */
     void GUIManager::subscribeEventHelper(CEGUI::Window* window, const std::string& event, const std::string& function)
     {
         window->subscribeScriptedEvent(event, function);
     }
+
+    /**
+    @brief
+        Set the input tooltip text for the input ListboxItem.
+    @param item
+        The ListboxItem for which the tooltip should be set.
+    @param tooltip
+        The tooltip text that should be set.
+    */
+    void GUIManager::setTooltipTextHelper(CEGUI::ListboxItem* item, const std::string& tooltip)
+    {
+        item->setTooltipText(tooltip);
+    }
+
+    /**
+    @brief
+        Set whether the tooltips for the input Listbox are enabled.
+    @param listbox
+        The Listbox for which to enable (or disable) tooltips.
+    @param enabled
+        Whether to enable or disabel the tooltips.
+    */
+    void GUIManager::setItemTooltipsEnabledHelper(CEGUI::Listbox* listbox, bool enabled)
+    {
+        listbox->setItemTooltipsEnabled(enabled);
+    }
+
 }
Index: /code/trunk/src/libraries/core/GUIManager.h
===================================================================
--- /code/trunk/src/libraries/core/GUIManager.h	(revision 7647)
+++ /code/trunk/src/libraries/core/GUIManager.h	(revision 7648)
@@ -106,4 +106,6 @@
         // TODO: Temporary hack because the tolua exported CEGUI method does not seem to work
         static void subscribeEventHelper(CEGUI::Window* window, const std::string& event, const std::string& function); //tolua_export
+        static void setTooltipTextHelper(CEGUI::ListboxItem* item, const std::string& toooltip); //tolua_export
+        static void setItemTooltipsEnabledHelper(CEGUI::Listbox* listbox, bool enabled); //tolua_export
 
         static GUIManager& getInstance() { return Singleton<GUIManager>::getInstance(); } // tolua_export
Index: /code/trunk/src/libraries/core/Loader.cc
===================================================================
--- /code/trunk/src/libraries/core/Loader.cc	(revision 7647)
+++ /code/trunk/src/libraries/core/Loader.cc	(revision 7648)
@@ -88,9 +88,19 @@
     }
 
-    bool Loader::load(const ClassTreeMask& mask)
+    /**
+    @brief
+        Loads all opened files, while conforming to the restrictions given by the input ClassTreeMask.
+    @param mask
+        A ClassTreeMask, which defines which types of classes are loaded and which aren't.
+    @param verbose
+        Whether the loader is verbose (prints its progress in a low output level) or not.
+    @return
+        Returns true if successful.
+    */
+    bool Loader::load(const ClassTreeMask& mask, bool verbose)
     {
         bool success = true;
         for (std::vector<std::pair<const XMLFile*, ClassTreeMask> >::iterator it = Loader::files_s.begin(); it != Loader::files_s.end(); ++it)
-            if (!Loader::load(it->first, it->second * mask))
+            if (!Loader::load(it->first, it->second * mask, verbose))
                 success = false;
 
@@ -109,11 +119,33 @@
     }
 
-    bool Loader::reload(const ClassTreeMask& mask)
+    /**
+    @brief
+        Reloads all opened files, while conforming to the restrictions given by the input ClassTreeMask.
+    @param mask
+        A ClassTreeMask, which defines which types of classes are reloaded and which aren't.
+    @param verbose
+        Whether the loader is verbose (prints its progress in a low output level) or not.
+    @return
+        Returns true if successful.
+    */
+    bool Loader::reload(const ClassTreeMask& mask, bool verbose)
     {
         Loader::unload(mask);
-        return Loader::load(mask);
-    }
-
-    bool Loader::load(const XMLFile* file, const ClassTreeMask& mask)
+        return Loader::load(mask, verbose);
+    }
+
+    /**
+    @brief
+        Loads the input file, while conforming to the restrictions given by the input ClassTreeMask.
+    @param file
+        The file to be loaded.
+    @param mask
+        A ClassTreeMask, which defines which types of classes are loaded and which aren't.
+    @param verbose
+        Whether the loader is verbose (prints its progress in a low output level) or not.
+    @return
+        Returns true if successful.
+    */
+    bool Loader::load(const XMLFile* file, const ClassTreeMask& mask, bool verbose)
     {
         if (!file)
@@ -144,6 +176,14 @@
         try
         {
-            COUT(0) << "Start loading " << file->getFilename() << "..." << std::endl;
-            COUT(3) << "Mask: " << Loader::currentMask_s << std::endl;
+            if(verbose)
+            {
+                COUT(0) << "Start loading " << file->getFilename() << "..." << std::endl;
+                COUT(3) << "Mask: " << Loader::currentMask_s << std::endl;
+            }
+            else
+            {
+                COUT(4) << "Start loading " << file->getFilename() << "..." << std::endl;
+                COUT(4) << "Mask: " << Loader::currentMask_s << std::endl;
+            }
 
             ticpp::Document xmlfile(file->getFilename());
@@ -165,5 +205,8 @@
             rootNamespace->XMLPort(rootElement, XMLPort::LoadObject);
 
-            COUT(0) << "Finished loading " << file->getFilename() << '.' << std::endl;
+            if(verbose)
+                COUT(0) << "Finished loading " << file->getFilename() << '.' << std::endl;
+            else
+                COUT(4) << "Finished loading " << file->getFilename() << '.' << std::endl;
 
             COUT(4) << "Namespace-tree:" << std::endl << rootNamespace->toString("  ") << std::endl;
@@ -210,8 +253,20 @@
     }
 
-    bool Loader::reload(const XMLFile* file, const ClassTreeMask& mask)
+    /**
+    @brief
+        Reloads the input file, while conforming to the restrictions given by the input ClassTreeMask.
+    @param file
+        The file to be reloaded.
+    @param mask
+        A ClassTreeMask, which defines which types of classes are reloaded and which aren't.
+    @param verbose
+        Whether the loader is verbose (prints its progress in a low output level) or not.
+    @return
+        Returns true if successful.
+    */
+    bool Loader::reload(const XMLFile* file, const ClassTreeMask& mask, bool verbose)
     {
         Loader::unload(file, mask);
-        return Loader::load(file, mask);
+        return Loader::load(file, mask, verbose);
     }
 
Index: /code/trunk/src/libraries/core/Loader.h
===================================================================
--- /code/trunk/src/libraries/core/Loader.h	(revision 7647)
+++ /code/trunk/src/libraries/core/Loader.h	(revision 7648)
@@ -57,11 +57,11 @@
             static void remove(const XMLFile* file);
 
-            static bool load(const ClassTreeMask& mask = ClassTreeMask());
+            static bool load(const ClassTreeMask& mask = ClassTreeMask(), bool verbose = true);
             static void unload(const ClassTreeMask& mask = ClassTreeMask());
-            static bool reload(const ClassTreeMask& mask = ClassTreeMask());
+            static bool reload(const ClassTreeMask& mask = ClassTreeMask(), bool verbose = true);
 
-            static bool load(const XMLFile* file, const ClassTreeMask& mask = ClassTreeMask());
+            static bool load(const XMLFile* file, const ClassTreeMask& mask = ClassTreeMask(), bool verbose = true);
             static void unload(const XMLFile* file, const ClassTreeMask& mask = ClassTreeMask());
-            static bool reload(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);
Index: /code/trunk/src/orxonox/CMakeLists.txt
===================================================================
--- /code/trunk/src/orxonox/CMakeLists.txt	(revision 7647)
+++ /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 7647)
+++ /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 7647)
+++ /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 7647)
+++ /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 7647)
+++ /code/trunk/src/orxonox/OrxonoxPrereqs.h	(revision 7648)
@@ -67,4 +67,6 @@
     class CameraManager;
     class Level;
+    class LevelInfo;
+    class LevelInfoItem;
     class LevelManager;
     class PawnManager;
